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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2017-07-03 22:39:52 +0300
committerClément Foucault <foucault.clem@gmail.com>2017-07-03 23:08:33 +0300
commit2eef097831caf14634cc0fc6749b857096baf3da (patch)
tree95496ea9adf3ae5b9f7e62f09d00f913769c30d4 /source/blender/gpu
parent65b01014b99ce7c6de67046ed7b8ae244fdb51c3 (diff)
GPU Codegen: Add new closure socket type.
This allow specialized shaders to redefine the closure interface to fit their needs. For instance, Volumetric closure needs to pass more than one vec4 (absorption vec3, scattering vec3, anisotropy float).
Diffstat (limited to 'source/blender/gpu')
-rw-r--r--source/blender/gpu/GPU_material.h2
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c41
-rw-r--r--source/blender/gpu/intern/gpu_material.c2
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl120
4 files changed, 112 insertions, 53 deletions
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index b12a59f607d..ec50bd9d9f5 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -76,6 +76,8 @@ typedef enum GPUType {
GPU_MAT3 = 9,
GPU_MAT4 = 16,
+ GPU_CLOSURE = 17,
+
GPU_TEX2D = 1002,
GPU_SHADOW2D = 1003,
GPU_TEXCUBE = 1004,
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 87fbccc0c87..cd367c821ba 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -86,9 +86,10 @@ typedef struct GPUFunction {
} GPUFunction;
/* Indices match the GPUType enum */
-static const char *GPU_DATATYPE_STR[17] = {
+static const char *GPU_DATATYPE_STR[18] = {
"", "float", "vec2", "vec3", "vec4",
NULL, NULL, NULL, NULL, "mat3", NULL, NULL, NULL, NULL, NULL, NULL, "mat4",
+ "Closure"
};
/* GLSL code parsing for finding function definitions.
@@ -172,7 +173,7 @@ static void gpu_parse_functions_string(GHash *hash, char *code)
/* test for type */
type = GPU_NONE;
- for (i = 1; i <= 16; i++) {
+ for (i = 1; i <= 17; i++) {
if (GPU_DATATYPE_STR[i] && gpu_str_prefix(code, GPU_DATATYPE_STR[i])) {
type = i;
break;
@@ -350,6 +351,8 @@ static void codegen_convert_datatype(DynStr *ds, int from, int to, const char *t
BLI_dynstr_appendf(ds, "vec4(%s.r, %s.r, %s.r, %s.g)", name, name, name, name);
else if (from == GPU_FLOAT)
BLI_dynstr_appendf(ds, "vec4(%s, %s, %s, 1.0)", name, name, name);
+ else /* can happen with closure */
+ BLI_dynstr_append(ds, name);
}
}
@@ -357,6 +360,11 @@ static void codegen_print_datatype(DynStr *ds, const GPUType type, float *data)
{
int i;
+ if (type == GPU_CLOSURE) {
+ BLI_dynstr_append(ds, "CLOSURE_DEFAULT");
+ return;
+ }
+
BLI_dynstr_appendf(ds, "%s(", GPU_DATATYPE_STR[type]);
for (i = 0; i < type; i++) {
@@ -543,9 +551,16 @@ static int codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes)
GPU_DATATYPE_STR[input->type], input->id);
}
else {
- /* for others use const so the compiler can do folding */
- BLI_dynstr_appendf(ds, "const %s cons%d = ",
- GPU_DATATYPE_STR[input->type], input->id);
+ if (input->type != GPU_CLOSURE) {
+ /* for others use const so the compiler can do folding */
+ BLI_dynstr_appendf(ds, "const %s cons%d = ",
+ GPU_DATATYPE_STR[input->type], input->id);
+ }
+ else {
+ /* const keyword does not work with struct */
+ BLI_dynstr_appendf(ds, "%s cons%d = ",
+ GPU_DATATYPE_STR[input->type], input->id);
+ }
codegen_print_datatype(ds, input->type, input->vec);
BLI_dynstr_append(ds, ";\n");
}
@@ -667,8 +682,7 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final
BLI_dynstr_append(ds, ");\n");
}
- BLI_dynstr_append(ds, "\n\tfragColor = ");
- codegen_convert_datatype(ds, finaloutput->type, GPU_VEC4, "tmp", finaloutput->id);
+ BLI_dynstr_appendf(ds, "\n\treturn tmp%d", finaloutput->id);
BLI_dynstr_append(ds, ";\n");
}
@@ -696,7 +710,7 @@ static char *code_generate_fragment(ListBase *nodes, GPUOutput *output, bool use
BLI_dynstr_appendf(ds, "/* %s */\n", name);
#endif
- BLI_dynstr_append(ds, "void main()\n{\n");
+ BLI_dynstr_append(ds, "Closure nodetree_exec(void)\n{\n");
if (use_new_shading) {
if (builtins & GPU_VIEW_MATRIX)
@@ -764,6 +778,17 @@ static char *code_generate_fragment(ListBase *nodes, GPUOutput *output, bool use
BLI_dynstr_append(ds, "}\n");
+ /* XXX This cannot go into gpu_shader_material.glsl because main() would be parsed and generate error */
+ /* Old glsl mode compat. */
+ BLI_dynstr_append(ds, "#ifndef NODETREE_EXEC\n");
+ BLI_dynstr_append(ds, "out vec4 fragColor;\n");
+ BLI_dynstr_append(ds, "void main()\n");
+ BLI_dynstr_append(ds, "{\n");
+ BLI_dynstr_append(ds, "\tClosure cl = nodetree_exec();\n");
+ BLI_dynstr_append(ds, "\tfragColor = vec4(cl.radiance, cl.opacity);\n");
+ BLI_dynstr_append(ds, "}\n");
+ BLI_dynstr_append(ds, "#endif\n\n");
+
/* create shader */
code = BLI_dynstr_get_cstring(ds);
BLI_dynstr_free(ds);
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index dafd305e8ba..40d1acfabd1 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -2366,6 +2366,7 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma)
case GPU_VEC4:
case GPU_MAT3:
case GPU_MAT4:
+ case GPU_CLOSURE:
case GPU_ATTRIB:
break;
}
@@ -2394,6 +2395,7 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma)
break;
case GPU_NONE:
+ case GPU_CLOSURE:
case GPU_TEX2D:
case GPU_TEXCUBE:
case GPU_SHADOW2D:
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index 1f9ab45e556..afe862bb70f 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -12,7 +12,37 @@ uniform mat4 ProjectionMatrixInverse;
uniform mat3 NormalMatrix;
uniform vec4 CameraTexCoFactors;
-out vec4 fragColor;
+/* Old glsl mode compat. */
+
+#ifndef NODETREE_EXEC
+
+struct Closure {
+ vec3 radiance;
+ float opacity;
+};
+
+#define CLOSURE_DEFAULT Closure(vec3(0.0), 0.0);
+
+Closure closure_mix(Closure cl1, Closure cl2, float fac)
+{
+ Closure cl;
+ cl.radiance = mix(cl1.radiance, cl2.radiance, fac);
+ cl.opacity = mix(cl1.opacity, cl2.opacity, fac);
+ return cl;
+}
+
+Closure closure_add(Closure cl1, Closure cl2)
+{
+ Closure cl;
+ cl.radiance = cl1.radiance + cl2.radiance;
+ cl.opacity = cl1.opacity + cl2.opacity;
+ return cl;
+}
+
+Closure nodetree_exec(void); /* Prototype */
+
+#endif /* NODETREE_EXEC */
+
/* Converters */
@@ -2625,7 +2655,7 @@ layout(std140) uniform lightSource {
/* bsdfs */
-void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out vec4 result)
+void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out Closure result)
{
/* ambient light */
vec3 L = vec3(0.2);
@@ -2639,10 +2669,10 @@ void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out vec4 result)
L += light_diffuse * bsdf;
}
- result = vec4(L * color.rgb, 1.0);
+ result = Closure(L * color.rgb, 1.0);
}
-void node_bsdf_glossy(vec4 color, float roughness, vec3 N, out vec4 result)
+void node_bsdf_glossy(vec4 color, float roughness, vec3 N, out Closure result)
{
/* ambient light */
vec3 L = vec3(0.2);
@@ -2660,29 +2690,29 @@ void node_bsdf_glossy(vec4 color, float roughness, vec3 N, out vec4 result)
L += light_specular * bsdf;
}
- result = vec4(L * color.rgb, 1.0);
+ result = Closure(L * color.rgb, 1.0);
}
void node_bsdf_anisotropic(
vec4 color, float roughness, float anisotropy, float rotation, vec3 N, vec3 T,
- out vec4 result)
+ out Closure result)
{
node_bsdf_diffuse(color, 0.0, N, result);
}
-void node_bsdf_glass(vec4 color, float roughness, float ior, vec3 N, out vec4 result)
+void node_bsdf_glass(vec4 color, float roughness, float ior, vec3 N, out Closure result)
{
node_bsdf_diffuse(color, 0.0, N, result);
}
-void node_bsdf_toon(vec4 color, float size, float tsmooth, vec3 N, out vec4 result)
+void node_bsdf_toon(vec4 color, float size, float tsmooth, vec3 N, out Closure result)
{
node_bsdf_diffuse(color, 0.0, N, result);
}
void node_bsdf_principled(vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, float metallic, float specular,
float specular_tint, float roughness, float anisotropic, float anisotropic_rotation, float sheen, float sheen_tint, float clearcoat,
- float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, out vec4 result)
+ float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, out Closure result)
{
vec3 X, Y;
float ax, ay;
@@ -2775,18 +2805,18 @@ void node_bsdf_principled(vec4 base_color, float subsurface, vec3 subsurface_rad
L += diffuse_and_specular_bsdf + clearcoat_bsdf;
}
- result = vec4(L, 1.0);
+ result = Closure(L, 1.0);
}
void node_bsdf_principled_simple(vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, float metallic, float specular,
float specular_tint, float roughness, float anisotropic, float anisotropic_rotation, float sheen, float sheen_tint, float clearcoat,
- float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, out vec4 result)
+ float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, out Closure result)
{
#ifdef EEVEE_ENGINE
vec3 diffuse, f0;
convert_metallic_to_specular_tinted(base_color.rgb, metallic, specular, specular_tint, diffuse, f0);
- result = vec4(eevee_surface_lit(N, diffuse, f0, roughness, 1.0), 1.0);
+ result = Closure(eevee_surface_lit(N, diffuse, f0, roughness, 1.0), 1.0);
#else
node_bsdf_principled(base_color, subsurface, subsurface_radius, subsurface_color, metallic, specular,
specular_tint, roughness, anisotropic, anisotropic_rotation, sheen, sheen_tint, clearcoat,
@@ -2796,7 +2826,7 @@ void node_bsdf_principled_simple(vec4 base_color, float subsurface, vec3 subsurf
void node_bsdf_principled_clearcoat(vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, float metallic, float specular,
float specular_tint, float roughness, float anisotropic, float anisotropic_rotation, float sheen, float sheen_tint, float clearcoat,
- float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, out vec4 result)
+ float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, out Closure result)
{
#ifdef EEVEE_ENGINE
vec3 diffuse, f0;
@@ -2825,9 +2855,9 @@ void node_bsdf_principled_clearcoat(vec4 base_color, float subsurface, vec3 subs
surface_color.a += 1.0;
}
}
- result = vec4(surface_color.rgb / surface_color.a, 1.0);
+ result = Closure(surface_color.rgb / surface_color.a, 1.0);
#else
- result = vec4(eevee_surface_clearcoat_lit(N, diffuse, f0, roughness, CN, clearcoat, clearcoat_roughness, 1.0), 1.0);
+ result = Closure(eevee_surface_clearcoat_lit(N, diffuse, f0, roughness, CN, clearcoat, clearcoat_roughness, 1.0), 1.0);
#endif
#else
@@ -2837,52 +2867,51 @@ void node_bsdf_principled_clearcoat(vec4 base_color, float subsurface, vec3 subs
#endif
}
-void node_bsdf_translucent(vec4 color, vec3 N, out vec4 result)
+void node_bsdf_translucent(vec4 color, vec3 N, out Closure result)
{
node_bsdf_diffuse(color, 0.0, N, result);
}
-void node_bsdf_transparent(vec4 color, out vec4 result)
+void node_bsdf_transparent(vec4 color, out Closure result)
{
/* this isn't right */
- result.r = color.r;
- result.g = color.g;
- result.b = color.b;
- result.a = 0.0;
+ result.radiance = color.rgb;
+ result.opacity = 0.0;
}
-void node_bsdf_velvet(vec4 color, float sigma, vec3 N, out vec4 result)
+void node_bsdf_velvet(vec4 color, float sigma, vec3 N, out Closure result)
{
node_bsdf_diffuse(color, 0.0, N, result);
}
void node_subsurface_scattering(
vec4 color, float scale, vec3 radius, float sharpen, float texture_blur, vec3 N,
- out vec4 result)
+ out Closure result)
{
node_bsdf_diffuse(color, 0.0, N, result);
}
-void node_bsdf_hair(vec4 color, float offset, float roughnessu, float roughnessv, vec3 tangent, out vec4 result)
+void node_bsdf_hair(vec4 color, float offset, float roughnessu, float roughnessv, vec3 tangent, out Closure result)
{
- result = color;
+ result = Closure(color.rgb, color.a);
}
-void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out vec4 result)
+void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out Closure result)
{
node_bsdf_diffuse(color, 0.0, N, result);
}
-void node_ambient_occlusion(vec4 color, out vec4 result)
+void node_ambient_occlusion(vec4 color, out Closure result)
{
- result = color;
+ result = Closure(color.rgb, color.a);
}
/* emission */
-void node_emission(vec4 color, float strength, vec3 N, out vec4 result)
+void node_emission(vec4 color, float strength, vec3 N, out Closure result)
{
- result = color * strength;
+ color *= strength;
+ result = Closure(color.rgb, color.a);
}
/* background */
@@ -2900,21 +2929,22 @@ void background_transform_to_world(vec3 viewvec, out vec3 worldvec)
#endif
}
-void node_background(vec4 color, float strength, out vec4 result)
+void node_background(vec4 color, float strength, out Closure result)
{
- result = color * strength;
+ color *= strength;
+ result = Closure(color.rgb, color.a);
}
/* closures */
-void node_mix_shader(float fac, vec4 shader1, vec4 shader2, out vec4 shader)
+void node_mix_shader(float fac, Closure shader1, Closure shader2, out Closure shader)
{
- shader = mix(shader1, shader2, fac);
+ shader = closure_mix(shader1, shader2, fac);
}
-void node_add_shader(vec4 shader1, vec4 shader2, out vec4 shader)
+void node_add_shader(Closure shader1, Closure shader2, out Closure shader)
{
- shader = shader1 + shader2;
+ shader = closure_add(shader1, shader2);
}
/* fresnel */
@@ -3908,16 +3938,16 @@ void node_bump(float strength, float dist, float height, vec3 N, vec3 surf_pos,
/* output */
-void node_output_material(vec4 surface, vec4 volume, float displacement, out vec4 result)
+void node_output_material(Closure surface, Closure volume, float displacement, out Closure result)
{
result = surface;
}
uniform float backgroundAlpha;
-void node_output_world(vec4 surface, vec4 volume, out vec4 result)
+void node_output_world(Closure surface, Closure volume, out Closure result)
{
- result = vec4(surface.rgb, backgroundAlpha);
+ result = Closure(surface.radiance, backgroundAlpha);
}
/* TODO : clean this ifdef mess */
@@ -3931,25 +3961,25 @@ void world_normals_get(out vec3 N)
void node_eevee_metallic(
vec4 basecol, float metallic, float specular, float roughness, vec4 emissive, float transp, vec3 normal,
float clearcoat, float clearcoat_roughness, vec3 clearcoat_normal,
- float occlusion, out vec4 result)
+ float occlusion, out Closure result)
{
vec3 diffuse, f0;
convert_metallic_to_specular(basecol.rgb, metallic, specular, diffuse, f0);
- result = vec4(eevee_surface_lit(normal, diffuse, f0, roughness, occlusion) + emissive.rgb, 1.0 - transp);
+ result = Closure(eevee_surface_lit(normal, diffuse, f0, roughness, occlusion) + emissive.rgb, 1.0 - transp);
}
void node_eevee_specular(
vec4 diffuse, vec4 specular, float roughness, vec4 emissive, float transp, vec3 normal,
float clearcoat, float clearcoat_roughness, vec3 clearcoat_normal,
- float occlusion, out vec4 result)
+ float occlusion, out Closure result)
{
- result = vec4(eevee_surface_lit(normal, diffuse.rgb, specular.rgb, roughness, occlusion) + emissive.rgb, 1.0 - transp);
+ result = Closure(eevee_surface_lit(normal, diffuse.rgb, specular.rgb, roughness, occlusion) + emissive.rgb, 1.0 - transp);
}
-void node_output_eevee_material(vec4 surface, out vec4 result)
+void node_output_eevee_material(Closure surface, out Closure result)
{
- result = vec4(surface.rgb, length(viewPosition));
+ result = Closure(surface.radiance, length(viewPosition));
}
#endif