diff options
29 files changed, 583 insertions, 506 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 6d3c203b076..522039a1df8 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -98,6 +98,7 @@ set(SRC intern/draw_texture_pool.cc intern/draw_view.c intern/draw_view_data.cc + intern/draw_volume.cc intern/smaa_textures.c engines/basic/basic_engine.c engines/basic/basic_shader.c @@ -132,6 +133,9 @@ set(SRC engines/eevee/eevee_temporal_sampling.c engines/eevee/eevee_volumes.c engines/eevee_next/eevee_engine.cc + engines/eevee_next/eevee_instance.cc + engines/eevee_next/eevee_shader.cc + engines/eevee_next/eevee_id_map.cc engines/workbench/workbench_data.c engines/workbench/workbench_effect_antialiasing.c engines/workbench/workbench_effect_cavity.c diff --git a/source/blender/draw/engines/eevee/eevee_shaders.c b/source/blender/draw/engines/eevee/eevee_shaders.c index 4e4a2a9eb8e..85cc7f65126 100644 --- a/source/blender/draw/engines/eevee/eevee_shaders.c +++ b/source/blender/draw/engines/eevee/eevee_shaders.c @@ -1487,6 +1487,10 @@ struct GPUMaterial *EEVEE_material_get( GPUMaterial *mat = eevee_material_get_ex(scene, ma, wo, options, deferred); int status = GPU_material_status(mat); + /* Return null material and bypass drawing for volume shaders. */ + if ((options & VAR_MAT_VOLUME) && status != GPU_MAT_SUCCESS) { + return NULL; + } switch (status) { case GPU_MAT_SUCCESS: break; diff --git a/source/blender/draw/engines/eevee/eevee_shaders_extra.cc b/source/blender/draw/engines/eevee/eevee_shaders_extra.cc index bb1a0b0abe4..7df26a95cfe 100644 --- a/source/blender/draw/engines/eevee/eevee_shaders_extra.cc +++ b/source/blender/draw/engines/eevee/eevee_shaders_extra.cc @@ -97,12 +97,26 @@ void eevee_shader_material_create_info_amend(GPUMaterial *gpumat, } attr_load << "};\n"; attr_load << iface.name << " " << iface.instance_name << ";\n"; - /* Global vars just to make code valid. Only Orco is supported. */ - for (const ShaderCreateInfo::VertIn &in : info.vertex_inputs_) { - attr_load << in.type << " " << in.name << ";\n"; + if (!is_volume) { + /* Global vars just to make code valid. Only Orco is supported. */ + for (const ShaderCreateInfo::VertIn &in : info.vertex_inputs_) { + attr_load << in.type << " " << in.name << ";\n"; + } } info.vertex_out_interfaces_.clear(); } + if (is_volume) { + /** Volume grid attributes come from 3D textures. Transfer attributes to samplers. */ + for (auto &input : info.vertex_inputs_) { + info.sampler(0, ImageType::FLOAT_3D, input.name, Frequency::BATCH); + } + info.additional_info("draw_volume_infos"); + /* Do not add twice. */ + if (!GPU_material_flag_get(gpumat, GPU_MATFLAG_OBJECT_INFO)) { + info.additional_info("draw_object_infos"); + } + info.vertex_inputs_.clear(); + } if (!is_volume) { info.define("EEVEE_GENERATED_INTERFACE"); diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c index 0ac6c6ad97c..b8bef61f8b1 100644 --- a/source/blender/draw/engines/eevee/eevee_volumes.c +++ b/source/blender/draw/engines/eevee/eevee_volumes.c @@ -45,30 +45,6 @@ static struct { GPUTexture *dummy_transmit; } e_data = {NULL}; /* Engine data */ -static void eevee_create_textures_volumes(void) -{ - const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - e_data.dummy_zero = DRW_texture_create_3d(1, 1, 1, GPU_RGBA8, DRW_TEX_WRAP, zero); - - const float one[4] = {1.0f, 1.0f, 1.0f, 1.0f}; - e_data.dummy_one = DRW_texture_create_3d(1, 1, 1, GPU_RGBA8, DRW_TEX_WRAP, one); - - const float flame = 0.0f; - e_data.dummy_flame = DRW_texture_create_3d(1, 1, 1, GPU_R8, DRW_TEX_WRAP, &flame); -} - -static GPUTexture *eevee_volume_default_texture(eGPUVolumeDefaultValue default_value) -{ - switch (default_value) { - case GPU_VOLUME_DEFAULT_0: - return e_data.dummy_zero; - case GPU_VOLUME_DEFAULT_1: - return e_data.dummy_one; - } - - return e_data.dummy_zero; -} - void EEVEE_volumes_set_jitter(EEVEE_ViewLayerData *sldata, uint current_sample) { EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; @@ -224,11 +200,6 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) Scene *scene = draw_ctx->scene; DRWShadingGroup *grp = NULL; - /* Textures */ - if (!e_data.dummy_zero) { - eevee_create_textures_volumes(); - } - /* Quick breakdown of the Volumetric rendering: * * The rendering is separated in 4 stages: @@ -265,7 +236,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_get(vedata, scene, NULL, wo, VAR_MAT_VOLUME); - if (GPU_material_has_volume_output(mat)) { + if (mat && GPU_material_has_volume_output(mat)) { grp = DRW_shgroup_material_create(mat, psl->volumetric_world_ps); } @@ -280,11 +251,7 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); /* Fix principle volumetric not working with world materials. */ - ListBase gpu_grids = GPU_material_volume_grids(mat); - LISTBASE_FOREACH (GPUMaterialVolumeGrid *, gpu_grid, &gpu_grids) { - DRW_shgroup_uniform_texture( - grp, gpu_grid->sampler_name, eevee_volume_default_texture(gpu_grid->default_value)); - } + grp = DRW_shgroup_volume_create_sub(NULL, NULL, grp, mat); DRW_shgroup_call_procedural_triangles(grp, NULL, common_data->vol_tex_size[2]); @@ -296,186 +263,17 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) /* If no world or volume material is present just clear the buffer with this drawcall */ grp = DRW_shgroup_create(EEVEE_shaders_volumes_clear_sh_get(), psl->volumetric_world_ps); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo); DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo); + DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); + DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); DRW_shgroup_call_procedural_triangles(grp, NULL, common_data->vol_tex_size[2]); } } -static bool eevee_volume_object_grids_init(Object *ob, ListBase *gpu_grids, DRWShadingGroup *grp) -{ - Volume *volume = ob->data; - BKE_volume_load(volume, G.main); - - /* Test if we need to use multiple transforms. */ - DRWVolumeGrid *first_drw_grid = NULL; - bool multiple_transforms = true; - - LISTBASE_FOREACH (GPUMaterialVolumeGrid *, gpu_grid, gpu_grids) { - const VolumeGrid *volume_grid = BKE_volume_grid_find_for_read(volume, gpu_grid->name); - DRWVolumeGrid *drw_grid = (volume_grid) ? - DRW_volume_batch_cache_get_grid(volume, volume_grid) : - NULL; - - if (drw_grid) { - if (first_drw_grid == NULL) { - first_drw_grid = drw_grid; - } - else if (drw_grid && - !equals_m4m4(drw_grid->object_to_texture, first_drw_grid->object_to_texture)) { - multiple_transforms = true; - break; - } - } - } - - /* Bail out of no grids to render. */ - if (first_drw_grid == NULL) { - return false; - } - - /* Set transform matrix for the volume as a whole. This one is also used for - * clipping so must map the entire bounding box to 0..1. */ - float bounds_to_object[4][4]; - - if (multiple_transforms) { - /* For multiple grids with different transform, we first transform from object space - * to bounds, then for each individual grid from bounds to texture. */ - const BoundBox *bb = BKE_volume_boundbox_get(ob); - float bb_size[3]; - sub_v3_v3v3(bb_size, bb->vec[6], bb->vec[0]); - size_to_mat4(bounds_to_object, bb_size); - copy_v3_v3(bounds_to_object[3], bb->vec[0]); - - invert_m4_m4(first_drw_grid->object_to_bounds, bounds_to_object); - DRW_shgroup_uniform_mat4(grp, "volumeObjectToTexture", first_drw_grid->object_to_bounds); - } - else { - /* All grid transforms are equal, we can transform to texture space immediately. */ - DRW_shgroup_uniform_mat4(grp, "volumeObjectToTexture", first_drw_grid->object_to_texture); - } - - /* Don't use orco transform here, only matrix. */ - DRW_shgroup_uniform_vec3_copy(grp, "volumeOrcoLoc", (float[3]){0.5f, 0.5f, 0.5f}); - DRW_shgroup_uniform_vec3_copy(grp, "volumeOrcoSize", (float[3]){0.5f, 0.5f, 0.5f}); - - /* Set density scale. */ - const float density_scale = BKE_volume_density_scale(volume, ob->obmat); - DRW_shgroup_uniform_float_copy(grp, "volumeDensityScale", density_scale); - - /* Bind volume grid textures. */ - LISTBASE_FOREACH (GPUMaterialVolumeGrid *, gpu_grid, gpu_grids) { - const VolumeGrid *volume_grid = BKE_volume_grid_find_for_read(volume, gpu_grid->name); - DRWVolumeGrid *drw_grid = (volume_grid) ? - DRW_volume_batch_cache_get_grid(volume, volume_grid) : - NULL; - - /* Handle 3 cases here: - * - Grid exists and texture was loaded -> use texture. - * - Grid exists but has zero size or failed to load -> use zero. - * - Grid does not exist -> use default value. */ - GPUTexture *grid_tex = (drw_grid) ? drw_grid->texture : - (volume_grid) ? e_data.dummy_zero : - eevee_volume_default_texture(gpu_grid->default_value); - - DRW_shgroup_uniform_texture(grp, gpu_grid->sampler_name, grid_tex); - - if (drw_grid && multiple_transforms) { - /* Specify per-volume transform matrix that is applied after the - * transform from object to bounds. */ - mul_m4_m4m4(drw_grid->bounds_to_texture, drw_grid->object_to_texture, bounds_to_object); - DRW_shgroup_uniform_mat4(grp, gpu_grid->transform_name, drw_grid->bounds_to_texture); - } - } - - return true; -} - -static bool eevee_volume_object_mesh_init(Scene *scene, - Object *ob, - ListBase *gpu_grids, - DRWShadingGroup *grp) -{ - static const float white[3] = {1.0f, 1.0f, 1.0f}; - ModifierData *md = NULL; - - /* Smoke Simulation */ - if ((md = BKE_modifiers_findby_type(ob, eModifierType_Fluid)) && - (BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) && - ((FluidModifierData *)md)->domain != NULL) { - FluidModifierData *fmd = (FluidModifierData *)md; - FluidDomainSettings *fds = fmd->domain; - - /* Don't try to show liquid domains here. */ - if (!fds->fluid || !(fds->type == FLUID_DOMAIN_TYPE_GAS)) { - return false; - } - - /* Don't show smoke before simulation starts, this could be made an option in the future. */ - /* (sebbas): Always show smoke for manta */ -#if 0 - const DRWContextState *draw_ctx = DRW_context_state_get(); - const bool show_smoke = ((int)DEG_get_ctime(draw_ctx->depsgraph) >= - *fds->point_cache[0]->startframe); -#endif - - if (fds->fluid && (fds->type == FLUID_DOMAIN_TYPE_GAS) /* && show_smoke */) { - DRW_smoke_ensure(fmd, fds->flags & FLUID_DOMAIN_USE_NOISE); - } - - LISTBASE_FOREACH (GPUMaterialVolumeGrid *, gpu_grid, gpu_grids) { - if (STREQ(gpu_grid->name, "density")) { - DRW_shgroup_uniform_texture_ref( - grp, gpu_grid->sampler_name, fds->tex_density ? &fds->tex_density : &e_data.dummy_one); - } - else if (STREQ(gpu_grid->name, "color")) { - DRW_shgroup_uniform_texture_ref( - grp, gpu_grid->sampler_name, fds->tex_color ? &fds->tex_color : &e_data.dummy_one); - } - else if (STR_ELEM(gpu_grid->name, "flame", "temperature")) { - DRW_shgroup_uniform_texture_ref( - grp, gpu_grid->sampler_name, fds->tex_flame ? &fds->tex_flame : &e_data.dummy_flame); - } - else { - DRW_shgroup_uniform_texture( - grp, gpu_grid->sampler_name, eevee_volume_default_texture(gpu_grid->default_value)); - } - } - - /* Constant Volume color. */ - bool use_constant_color = ((fds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS) == 0 && - (fds->active_fields & FLUID_DOMAIN_ACTIVE_COLOR_SET) != 0); - - DRW_shgroup_uniform_vec3( - grp, "volumeColor", (use_constant_color) ? fds->active_color : white, 1); - - /* Output is such that 0..1 maps to 0..1000K */ - DRW_shgroup_uniform_vec2(grp, "volumeTemperature", &fds->flame_ignition, 1); - } - else { - LISTBASE_FOREACH (GPUMaterialVolumeGrid *, gpu_grid, gpu_grids) { - DRW_shgroup_uniform_texture( - grp, gpu_grid->sampler_name, eevee_volume_default_texture(gpu_grid->default_value)); - } - } - - /* Transform for mesh volumes. */ - static const float unit_mat[4][4] = {{1.0f, 0.0f, 0.0f, 0.0f}, - {0.0f, 1.0f, 0.0f, 0.0f}, - {0.0f, 0.0f, 1.0f, 0.0f}, - {0.0f, 0.0f, 0.0f, 1.0f}}; - float *texco_loc, *texco_size; - BKE_mesh_texspace_get_reference((struct Mesh *)ob->data, NULL, &texco_loc, &texco_size); - - DRW_shgroup_uniform_mat4(grp, "volumeObjectToTexture", unit_mat); - DRW_shgroup_uniform_vec3(grp, "volumeOrcoLoc", texco_loc, 1); - DRW_shgroup_uniform_vec3(grp, "volumeOrcoSize", texco_size, 1); - - return true; -} - void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Scene *scene, @@ -502,15 +300,22 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, int mat_options = VAR_MAT_VOLUME | VAR_MAT_MESH; struct GPUMaterial *mat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options); - eGPUMaterialStatus status = GPU_material_status(mat); /* If shader failed to compile or is currently compiling. */ - if (status != GPU_MAT_SUCCESS) { + if (mat == NULL) { return; } + /* TODO(fclem): Reuse main shading group to avoid shading binding cost just like for surface + * shaders. */ DRWShadingGroup *grp = DRW_shgroup_material_create(mat, vedata->psl->volumetric_objects_ps); + grp = DRW_shgroup_volume_create_sub(scene, ob, grp, mat); + + if (grp == NULL) { + return; + } + /* TODO(fclem): remove those "unnecessary" UBOs */ DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo); @@ -518,22 +323,7 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo); DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); - DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - - ListBase gpu_grids = GPU_material_volume_grids(mat); - - if (ob->type == OB_VOLUME) { - if (!eevee_volume_object_grids_init(ob, &gpu_grids, grp)) { - return; - } - } - else { - if (!eevee_volume_object_mesh_init(scene, ob, &gpu_grids, grp)) { - return; - } - } - /* TODO: Reduce to number of slices intersecting. */ /* TODO: Preemptive culling. */ DRW_shgroup_call_procedural_triangles(grp, ob, sldata->common_data.vol_tex_size[2]); diff --git a/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl index 0e8e8dd9d01..ab0f4d6bec8 100644 --- a/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl @@ -144,3 +144,13 @@ vec3 attr_load_uv(vec3 attr) return attr; } #endif + +/* Passthrough. */ +float attr_load_temperature_post(float attr) +{ + return attr; +} +vec4 attr_load_color_post(vec4 attr) +{ + return attr; +} diff --git a/source/blender/draw/engines/eevee/shaders/surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/surface_frag.glsl index 9ad7a4fdbc1..79ec3807d0b 100644 --- a/source/blender/draw/engines/eevee/shaders/surface_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/surface_frag.glsl @@ -179,3 +179,13 @@ vec3 attr_load_uv(vec3 attr) { return vec3(0); } + +/* Passthrough. */ +float attr_load_temperature_post(float attr) +{ + return attr; +} +vec4 attr_load_color_post(vec4 attr) +{ + return attr; +} diff --git a/source/blender/draw/engines/eevee/shaders/surface_vert.glsl b/source/blender/draw/engines/eevee/shaders/surface_vert.glsl index 6c6b810422b..49c18832f72 100644 --- a/source/blender/draw/engines/eevee/shaders/surface_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/surface_vert.glsl @@ -157,3 +157,13 @@ vec3 attr_load_uv(vec3 attr) return attr; } #endif + +/* Passthrough. */ +float attr_load_temperature_post(float attr) +{ + return attr; +} +vec4 attr_load_color_post(vec4 attr) +{ + return attr; +} diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl index e0a79872928..914261d7f59 100644 --- a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl @@ -4,17 +4,13 @@ /* Based on Frosbite Unified Volumetric. * https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */ -#ifdef MESH_SHADER -uniform vec3 volumeOrcoLoc; -uniform vec3 volumeOrcoSize; -uniform mat4 volumeObjectToTexture; -uniform float volumeDensityScale = 1.0; -#endif +/* Store volumetric properties into the froxel textures. */ flat in int slice; /* Warning: these are not attributes, these are global vars. */ vec3 worldPosition = vec3(0.0); +vec3 objectPosition = vec3(0.0); vec3 viewPosition = vec3(0.0); vec3 viewNormal = vec3(0.0); vec3 volumeOrco = vec3(0.0); @@ -24,9 +20,9 @@ layout(location = 1) out vec4 volumeExtinction; layout(location = 2) out vec4 volumeEmissive; layout(location = 3) out vec4 volumePhase; -/* Store volumetric properties into the froxel textures. */ +int attr_id; -#ifdef MESH_SHADER +#ifndef CLEAR GlobalData init_globals(void) { GlobalData surf; @@ -80,10 +76,8 @@ void main() viewPosition = get_view_space_from_depth(ndc_cell.xy, ndc_cell.z); worldPosition = point_view_to_world(viewPosition); #ifdef MESH_SHADER - volumeOrco = point_world_to_object(worldPosition); - /* TODO: redundant transform */ - volumeOrco = (volumeOrco - volumeOrcoLoc + volumeOrcoSize) / (volumeOrcoSize * 2.0); - volumeOrco = (volumeObjectToTexture * vec4(volumeOrco, 1.0)).xyz; + objectPosition = point_world_to_object(worldPosition); + volumeOrco = OrcoTexCoFactors[0].xyz + objectPosition * OrcoTexCoFactors[1].xyz; if (any(lessThan(volumeOrco, vec3(0.0))) || any(greaterThan(volumeOrco, vec3(1.0)))) { /* Note: Discard is not an explicit return in Metal prior to versions 2.3. @@ -100,15 +94,13 @@ void main() volumeEmissive = vec4(0.0, 0.0, 0.0, 1.0); volumePhase = vec4(0.0, 0.0, 0.0, 0.0); #else -# ifdef MESH_SHADER g_data = init_globals(); attrib_load(); -# endif Closure cl = nodetree_exec(); # ifdef MESH_SHADER - cl.scatter *= volumeDensityScale; - cl.absorption *= volumeDensityScale; - cl.emission *= volumeDensityScale; + cl.scatter *= drw_volume.density_scale; + cl.absorption *= drw_volume.density_scale; + cl.emission *= drw_volume.density_scale; # endif volumeScattering = vec4(cl.scatter, 1.0); @@ -124,35 +116,72 @@ void main() #endif } -vec3 attr_load_orco(vec4 orco) +vec3 grid_coordinates() +{ + vec3 co = volumeOrco; +#ifdef MESH_SHADER + /* Optional per-grid transform. */ + if (drw_volume.grids_xform[attr_id][3][3] != 0.0) { + co = (drw_volume.grids_xform[attr_id] * vec4(objectPosition, 1.0)).xyz; + } +#endif + attr_id += 1; + return co; +} + +vec3 attr_load_orco(sampler3D orco) { + attr_id += 1; return volumeOrco; } -vec4 attr_load_tangent(vec4 tangent) +vec4 attr_load_tangent(sampler3D tangent) { + attr_id += 1; return vec4(0); } -vec4 attr_load_vec4(vec4 attr) +vec4 attr_load_vec4(sampler3D tex) { - return vec4(0); + return texture(tex, grid_coordinates()); } -vec3 attr_load_vec3(vec3 attr) +vec3 attr_load_vec3(sampler3D tex) { - return vec3(0); + return texture(tex, grid_coordinates()).rgb; } -vec2 attr_load_vec2(vec2 attr) +vec2 attr_load_vec2(sampler3D tex) { - return vec2(0); + return texture(tex, grid_coordinates()).rg; } -float attr_load_float(float attr) +float attr_load_float(sampler3D tex) { - return 0.0; + return texture(tex, grid_coordinates()).r; } -vec4 attr_load_color(vec4 attr) +vec4 attr_load_color(sampler3D tex) { - return vec4(0); + return texture(tex, grid_coordinates()); } -vec3 attr_load_uv(vec3 attr) +vec3 attr_load_uv(sampler3D attr) { + attr_id += 1; return vec3(0); } + +/* TODO(@fclem): These implementation details should concern the DRWManager and not be a fix on + * the engine side. But as of now, the engines are reponsible for loading the attributes. */ +float attr_load_temperature_post(float attr) +{ +#ifdef MESH_SHADER + /* Bring the into standard range without having to modify the grid values */ + attr = (attr > 0.01) ? (attr * drw_volume.temperature_mul + drw_volume.temperature_bias) : 0.0; +#endif + return attr; +} +vec4 attr_load_color_post(vec4 attr) +{ +#ifdef MESH_SHADER + /* Density is premultiplied for interpolation, divide it out here. */ + attr.rgb *= safe_rcp(attr.a); + attr.rgb *= drw_volume.color_mul.rgb; + attr.a = 1.0; +#endif + return attr; +} diff --git a/source/blender/draw/intern/DRW_gpu_wrapper.hh b/source/blender/draw/intern/DRW_gpu_wrapper.hh index ed94c485b32..d7e752a43f4 100644 --- a/source/blender/draw/intern/DRW_gpu_wrapper.hh +++ b/source/blender/draw/intern/DRW_gpu_wrapper.hh @@ -53,6 +53,8 @@ * */ +#include "DRW_render.h" + #include "MEM_guardedalloc.h" #include "draw_texture_pool.h" @@ -61,6 +63,7 @@ #include "BLI_span.hh" #include "BLI_utildefines.h" #include "BLI_utility_mixins.hh" +#include "BLI_vector.hh" #include "GPU_framebuffer.h" #include "GPU_storage_buffer.h" diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h index 566e68a5c84..af2efd338e4 100644 --- a/source/blender/draw/intern/draw_common.h +++ b/source/blender/draw/intern/draw_common.h @@ -21,6 +21,7 @@ struct Object; struct ParticleSystem; struct RegionView3D; struct ViewLayer; +struct Scene; struct DRWData; /* Keep in sync with globalsBlock in shaders */ @@ -74,6 +75,22 @@ void DRW_hair_init(void); void DRW_hair_update(void); void DRW_hair_free(void); +/* draw_volume.cc */ + +/** + * Add attributes bindings of volume grids to an exhisting shading group. + * No draw call is added so the caller can decide how to use the data. + * \return nullptr if there is something to draw. + */ +struct DRWShadingGroup *DRW_shgroup_volume_create_sub(struct Scene *scene, + struct Object *ob, + struct DRWShadingGroup *shgrp, + struct GPUMaterial *gpu_material); + +void DRW_volume_init(struct DRWData *drw_data); +void DRW_volume_ubos_pool_free(void *pool); +void DRW_volume_free(void); + /* draw_fluid.c */ /* Fluid simulation. */ diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 441628f2490..e0dfc29b966 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -478,6 +478,7 @@ void DRW_viewport_data_free(DRWData *drw_data) MEM_freeN(drw_data->matrices_ubo); MEM_freeN(drw_data->obinfos_ubo); } + DRW_volume_ubos_pool_free(drw_data->volume_grids_ubos); MEM_freeN(drw_data); } @@ -1650,6 +1651,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph, drw_debug_init(); DRW_hair_init(); + DRW_volume_init(DST.vmempool); DRW_smoke_init(DST.vmempool); /* No frame-buffer allowed before drawing. */ @@ -2021,6 +2023,7 @@ void DRW_render_object_iter( { const DRWContextState *draw_ctx = DRW_context_state_get(); DRW_hair_init(); + DRW_volume_init(DST.vmempool); DRW_smoke_init(DST.vmempool); drw_task_graph_init(); @@ -2077,6 +2080,7 @@ void DRW_custom_pipeline(DrawEngineType *draw_engine_type, drw_manager_init(&DST, NULL, NULL); DRW_hair_init(); + DRW_volume_init(DST.vmempool); DRW_smoke_init(DST.vmempool); ViewportEngineData *data = DRW_view_data_engine_data_get_ensure(DST.view_data_active, @@ -2111,6 +2115,7 @@ void DRW_cache_restart(void) DST.buffer_finish_called = false; DRW_hair_init(); + DRW_volume_init(DST.vmempool); DRW_smoke_init(DST.vmempool); } @@ -2429,6 +2434,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, /* Init engines */ drw_engines_init(); DRW_hair_init(); + DRW_volume_init(DST.vmempool); DRW_smoke_init(DST.vmempool); { @@ -2602,6 +2608,7 @@ static void drw_draw_depth_loop_impl(struct Depsgraph *depsgraph, /* Init engines */ drw_engines_init(); DRW_hair_init(); + DRW_volume_init(DST.vmempool); DRW_smoke_init(DST.vmempool); { @@ -3027,6 +3034,7 @@ void DRW_engines_free(void) DRW_shaders_free(); DRW_hair_free(); + DRW_volume_free(); DRW_shape_cache_free(); DRW_stats_free(); DRW_globals_free(); diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h index e861d91d47e..8812f112014 100644 --- a/source/blender/draw/intern/draw_manager.h +++ b/source/blender/draw/intern/draw_manager.h @@ -527,6 +527,8 @@ typedef struct DRWData { struct GPUUniformBuf **obinfos_ubo; struct GHash *obattrs_ubo_pool; uint ubo_len; + /** Per draw-call volume object data. */ + void *volume_grids_ubos; /* VolumeUniformBufPool */ /** List of smoke textures to free after drawing. */ ListBase smoke_textures; /** Texture pool to reuse temp texture across engines. */ diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c index 39f083aaf96..7c779b42c73 100644 --- a/source/blender/draw/intern/draw_manager_data.c +++ b/source/blender/draw/intern/draw_manager_data.c @@ -15,6 +15,7 @@ #include "BKE_object.h" #include "BKE_paint.h" #include "BKE_pbvh.h" +#include "BKE_volume.h" #include "DNA_curve_types.h" #include "DNA_mesh_types.h" @@ -555,10 +556,19 @@ void DRW_shgroup_vertex_buffer_ref_ex(DRWShadingGroup *shgroup, static void drw_call_calc_orco(Object *ob, float (*r_orcofacs)[4]) { ID *ob_data = (ob) ? ob->data : NULL; + float loc[3], size[3]; float *texcoloc = NULL; float *texcosize = NULL; if (ob_data != NULL) { switch (GS(ob_data->name)) { + case ID_VO: { + BoundBox *bbox = BKE_volume_boundbox_get(ob); + mid_v3_v3v3(loc, bbox->vec[0], bbox->vec[6]); + sub_v3_v3v3(size, bbox->vec[0], bbox->vec[6]); + texcoloc = loc; + texcosize = size; + break; + } case ID_ME: BKE_mesh_texspace_get_reference((Mesh *)ob_data, NULL, &texcoloc, &texcosize); break; @@ -614,7 +624,7 @@ static void drw_call_obinfos_init(DRWObjectInfos *ob_infos, Object *ob) drw_call_calc_orco(ob, ob_infos->orcotexfac); /* Random float value. */ uint random = (DST.dupli_source) ? - DST.dupli_source->random_id : + DST.dupli_source->random_id : /* TODO(fclem): this is rather costly to do at runtime. Maybe we can * put it in ob->runtime and make depsgraph ensure it is up to date. */ BLI_hash_int_2d(BLI_hash_string(ob->id.name + 2), 0); diff --git a/source/blender/draw/intern/draw_shader_shared.h b/source/blender/draw/intern/draw_shader_shared.h index 58875c0496a..d2e51b67468 100644 --- a/source/blender/draw/intern/draw_shader_shared.h +++ b/source/blender/draw/intern/draw_shader_shared.h @@ -6,12 +6,16 @@ typedef struct ViewInfos ViewInfos; typedef struct ObjectMatrices ObjectMatrices; typedef struct ObjectInfos ObjectInfos; +typedef struct VolumeInfos VolumeInfos; #endif #define DRW_SHADER_SHARED_H #define DRW_RESOURCE_CHUNK_LEN 512 +/* Define the maximum number of grid we allow in a volume UBO. */ +#define DRW_GRID_PER_VOLUME_MAX 16 + struct ViewInfos { /* View matrices */ float4x4 persmat; @@ -63,6 +67,18 @@ struct ObjectInfos { }; BLI_STATIC_ASSERT_ALIGN(ViewInfos, 16) +struct VolumeInfos { + /* Object to grid-space. */ + float4x4 grids_xform[DRW_GRID_PER_VOLUME_MAX]; + /* NOTE: vec4 for alignement. Only float3 needed. */ + float4 color_mul; + float density_scale; + float temperature_mul; + float temperature_bias; + float _pad; +}; +BLI_STATIC_ASSERT_ALIGN(VolumeInfos, 16) + #define OrcoTexCoFactors (drw_infos[resource_id].drw_OrcoTexCoFactors) #define ObjectInfo (drw_infos[resource_id].drw_Infos) #define ObjectColor (drw_infos[resource_id].drw_ObjectColor) diff --git a/source/blender/draw/intern/draw_volume.cc b/source/blender/draw/intern/draw_volume.cc new file mode 100644 index 00000000000..c9c8acaef40 --- /dev/null +++ b/source/blender/draw/intern/draw_volume.cc @@ -0,0 +1,266 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup draw + * + * \brief Contains Volume object GPU attributes configuration. + */ + +#include "DRW_gpu_wrapper.hh" +#include "DRW_render.h" + +#include "DNA_fluid_types.h" +#include "DNA_volume_types.h" + +#include "BKE_fluid.h" +#include "BKE_global.h" +#include "BKE_mesh.h" +#include "BKE_modifier.h" +#include "BKE_volume.h" +#include "BKE_volume_render.h" + +#include "GPU_material.h" + +#include "draw_common.h" +#include "draw_manager.h" + +using namespace blender; +using namespace blender::draw; +using VolumeInfosBuf = blender::draw::UniformBuffer<VolumeInfos>; + +static struct { + GPUTexture *dummy_zero; + GPUTexture *dummy_one; + float dummy_grid_mat[4][4]; +} g_data = {}; + +struct VolumeUniformBufPool { + Vector<VolumeInfosBuf *> ubos; + uint used = 0; + + ~VolumeUniformBufPool() + { + for (VolumeInfosBuf *ubo : ubos) { + delete ubo; + } + } + + void reset() + { + used = 0; + } + + VolumeInfosBuf *alloc() + { + if (used >= ubos.size()) { + VolumeInfosBuf *buf = new VolumeInfosBuf(); + ubos.append(buf); + return buf; + } + return ubos[used++]; + } +}; + +void DRW_volume_ubos_pool_free(void *pool) +{ + delete reinterpret_cast<VolumeUniformBufPool *>(pool); +} + +static void drw_volume_globals_init(void) +{ + const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + const float one[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + g_data.dummy_zero = GPU_texture_create_3d( + "dummy_zero", 1, 1, 1, 1, GPU_RGBA8, GPU_DATA_FLOAT, zero); + g_data.dummy_one = GPU_texture_create_3d( + "dummy_one", 1, 1, 1, 1, GPU_RGBA8, GPU_DATA_FLOAT, one); + GPU_texture_wrap_mode(g_data.dummy_zero, true, true); + GPU_texture_wrap_mode(g_data.dummy_one, true, true); + + memset(g_data.dummy_grid_mat, 0, sizeof(g_data.dummy_grid_mat)); +} + +void DRW_volume_free(void) +{ + GPU_TEXTURE_FREE_SAFE(g_data.dummy_zero); + GPU_TEXTURE_FREE_SAFE(g_data.dummy_one); +} + +static GPUTexture *grid_default_texture(eGPUDefaultValue default_value) +{ + switch (default_value) { + case GPU_DEFAULT_0: + return g_data.dummy_zero; + case GPU_DEFAULT_1: + return g_data.dummy_one; + } + return g_data.dummy_zero; +} + +void DRW_volume_init(DRWData *drw_data) +{ + if (drw_data->volume_grids_ubos == nullptr) { + drw_data->volume_grids_ubos = new VolumeUniformBufPool(); + } + VolumeUniformBufPool *pool = (VolumeUniformBufPool *)drw_data->volume_grids_ubos; + pool->reset(); + + if (g_data.dummy_one == nullptr) { + drw_volume_globals_init(); + } +} + +static DRWShadingGroup *drw_volume_object_grids_init(Object *ob, + ListBase *attrs, + DRWShadingGroup *grp) +{ + VolumeUniformBufPool *pool = (VolumeUniformBufPool *)DST.vmempool->volume_grids_ubos; + VolumeInfosBuf &volume_infos = *pool->alloc(); + + Volume *volume = (Volume *)ob->data; + BKE_volume_load(volume, G.main); + + grp = DRW_shgroup_create_sub(grp); + + volume_infos.density_scale = BKE_volume_density_scale(volume, ob->obmat); + volume_infos.color_mul = float4(1.0f); + volume_infos.temperature_mul = 1.0f; + volume_infos.temperature_bias = 0.0f; + + /* Bind volume grid textures. */ + int grid_id = 0; + LISTBASE_FOREACH (GPUMaterialAttribute *, attr, attrs) { + const VolumeGrid *volume_grid = BKE_volume_grid_find_for_read(volume, attr->name); + DRWVolumeGrid *drw_grid = (volume_grid) ? + DRW_volume_batch_cache_get_grid(volume, volume_grid) : + NULL; + + /* Handle 3 cases here: + * - Grid exists and texture was loaded -> use texture. + * - Grid exists but has zero size or failed to load -> use zero. + * - Grid does not exist -> use default value. */ + GPUTexture *grid_tex = (drw_grid) ? drw_grid->texture : + (volume_grid) ? g_data.dummy_zero : + grid_default_texture(attr->default_value); + DRW_shgroup_uniform_texture(grp, attr->input_name, grid_tex); + + copy_m4_m4(volume_infos.grids_xform[grid_id++].ptr(), drw_grid->object_to_texture); + } + + volume_infos.push_update(); + + DRW_shgroup_uniform_block(grp, "drw_volume", volume_infos); + + return grp; +} + +static DRWShadingGroup *drw_volume_object_mesh_init(Scene *scene, + Object *ob, + ListBase *attrs, + DRWShadingGroup *grp) +{ + VolumeUniformBufPool *pool = (VolumeUniformBufPool *)DST.vmempool->volume_grids_ubos; + VolumeInfosBuf &volume_infos = *pool->alloc(); + + ModifierData *md = NULL; + + volume_infos.density_scale = 1.0f; + volume_infos.color_mul = float4(1.0f); + volume_infos.temperature_mul = 1.0f; + volume_infos.temperature_bias = 0.0f; + + /* Smoke Simulation */ + if ((md = BKE_modifiers_findby_type(ob, eModifierType_Fluid)) && + (BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) && + ((FluidModifierData *)md)->domain != NULL) { + FluidModifierData *fmd = (FluidModifierData *)md; + FluidDomainSettings *fds = fmd->domain; + + /* Don't try to show liquid domains here. */ + if (!fds->fluid || !(fds->type == FLUID_DOMAIN_TYPE_GAS)) { + return nullptr; + } + + if (fds->fluid && (fds->type == FLUID_DOMAIN_TYPE_GAS)) { + DRW_smoke_ensure(fmd, fds->flags & FLUID_DOMAIN_USE_NOISE); + } + + grp = DRW_shgroup_create_sub(grp); + + int grid_id = 0; + LISTBASE_FOREACH (GPUMaterialAttribute *, attr, attrs) { + if (STREQ(attr->name, "density")) { + DRW_shgroup_uniform_texture_ref( + grp, attr->input_name, fds->tex_density ? &fds->tex_density : &g_data.dummy_one); + } + else if (STREQ(attr->name, "color")) { + DRW_shgroup_uniform_texture_ref( + grp, attr->input_name, fds->tex_color ? &fds->tex_color : &g_data.dummy_one); + } + else if (STR_ELEM(attr->name, "flame", "temperature")) { + DRW_shgroup_uniform_texture_ref( + grp, attr->input_name, fds->tex_flame ? &fds->tex_flame : &g_data.dummy_zero); + } + else { + DRW_shgroup_uniform_texture( + grp, attr->input_name, grid_default_texture(attr->default_value)); + } + copy_m4_m4(volume_infos.grids_xform[grid_id++].ptr(), g_data.dummy_grid_mat); + } + + bool use_constant_color = ((fds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS) == 0 && + (fds->active_fields & FLUID_DOMAIN_ACTIVE_COLOR_SET) != 0); + if (use_constant_color) { + volume_infos.color_mul = float4(UNPACK3(fds->active_color), 1.0f); + } + + /* Output is such that 0..1 maps to 0..1000K */ + volume_infos.temperature_mul = fds->flame_max_temp - fds->flame_ignition; + volume_infos.temperature_bias = fds->flame_ignition; + } + else { + grp = DRW_shgroup_create_sub(grp); + + int grid_id = 0; + LISTBASE_FOREACH (GPUMaterialAttribute *, attr, attrs) { + DRW_shgroup_uniform_texture( + grp, attr->input_name, grid_default_texture(attr->default_value)); + copy_m4_m4(volume_infos.grids_xform[grid_id++].ptr(), g_data.dummy_grid_mat); + } + } + + volume_infos.push_update(); + + DRW_shgroup_uniform_block(grp, "drw_volume", volume_infos); + + return grp; +} + +static DRWShadingGroup *drw_volume_world_grids_init(ListBase *attrs, DRWShadingGroup *grp) +{ + /* Bind default volume grid textures. */ + int grid_id = 0; + LISTBASE_FOREACH (GPUMaterialAttribute *, attr, attrs) { + DRW_shgroup_uniform_texture(grp, attr->input_name, grid_default_texture(attr->default_value)); + } + return grp; +} + +DRWShadingGroup *DRW_shgroup_volume_create_sub(Scene *scene, + Object *ob, + DRWShadingGroup *shgrp, + GPUMaterial *gpu_material) +{ + ListBase attrs = GPU_material_attributes(gpu_material); + + if (ob == nullptr) { + return drw_volume_world_grids_init(&attrs, shgrp); + } + else if (ob->type == OB_VOLUME) { + return drw_volume_object_grids_init(ob, &attrs, shgrp); + } + else { + return drw_volume_object_mesh_init(scene, ob, &attrs, shgrp); + } +} diff --git a/source/blender/draw/intern/shaders/common_attribute_lib.glsl b/source/blender/draw/intern/shaders/common_attribute_lib.glsl index 99db2929a13..30239a84c0c 100644 --- a/source/blender/draw/intern/shaders/common_attribute_lib.glsl +++ b/source/blender/draw/intern/shaders/common_attribute_lib.glsl @@ -19,3 +19,15 @@ vec4 attr_load_vec4(samplerBuffer attr); vec3 attr_load_vec3(samplerBuffer attr); vec2 attr_load_vec2(samplerBuffer attr); float attr_load_float(samplerBuffer attr); + +vec3 attr_load_orco(sampler3D orco); +vec4 attr_load_tangent(sampler3D tangent); +vec3 attr_load_uv(sampler3D attr); +vec4 attr_load_color(sampler3D tex); +vec4 attr_load_vec4(sampler3D tex); +vec3 attr_load_vec3(sampler3D tex); +vec2 attr_load_vec2(sampler3D tex); +float attr_load_float(sampler3D tex); + +float attr_load_temperature_post(float attr); +vec4 attr_load_color_post(vec4 attr); diff --git a/source/blender/draw/intern/shaders/draw_object_infos_info.hh b/source/blender/draw/intern/shaders/draw_object_infos_info.hh index 392b016fc3b..c74a043ec97 100644 --- a/source/blender/draw/intern/shaders/draw_object_infos_info.hh +++ b/source/blender/draw/intern/shaders/draw_object_infos_info.hh @@ -6,3 +6,7 @@ GPU_SHADER_CREATE_INFO(draw_object_infos) .typedef_source("draw_shader_shared.h") .define("OBINFO_LIB") .uniform_buf(1, "ObjectInfos", "drw_infos[DRW_RESOURCE_CHUNK_LEN]", Frequency::BATCH); + +GPU_SHADER_CREATE_INFO(draw_volume_infos) + .typedef_source("draw_shader_shared.h") + .uniform_buf(2, "VolumeInfos", "drw_volume", Frequency::BATCH); diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 98d15a1024c..93030d6ab6e 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -370,7 +370,6 @@ set(GLSL_SRC shaders/material/gpu_shader_material_velvet.glsl shaders/material/gpu_shader_material_vertex_color.glsl shaders/material/gpu_shader_material_volume_absorption.glsl - shaders/material/gpu_shader_material_volume_info.glsl shaders/material/gpu_shader_material_volume_principled.glsl shaders/material/gpu_shader_material_volume_scatter.glsl shaders/material/gpu_shader_material_wireframe.glsl diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index f38b9681ad7..55fbe3f981f 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -109,10 +109,10 @@ typedef enum eGPUMaterialStatus { GPU_MAT_SUCCESS, } eGPUMaterialStatus; -typedef enum eGPUVolumeDefaultValue { - GPU_VOLUME_DEFAULT_0, - GPU_VOLUME_DEFAULT_1, -} eGPUVolumeDefaultValue; +typedef enum eGPUDefaultValue { + GPU_DEFAULT_0 = 0, + GPU_DEFAULT_1, +} eGPUDefaultValue; typedef struct GPUCodegenOutput { char *attr_load; @@ -131,6 +131,10 @@ typedef void (*GPUCodegenCallbackFn)(void *thunk, GPUMaterial *mat, GPUCodegenOu GPUNodeLink *GPU_constant(const float *num); GPUNodeLink *GPU_uniform(const float *num); GPUNodeLink *GPU_attribute(GPUMaterial *mat, CustomDataType type, const char *name); +GPUNodeLink *GPU_attribute_with_default(GPUMaterial *mat, + CustomDataType type, + const char *name, + eGPUDefaultValue default_value); GPUNodeLink *GPU_uniform_attribute(GPUMaterial *mat, const char *name, bool use_dupli); GPUNodeLink *GPU_image(GPUMaterial *mat, struct Image *ima, @@ -142,9 +146,7 @@ GPUNodeLink *GPU_image_tiled(GPUMaterial *mat, eGPUSamplerState sampler_state); GPUNodeLink *GPU_image_tiled_mapping(GPUMaterial *mat, struct Image *ima, struct ImageUser *iuser); GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *row); -GPUNodeLink *GPU_volume_grid(GPUMaterial *mat, - const char *name, - eGPUVolumeDefaultValue default_value); + /** * Create an implementation defined differential calculation of a float function. * The given function should return a float. @@ -255,9 +257,11 @@ void GPU_pass_cache_free(void); typedef struct GPUMaterialAttribute { struct GPUMaterialAttribute *next, *prev; - int type; /* CustomDataType */ - char name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */ + int type; /* CustomDataType */ + char name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */ + char input_name[12 + 1]; /* GPU_MAX_SAFE_ATTR_NAME + 1 */ eGPUType gputype; + eGPUDefaultValue default_value; /* Only for volumes attributes. */ int id; int users; } GPUMaterialAttribute; @@ -274,18 +278,8 @@ typedef struct GPUMaterialTexture { int sampler_state; /* eGPUSamplerState */ } GPUMaterialTexture; -typedef struct GPUMaterialVolumeGrid { - struct GPUMaterialVolumeGrid *next, *prev; - char *name; - eGPUVolumeDefaultValue default_value; - char sampler_name[32]; /* Name of sampler in GLSL. */ - char transform_name[32]; /* Name of 4x4 matrix in GLSL. */ - int users; -} GPUMaterialVolumeGrid; - ListBase GPU_material_attributes(GPUMaterial *material); ListBase GPU_material_textures(GPUMaterial *material); -ListBase GPU_material_volume_grids(GPUMaterial *material); typedef struct GPUUniformAttr { struct GPUUniformAttr *next, *prev; diff --git a/source/blender/gpu/intern/gpu_codegen.cc b/source/blender/gpu/intern/gpu_codegen.cc index 8963fa45c96..048928b2312 100644 --- a/source/blender/gpu/intern/gpu_codegen.cc +++ b/source/blender/gpu/intern/gpu_codegen.cc @@ -49,7 +49,6 @@ using namespace blender::gpu::shader; struct GPUCodegenCreateInfo : ShaderCreateInfo { struct NameBuffer { - char attr_names[16][GPU_MAX_SAFE_ATTR_NAME + 1]; char var_names[16][8]; }; @@ -171,10 +170,6 @@ static std::ostream &operator<<(std::ostream &stream, const GPUInput *input) return stream << input->texture->sampler_name; case GPU_SOURCE_TEX_TILED_MAPPING: return stream << input->texture->tiled_mapping_name; - case GPU_SOURCE_VOLUME_GRID: - return stream << input->volume_grid->sampler_name; - case GPU_SOURCE_VOLUME_GRID_TRANSFORM: - return stream << input->volume_grid->transform_name; default: BLI_assert(0); return stream; @@ -276,28 +271,6 @@ class GPUCodegen { } }; -static char attr_prefix_get(CustomDataType type) -{ - switch (type) { - case CD_MTFACE: - return 'u'; - case CD_TANGENT: - return 't'; - case CD_MCOL: - case CD_MLOOPCOL: - return 'c'; - case CD_PROP_COLOR: - return 'c'; - case CD_AUTO_FROM_NAME: - return 'a'; - case CD_HAIRLENGTH: - return 'l'; - default: - BLI_assert_msg(0, "GPUVertAttr Prefix type not found : This should not happen!"); - return '\0'; - } -} - void GPUCodegen::generate_attribs() { if (BLI_listbase_is_empty(&graph.attributes)) { @@ -317,24 +290,9 @@ void GPUCodegen::generate_attribs() int slot = 15; LISTBASE_FOREACH (GPUMaterialAttribute *, attr, &graph.attributes) { - - /* NOTE: Replicate changes to mesh_render_data_create() in draw_cache_impl_mesh.c */ - if (attr->type == CD_ORCO) { - /* OPTI: orco is computed from local positions, but only if no modifier is present. */ - STRNCPY(info.name_buffer->attr_names[slot], "orco"); - } - else { - char *name = info.name_buffer->attr_names[slot]; - name[0] = attr_prefix_get(static_cast<CustomDataType>(attr->type)); - name[1] = '\0'; - if (attr->name[0] != '\0') { - /* XXX FIXME: see notes in mesh_render_data_create() */ - GPU_vertformat_safe_attr_name(attr->name, &name[1], GPU_MAX_SAFE_ATTR_NAME); - } - } SNPRINTF(info.name_buffer->var_names[slot], "v%d", attr->id); - blender::StringRefNull attr_name = info.name_buffer->attr_names[slot]; + blender::StringRefNull attr_name = attr->input_name; blender::StringRefNull var_name = info.name_buffer->var_names[slot]; eGPUType input_type, iface_type; @@ -395,12 +353,6 @@ void GPUCodegen::generate_resources() info.sampler(0, ImageType::FLOAT_2D, tex->sampler_name, Frequency::BATCH); } } - /* Volume Grids. */ - LISTBASE_FOREACH (GPUMaterialVolumeGrid *, grid, &graph.volume_grids) { - info.sampler(0, ImageType::FLOAT_3D, grid->sampler_name, Frequency::BATCH); - /* TODO(@fclem): Global uniform. To put in an UBO. */ - info.push_constant(Type::MAT4, grid->transform_name); - } if (!BLI_listbase_is_empty(&ubo_inputs_)) { /* NOTE: generate_uniform_buffer() should have sorted the inputs before this. */ diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 711a3943a25..21e40a67d5e 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -219,11 +219,6 @@ ListBase GPU_material_textures(GPUMaterial *material) return material->graph.textures; } -ListBase GPU_material_volume_grids(GPUMaterial *material) -{ - return material->graph.volume_grids; -} - GPUUniformAttrList *GPU_material_uniform_attributes(GPUMaterial *material) { GPUUniformAttrList *attrs = &material->graph.uniform_attrs; diff --git a/source/blender/gpu/intern/gpu_node_graph.c b/source/blender/gpu/intern/gpu_node_graph.c index d9143a12d5b..20551785535 100644 --- a/source/blender/gpu/intern/gpu_node_graph.c +++ b/source/blender/gpu/intern/gpu_node_graph.c @@ -20,6 +20,7 @@ #include "BLI_utildefines.h" #include "GPU_texture.h" +#include "GPU_vertex_format.h" #include "gpu_material_library.h" #include "gpu_node_graph.h" @@ -102,14 +103,6 @@ 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_VOLUME_GRID_TRANSFORM: - input->source = GPU_SOURCE_VOLUME_GRID_TRANSFORM; - input->volume_grid = link->volume_grid; - break; case GPU_NODE_LINK_ATTR: input->source = GPU_SOURCE_ATTR; input->attr = link->attr; @@ -335,6 +328,45 @@ void gpu_node_graph_finalize_uniform_attrs(GPUNodeGraph *graph) /* Attributes and Textures */ +static char attr_prefix_get(CustomDataType type) +{ + switch (type) { + case CD_MTFACE: + return 'u'; + case CD_TANGENT: + return 't'; + case CD_MCOL: + case CD_MLOOPCOL: + return 'c'; + case CD_PROP_COLOR: + return 'c'; + case CD_AUTO_FROM_NAME: + return 'a'; + case CD_HAIRLENGTH: + return 'l'; + default: + BLI_assert_msg(0, "GPUVertAttr Prefix type not found : This should not happen!"); + return '\0'; + } +} + +static void attr_input_name(GPUMaterialAttribute *attr) +{ + /* NOTE: Replicate changes to mesh_render_data_create() in draw_cache_impl_mesh.c */ + if (attr->type == CD_ORCO) { + /* OPTI: orco is computed from local positions, but only if no modifier is present. */ + STRNCPY(attr->input_name, "orco"); + } + else { + attr->input_name[0] = attr_prefix_get(attr->type); + attr->input_name[1] = '\0'; + if (attr->name[0] != '\0') { + /* XXX FIXME: see notes in mesh_render_data_create() */ + GPU_vertformat_safe_attr_name(attr->name, &attr->input_name[1], GPU_MAX_SAFE_ATTR_NAME); + } + } +} + /** Add a new varying attribute of given type and name. Returns NULL if out of slots. */ static GPUMaterialAttribute *gpu_node_graph_add_attribute(GPUNodeGraph *graph, CustomDataType type, @@ -360,6 +392,7 @@ static GPUMaterialAttribute *gpu_node_graph_add_attribute(GPUNodeGraph *graph, attr = MEM_callocN(sizeof(*attr), __func__); attr->type = type; STRNCPY(attr->name, name); + attr_input_name(attr); attr->id = num_attributes; BLI_addtail(&graph->attributes, attr); } @@ -443,35 +476,6 @@ static GPUMaterialTexture *gpu_node_graph_add_texture(GPUNodeGraph *graph, return tex; } -static GPUMaterialVolumeGrid *gpu_node_graph_add_volume_grid(GPUNodeGraph *graph, - const char *name, - eGPUVolumeDefaultValue default_value) -{ - /* Find existing volume grid. */ - int num_grids = 0; - GPUMaterialVolumeGrid *grid = graph->volume_grids.first; - for (; grid; grid = grid->next) { - if (STREQ(grid->name, name) && grid->default_value == default_value) { - break; - } - num_grids++; - } - - /* Add new requested volume grid. */ - if (grid == NULL) { - grid = MEM_callocN(sizeof(*grid), __func__); - grid->name = BLI_strdup(name); - grid->default_value = default_value; - BLI_snprintf(grid->sampler_name, sizeof(grid->sampler_name), "vsamp%d", num_grids); - BLI_snprintf(grid->transform_name, sizeof(grid->transform_name), "vtfm%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) @@ -496,6 +500,18 @@ GPUNodeLink *GPU_attribute(GPUMaterial *mat, const CustomDataType type, const ch return link; } +GPUNodeLink *GPU_attribute_with_default(GPUMaterial *mat, + const CustomDataType type, + const char *name, + eGPUDefaultValue default_value) +{ + GPUNodeLink *link = GPU_attribute(mat, type, name); + if (link->link_type == GPU_NODE_LINK_ATTR) { + link->attr->default_value = default_value; + } + return link; +} + GPUNodeLink *GPU_uniform_attribute(GPUMaterial *mat, const char *name, bool use_dupli) { GPUNodeGraph *graph = gpu_material_node_graph(mat); @@ -586,39 +602,6 @@ GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *ro return link; } -GPUNodeLink *GPU_volume_grid(GPUMaterial *mat, - const char *name, - eGPUVolumeDefaultValue default_value) -{ - /* 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, default_value); - - GPUNodeLink *transform_link = gpu_node_link_create(); - transform_link->link_type = GPU_NODE_LINK_VOLUME_GRID_TRANSFORM; - transform_link->volume_grid = link->volume_grid; - transform_link->volume_grid->users++; - - GPUNodeLink *cos_link = GPU_attribute(mat, CD_ORCO, ""); - - /* 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 (STREQ(name, "color")) { - GPU_link(mat, "node_attribute_volume_color", link, transform_link, cos_link, &link); - } - else if (STREQ(name, "temperature")) { - GPU_link(mat, "node_attribute_volume_temperature", link, transform_link, cos_link, &link); - } - else { - GPU_link(mat, "node_attribute_volume", link, transform_link, cos_link, &link); - } - - return link; -} - /* Creating Nodes */ bool GPU_link(GPUMaterial *mat, const char *name, ...) @@ -767,9 +750,6 @@ 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, GPU_SOURCE_VOLUME_GRID_TRANSFORM)) { - input->volume_grid->users--; - } if (input->link) { gpu_node_link_free(input->link); @@ -816,10 +796,6 @@ void gpu_node_graph_free(GPUNodeGraph *graph) BLI_freelistN(&graph->material_functions); gpu_node_graph_free_nodes(graph); - LISTBASE_FOREACH (GPUMaterialVolumeGrid *, grid, &graph->volume_grids) { - MEM_SAFE_FREE(grid->name); - } - BLI_freelistN(&graph->volume_grids); BLI_freelistN(&graph->textures); BLI_freelistN(&graph->attributes); GPU_uniform_attr_list_free(&graph->uniform_attrs); @@ -894,14 +870,6 @@ void gpu_node_graph_prune_unused(GPUNodeGraph *graph) } } - 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); - } - } - GPUUniformAttrList *uattrs = &graph->uniform_attrs; LISTBASE_FOREACH_MUTABLE (GPUUniformAttr *, attr, &uattrs->list) { diff --git a/source/blender/gpu/intern/gpu_node_graph.h b/source/blender/gpu/intern/gpu_node_graph.h index 024119e1c24..ae472d5b7aa 100644 --- a/source/blender/gpu/intern/gpu_node_graph.h +++ b/source/blender/gpu/intern/gpu_node_graph.h @@ -34,8 +34,6 @@ typedef enum eGPUDataSource { GPU_SOURCE_STRUCT, GPU_SOURCE_TEX, GPU_SOURCE_TEX_TILED_MAPPING, - GPU_SOURCE_VOLUME_GRID, - GPU_SOURCE_VOLUME_GRID_TRANSFORM, GPU_SOURCE_FUNCTION_CALL, } eGPUDataSource; @@ -48,8 +46,6 @@ 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_VOLUME_GRID_TRANSFORM, GPU_NODE_LINK_OUTPUT, GPU_NODE_LINK_UNIFORM, GPU_NODE_LINK_DIFFERENTIATE_FLOAT_FN, @@ -90,8 +86,6 @@ struct GPUNodeLink { const float *data; /* 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 */ @@ -134,8 +128,6 @@ typedef struct GPUInput { struct GPUMaterialAttribute *attr; /* GPU_SOURCE_UNIFORM_ATTR */ struct GPUUniformAttr *uniform_attr; - /* GPU_SOURCE_VOLUME_GRID | GPU_SOURCE_VOLUME_GRID_TRANSFORM */ - struct GPUMaterialVolumeGrid *volume_grid; /* GPU_SOURCE_FUNCTION_CALL */ char function_call[64]; }; @@ -170,7 +162,6 @@ typedef struct GPUNodeGraph { /* Requested attributes and textures. */ ListBase attributes; ListBase textures; - ListBase volume_grids; /* The list of uniform attributes. */ GPUUniformAttrList uniform_attrs; diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_attribute.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_attribute.glsl index faf37db3ea6..2ae53b35b3f 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_attribute.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_attribute.glsl @@ -1,3 +1,17 @@ + +void node_attribute_color(vec4 attr, out vec4 out_attr) +{ + out_attr = attr_load_color_post(attr); +} + +void node_attribute_temperature(vec4 attr, out vec4 out_attr) +{ + out_attr.x = attr_load_temperature_post(attr.x); + out_attr.y = 0.0; + out_attr.z = 0.0; + out_attr.w = 1.0; +} + void node_attribute( vec4 attr, out vec4 outcol, out vec3 outvec, out float outf, out float outalpha) { 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 deleted file mode 100644 index 464cf5227b4..00000000000 --- a/source/blender/gpu/shaders/material/gpu_shader_material_volume_info.glsl +++ /dev/null @@ -1,51 +0,0 @@ - -/* 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, mat4 transform, vec3 cos, out vec3 outvec) -{ - /* Optional per-grid transform. */ - if (transform[3][3] != 0.0) { - cos = (transform * vec4(cos, 1.0)).xyz; - } - - outvec = texture(tex, cos).rgb; -} - -/* Special color attribute for smoke. */ -void node_attribute_volume_color(sampler3D tex, mat4 transform, vec3 cos, out vec3 outvec) -{ - /* Optional per-grid transform. */ - if (transform[3][3] != 0.0) { - cos = (transform * vec4(cos, 1.0)).xyz; - } - - /* 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; -} - -/* Special temperature attribute for smoke. */ -void node_attribute_volume_temperature(sampler3D tex, mat4 transform, vec3 cos, out float outf) -{ - /* Optional per-grid transform. */ - if (transform[3][3] != 0.0) { - cos = (transform * vec4(cos, 1.0)).xyz; - } - - 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; - } -} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_volume_principled.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_volume_principled.glsl index 1127c34b3ac..21c4aba0ffe 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_volume_principled.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_volume_principled.glsl @@ -10,9 +10,9 @@ void node_volume_principled(vec4 color, vec4 blackbody_tint, float temperature, float weight, - float density_attribute, + vec4 density_attribute, vec4 color_attribute, - float temperature_attribute, + vec4 temperature_attribute, sampler1DArray spectrummap, float layer, out Closure result) @@ -25,7 +25,7 @@ void node_volume_principled(vec4 color, density = max(density, 0.0); if (density > 1e-5) { - density = max(density * density_attribute, 0.0); + density = max(density * density_attribute.x, 0.0); } if (density > 1e-5) { @@ -47,7 +47,7 @@ void node_volume_principled(vec4 color, if (blackbody_intensity > 1e-3) { /* Add temperature from attribute. */ - float T = max(temperature * max(temperature_attribute, 0.0), 0.0); + float T = max(temperature * max(temperature_attribute.x, 0.0), 0.0); /* Stefan-Boltzman law. */ float T2 = T * T; diff --git a/source/blender/nodes/shader/nodes/node_shader_attribute.cc b/source/blender/nodes/shader/nodes/node_shader_attribute.cc index bb01818e734..d01271c15d3 100644 --- a/source/blender/nodes/shader/nodes/node_shader_attribute.cc +++ b/source/blender/nodes/shader/nodes/node_shader_attribute.cc @@ -37,24 +37,6 @@ static int node_shader_gpu_attribute(GPUMaterial *mat, NodeShaderAttribute *attr = static_cast<NodeShaderAttribute *>(node->storage); bool is_varying = attr->type == SHD_ATTRIBUTE_GEOMETRY; - if (GPU_material_is_volume_shader(mat) && is_varying) { - if (out[0].hasoutput) { - out[0].link = GPU_volume_grid(mat, attr->name, GPU_VOLUME_DEFAULT_0); - } - if (out[1].hasoutput) { - out[1].link = GPU_volume_grid(mat, attr->name, GPU_VOLUME_DEFAULT_0); - } - if (out[2].hasoutput) { - out[2].link = GPU_volume_grid(mat, attr->name, GPU_VOLUME_DEFAULT_0); - } - if (out[3].hasoutput) { - static const float default_alpha = 1.0f; - out[3].link = GPU_constant(&default_alpha); - } - - return 1; - } - GPUNodeLink *cd_attr; if (is_varying) { @@ -64,6 +46,13 @@ static int node_shader_gpu_attribute(GPUMaterial *mat, cd_attr = GPU_uniform_attribute(mat, attr->name, attr->type == SHD_ATTRIBUTE_INSTANCER); } + if (STREQ(attr->name, "color")) { + GPU_link(mat, "node_attribute_color", cd_attr, &cd_attr); + } + else if (STREQ(attr->name, "temperature")) { + GPU_link(mat, "node_attribute_temperature", cd_attr, &cd_attr); + } + GPU_stack_link(mat, node, "node_attribute", in, out, cd_attr); int i; diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_info.cc b/source/blender/nodes/shader/nodes/node_shader_volume_info.cc index 6676a7653fe..a202312f8d8 100644 --- a/source/blender/nodes/shader/nodes/node_shader_volume_info.cc +++ b/source/blender/nodes/shader/nodes/node_shader_volume_info.cc @@ -20,16 +20,18 @@ static int node_shader_gpu_volume_info(GPUMaterial *mat, GPUNodeStack *out) { if (out[0].hasoutput) { - out[0].link = GPU_volume_grid(mat, "color", GPU_VOLUME_DEFAULT_0); + out[0].link = GPU_attribute(mat, CD_AUTO_FROM_NAME, "color"); + GPU_link(mat, "node_attribute_color", out[0].link, &out[0].link); } if (out[1].hasoutput) { - out[1].link = GPU_volume_grid(mat, "density", GPU_VOLUME_DEFAULT_0); + out[1].link = GPU_attribute(mat, CD_AUTO_FROM_NAME, "density"); } if (out[2].hasoutput) { - out[2].link = GPU_volume_grid(mat, "flame", GPU_VOLUME_DEFAULT_0); + out[2].link = GPU_attribute(mat, CD_AUTO_FROM_NAME, "flame"); } if (out[3].hasoutput) { - out[3].link = GPU_volume_grid(mat, "temperature", GPU_VOLUME_DEFAULT_0); + out[3].link = GPU_attribute(mat, CD_AUTO_FROM_NAME, "temperature"); + GPU_link(mat, "node_attribute_temperature", out[3].link, &out[3].link); } return true; diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_principled.cc b/source/blender/nodes/shader/nodes/node_shader_volume_principled.cc index d414b4b2ef7..d4d5c4789ed 100644 --- a/source/blender/nodes/shader/nodes/node_shader_volume_principled.cc +++ b/source/blender/nodes/shader/nodes/node_shader_volume_principled.cc @@ -43,6 +43,18 @@ static void node_shader_init_volume_principled(bNodeTree *UNUSED(ntree), bNode * } } +static void attribute_post_process(GPUMaterial *mat, + const char *attribute_name, + GPUNodeLink **attribute_link) +{ + if (STREQ(attribute_name, "color")) { + GPU_link(mat, "node_attribute_color", *attribute_link, attribute_link); + } + else if (STREQ(attribute_name, "temperature")) { + GPU_link(mat, "node_attribute_temperature", *attribute_link, attribute_link); + } +} + static int node_shader_gpu_volume_principled(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), @@ -67,13 +79,16 @@ static int node_shader_gpu_volume_principled(GPUMaterial *mat, } if (STREQ(sock->name, "Density Attribute")) { - density = GPU_volume_grid(mat, attribute_name, GPU_VOLUME_DEFAULT_1); + density = GPU_attribute_with_default(mat, CD_AUTO_FROM_NAME, attribute_name, GPU_DEFAULT_1); + attribute_post_process(mat, attribute_name, &density); } else if (STREQ(sock->name, "Color Attribute")) { - color = GPU_volume_grid(mat, attribute_name, GPU_VOLUME_DEFAULT_1); + color = GPU_attribute_with_default(mat, CD_AUTO_FROM_NAME, attribute_name, GPU_DEFAULT_1); + attribute_post_process(mat, attribute_name, &color); } else if (use_blackbody && STREQ(sock->name, "Temperature Attribute")) { - temperature = GPU_volume_grid(mat, attribute_name, GPU_VOLUME_DEFAULT_0); + temperature = GPU_attribute(mat, CD_AUTO_FROM_NAME, attribute_name); + attribute_post_process(mat, attribute_name, &temperature); } } |