Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brecht>2020-03-11 16:58:19 +0300
committerBrecht Van Lommel <brecht@blender.org>2020-03-11 16:59:05 +0300
commitb9f6d033beecd75398be14419d37d8aab0609812 (patch)
treeb2385a92388dfb1d17a99a72dd442bc5bc38de85
parente1e772a80243f3c279fcd076c8311301e8885d41 (diff)
Eevee: internal support for arbitrary number of volume grids
This has no user visible impact yet since smoke volumes only support a fixed set of attributes, but will become important with the new volume object. For GPU shader compilation, volume grids are now handled separately from image textures. They are somewhere between a vertex attribute and an image texture, basically an attribute that is stored as a texture. Differential Revision: https://developer.blender.org/D6952
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c11
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c46
-rw-r--r--source/blender/draw/intern/DRW_render.h10
-rw-r--r--source/blender/draw/intern/draw_manager_shader.c12
-rw-r--r--source/blender/gpu/GPU_material.h29
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c28
-rw-r--r--source/blender/gpu/intern/gpu_material.c34
-rw-r--r--source/blender/gpu/intern/gpu_node_graph.c69
-rw-r--r--source/blender/gpu/intern/gpu_node_graph.h8
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_volume_info.glsl78
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_attribute.c34
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_volume_info.c26
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_volume_principled.c47
13 files changed, 236 insertions, 196 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index a37c063adf6..05127585e6c 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -776,6 +776,7 @@ struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, Wor
wo,
engine,
options,
+ false,
e_data.vert_background_shader_str,
NULL,
e_data.frag_shader_lib,
@@ -796,6 +797,7 @@ struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, Wor
wo,
engine,
options,
+ false,
e_data.vert_background_shader_str,
NULL,
e_data.frag_shader_lib,
@@ -819,6 +821,7 @@ struct GPUMaterial *EEVEE_material_world_volume_get(struct Scene *scene, World *
wo,
engine,
options,
+ true,
e_data.vert_volume_shader_str,
e_data.geom_volume_shader_str,
e_data.volume_shader_lib,
@@ -853,6 +856,7 @@ struct GPUMaterial *EEVEE_material_mesh_get(struct Scene *scene,
ma,
engine,
options,
+ false,
e_data.vert_shader_str,
NULL,
e_data.frag_shader_lib,
@@ -880,6 +884,7 @@ struct GPUMaterial *EEVEE_material_mesh_volume_get(struct Scene *scene, Material
ma,
engine,
options,
+ true,
e_data.vert_volume_shader_str,
e_data.geom_volume_shader_str,
e_data.volume_shader_lib,
@@ -916,6 +921,7 @@ struct GPUMaterial *EEVEE_material_mesh_depth_get(struct Scene *scene,
ma,
engine,
options,
+ false,
(is_shadow) ? e_data.vert_shadow_shader_str :
e_data.vert_shader_str,
NULL,
@@ -945,6 +951,7 @@ struct GPUMaterial *EEVEE_material_hair_get(struct Scene *scene, Material *ma)
ma,
engine,
options,
+ false,
e_data.vert_shader_str,
NULL,
e_data.frag_shader_lib,
@@ -1919,7 +1926,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
* to know if the material has a "volume nodetree".
*/
bool use_volume_material = (gpumat_array[0] &&
- GPU_material_use_domain_volume(gpumat_array[0]));
+ GPU_material_has_volume_output(gpumat_array[0]));
if ((ob->dt >= OB_SOLID) || DRW_state_is_image_render()) {
/* Get per-material split surface */
@@ -1968,7 +1975,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
/* Do not render surface if we are rendering a volume object
* and do not have a surface closure. */
if (use_volume_material &&
- (gpumat_array[i] && !GPU_material_use_domain_surface(gpumat_array[i]))) {
+ (gpumat_array[i] && !GPU_material_has_surface_output(gpumat_array[i]))) {
continue;
}
diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c
index dcb8b04fbcd..efe2ef5fc17 100644
--- a/source/blender/draw/engines/eevee/eevee_volumes.c
+++ b/source/blender/draw/engines/eevee/eevee_volumes.c
@@ -351,7 +351,7 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
!LOOK_DEV_STUDIO_LIGHT_ENABLED(draw_ctx->v3d)) {
struct GPUMaterial *mat = EEVEE_material_world_volume_get(scene, wo);
- if (GPU_material_use_domain_volume(mat)) {
+ if (GPU_material_has_volume_output(mat)) {
grp = DRW_shgroup_material_create(mat, psl->volumetric_world_ps);
}
@@ -367,10 +367,11 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
/* Fix principle volumetric not working with world materials. */
- DRW_shgroup_uniform_texture(grp, "sampdensity", e_data.dummy_density);
- DRW_shgroup_uniform_texture(grp, "sampcolor", e_data.dummy_density);
- DRW_shgroup_uniform_texture(grp, "sampflame", e_data.dummy_flame);
- DRW_shgroup_uniform_vec2_copy(grp, "unftemperature", (float[2]){0.0f, 1.0f});
+ ListBase gpu_grids = GPU_material_volume_grids(mat);
+ for (GPUMaterialVolumeGrid *gpu_grid = gpu_grids.first; gpu_grid;
+ gpu_grid = gpu_grid->next) {
+ DRW_shgroup_uniform_texture(grp, gpu_grid->sampler_name, e_data.dummy_density);
+ }
DRW_shgroup_call_procedural_triangles(grp, NULL, common_data->vol_tex_size[2]);
@@ -446,6 +447,7 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
DRW_shgroup_uniform_vec3(grp, "volumeOrcoLoc", texcoloc, 1);
DRW_shgroup_uniform_vec3(grp, "volumeOrcoSize", texcosize, 1);
+ ListBase gpu_grids = GPU_material_volume_grids(mat);
/* Smoke Simulation */
if (((ob->base_flag & BASE_FROM_DUPLI) == 0) &&
(md = modifiers_findByType(ob, eModifierType_Fluid)) &&
@@ -477,12 +479,25 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
BLI_addtail(&e_data.smoke_domains, BLI_genericNodeN(mmd));
}
- DRW_shgroup_uniform_texture_ref(
- grp, "sampdensity", mds->tex_density ? &mds->tex_density : &e_data.dummy_density);
- DRW_shgroup_uniform_texture_ref(
- grp, "sampcolor", mds->tex_color ? &mds->tex_color : &e_data.dummy_density);
- DRW_shgroup_uniform_texture_ref(
- grp, "sampflame", mds->tex_flame ? &mds->tex_flame : &e_data.dummy_flame);
+ for (GPUMaterialVolumeGrid *gpu_grid = gpu_grids.first; gpu_grid; gpu_grid = gpu_grid->next) {
+ if (STREQ(gpu_grid->name, "density")) {
+ DRW_shgroup_uniform_texture_ref(grp,
+ gpu_grid->sampler_name,
+ mds->tex_density ? &mds->tex_density :
+ &e_data.dummy_density);
+ }
+ else if (STREQ(gpu_grid->name, "color")) {
+ DRW_shgroup_uniform_texture_ref(
+ grp, gpu_grid->sampler_name, mds->tex_color ? &mds->tex_color : &e_data.dummy_density);
+ }
+ else if (STREQ(gpu_grid->name, "flame") || STREQ(gpu_grid->name, "temperature")) {
+ DRW_shgroup_uniform_texture_ref(
+ grp, gpu_grid->sampler_name, mds->tex_flame ? &mds->tex_flame : &e_data.dummy_flame);
+ }
+ else {
+ DRW_shgroup_uniform_texture_ref(grp, gpu_grid->sampler_name, &e_data.dummy_density);
+ }
+ }
/* Constant Volume color. */
bool use_constant_color = ((mds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS) == 0 &&
@@ -492,14 +507,13 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
grp, "volumeColor", (use_constant_color) ? mds->active_color : white, 1);
/* Output is such that 0..1 maps to 0..1000K */
- DRW_shgroup_uniform_vec2(grp, "unftemperature", &mds->flame_ignition, 1);
+ DRW_shgroup_uniform_vec2(grp, "volumeTemperature", &mds->flame_ignition, 1);
}
else {
- DRW_shgroup_uniform_texture(grp, "sampdensity", e_data.dummy_density);
- DRW_shgroup_uniform_texture(grp, "sampcolor", e_data.dummy_density);
- DRW_shgroup_uniform_texture(grp, "sampflame", e_data.dummy_flame);
+ for (GPUMaterialVolumeGrid *gpu_grid = gpu_grids.first; gpu_grid; gpu_grid = gpu_grid->next) {
+ DRW_shgroup_uniform_texture(grp, gpu_grid->sampler_name, e_data.dummy_density);
+ }
DRW_shgroup_uniform_vec3(grp, "volumeColor", white, 1);
- DRW_shgroup_uniform_vec2(grp, "unftemperature", (float[2]){0.0f, 1.0f}, 1);
}
/* TODO Reduce to number of slices intersecting. */
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 904510b1357..c3e94fda4fc 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -211,16 +211,17 @@ struct GPUShader *DRW_shader_create_fullscreen(const char *frag, const char *def
struct GPUShader *DRW_shader_create_3d_depth_only(eGPUShaderConfig slot);
struct GPUMaterial *DRW_shader_find_from_world(struct World *wo,
const void *engine_type,
- int options,
+ const int options,
bool deferred);
struct GPUMaterial *DRW_shader_find_from_material(struct Material *ma,
const void *engine_type,
- int options,
+ const int options,
bool deferred);
struct GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
struct World *wo,
const void *engine_type,
- int options,
+ const int options,
+ const bool is_volume_shader,
const char *vert,
const char *geom,
const char *frag_lib,
@@ -229,7 +230,8 @@ struct GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
struct GPUMaterial *DRW_shader_create_from_material(struct Scene *scene,
struct Material *ma,
const void *engine_type,
- int options,
+ const int options,
+ const bool is_volume_shader,
const char *vert,
const char *geom,
const char *frag_lib,
diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c
index 9c34cdbac3b..ed05fb85dc9 100644
--- a/source/blender/draw/intern/draw_manager_shader.c
+++ b/source/blender/draw/intern/draw_manager_shader.c
@@ -356,7 +356,7 @@ GPUShader *DRW_shader_create_3d_depth_only(eGPUShaderConfig sh_cfg)
GPUMaterial *DRW_shader_find_from_world(World *wo,
const void *engine_type,
- int options,
+ const int options,
bool deferred)
{
GPUMaterial *mat = GPU_material_from_nodetree_find(&wo->gpumaterial, engine_type, options);
@@ -372,7 +372,7 @@ GPUMaterial *DRW_shader_find_from_world(World *wo,
GPUMaterial *DRW_shader_find_from_material(Material *ma,
const void *engine_type,
- int options,
+ const int options,
bool deferred)
{
GPUMaterial *mat = GPU_material_from_nodetree_find(&ma->gpumaterial, engine_type, options);
@@ -389,7 +389,8 @@ GPUMaterial *DRW_shader_find_from_material(Material *ma,
GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
World *wo,
const void *engine_type,
- int options,
+ const int options,
+ const bool is_volume_shader,
const char *vert,
const char *geom,
const char *frag_lib,
@@ -409,6 +410,7 @@ GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
&wo->gpumaterial,
engine_type,
options,
+ is_volume_shader,
vert,
geom,
frag_lib,
@@ -426,7 +428,8 @@ GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
GPUMaterial *DRW_shader_create_from_material(struct Scene *scene,
Material *ma,
const void *engine_type,
- int options,
+ const int options,
+ const bool is_volume_shader,
const char *vert,
const char *geom,
const char *frag_lib,
@@ -446,6 +449,7 @@ GPUMaterial *DRW_shader_create_from_material(struct Scene *scene,
&ma->gpumaterial,
engine_type,
options,
+ is_volume_shader,
vert,
geom,
frag_lib,
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index 7107748e62a..da00306bf9f 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -98,13 +98,9 @@ typedef enum eGPUBuiltin {
GPU_LOC_TO_VIEW_MATRIX = (1 << 13),
GPU_INVERSE_LOC_TO_VIEW_MATRIX = (1 << 14),
GPU_OBJECT_INFO = (1 << 15),
- GPU_VOLUME_DENSITY = (1 << 16),
- GPU_VOLUME_COLOR = (1 << 17),
- GPU_VOLUME_FLAME = (1 << 18),
- GPU_VOLUME_TEMPERATURE = (1 << 19),
- GPU_BARYCENTRIC_TEXCO = (1 << 20),
- GPU_BARYCENTRIC_DIST = (1 << 21),
- GPU_WORLD_NORMAL = (1 << 22),
+ GPU_BARYCENTRIC_TEXCO = (1 << 16),
+ GPU_BARYCENTRIC_DIST = (1 << 17),
+ GPU_WORLD_NORMAL = (1 << 18),
} eGPUBuiltin;
typedef enum eGPUMatFlag {
@@ -146,6 +142,7 @@ GPUNodeLink *GPU_image(GPUMaterial *mat, struct Image *ima, struct ImageUser *iu
GPUNodeLink *GPU_image_tiled(GPUMaterial *mat, struct Image *ima, struct ImageUser *iuser);
GPUNodeLink *GPU_image_tiled_mapping(GPUMaterial *mat, struct Image *ima, struct ImageUser *iuser);
GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *layer);
+GPUNodeLink *GPU_volume_grid(GPUMaterial *mat, const char *name);
GPUNodeLink *GPU_builtin(eGPUBuiltin builtin);
bool GPU_link(GPUMaterial *mat, const char *name, ...);
@@ -179,7 +176,8 @@ GPUMaterial *GPU_material_from_nodetree(struct Scene *scene,
struct bNodeTree *ntree,
struct ListBase *gpumaterials,
const void *engine_type,
- int options,
+ const int options,
+ const bool is_volume_shader,
const char *vert_code,
const char *geom_code,
const char *frag_lib,
@@ -192,7 +190,6 @@ void GPU_materials_free(struct Main *bmain);
struct Scene *GPU_material_scene(GPUMaterial *material);
struct GPUPass *GPU_material_get_pass(GPUMaterial *material);
-struct ListBase *GPU_material_get_inputs(GPUMaterial *material);
struct Material *GPU_material_get_material(GPUMaterial *material);
eGPUMaterialStatus GPU_material_status(GPUMaterial *mat);
@@ -200,8 +197,10 @@ struct GPUUniformBuffer *GPU_material_uniform_buffer_get(GPUMaterial *material);
void GPU_material_uniform_buffer_create(GPUMaterial *material, ListBase *inputs);
struct GPUUniformBuffer *GPU_material_create_sss_profile_ubo(void);
-bool GPU_material_use_domain_surface(GPUMaterial *mat);
-bool GPU_material_use_domain_volume(GPUMaterial *mat);
+bool GPU_material_has_surface_output(GPUMaterial *mat);
+bool GPU_material_has_volume_output(GPUMaterial *mat);
+
+bool GPU_material_is_volume_shader(GPUMaterial *mat);
void GPU_material_flag_set(GPUMaterial *mat, eGPUMatFlag flag);
bool GPU_material_flag_get(GPUMaterial *mat, eGPUMatFlag flag);
@@ -231,8 +230,16 @@ typedef struct GPUMaterialTexture {
int users;
} GPUMaterialTexture;
+typedef struct GPUMaterialVolumeGrid {
+ struct GPUMaterialVolumeGrid *next, *prev;
+ char *name;
+ char sampler_name[32]; /* Name of sampler in GLSL. */
+ int users;
+} GPUMaterialVolumeGrid;
+
ListBase GPU_material_attributes(GPUMaterial *material);
ListBase GPU_material_textures(GPUMaterial *material);
+ListBase GPU_material_volume_grids(GPUMaterial *material);
#ifdef __cplusplus
}
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index e8616c1e256..bcaa95c2f59 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -269,18 +269,6 @@ static const char *gpu_builtin_name(eGPUBuiltin builtin)
else if (builtin == GPU_OBJECT_INFO) {
return "unfobjectinfo";
}
- else if (builtin == GPU_VOLUME_DENSITY) {
- return "sampdensity";
- }
- else if (builtin == GPU_VOLUME_COLOR) {
- return "sampcolor";
- }
- else if (builtin == GPU_VOLUME_FLAME) {
- return "sampflame";
- }
- else if (builtin == GPU_VOLUME_TEMPERATURE) {
- return "unftemperature";
- }
else if (builtin == GPU_BARYCENTRIC_TEXCO) {
return "unfbarycentrictex";
}
@@ -344,6 +332,11 @@ static int codegen_process_uniforms_functions(GPUMaterial *material,
}
}
+ /* Volume Grids */
+ for (GPUMaterialVolumeGrid *grid = graph->volume_grids.first; grid; grid = grid->next) {
+ BLI_dynstr_appendf(ds, "uniform sampler3D %s;\n", grid->sampler_name);
+ }
+
/* Print other uniforms */
for (node = graph->nodes.first; node; node = node->next) {
for (input = node->inputs.first; input; input = input->next) {
@@ -353,13 +346,7 @@ static int codegen_process_uniforms_functions(GPUMaterial *material,
builtins |= input->builtin;
name = gpu_builtin_name(input->builtin);
- if (BLI_str_startswith(name, "samp")) {
- if ((input->builtin == GPU_VOLUME_DENSITY) || (input->builtin == GPU_VOLUME_COLOR) ||
- (input->builtin == GPU_VOLUME_FLAME)) {
- BLI_dynstr_appendf(ds, "uniform sampler3D %s;\n", name);
- }
- }
- else if (BLI_str_startswith(name, "unf")) {
+ if (BLI_str_startswith(name, "unf")) {
BLI_dynstr_appendf(ds, "uniform %s %s;\n", gpu_data_type_to_string(input->type), name);
}
else {
@@ -442,6 +429,9 @@ static void codegen_call_functions(DynStr *ds, GPUNodeGraph *graph, GPUOutput *f
else if (input->source == GPU_SOURCE_TEX_TILED_MAPPING) {
BLI_dynstr_append(ds, input->texture->tiled_mapping_name);
}
+ else if (input->source == GPU_SOURCE_VOLUME_GRID) {
+ BLI_dynstr_append(ds, input->volume_grid->sampler_name);
+ }
else if (input->source == GPU_SOURCE_OUTPUT) {
codegen_convert_datatype(
ds, input->link->output->type, input->type, "tmp", input->link->output->id);
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index b2658839d67..8a4a88d0663 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -70,6 +70,7 @@ struct GPUMaterial {
const void *engine_type; /* attached engine type */
int options; /* to identify shader variations (shadow, probe, world background...) */
+ bool is_volume_shader; /* is volumetric shader */
/* Nodes */
GPUNodeGraph graph;
@@ -80,7 +81,8 @@ struct GPUMaterial {
/* XXX: Should be in Material. But it depends on the output node
* used and since the output selection is different for GPUMaterial...
*/
- int domain;
+ bool has_volume_output;
+ bool has_surface_output;
/* Only used by Eevee to know which bsdf are used. */
int flag;
@@ -109,8 +111,8 @@ struct GPUMaterial {
};
enum {
- GPU_DOMAIN_SURFACE = (1 << 0),
- GPU_DOMAIN_VOLUME = (1 << 1),
+ GPU_USE_SURFACE_OUTPUT = (1 << 0),
+ GPU_USE_VOLUME_OUTPUT = (1 << 1),
};
/* Functions */
@@ -567,6 +569,11 @@ ListBase GPU_material_textures(GPUMaterial *material)
return material->graph.textures;
}
+ListBase GPU_material_volume_grids(GPUMaterial *material)
+{
+ return material->graph.volume_grids;
+}
+
void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link)
{
if (!material->graph.outlink) {
@@ -592,14 +599,19 @@ eGPUMaterialStatus GPU_material_status(GPUMaterial *mat)
/* Code generation */
-bool GPU_material_use_domain_surface(GPUMaterial *mat)
+bool GPU_material_has_surface_output(GPUMaterial *mat)
+{
+ return mat->has_surface_output;
+}
+
+bool GPU_material_has_volume_output(GPUMaterial *mat)
{
- return (mat->domain & GPU_DOMAIN_SURFACE);
+ return mat->has_volume_output;
}
-bool GPU_material_use_domain_volume(GPUMaterial *mat)
+bool GPU_material_is_volume_shader(GPUMaterial *mat)
{
- return (mat->domain & GPU_DOMAIN_VOLUME);
+ return mat->is_volume_shader;
}
void GPU_material_flag_set(GPUMaterial *mat, eGPUMatFlag flag)
@@ -636,7 +648,8 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene,
struct bNodeTree *ntree,
ListBase *gpumaterials,
const void *engine_type,
- int options,
+ const int options,
+ const bool is_volume_shader,
const char *vert_code,
const char *geom_code,
const char *frag_lib,
@@ -655,6 +668,7 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene,
mat->scene = scene;
mat->engine_type = engine_type;
mat->options = options;
+ mat->is_volume_shader = is_volume_shader;
#ifndef NDEBUG
BLI_snprintf(mat->name, sizeof(mat->name), "%s", name);
#else
@@ -670,8 +684,8 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene,
gpu_material_ramp_texture_build(mat);
- SET_FLAG_FROM_TEST(mat->domain, has_surface_output, GPU_DOMAIN_SURFACE);
- SET_FLAG_FROM_TEST(mat->domain, has_volume_output, GPU_DOMAIN_VOLUME);
+ mat->has_surface_output = has_surface_output;
+ mat->has_volume_output = has_volume_output;
if (mat->graph.outlink) {
/* HACK: this is only for eevee. We add the define here after the nodetree evaluation. */
diff --git a/source/blender/gpu/intern/gpu_node_graph.c b/source/blender/gpu/intern/gpu_node_graph.c
index de35b43109f..0d5cc46c0b9 100644
--- a/source/blender/gpu/intern/gpu_node_graph.c
+++ b/source/blender/gpu/intern/gpu_node_graph.c
@@ -119,6 +119,10 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const eGPUType
input->source = GPU_SOURCE_TEX_TILED_MAPPING;
input->texture = link->texture;
break;
+ case GPU_NODE_LINK_VOLUME_GRID:
+ input->source = GPU_SOURCE_VOLUME_GRID;
+ input->volume_grid = link->volume_grid;
+ break;
case GPU_NODE_LINK_ATTR:
input->source = GPU_SOURCE_ATTR;
input->attr = link->attr;
@@ -321,6 +325,31 @@ static GPUMaterialTexture *gpu_node_graph_add_texture(GPUNodeGraph *graph,
return tex;
}
+static GPUMaterialVolumeGrid *gpu_node_graph_add_volume_grid(GPUNodeGraph *graph, const char *name)
+{
+ /* Find existing volume grid. */
+ int num_grids = 0;
+ GPUMaterialVolumeGrid *grid = graph->volume_grids.first;
+ for (; grid; grid = grid->next) {
+ if (STREQ(grid->name, name)) {
+ break;
+ }
+ num_grids++;
+ }
+
+ /* Add new requested volume grid. */
+ if (grid == NULL) {
+ grid = MEM_callocN(sizeof(*grid), __func__);
+ grid->name = BLI_strdup(name);
+ BLI_snprintf(grid->sampler_name, sizeof(grid->sampler_name), "vsamp%d", num_grids);
+ BLI_addtail(&graph->volume_grids, grid);
+ }
+
+ grid->users++;
+
+ return grid;
+}
+
/* Creating Inputs */
GPUNodeLink *GPU_attribute(GPUMaterial *mat, const CustomDataType type, const char *name)
@@ -394,6 +423,30 @@ GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *ro
return link;
}
+GPUNodeLink *GPU_volume_grid(GPUMaterial *mat, const char *name)
+{
+ /* NOTE: this could be optimized by automatically merging duplicate
+ * lookups of the same attribute. */
+ GPUNodeGraph *graph = gpu_material_node_graph(mat);
+ GPUNodeLink *link = gpu_node_link_create();
+ link->link_type = GPU_NODE_LINK_VOLUME_GRID;
+ link->volume_grid = gpu_node_graph_add_volume_grid(graph, name);
+
+ /* Two special cases, where we adjust the output values of smoke grids to
+ * bring the into standard range without having to modify the grid values. */
+ if (strcmp(name, "color") == 0) {
+ GPU_link(mat, "node_attribute_volume_color", link, &link);
+ }
+ else if (strcmp(name, "temperature") == 0) {
+ GPU_link(mat, "node_attribute_volume_temperature", link, &link);
+ }
+ else {
+ GPU_link(mat, "node_attribute_volume", link, &link);
+ }
+
+ return link;
+}
+
GPUNodeLink *GPU_builtin(eGPUBuiltin builtin)
{
GPUNodeLink *link = gpu_node_link_create();
@@ -537,6 +590,9 @@ static void gpu_inputs_free(ListBase *inputs)
else if (ELEM(input->source, GPU_SOURCE_TEX, GPU_SOURCE_TEX_TILED_MAPPING)) {
input->texture->users--;
}
+ else if (ELEM(input->source, GPU_SOURCE_VOLUME_GRID)) {
+ input->volume_grid->users--;
+ }
if (input->link) {
gpu_node_link_free(input->link);
@@ -579,6 +635,11 @@ void gpu_node_graph_free_nodes(GPUNodeGraph *graph)
void gpu_node_graph_free(GPUNodeGraph *graph)
{
gpu_node_graph_free_nodes(graph);
+
+ for (GPUMaterialVolumeGrid *grid = graph->volume_grids.first; grid; grid = grid->next) {
+ MEM_SAFE_FREE(grid->name);
+ }
+ BLI_freelistN(&graph->volume_grids);
BLI_freelistN(&graph->textures);
BLI_freelistN(&graph->attributes);
}
@@ -637,4 +698,12 @@ void gpu_node_graph_prune_unused(GPUNodeGraph *graph)
BLI_freelinkN(&graph->textures, tex);
}
}
+
+ for (GPUMaterialVolumeGrid *grid = graph->volume_grids.first, *next = NULL; grid; grid = next) {
+ next = grid->next;
+ if (grid->users == 0) {
+ MEM_SAFE_FREE(grid->name);
+ BLI_freelinkN(&graph->volume_grids, grid);
+ }
+ }
}
diff --git a/source/blender/gpu/intern/gpu_node_graph.h b/source/blender/gpu/intern/gpu_node_graph.h
index 9214bd7f1ba..ceaeea2bfa8 100644
--- a/source/blender/gpu/intern/gpu_node_graph.h
+++ b/source/blender/gpu/intern/gpu_node_graph.h
@@ -48,6 +48,8 @@ typedef enum eGPUDataSource {
GPU_SOURCE_STRUCT,
GPU_SOURCE_TEX,
GPU_SOURCE_TEX_TILED_MAPPING,
+ GPU_SOURCE_VOLUME_GRID,
+ GPU_SOURCE_VOLUME_GRID_TRANSFORM,
} eGPUDataSource;
typedef enum {
@@ -59,6 +61,7 @@ typedef enum {
GPU_NODE_LINK_IMAGE,
GPU_NODE_LINK_IMAGE_TILED,
GPU_NODE_LINK_IMAGE_TILED_MAPPING,
+ GPU_NODE_LINK_VOLUME_GRID,
GPU_NODE_LINK_OUTPUT,
GPU_NODE_LINK_UNIFORM,
} GPUNodeLinkType;
@@ -88,6 +91,8 @@ struct GPUNodeLink {
eGPUBuiltin builtin;
/* GPU_NODE_LINK_COLORBAND */
struct GPUTexture **colorband;
+ /* GPU_NODE_LINK_VOLUME_GRID */
+ struct GPUMaterialVolumeGrid *volume_grid;
/* GPU_NODE_LINK_OUTPUT */
struct GPUOutput *output;
/* GPU_NODE_LINK_ATTR */
@@ -126,6 +131,8 @@ typedef struct GPUInput {
struct GPUMaterialTexture *texture;
/* GPU_SOURCE_ATTR */
struct GPUMaterialAttribute *attr;
+ /* GPU_SOURCE_VOLUME_GRID */
+ struct GPUMaterialVolumeGrid *volume_grid;
};
} GPUInput;
@@ -139,6 +146,7 @@ typedef struct GPUNodeGraph {
/* Requested attributes and textures. */
ListBase attributes;
ListBase textures;
+ ListBase volume_grids;
} GPUNodeGraph;
/* Node Graph */
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_volume_info.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_volume_info.glsl
index 0fecb5bd1f9..a80cd3cb329 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_volume_info.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_volume_info.glsl
@@ -1,18 +1,21 @@
-void node_attribute_volume_density(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf)
+
+/* Uniforms to convert smoke grid values into standard range. */
+uniform vec3 volumeColor = vec3(1.0);
+uniform vec2 volumeTemperature = vec2(0.0);
+
+/* Generic volume attribute. */
+void node_attribute_volume(sampler3D tex, out vec3 outvec)
{
#if defined(MESH_SHADER) && defined(VOLUMETRICS)
vec3 cos = volumeObjectLocalCoord;
#else
vec3 cos = vec3(0.0);
#endif
- outf = texture(tex, cos).r;
- outvec = vec3(outf, outf, outf);
- outcol = vec4(outf, outf, outf, 1.0);
+ outvec = texture(tex, cos).rgb;
}
-uniform vec3 volumeColor = vec3(1.0);
-
-void node_attribute_volume_color(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf)
+/* Special color attribute for smoke. */
+void node_attribute_volume_color(sampler3D tex, out vec3 outvec)
{
#if defined(MESH_SHADER) && defined(VOLUMETRICS)
vec3 cos = volumeObjectLocalCoord;
@@ -20,70 +23,31 @@ void node_attribute_volume_color(sampler3D tex, out vec4 outcol, out vec3 outvec
vec3 cos = vec3(0.0);
#endif
- vec4 value = texture(tex, cos).rgba;
/* Density is premultiplied for interpolation, divide it out here. */
+ vec4 value = texture(tex, cos).rgba;
if (value.a > 1e-8) {
value.rgb /= value.a;
}
outvec = value.rgb * volumeColor;
- outcol = vec4(outvec, 1.0);
- outf = avg(outvec);
-}
-
-void node_attribute_volume_flame(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf)
-{
-#if defined(MESH_SHADER) && defined(VOLUMETRICS)
- vec3 cos = volumeObjectLocalCoord;
-#else
- vec3 cos = vec3(0.0);
-#endif
- outf = texture(tex, cos).r;
- outvec = vec3(outf, outf, outf);
- outcol = vec4(outf, outf, outf, 1.0);
}
-void node_attribute_volume_temperature(
- sampler3D tex, vec2 temperature, out vec4 outcol, out vec3 outvec, out float outf)
+/* Special temperature attribute for smoke. */
+void node_attribute_volume_temperature(sampler3D tex, out float outf)
{
#if defined(MESH_SHADER) && defined(VOLUMETRICS)
vec3 cos = volumeObjectLocalCoord;
#else
vec3 cos = vec3(0.0);
#endif
- float flame = texture(tex, cos).r;
-
- outf = (flame > 0.01) ? temperature.x + flame * (temperature.y - temperature.x) : 0.0;
- outvec = vec3(outf, outf, outf);
- outcol = vec4(outf, outf, outf, 1.0);
-}
-void node_volume_info(sampler3D densitySampler,
- sampler3D colorSampler,
- sampler3D flameSampler,
- vec2 temperature,
- out vec4 outColor,
- out float outDensity,
- out float outFlame,
- out float outTemprature)
-{
-#if defined(MESH_SHADER) && defined(VOLUMETRICS)
- vec3 p = volumeObjectLocalCoord;
-#else
- vec3 p = vec3(0.0);
-#endif
-
- outDensity = texture(densitySampler, p).r;
-
- /* Color is premultiplied for interpolation, divide it out here. */
- vec4 color = texture(colorSampler, p);
- if (color.a > 1e-8) {
- color.rgb /= color.a;
+ float value = texture(tex, cos).r;
+ if (volumeTemperature.x < volumeTemperature.y) {
+ outf = (value > 0.01) ?
+ volumeTemperature.x + value * (volumeTemperature.y - volumeTemperature.x) :
+ 0.0;
+ }
+ else {
+ outf = value;
}
- outColor = vec4(color.rgb * volumeColor, 1.0);
-
- float flame = texture(flameSampler, p).r;
- outFlame = flame;
-
- outTemprature = (flame > 0.01) ? temperature.x + flame * (temperature.y - temperature.x) : 0.0;
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_attribute.c b/source/blender/nodes/shader/nodes/node_shader_attribute.c
index fa0b8955c58..6b5d46e250b 100644
--- a/source/blender/nodes/shader/nodes/node_shader_attribute.c
+++ b/source/blender/nodes/shader/nodes/node_shader_attribute.c
@@ -42,28 +42,18 @@ static int node_shader_gpu_attribute(GPUMaterial *mat,
{
NodeShaderAttribute *attr = node->storage;
- /* FIXME : if an attribute layer (like vertex color) has one of these names,
- * it will not work as expected. */
- if (strcmp(attr->name, "density") == 0) {
- return GPU_stack_link(
- mat, node, "node_attribute_volume_density", in, out, GPU_builtin(GPU_VOLUME_DENSITY));
- }
- else if (strcmp(attr->name, "color") == 0) {
- return GPU_stack_link(
- mat, node, "node_attribute_volume_color", in, out, GPU_builtin(GPU_VOLUME_COLOR));
- }
- else if (strcmp(attr->name, "flame") == 0) {
- return GPU_stack_link(
- mat, node, "node_attribute_volume_flame", in, out, GPU_builtin(GPU_VOLUME_FLAME));
- }
- else if (strcmp(attr->name, "temperature") == 0) {
- return GPU_stack_link(mat,
- node,
- "node_attribute_volume_temperature",
- in,
- out,
- GPU_builtin(GPU_VOLUME_FLAME),
- GPU_builtin(GPU_VOLUME_TEMPERATURE));
+ if (GPU_material_is_volume_shader(mat)) {
+ if (out[0].hasoutput) {
+ out[0].link = GPU_volume_grid(mat, attr->name);
+ }
+ if (out[1].hasoutput) {
+ out[1].link = GPU_volume_grid(mat, attr->name);
+ }
+ if (out[2].hasoutput) {
+ out[2].link = GPU_volume_grid(mat, attr->name);
+ }
+
+ return 1;
}
else {
GPUNodeLink *cd_attr = GPU_attribute(mat, CD_AUTO_FROM_NAME, attr->name);
diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_info.c b/source/blender/nodes/shader/nodes/node_shader_volume_info.c
index c91c82eee6c..7ccc00f1af3 100644
--- a/source/blender/nodes/shader/nodes/node_shader_volume_info.c
+++ b/source/blender/nodes/shader/nodes/node_shader_volume_info.c
@@ -28,21 +28,25 @@ static bNodeSocketTemplate sh_node_volume_info_out[] = {
};
static int node_shader_gpu_volume_info(GPUMaterial *mat,
- bNode *node,
+ bNode *UNUSED(node),
bNodeExecData *UNUSED(execdata),
- GPUNodeStack *in,
+ GPUNodeStack *UNUSED(in),
GPUNodeStack *out)
{
+ if (out[0].hasoutput) {
+ out[0].link = GPU_volume_grid(mat, "color");
+ }
+ if (out[1].hasoutput) {
+ out[1].link = GPU_volume_grid(mat, "density");
+ }
+ if (out[2].hasoutput) {
+ out[2].link = GPU_volume_grid(mat, "flame");
+ }
+ if (out[3].hasoutput) {
+ out[3].link = GPU_volume_grid(mat, "temperature");
+ }
- return GPU_stack_link(mat,
- node,
- "node_volume_info",
- in,
- out,
- GPU_builtin(GPU_VOLUME_DENSITY),
- GPU_builtin(GPU_VOLUME_COLOR),
- GPU_builtin(GPU_VOLUME_FLAME),
- GPU_builtin(GPU_VOLUME_TEMPERATURE));
+ return true;
}
void register_node_type_sh_volume_info(void)
diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_principled.c b/source/blender/nodes/shader/nodes/node_shader_volume_principled.c
index d82ef1a03e9..92e1b3435c8 100644
--- a/source/blender/nodes/shader/nodes/node_shader_volume_principled.c
+++ b/source/blender/nodes/shader/nodes/node_shader_volume_principled.c
@@ -54,42 +54,6 @@ static void node_shader_init_volume_principled(bNodeTree *UNUSED(ntree), bNode *
}
}
-static void node_shader_gpu_volume_attribute(GPUMaterial *mat,
- const char *name,
- GPUNodeLink **outcol,
- GPUNodeLink **outvec,
- GPUNodeLink **outf)
-{
- if (strcmp(name, "density") == 0) {
- GPU_link(mat,
- "node_attribute_volume_density",
- GPU_builtin(GPU_VOLUME_DENSITY),
- outcol,
- outvec,
- outf);
- }
- else if (strcmp(name, "color") == 0) {
- GPU_link(
- mat, "node_attribute_volume_color", GPU_builtin(GPU_VOLUME_COLOR), outcol, outvec, outf);
- }
- else if (strcmp(name, "flame") == 0) {
- GPU_link(
- mat, "node_attribute_volume_flame", GPU_builtin(GPU_VOLUME_FLAME), outcol, outvec, outf);
- }
- else if (strcmp(name, "temperature") == 0) {
- GPU_link(mat,
- "node_attribute_volume_temperature",
- GPU_builtin(GPU_VOLUME_FLAME),
- GPU_builtin(GPU_VOLUME_TEMPERATURE),
- outcol,
- outvec,
- outf);
- }
- else {
- *outcol = *outvec = *outf = NULL;
- }
-}
-
static int node_shader_gpu_volume_principled(GPUMaterial *mat,
bNode *node,
bNodeExecData *UNUSED(execdata),
@@ -108,16 +72,19 @@ static int node_shader_gpu_volume_principled(GPUMaterial *mat,
}
bNodeSocketValueString *value = sock->default_value;
- GPUNodeLink *outcol, *outvec, *outf;
+ const char *attribute_name = value->value;
+ if (attribute_name[0] == '\0') {
+ continue;
+ }
if (STREQ(sock->name, "Density Attribute")) {
- node_shader_gpu_volume_attribute(mat, value->value, &outcol, &outvec, &density);
+ density = GPU_volume_grid(mat, attribute_name);
}
else if (STREQ(sock->name, "Color Attribute")) {
- node_shader_gpu_volume_attribute(mat, value->value, &color, &outvec, &outf);
+ color = GPU_volume_grid(mat, attribute_name);
}
else if (use_blackbody && STREQ(sock->name, "Temperature Attribute")) {
- node_shader_gpu_volume_attribute(mat, value->value, &outcol, &outvec, &temperature);
+ temperature = GPU_volume_grid(mat, attribute_name);
}
}