diff options
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_materials.c | 11 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_volumes.c | 46 | ||||
-rw-r--r-- | source/blender/draw/intern/DRW_render.h | 10 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_manager_shader.c | 12 | ||||
-rw-r--r-- | source/blender/gpu/GPU_material.h | 29 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_codegen.c | 28 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_material.c | 34 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_node_graph.c | 69 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_node_graph.h | 8 | ||||
-rw-r--r-- | source/blender/gpu/shaders/material/gpu_shader_material_volume_info.glsl | 78 | ||||
-rw-r--r-- | source/blender/nodes/shader/nodes/node_shader_attribute.c | 34 | ||||
-rw-r--r-- | source/blender/nodes/shader/nodes/node_shader_volume_info.c | 26 | ||||
-rw-r--r-- | source/blender/nodes/shader/nodes/node_shader_volume_principled.c | 47 |
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); } } |