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:
authorBrecht Van Lommel <brecht>2020-03-11 16:58:19 +0300
committerBrecht Van Lommel <brecht@blender.org>2020-03-11 16:59:05 +0300
commitb9f6d033beecd75398be14419d37d8aab0609812 (patch)
treeb2385a92388dfb1d17a99a72dd442bc5bc38de85 /source/blender/gpu
parente1e772a80243f3c279fcd076c8311301e8885d41 (diff)
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
Diffstat (limited to 'source/blender/gpu')
-rw-r--r--source/blender/gpu/GPU_material.h29
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c28
-rw-r--r--source/blender/gpu/intern/gpu_material.c34
-rw-r--r--source/blender/gpu/intern/gpu_node_graph.c69
-rw-r--r--source/blender/gpu/intern/gpu_node_graph.h8
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_volume_info.glsl78
6 files changed, 149 insertions, 97 deletions
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index 7107748e62a..da00306bf9f 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -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
}
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index e8616c1e256..bcaa95c2f59 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -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);
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index b2658839d67..8a4a88d0663 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -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->has_surface_output;
+}
+
+bool GPU_material_has_volume_output(GPUMaterial *mat)
{
- return (mat->domain & GPU_DOMAIN_SURFACE);
+ return mat->has_volume_output;
}
-bool GPU_material_use_domain_volume(GPUMaterial *mat)
+bool GPU_material_is_volume_shader(GPUMaterial *mat)
{
- return (mat->domain & GPU_DOMAIN_VOLUME);
+ 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. */
diff --git a/source/blender/gpu/intern/gpu_node_graph.c b/source/blender/gpu/intern/gpu_node_graph.c
index de35b43109f..0d5cc46c0b9 100644
--- a/source/blender/gpu/intern/gpu_node_graph.c
+++ b/source/blender/gpu/intern/gpu_node_graph.c
@@ -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);
+ }
+ }
}
diff --git a/source/blender/gpu/intern/gpu_node_graph.h b/source/blender/gpu/intern/gpu_node_graph.h
index 9214bd7f1ba..ceaeea2bfa8 100644
--- a/source/blender/gpu/intern/gpu_node_graph.h
+++ b/source/blender/gpu/intern/gpu_node_graph.h
@@ -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 */
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
index 0fecb5bd1f9..a80cd3cb329 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_volume_info.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_volume_info.glsl
@@ -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)
-{
-#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)
+/* 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
- 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;
}