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:
committed by
Brecht Van Lommel
parent
e1e772a802
commit
b9f6d033be
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user