Fix T80332: principle volume shader not working for world in Eevee
The handling of missing volume grids for the principled volume shader was incomplete, different inputs need different default values.
This commit is contained in:
parent
96439de784
commit
f0c376a52a
Notes:
blender-bot
2023-02-13 21:19:11 +01:00
Referenced by issue #80760, Volumetric Light Doesn't work Referenced by issue #80749, Principled volume doesn't work with EEVEE Referenced by issue #80630, Use-after-free when rendering material previews Referenced by issue #80614, blender2.90.0 Eevee Volumetrics not working Referenced by issue #80396, Potential candidates for corrective releases Referenced by issue #80332, Principle Volume in World Shader is not working
|
@ -59,10 +59,9 @@ static struct {
|
|||
|
||||
GPUTexture *depth_src;
|
||||
|
||||
GPUTexture *dummy_density;
|
||||
GPUTexture *dummy_color;
|
||||
GPUTexture *dummy_zero;
|
||||
GPUTexture *dummy_one;
|
||||
GPUTexture *dummy_flame;
|
||||
GPUTexture *dummy_missing;
|
||||
|
||||
GPUTexture *dummy_scatter;
|
||||
GPUTexture *dummy_transmit;
|
||||
|
@ -137,14 +136,24 @@ static void eevee_create_shader_volumes(void)
|
|||
e_data.volumetric_accum_sh = DRW_shader_create_fullscreen_with_shaderlib(
|
||||
datatoc_volumetric_accum_frag_glsl, lib, SHADER_DEFINES);
|
||||
|
||||
const float density[4] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
e_data.dummy_density = DRW_texture_create_3d(1, 1, 1, GPU_RGBA8, DRW_TEX_WRAP, density);
|
||||
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);
|
||||
}
|
||||
|
||||
const float missing[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
e_data.dummy_missing = DRW_texture_create_3d(1, 1, 1, GPU_RGBA8, DRW_TEX_WRAP, missing);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void EEVEE_volumes_set_jitter(EEVEE_ViewLayerData *sldata, uint current_sample)
|
||||
|
@ -359,7 +368,8 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
|
|||
/* 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, e_data.dummy_missing);
|
||||
DRW_shgroup_uniform_texture(
|
||||
grp, gpu_grid->sampler_name, eevee_volume_default_texture(gpu_grid->default_value));
|
||||
}
|
||||
|
||||
DRW_shgroup_call_procedural_triangles(grp, NULL, common_data->vol_tex_size[2]);
|
||||
|
@ -449,7 +459,9 @@ static bool eevee_volume_object_grids_init(Object *ob, ListBase *gpu_grids, DRWS
|
|||
NULL;
|
||||
|
||||
DRW_shgroup_uniform_texture(
|
||||
grp, gpu_grid->sampler_name, (drw_grid) ? drw_grid->texture : e_data.dummy_missing);
|
||||
grp,
|
||||
gpu_grid->sampler_name,
|
||||
(drw_grid) ? drw_grid->texture : eevee_volume_default_texture(gpu_grid->default_value));
|
||||
|
||||
if (drw_grid && multiple_transforms) {
|
||||
/* Specify per-volume transform matrix that is applied after the
|
||||
|
@ -497,21 +509,20 @@ static bool eevee_volume_object_mesh_init(Scene *scene,
|
|||
|
||||
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_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_density);
|
||||
grp, gpu_grid->sampler_name, fds->tex_color ? &fds->tex_color : &e_data.dummy_one);
|
||||
}
|
||||
else if (STREQ(gpu_grid->name, "flame") || STREQ(gpu_grid->name, "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_ref(grp, gpu_grid->sampler_name, &e_data.dummy_density);
|
||||
DRW_shgroup_uniform_texture(
|
||||
grp, gpu_grid->sampler_name, eevee_volume_default_texture(gpu_grid->default_value));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -527,7 +538,8 @@ static bool eevee_volume_object_mesh_init(Scene *scene,
|
|||
}
|
||||
else {
|
||||
LISTBASE_FOREACH (GPUMaterialVolumeGrid *, gpu_grid, gpu_grids) {
|
||||
DRW_shgroup_uniform_texture(grp, gpu_grid->sampler_name, e_data.dummy_density);
|
||||
DRW_shgroup_uniform_texture(
|
||||
grp, gpu_grid->sampler_name, eevee_volume_default_texture(gpu_grid->default_value));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -836,10 +848,9 @@ void EEVEE_volumes_free(void)
|
|||
DRW_TEXTURE_FREE_SAFE(e_data.dummy_scatter);
|
||||
DRW_TEXTURE_FREE_SAFE(e_data.dummy_transmit);
|
||||
|
||||
DRW_TEXTURE_FREE_SAFE(e_data.dummy_density);
|
||||
DRW_TEXTURE_FREE_SAFE(e_data.dummy_zero);
|
||||
DRW_TEXTURE_FREE_SAFE(e_data.dummy_one);
|
||||
DRW_TEXTURE_FREE_SAFE(e_data.dummy_flame);
|
||||
DRW_TEXTURE_FREE_SAFE(e_data.dummy_color);
|
||||
DRW_TEXTURE_FREE_SAFE(e_data.dummy_missing);
|
||||
|
||||
DRW_SHADER_FREE_SAFE(e_data.volumetric_clear_sh);
|
||||
DRW_SHADER_FREE_SAFE(e_data.scatter_sh);
|
||||
|
|
|
@ -128,6 +128,11 @@ typedef enum eGPUMaterialStatus {
|
|||
GPU_MAT_SUCCESS,
|
||||
} eGPUMaterialStatus;
|
||||
|
||||
typedef enum eGPUVolumeDefaultValue {
|
||||
GPU_VOLUME_DEFAULT_0,
|
||||
GPU_VOLUME_DEFAULT_1,
|
||||
} eGPUVolumeDefaultValue;
|
||||
|
||||
typedef void (*GPUMaterialEvalCallbackFn)(GPUMaterial *mat,
|
||||
int options,
|
||||
const char **vert_code,
|
||||
|
@ -148,7 +153,9 @@ 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 *layer);
|
||||
GPUNodeLink *GPU_volume_grid(GPUMaterial *mat, const char *name);
|
||||
GPUNodeLink *GPU_volume_grid(GPUMaterial *mat,
|
||||
const char *name,
|
||||
eGPUVolumeDefaultValue default_value);
|
||||
GPUNodeLink *GPU_builtin(eGPUBuiltin builtin);
|
||||
|
||||
bool GPU_link(GPUMaterial *mat, const char *name, ...);
|
||||
|
@ -242,6 +249,7 @@ typedef struct 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;
|
||||
|
|
|
@ -333,13 +333,15 @@ static GPUMaterialTexture *gpu_node_graph_add_texture(GPUNodeGraph *graph,
|
|||
return tex;
|
||||
}
|
||||
|
||||
static GPUMaterialVolumeGrid *gpu_node_graph_add_volume_grid(GPUNodeGraph *graph, const char *name)
|
||||
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)) {
|
||||
if (STREQ(grid->name, name) && grid->default_value == default_value) {
|
||||
break;
|
||||
}
|
||||
num_grids++;
|
||||
|
@ -349,6 +351,7 @@ static GPUMaterialVolumeGrid *gpu_node_graph_add_volume_grid(GPUNodeGraph *graph
|
|||
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);
|
||||
|
@ -442,14 +445,16 @@ GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *ro
|
|||
return link;
|
||||
}
|
||||
|
||||
GPUNodeLink *GPU_volume_grid(GPUMaterial *mat, const char *name)
|
||||
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);
|
||||
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;
|
||||
|
|
|
@ -44,13 +44,13 @@ static int node_shader_gpu_attribute(GPUMaterial *mat,
|
|||
|
||||
if (GPU_material_is_volume_shader(mat)) {
|
||||
if (out[0].hasoutput) {
|
||||
out[0].link = GPU_volume_grid(mat, attr->name);
|
||||
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);
|
||||
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);
|
||||
out[2].link = GPU_volume_grid(mat, attr->name, GPU_VOLUME_DEFAULT_0);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
|
|
@ -34,16 +34,16 @@ static int node_shader_gpu_volume_info(GPUMaterial *mat,
|
|||
GPUNodeStack *out)
|
||||
{
|
||||
if (out[0].hasoutput) {
|
||||
out[0].link = GPU_volume_grid(mat, "color");
|
||||
out[0].link = GPU_volume_grid(mat, "color", GPU_VOLUME_DEFAULT_0);
|
||||
}
|
||||
if (out[1].hasoutput) {
|
||||
out[1].link = GPU_volume_grid(mat, "density");
|
||||
out[1].link = GPU_volume_grid(mat, "density", GPU_VOLUME_DEFAULT_0);
|
||||
}
|
||||
if (out[2].hasoutput) {
|
||||
out[2].link = GPU_volume_grid(mat, "flame");
|
||||
out[2].link = GPU_volume_grid(mat, "flame", GPU_VOLUME_DEFAULT_0);
|
||||
}
|
||||
if (out[3].hasoutput) {
|
||||
out[3].link = GPU_volume_grid(mat, "temperature");
|
||||
out[3].link = GPU_volume_grid(mat, "temperature", GPU_VOLUME_DEFAULT_0);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -78,13 +78,13 @@ static int node_shader_gpu_volume_principled(GPUMaterial *mat,
|
|||
}
|
||||
|
||||
if (STREQ(sock->name, "Density Attribute")) {
|
||||
density = GPU_volume_grid(mat, attribute_name);
|
||||
density = GPU_volume_grid(mat, attribute_name, GPU_VOLUME_DEFAULT_1);
|
||||
}
|
||||
else if (STREQ(sock->name, "Color Attribute")) {
|
||||
color = GPU_volume_grid(mat, attribute_name);
|
||||
color = GPU_volume_grid(mat, attribute_name, GPU_VOLUME_DEFAULT_1);
|
||||
}
|
||||
else if (use_blackbody && STREQ(sock->name, "Temperature Attribute")) {
|
||||
temperature = GPU_volume_grid(mat, attribute_name);
|
||||
temperature = GPU_volume_grid(mat, attribute_name, GPU_VOLUME_DEFAULT_0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue