Eevee: internal support for arbitrary number of volume grids

This has no user visible impact yet since smoke volumes only support a fixed
set of attributes, but will become important with the new volume object.

For GPU shader compilation, volume grids are now handled separately from
image textures. They are somewhere between a vertex attribute and an image
texture, basically an attribute that is stored as a texture.

Differential Revision: https://developer.blender.org/D6952
This commit is contained in:
Brecht Van Lommel
2020-03-11 14:58:19 +01:00
committed by Brecht Van Lommel
parent e1e772a802
commit b9f6d033be
13 changed files with 236 additions and 196 deletions

View File

@@ -776,6 +776,7 @@ struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, Wor
wo,
engine,
options,
false,
e_data.vert_background_shader_str,
NULL,
e_data.frag_shader_lib,
@@ -796,6 +797,7 @@ struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, Wor
wo,
engine,
options,
false,
e_data.vert_background_shader_str,
NULL,
e_data.frag_shader_lib,
@@ -819,6 +821,7 @@ struct GPUMaterial *EEVEE_material_world_volume_get(struct Scene *scene, World *
wo,
engine,
options,
true,
e_data.vert_volume_shader_str,
e_data.geom_volume_shader_str,
e_data.volume_shader_lib,
@@ -853,6 +856,7 @@ struct GPUMaterial *EEVEE_material_mesh_get(struct Scene *scene,
ma,
engine,
options,
false,
e_data.vert_shader_str,
NULL,
e_data.frag_shader_lib,
@@ -880,6 +884,7 @@ struct GPUMaterial *EEVEE_material_mesh_volume_get(struct Scene *scene, Material
ma,
engine,
options,
true,
e_data.vert_volume_shader_str,
e_data.geom_volume_shader_str,
e_data.volume_shader_lib,
@@ -916,6 +921,7 @@ struct GPUMaterial *EEVEE_material_mesh_depth_get(struct Scene *scene,
ma,
engine,
options,
false,
(is_shadow) ? e_data.vert_shadow_shader_str :
e_data.vert_shader_str,
NULL,
@@ -945,6 +951,7 @@ struct GPUMaterial *EEVEE_material_hair_get(struct Scene *scene, Material *ma)
ma,
engine,
options,
false,
e_data.vert_shader_str,
NULL,
e_data.frag_shader_lib,
@@ -1919,7 +1926,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
* to know if the material has a "volume nodetree".
*/
bool use_volume_material = (gpumat_array[0] &&
GPU_material_use_domain_volume(gpumat_array[0]));
GPU_material_has_volume_output(gpumat_array[0]));
if ((ob->dt >= OB_SOLID) || DRW_state_is_image_render()) {
/* Get per-material split surface */
@@ -1968,7 +1975,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
/* Do not render surface if we are rendering a volume object
* and do not have a surface closure. */
if (use_volume_material &&
(gpumat_array[i] && !GPU_material_use_domain_surface(gpumat_array[i]))) {
(gpumat_array[i] && !GPU_material_has_surface_output(gpumat_array[i]))) {
continue;
}

View File

@@ -351,7 +351,7 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
!LOOK_DEV_STUDIO_LIGHT_ENABLED(draw_ctx->v3d)) {
struct GPUMaterial *mat = EEVEE_material_world_volume_get(scene, wo);
if (GPU_material_use_domain_volume(mat)) {
if (GPU_material_has_volume_output(mat)) {
grp = DRW_shgroup_material_create(mat, psl->volumetric_world_ps);
}
@@ -367,10 +367,11 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
/* Fix principle volumetric not working with world materials. */
DRW_shgroup_uniform_texture(grp, "sampdensity", e_data.dummy_density);
DRW_shgroup_uniform_texture(grp, "sampcolor", e_data.dummy_density);
DRW_shgroup_uniform_texture(grp, "sampflame", e_data.dummy_flame);
DRW_shgroup_uniform_vec2_copy(grp, "unftemperature", (float[2]){0.0f, 1.0f});
ListBase gpu_grids = GPU_material_volume_grids(mat);
for (GPUMaterialVolumeGrid *gpu_grid = gpu_grids.first; gpu_grid;
gpu_grid = gpu_grid->next) {
DRW_shgroup_uniform_texture(grp, gpu_grid->sampler_name, e_data.dummy_density);
}
DRW_shgroup_call_procedural_triangles(grp, NULL, common_data->vol_tex_size[2]);
@@ -446,6 +447,7 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
DRW_shgroup_uniform_vec3(grp, "volumeOrcoLoc", texcoloc, 1);
DRW_shgroup_uniform_vec3(grp, "volumeOrcoSize", texcosize, 1);
ListBase gpu_grids = GPU_material_volume_grids(mat);
/* Smoke Simulation */
if (((ob->base_flag & BASE_FROM_DUPLI) == 0) &&
(md = modifiers_findByType(ob, eModifierType_Fluid)) &&
@@ -477,12 +479,25 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
BLI_addtail(&e_data.smoke_domains, BLI_genericNodeN(mmd));
}
DRW_shgroup_uniform_texture_ref(
grp, "sampdensity", mds->tex_density ? &mds->tex_density : &e_data.dummy_density);
DRW_shgroup_uniform_texture_ref(
grp, "sampcolor", mds->tex_color ? &mds->tex_color : &e_data.dummy_density);
DRW_shgroup_uniform_texture_ref(
grp, "sampflame", mds->tex_flame ? &mds->tex_flame : &e_data.dummy_flame);
for (GPUMaterialVolumeGrid *gpu_grid = gpu_grids.first; gpu_grid; gpu_grid = gpu_grid->next) {
if (STREQ(gpu_grid->name, "density")) {
DRW_shgroup_uniform_texture_ref(grp,
gpu_grid->sampler_name,
mds->tex_density ? &mds->tex_density :
&e_data.dummy_density);
}
else if (STREQ(gpu_grid->name, "color")) {
DRW_shgroup_uniform_texture_ref(
grp, gpu_grid->sampler_name, mds->tex_color ? &mds->tex_color : &e_data.dummy_density);
}
else if (STREQ(gpu_grid->name, "flame") || STREQ(gpu_grid->name, "temperature")) {
DRW_shgroup_uniform_texture_ref(
grp, gpu_grid->sampler_name, mds->tex_flame ? &mds->tex_flame : &e_data.dummy_flame);
}
else {
DRW_shgroup_uniform_texture_ref(grp, gpu_grid->sampler_name, &e_data.dummy_density);
}
}
/* Constant Volume color. */
bool use_constant_color = ((mds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS) == 0 &&
@@ -492,14 +507,13 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
grp, "volumeColor", (use_constant_color) ? mds->active_color : white, 1);
/* Output is such that 0..1 maps to 0..1000K */
DRW_shgroup_uniform_vec2(grp, "unftemperature", &mds->flame_ignition, 1);
DRW_shgroup_uniform_vec2(grp, "volumeTemperature", &mds->flame_ignition, 1);
}
else {
DRW_shgroup_uniform_texture(grp, "sampdensity", e_data.dummy_density);
DRW_shgroup_uniform_texture(grp, "sampcolor", e_data.dummy_density);
DRW_shgroup_uniform_texture(grp, "sampflame", e_data.dummy_flame);
for (GPUMaterialVolumeGrid *gpu_grid = gpu_grids.first; gpu_grid; gpu_grid = gpu_grid->next) {
DRW_shgroup_uniform_texture(grp, gpu_grid->sampler_name, e_data.dummy_density);
}
DRW_shgroup_uniform_vec3(grp, "volumeColor", white, 1);
DRW_shgroup_uniform_vec2(grp, "unftemperature", (float[2]){0.0f, 1.0f}, 1);
}
/* TODO Reduce to number of slices intersecting. */

View File

@@ -211,16 +211,17 @@ struct GPUShader *DRW_shader_create_fullscreen(const char *frag, const char *def
struct GPUShader *DRW_shader_create_3d_depth_only(eGPUShaderConfig slot);
struct GPUMaterial *DRW_shader_find_from_world(struct World *wo,
const void *engine_type,
int options,
const int options,
bool deferred);
struct GPUMaterial *DRW_shader_find_from_material(struct Material *ma,
const void *engine_type,
int options,
const int options,
bool deferred);
struct GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
struct World *wo,
const void *engine_type,
int options,
const int options,
const bool is_volume_shader,
const char *vert,
const char *geom,
const char *frag_lib,
@@ -229,7 +230,8 @@ struct GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
struct GPUMaterial *DRW_shader_create_from_material(struct Scene *scene,
struct Material *ma,
const void *engine_type,
int options,
const int options,
const bool is_volume_shader,
const char *vert,
const char *geom,
const char *frag_lib,

View File

@@ -356,7 +356,7 @@ GPUShader *DRW_shader_create_3d_depth_only(eGPUShaderConfig sh_cfg)
GPUMaterial *DRW_shader_find_from_world(World *wo,
const void *engine_type,
int options,
const int options,
bool deferred)
{
GPUMaterial *mat = GPU_material_from_nodetree_find(&wo->gpumaterial, engine_type, options);
@@ -372,7 +372,7 @@ GPUMaterial *DRW_shader_find_from_world(World *wo,
GPUMaterial *DRW_shader_find_from_material(Material *ma,
const void *engine_type,
int options,
const int options,
bool deferred)
{
GPUMaterial *mat = GPU_material_from_nodetree_find(&ma->gpumaterial, engine_type, options);
@@ -389,7 +389,8 @@ GPUMaterial *DRW_shader_find_from_material(Material *ma,
GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
World *wo,
const void *engine_type,
int options,
const int options,
const bool is_volume_shader,
const char *vert,
const char *geom,
const char *frag_lib,
@@ -409,6 +410,7 @@ GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
&wo->gpumaterial,
engine_type,
options,
is_volume_shader,
vert,
geom,
frag_lib,
@@ -426,7 +428,8 @@ GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
GPUMaterial *DRW_shader_create_from_material(struct Scene *scene,
Material *ma,
const void *engine_type,
int options,
const int options,
const bool is_volume_shader,
const char *vert,
const char *geom,
const char *frag_lib,
@@ -446,6 +449,7 @@ GPUMaterial *DRW_shader_create_from_material(struct Scene *scene,
&ma->gpumaterial,
engine_type,
options,
is_volume_shader,
vert,
geom,
frag_lib,

View File

@@ -98,13 +98,9 @@ typedef enum eGPUBuiltin {
GPU_LOC_TO_VIEW_MATRIX = (1 << 13),
GPU_INVERSE_LOC_TO_VIEW_MATRIX = (1 << 14),
GPU_OBJECT_INFO = (1 << 15),
GPU_VOLUME_DENSITY = (1 << 16),
GPU_VOLUME_COLOR = (1 << 17),
GPU_VOLUME_FLAME = (1 << 18),
GPU_VOLUME_TEMPERATURE = (1 << 19),
GPU_BARYCENTRIC_TEXCO = (1 << 20),
GPU_BARYCENTRIC_DIST = (1 << 21),
GPU_WORLD_NORMAL = (1 << 22),
GPU_BARYCENTRIC_TEXCO = (1 << 16),
GPU_BARYCENTRIC_DIST = (1 << 17),
GPU_WORLD_NORMAL = (1 << 18),
} eGPUBuiltin;
typedef enum eGPUMatFlag {
@@ -146,6 +142,7 @@ GPUNodeLink *GPU_image(GPUMaterial *mat, struct Image *ima, struct ImageUser *iu
GPUNodeLink *GPU_image_tiled(GPUMaterial *mat, struct Image *ima, struct ImageUser *iuser);
GPUNodeLink *GPU_image_tiled_mapping(GPUMaterial *mat, struct Image *ima, struct ImageUser *iuser);
GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *layer);
GPUNodeLink *GPU_volume_grid(GPUMaterial *mat, const char *name);
GPUNodeLink *GPU_builtin(eGPUBuiltin builtin);
bool GPU_link(GPUMaterial *mat, const char *name, ...);
@@ -179,7 +176,8 @@ GPUMaterial *GPU_material_from_nodetree(struct Scene *scene,
struct bNodeTree *ntree,
struct ListBase *gpumaterials,
const void *engine_type,
int options,
const int options,
const bool is_volume_shader,
const char *vert_code,
const char *geom_code,
const char *frag_lib,
@@ -192,7 +190,6 @@ void GPU_materials_free(struct Main *bmain);
struct Scene *GPU_material_scene(GPUMaterial *material);
struct GPUPass *GPU_material_get_pass(GPUMaterial *material);
struct ListBase *GPU_material_get_inputs(GPUMaterial *material);
struct Material *GPU_material_get_material(GPUMaterial *material);
eGPUMaterialStatus GPU_material_status(GPUMaterial *mat);
@@ -200,8 +197,10 @@ struct GPUUniformBuffer *GPU_material_uniform_buffer_get(GPUMaterial *material);
void GPU_material_uniform_buffer_create(GPUMaterial *material, ListBase *inputs);
struct GPUUniformBuffer *GPU_material_create_sss_profile_ubo(void);
bool GPU_material_use_domain_surface(GPUMaterial *mat);
bool GPU_material_use_domain_volume(GPUMaterial *mat);
bool GPU_material_has_surface_output(GPUMaterial *mat);
bool GPU_material_has_volume_output(GPUMaterial *mat);
bool GPU_material_is_volume_shader(GPUMaterial *mat);
void GPU_material_flag_set(GPUMaterial *mat, eGPUMatFlag flag);
bool GPU_material_flag_get(GPUMaterial *mat, eGPUMatFlag flag);
@@ -231,8 +230,16 @@ typedef struct GPUMaterialTexture {
int users;
} GPUMaterialTexture;
typedef struct GPUMaterialVolumeGrid {
struct GPUMaterialVolumeGrid *next, *prev;
char *name;
char sampler_name[32]; /* Name of sampler in GLSL. */
int users;
} GPUMaterialVolumeGrid;
ListBase GPU_material_attributes(GPUMaterial *material);
ListBase GPU_material_textures(GPUMaterial *material);
ListBase GPU_material_volume_grids(GPUMaterial *material);
#ifdef __cplusplus
}

View File

@@ -269,18 +269,6 @@ static const char *gpu_builtin_name(eGPUBuiltin builtin)
else if (builtin == GPU_OBJECT_INFO) {
return "unfobjectinfo";
}
else if (builtin == GPU_VOLUME_DENSITY) {
return "sampdensity";
}
else if (builtin == GPU_VOLUME_COLOR) {
return "sampcolor";
}
else if (builtin == GPU_VOLUME_FLAME) {
return "sampflame";
}
else if (builtin == GPU_VOLUME_TEMPERATURE) {
return "unftemperature";
}
else if (builtin == GPU_BARYCENTRIC_TEXCO) {
return "unfbarycentrictex";
}
@@ -344,6 +332,11 @@ static int codegen_process_uniforms_functions(GPUMaterial *material,
}
}
/* Volume Grids */
for (GPUMaterialVolumeGrid *grid = graph->volume_grids.first; grid; grid = grid->next) {
BLI_dynstr_appendf(ds, "uniform sampler3D %s;\n", grid->sampler_name);
}
/* Print other uniforms */
for (node = graph->nodes.first; node; node = node->next) {
for (input = node->inputs.first; input; input = input->next) {
@@ -353,13 +346,7 @@ static int codegen_process_uniforms_functions(GPUMaterial *material,
builtins |= input->builtin;
name = gpu_builtin_name(input->builtin);
if (BLI_str_startswith(name, "samp")) {
if ((input->builtin == GPU_VOLUME_DENSITY) || (input->builtin == GPU_VOLUME_COLOR) ||
(input->builtin == GPU_VOLUME_FLAME)) {
BLI_dynstr_appendf(ds, "uniform sampler3D %s;\n", name);
}
}
else if (BLI_str_startswith(name, "unf")) {
if (BLI_str_startswith(name, "unf")) {
BLI_dynstr_appendf(ds, "uniform %s %s;\n", gpu_data_type_to_string(input->type), name);
}
else {
@@ -442,6 +429,9 @@ static void codegen_call_functions(DynStr *ds, GPUNodeGraph *graph, GPUOutput *f
else if (input->source == GPU_SOURCE_TEX_TILED_MAPPING) {
BLI_dynstr_append(ds, input->texture->tiled_mapping_name);
}
else if (input->source == GPU_SOURCE_VOLUME_GRID) {
BLI_dynstr_append(ds, input->volume_grid->sampler_name);
}
else if (input->source == GPU_SOURCE_OUTPUT) {
codegen_convert_datatype(
ds, input->link->output->type, input->type, "tmp", input->link->output->id);

View File

@@ -70,6 +70,7 @@ struct GPUMaterial {
const void *engine_type; /* attached engine type */
int options; /* to identify shader variations (shadow, probe, world background...) */
bool is_volume_shader; /* is volumetric shader */
/* Nodes */
GPUNodeGraph graph;
@@ -80,7 +81,8 @@ struct GPUMaterial {
/* XXX: Should be in Material. But it depends on the output node
* used and since the output selection is different for GPUMaterial...
*/
int domain;
bool has_volume_output;
bool has_surface_output;
/* Only used by Eevee to know which bsdf are used. */
int flag;
@@ -109,8 +111,8 @@ struct GPUMaterial {
};
enum {
GPU_DOMAIN_SURFACE = (1 << 0),
GPU_DOMAIN_VOLUME = (1 << 1),
GPU_USE_SURFACE_OUTPUT = (1 << 0),
GPU_USE_VOLUME_OUTPUT = (1 << 1),
};
/* Functions */
@@ -567,6 +569,11 @@ ListBase GPU_material_textures(GPUMaterial *material)
return material->graph.textures;
}
ListBase GPU_material_volume_grids(GPUMaterial *material)
{
return material->graph.volume_grids;
}
void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link)
{
if (!material->graph.outlink) {
@@ -592,14 +599,19 @@ eGPUMaterialStatus GPU_material_status(GPUMaterial *mat)
/* Code generation */
bool GPU_material_use_domain_surface(GPUMaterial *mat)
bool GPU_material_has_surface_output(GPUMaterial *mat)
{
return (mat->domain & GPU_DOMAIN_SURFACE);
return mat->has_surface_output;
}
bool GPU_material_use_domain_volume(GPUMaterial *mat)
bool GPU_material_has_volume_output(GPUMaterial *mat)
{
return (mat->domain & GPU_DOMAIN_VOLUME);
return mat->has_volume_output;
}
bool GPU_material_is_volume_shader(GPUMaterial *mat)
{
return mat->is_volume_shader;
}
void GPU_material_flag_set(GPUMaterial *mat, eGPUMatFlag flag)
@@ -636,7 +648,8 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene,
struct bNodeTree *ntree,
ListBase *gpumaterials,
const void *engine_type,
int options,
const int options,
const bool is_volume_shader,
const char *vert_code,
const char *geom_code,
const char *frag_lib,
@@ -655,6 +668,7 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene,
mat->scene = scene;
mat->engine_type = engine_type;
mat->options = options;
mat->is_volume_shader = is_volume_shader;
#ifndef NDEBUG
BLI_snprintf(mat->name, sizeof(mat->name), "%s", name);
#else
@@ -670,8 +684,8 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene,
gpu_material_ramp_texture_build(mat);
SET_FLAG_FROM_TEST(mat->domain, has_surface_output, GPU_DOMAIN_SURFACE);
SET_FLAG_FROM_TEST(mat->domain, has_volume_output, GPU_DOMAIN_VOLUME);
mat->has_surface_output = has_surface_output;
mat->has_volume_output = has_volume_output;
if (mat->graph.outlink) {
/* HACK: this is only for eevee. We add the define here after the nodetree evaluation. */

View File

@@ -119,6 +119,10 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const eGPUType
input->source = GPU_SOURCE_TEX_TILED_MAPPING;
input->texture = link->texture;
break;
case GPU_NODE_LINK_VOLUME_GRID:
input->source = GPU_SOURCE_VOLUME_GRID;
input->volume_grid = link->volume_grid;
break;
case GPU_NODE_LINK_ATTR:
input->source = GPU_SOURCE_ATTR;
input->attr = link->attr;
@@ -321,6 +325,31 @@ static GPUMaterialTexture *gpu_node_graph_add_texture(GPUNodeGraph *graph,
return tex;
}
static GPUMaterialVolumeGrid *gpu_node_graph_add_volume_grid(GPUNodeGraph *graph, const char *name)
{
/* Find existing volume grid. */
int num_grids = 0;
GPUMaterialVolumeGrid *grid = graph->volume_grids.first;
for (; grid; grid = grid->next) {
if (STREQ(grid->name, name)) {
break;
}
num_grids++;
}
/* Add new requested volume grid. */
if (grid == NULL) {
grid = MEM_callocN(sizeof(*grid), __func__);
grid->name = BLI_strdup(name);
BLI_snprintf(grid->sampler_name, sizeof(grid->sampler_name), "vsamp%d", num_grids);
BLI_addtail(&graph->volume_grids, grid);
}
grid->users++;
return grid;
}
/* Creating Inputs */
GPUNodeLink *GPU_attribute(GPUMaterial *mat, const CustomDataType type, const char *name)
@@ -394,6 +423,30 @@ GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *ro
return link;
}
GPUNodeLink *GPU_volume_grid(GPUMaterial *mat, const char *name)
{
/* NOTE: this could be optimized by automatically merging duplicate
* lookups of the same attribute. */
GPUNodeGraph *graph = gpu_material_node_graph(mat);
GPUNodeLink *link = gpu_node_link_create();
link->link_type = GPU_NODE_LINK_VOLUME_GRID;
link->volume_grid = gpu_node_graph_add_volume_grid(graph, name);
/* Two special cases, where we adjust the output values of smoke grids to
* bring the into standard range without having to modify the grid values. */
if (strcmp(name, "color") == 0) {
GPU_link(mat, "node_attribute_volume_color", link, &link);
}
else if (strcmp(name, "temperature") == 0) {
GPU_link(mat, "node_attribute_volume_temperature", link, &link);
}
else {
GPU_link(mat, "node_attribute_volume", link, &link);
}
return link;
}
GPUNodeLink *GPU_builtin(eGPUBuiltin builtin)
{
GPUNodeLink *link = gpu_node_link_create();
@@ -537,6 +590,9 @@ static void gpu_inputs_free(ListBase *inputs)
else if (ELEM(input->source, GPU_SOURCE_TEX, GPU_SOURCE_TEX_TILED_MAPPING)) {
input->texture->users--;
}
else if (ELEM(input->source, GPU_SOURCE_VOLUME_GRID)) {
input->volume_grid->users--;
}
if (input->link) {
gpu_node_link_free(input->link);
@@ -579,6 +635,11 @@ void gpu_node_graph_free_nodes(GPUNodeGraph *graph)
void gpu_node_graph_free(GPUNodeGraph *graph)
{
gpu_node_graph_free_nodes(graph);
for (GPUMaterialVolumeGrid *grid = graph->volume_grids.first; grid; grid = grid->next) {
MEM_SAFE_FREE(grid->name);
}
BLI_freelistN(&graph->volume_grids);
BLI_freelistN(&graph->textures);
BLI_freelistN(&graph->attributes);
}
@@ -637,4 +698,12 @@ void gpu_node_graph_prune_unused(GPUNodeGraph *graph)
BLI_freelinkN(&graph->textures, tex);
}
}
for (GPUMaterialVolumeGrid *grid = graph->volume_grids.first, *next = NULL; grid; grid = next) {
next = grid->next;
if (grid->users == 0) {
MEM_SAFE_FREE(grid->name);
BLI_freelinkN(&graph->volume_grids, grid);
}
}
}

View File

@@ -48,6 +48,8 @@ typedef enum eGPUDataSource {
GPU_SOURCE_STRUCT,
GPU_SOURCE_TEX,
GPU_SOURCE_TEX_TILED_MAPPING,
GPU_SOURCE_VOLUME_GRID,
GPU_SOURCE_VOLUME_GRID_TRANSFORM,
} eGPUDataSource;
typedef enum {
@@ -59,6 +61,7 @@ typedef enum {
GPU_NODE_LINK_IMAGE,
GPU_NODE_LINK_IMAGE_TILED,
GPU_NODE_LINK_IMAGE_TILED_MAPPING,
GPU_NODE_LINK_VOLUME_GRID,
GPU_NODE_LINK_OUTPUT,
GPU_NODE_LINK_UNIFORM,
} GPUNodeLinkType;
@@ -88,6 +91,8 @@ struct GPUNodeLink {
eGPUBuiltin builtin;
/* GPU_NODE_LINK_COLORBAND */
struct GPUTexture **colorband;
/* GPU_NODE_LINK_VOLUME_GRID */
struct GPUMaterialVolumeGrid *volume_grid;
/* GPU_NODE_LINK_OUTPUT */
struct GPUOutput *output;
/* GPU_NODE_LINK_ATTR */
@@ -126,6 +131,8 @@ typedef struct GPUInput {
struct GPUMaterialTexture *texture;
/* GPU_SOURCE_ATTR */
struct GPUMaterialAttribute *attr;
/* GPU_SOURCE_VOLUME_GRID */
struct GPUMaterialVolumeGrid *volume_grid;
};
} GPUInput;
@@ -139,6 +146,7 @@ typedef struct GPUNodeGraph {
/* Requested attributes and textures. */
ListBase attributes;
ListBase textures;
ListBase volume_grids;
} GPUNodeGraph;
/* Node Graph */

View File

@@ -1,18 +1,21 @@
void node_attribute_volume_density(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf)
/* Uniforms to convert smoke grid values into standard range. */
uniform vec3 volumeColor = vec3(1.0);
uniform vec2 volumeTemperature = vec2(0.0);
/* Generic volume attribute. */
void node_attribute_volume(sampler3D tex, out vec3 outvec)
{
#if defined(MESH_SHADER) && defined(VOLUMETRICS)
vec3 cos = volumeObjectLocalCoord;
#else
vec3 cos = vec3(0.0);
#endif
outf = texture(tex, cos).r;
outvec = vec3(outf, outf, outf);
outcol = vec4(outf, outf, outf, 1.0);
outvec = texture(tex, cos).rgb;
}
uniform vec3 volumeColor = vec3(1.0);
void node_attribute_volume_color(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf)
/* Special color attribute for smoke. */
void node_attribute_volume_color(sampler3D tex, out vec3 outvec)
{
#if defined(MESH_SHADER) && defined(VOLUMETRICS)
vec3 cos = volumeObjectLocalCoord;
@@ -20,70 +23,31 @@ void node_attribute_volume_color(sampler3D tex, out vec4 outcol, out vec3 outvec
vec3 cos = vec3(0.0);
#endif
vec4 value = texture(tex, cos).rgba;
/* Density is premultiplied for interpolation, divide it out here. */
vec4 value = texture(tex, cos).rgba;
if (value.a > 1e-8) {
value.rgb /= value.a;
}
outvec = value.rgb * volumeColor;
outcol = vec4(outvec, 1.0);
outf = avg(outvec);
}
void node_attribute_volume_flame(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf)
/* Special temperature attribute for smoke. */
void node_attribute_volume_temperature(sampler3D tex, out float outf)
{
#if defined(MESH_SHADER) && defined(VOLUMETRICS)
vec3 cos = volumeObjectLocalCoord;
#else
vec3 cos = vec3(0.0);
#endif
outf = texture(tex, cos).r;
outvec = vec3(outf, outf, outf);
outcol = vec4(outf, outf, outf, 1.0);
}
void node_attribute_volume_temperature(
sampler3D tex, vec2 temperature, out vec4 outcol, out vec3 outvec, out float outf)
{
#if defined(MESH_SHADER) && defined(VOLUMETRICS)
vec3 cos = volumeObjectLocalCoord;
#else
vec3 cos = vec3(0.0);
#endif
float flame = texture(tex, cos).r;
outf = (flame > 0.01) ? temperature.x + flame * (temperature.y - temperature.x) : 0.0;
outvec = vec3(outf, outf, outf);
outcol = vec4(outf, outf, outf, 1.0);
}
void node_volume_info(sampler3D densitySampler,
sampler3D colorSampler,
sampler3D flameSampler,
vec2 temperature,
out vec4 outColor,
out float outDensity,
out float outFlame,
out float outTemprature)
{
#if defined(MESH_SHADER) && defined(VOLUMETRICS)
vec3 p = volumeObjectLocalCoord;
#else
vec3 p = vec3(0.0);
#endif
outDensity = texture(densitySampler, p).r;
/* Color is premultiplied for interpolation, divide it out here. */
vec4 color = texture(colorSampler, p);
if (color.a > 1e-8) {
color.rgb /= color.a;
float value = texture(tex, cos).r;
if (volumeTemperature.x < volumeTemperature.y) {
outf = (value > 0.01) ?
volumeTemperature.x + value * (volumeTemperature.y - volumeTemperature.x) :
0.0;
}
else {
outf = value;
}
outColor = vec4(color.rgb * volumeColor, 1.0);
float flame = texture(flameSampler, p).r;
outFlame = flame;
outTemprature = (flame > 0.01) ? temperature.x + flame * (temperature.y - temperature.x) : 0.0;
}

View File

@@ -42,28 +42,18 @@ static int node_shader_gpu_attribute(GPUMaterial *mat,
{
NodeShaderAttribute *attr = node->storage;
/* FIXME : if an attribute layer (like vertex color) has one of these names,
* it will not work as expected. */
if (strcmp(attr->name, "density") == 0) {
return GPU_stack_link(
mat, node, "node_attribute_volume_density", in, out, GPU_builtin(GPU_VOLUME_DENSITY));
}
else if (strcmp(attr->name, "color") == 0) {
return GPU_stack_link(
mat, node, "node_attribute_volume_color", in, out, GPU_builtin(GPU_VOLUME_COLOR));
}
else if (strcmp(attr->name, "flame") == 0) {
return GPU_stack_link(
mat, node, "node_attribute_volume_flame", in, out, GPU_builtin(GPU_VOLUME_FLAME));
}
else if (strcmp(attr->name, "temperature") == 0) {
return GPU_stack_link(mat,
node,
"node_attribute_volume_temperature",
in,
out,
GPU_builtin(GPU_VOLUME_FLAME),
GPU_builtin(GPU_VOLUME_TEMPERATURE));
if (GPU_material_is_volume_shader(mat)) {
if (out[0].hasoutput) {
out[0].link = GPU_volume_grid(mat, attr->name);
}
if (out[1].hasoutput) {
out[1].link = GPU_volume_grid(mat, attr->name);
}
if (out[2].hasoutput) {
out[2].link = GPU_volume_grid(mat, attr->name);
}
return 1;
}
else {
GPUNodeLink *cd_attr = GPU_attribute(mat, CD_AUTO_FROM_NAME, attr->name);

View File

@@ -28,21 +28,25 @@ static bNodeSocketTemplate sh_node_volume_info_out[] = {
};
static int node_shader_gpu_volume_info(GPUMaterial *mat,
bNode *node,
bNode *UNUSED(node),
bNodeExecData *UNUSED(execdata),
GPUNodeStack *in,
GPUNodeStack *UNUSED(in),
GPUNodeStack *out)
{
if (out[0].hasoutput) {
out[0].link = GPU_volume_grid(mat, "color");
}
if (out[1].hasoutput) {
out[1].link = GPU_volume_grid(mat, "density");
}
if (out[2].hasoutput) {
out[2].link = GPU_volume_grid(mat, "flame");
}
if (out[3].hasoutput) {
out[3].link = GPU_volume_grid(mat, "temperature");
}
return GPU_stack_link(mat,
node,
"node_volume_info",
in,
out,
GPU_builtin(GPU_VOLUME_DENSITY),
GPU_builtin(GPU_VOLUME_COLOR),
GPU_builtin(GPU_VOLUME_FLAME),
GPU_builtin(GPU_VOLUME_TEMPERATURE));
return true;
}
void register_node_type_sh_volume_info(void)

View File

@@ -54,42 +54,6 @@ static void node_shader_init_volume_principled(bNodeTree *UNUSED(ntree), bNode *
}
}
static void node_shader_gpu_volume_attribute(GPUMaterial *mat,
const char *name,
GPUNodeLink **outcol,
GPUNodeLink **outvec,
GPUNodeLink **outf)
{
if (strcmp(name, "density") == 0) {
GPU_link(mat,
"node_attribute_volume_density",
GPU_builtin(GPU_VOLUME_DENSITY),
outcol,
outvec,
outf);
}
else if (strcmp(name, "color") == 0) {
GPU_link(
mat, "node_attribute_volume_color", GPU_builtin(GPU_VOLUME_COLOR), outcol, outvec, outf);
}
else if (strcmp(name, "flame") == 0) {
GPU_link(
mat, "node_attribute_volume_flame", GPU_builtin(GPU_VOLUME_FLAME), outcol, outvec, outf);
}
else if (strcmp(name, "temperature") == 0) {
GPU_link(mat,
"node_attribute_volume_temperature",
GPU_builtin(GPU_VOLUME_FLAME),
GPU_builtin(GPU_VOLUME_TEMPERATURE),
outcol,
outvec,
outf);
}
else {
*outcol = *outvec = *outf = NULL;
}
}
static int node_shader_gpu_volume_principled(GPUMaterial *mat,
bNode *node,
bNodeExecData *UNUSED(execdata),
@@ -108,16 +72,19 @@ static int node_shader_gpu_volume_principled(GPUMaterial *mat,
}
bNodeSocketValueString *value = sock->default_value;
GPUNodeLink *outcol, *outvec, *outf;
const char *attribute_name = value->value;
if (attribute_name[0] == '\0') {
continue;
}
if (STREQ(sock->name, "Density Attribute")) {
node_shader_gpu_volume_attribute(mat, value->value, &outcol, &outvec, &density);
density = GPU_volume_grid(mat, attribute_name);
}
else if (STREQ(sock->name, "Color Attribute")) {
node_shader_gpu_volume_attribute(mat, value->value, &color, &outvec, &outf);
color = GPU_volume_grid(mat, attribute_name);
}
else if (use_blackbody && STREQ(sock->name, "Temperature Attribute")) {
node_shader_gpu_volume_attribute(mat, value->value, &outcol, &outvec, &temperature);
temperature = GPU_volume_grid(mat, attribute_name);
}
}