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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2022-04-19 13:01:16 +0300
committerClément Foucault <foucault.clem@gmail.com>2022-04-19 13:09:18 +0300
commitfa3bd17ae87301ca198d16d2dc7d2432548f34f9 (patch)
treec08eb8740784799dd3bf9517f4eb4380bc4e6cab
parent1e3f4c70ab56578b8b0e0056870bd17cc118982a (diff)
GPU: Replace `GPUMaterialVolumeGrid` by `GPUMaterialAttribute`
This is to make the codegen and shading nodes object type agnostic. This is essential for flexibility of the engine to use the nodetree as it see fits. The essential volume attributes struct properties are moved to the `GPUMaterialAttribute` which see its final input name set on creation. The binding process is centralized into `draw_volume.cc` to avoid duplicating the code between multiple engines. It mimics the hair attributes process. Volume object grid transforms and other per object uniforms are packed into one UBO per object. The grid transform is now based on object which simplify the matrix preparations. This also gets rid of the double transforms and use object info orco factors for volume objects. Tagging @brecht because he did the initial implementation of Volume Grids.
-rw-r--r--source/blender/draw/CMakeLists.txt4
-rw-r--r--source/blender/draw/engines/eevee/eevee_shaders.c4
-rw-r--r--source/blender/draw/engines/eevee/eevee_shaders_extra.cc20
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c238
-rw-r--r--source/blender/draw/engines/eevee/shaders/shadow_vert.glsl10
-rw-r--r--source/blender/draw/engines/eevee/shaders/surface_frag.glsl10
-rw-r--r--source/blender/draw/engines/eevee/shaders/surface_vert.glsl10
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl89
-rw-r--r--source/blender/draw/intern/DRW_gpu_wrapper.hh3
-rw-r--r--source/blender/draw/intern/draw_common.h17
-rw-r--r--source/blender/draw/intern/draw_manager.c8
-rw-r--r--source/blender/draw/intern/draw_manager.h2
-rw-r--r--source/blender/draw/intern/draw_manager_data.c12
-rw-r--r--source/blender/draw/intern/draw_shader_shared.h16
-rw-r--r--source/blender/draw/intern/draw_volume.cc266
-rw-r--r--source/blender/draw/intern/shaders/common_attribute_lib.glsl12
-rw-r--r--source/blender/draw/intern/shaders/draw_object_infos_info.hh4
-rw-r--r--source/blender/gpu/CMakeLists.txt1
-rw-r--r--source/blender/gpu/GPU_material.h32
-rw-r--r--source/blender/gpu/intern/gpu_codegen.cc50
-rw-r--r--source/blender/gpu/intern/gpu_material.c5
-rw-r--r--source/blender/gpu/intern/gpu_node_graph.c138
-rw-r--r--source/blender/gpu/intern/gpu_node_graph.h9
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_attribute.glsl14
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_volume_info.glsl51
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_volume_principled.glsl8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_attribute.cc25
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_volume_info.cc10
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_volume_principled.cc21
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);
}
}