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
path: root/source
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2020-02-27 19:58:14 +0300
committerClément Foucault <foucault.clem@gmail.com>2020-02-28 04:38:47 +0300
commit1545c37cdb7e8ca485cb9defcca0352a9b8ee3b3 (patch)
tree16ee034ea317259a798843fe5043c2a67822af4a /source
parent616545b5cfaae77058173f42ee45e3e84047054f (diff)
Workbench: Refactor: Code reorganization
Diffstat (limited to 'source')
-rw-r--r--source/blender/draw/CMakeLists.txt6
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl103
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl31
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl6
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_image_lib.glsl94
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl92
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_prepass_hair_vert.glsl129
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl140
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl5
-rw-r--r--source/blender/draw/engines/workbench/workbench_data.c43
-rw-r--r--source/blender/draw/engines/workbench/workbench_effect_cavity.c78
-rw-r--r--source/blender/draw/engines/workbench/workbench_engine.c137
-rw-r--r--source/blender/draw/engines/workbench/workbench_opaque.c106
-rw-r--r--source/blender/draw/engines/workbench/workbench_private.h25
-rw-r--r--source/blender/draw/engines/workbench/workbench_shader.c174
-rw-r--r--source/blender/draw/engines/workbench/workbench_shadow.c25
-rw-r--r--source/blender/draw/engines/workbench/workbench_transparent.c26
-rw-r--r--source/blender/draw/intern/DRW_render.h2
-rw-r--r--source/blender/draw/intern/draw_manager.c33
-rw-r--r--source/blender/draw/intern/draw_manager_texture.c7
20 files changed, 960 insertions, 302 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 6d7b422c4fb..8538defa7f1 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -101,14 +101,19 @@ set(SRC
engines/workbench/workbench_data.c
engines/workbench/workbench_deferred.c
engines/workbench/workbench_effect_aa.c
+ engines/workbench/workbench_effect_cavity.c
engines/workbench/workbench_effect_dof.c
engines/workbench/workbench_effect_fxaa.c
engines/workbench/workbench_effect_taa.c
engines/workbench/workbench_engine.c
engines/workbench/workbench_forward.c
engines/workbench/workbench_materials.c
+ engines/workbench/workbench_opaque.c
engines/workbench/workbench_render.c
+ engines/workbench/workbench_shader.c
+ engines/workbench/workbench_shadow.c
engines/workbench/workbench_studiolight.c
+ engines/workbench/workbench_transparent.c
engines/workbench/workbench_volume.c
engines/external/external_engine.c
engines/gpencil/gpencil_cache_utils.c
@@ -246,6 +251,7 @@ data_to_c_simple(engines/eevee/shaders/volumetric_integration_frag.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_cavity_lib.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_cavity_frag.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_common_lib.glsl SRC)
+data_to_c_simple(engines/workbench/shaders/workbench_composite_frag.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_data_lib.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_deferred_composite_frag.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_deferred_background_frag.glsl SRC)
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl
index c0d7719180b..4af03d8b82e 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl
@@ -2,21 +2,13 @@
#define EPSILON 0.00001
#define M_PI 3.14159265358979323846
-#define CAVITY_BUFFER_RANGE 4.0
-
-/* 4x4 bayer matrix prepared for 8bit UNORM precision error. */
-#define P(x) (((x + 0.5) * (1.0 / 16.0) - 0.5) * (1.0 / 255.0))
-const vec4 dither_mat4x4[4] = vec4[4](vec4(P(0.0), P(8.0), P(2.0), P(10.0)),
- vec4(P(12.0), P(4.0), P(14.0), P(6.0)),
- vec4(P(3.0), P(11.0), P(1.0), P(9.0)),
- vec4(P(15.0), P(7.0), P(13.0), P(5.0)));
+#ifdef GPU_VERTEX_SHADER
+# define IN_OUT out
+#else
+# define IN_OUT in
+#endif
-float bayer_dither_noise()
-{
- ivec2 tx1 = ivec2(gl_FragCoord.xy) % 4;
- ivec2 tx2 = ivec2(gl_FragCoord.xy) % 2;
- return dither_mat4x4[tx1.x][tx1.y];
-}
+#define CAVITY_BUFFER_RANGE 4.0
#ifdef WORKBENCH_ENCODE_NORMALS
@@ -24,7 +16,7 @@ float bayer_dither_noise()
/* From http://aras-p.info/texts/CompactNormalStorage.html
* Using Method #4: Spheremap Transform */
-vec3 workbench_normal_decode(WB_Normal enc)
+vec3 workbench_normal_decode(vec4 enc)
{
vec2 fenc = enc.xy * 4.0 - 2.0;
float f = dot(fenc, fenc);
@@ -37,8 +29,9 @@ vec3 workbench_normal_decode(WB_Normal enc)
/* From http://aras-p.info/texts/CompactNormalStorage.html
* Using Method #4: Spheremap Transform */
-WB_Normal workbench_normal_encode(vec3 n)
+WB_Normal workbench_normal_encode(bool front_face, vec3 n)
{
+ n = normalize(front_face ? n : -n);
float p = sqrt(n.z * 8.0 + 8.0);
n.xy = clamp(n.xy / p + 0.5, 0.0, 1.0);
return n.xy;
@@ -47,8 +40,8 @@ WB_Normal workbench_normal_encode(vec3 n)
#else
# define WB_Normal vec3
/* Well just do nothing... */
-# define workbench_normal_encode(a) (a)
-# define workbench_normal_decode(a) (a)
+# define workbench_normal_encode(f, a) (a)
+# define workbench_normal_decode(a) (a.xyz)
#endif /* WORKBENCH_ENCODE_NORMALS */
/* Encoding into the alpha of a RGBA8 UNORM texture. */
@@ -122,8 +115,12 @@ float linear_zdepth(float depth, vec4 viewvecs[3], mat4 proj_mat)
vec3 view_vector_from_screen_uv(vec2 uv, vec4 viewvecs[3], mat4 proj_mat)
{
- return (proj_mat[3][3] == 0.0) ? normalize(viewvecs[0].xyz + vec3(uv, 0.0) * viewvecs[1].xyz) :
- vec3(0.0, 0.0, 1.0);
+ if (proj_mat[3][3] == 0.0) {
+ return normalize(viewvecs[0].xyz + vec3(uv, 0.0) * viewvecs[1].xyz);
+ }
+ else {
+ return vec3(0.0, 0.0, 1.0);
+ }
}
vec2 matcap_uv_compute(vec3 I, vec3 N, bool flipped)
@@ -139,69 +136,3 @@ vec2 matcap_uv_compute(vec3 I, vec3 N, bool flipped)
}
return matcap_uv * 0.496 + 0.5;
}
-
-bool node_tex_tile_lookup(inout vec3 co, sampler2DArray ima, sampler1DArray map)
-{
- vec2 tile_pos = floor(co.xy);
-
- if (tile_pos.x < 0 || tile_pos.y < 0 || tile_pos.x >= 10)
- return false;
-
- float tile = 10.0 * tile_pos.y + tile_pos.x;
- if (tile >= textureSize(map, 0).x)
- return false;
-
- /* Fetch tile information. */
- float tile_layer = texelFetch(map, ivec2(tile, 0), 0).x;
- if (tile_layer < 0.0)
- return false;
-
- vec4 tile_info = texelFetch(map, ivec2(tile, 1), 0);
-
- co = vec3(((co.xy - tile_pos) * tile_info.zw) + tile_info.xy, tile_layer);
- return true;
-}
-
-vec4 workbench_sample_texture(sampler2D image,
- vec2 coord,
- bool nearest_sampling,
- bool premultiplied)
-{
- vec2 tex_size = vec2(textureSize(image, 0).xy);
- /* TODO(fclem) We could do the same with sampler objects.
- * But this is a quick workaround instead of messing with the GPUTexture itself. */
- vec2 uv = nearest_sampling ? (floor(coord * tex_size) + 0.5) / tex_size : coord;
- vec4 color = texture(image, uv);
-
- /* Unpremultiply if stored multiplied, since straight alpha is expected by shaders. */
- if (premultiplied && !(color.a == 0.0 || color.a == 1.0)) {
- color.rgb = color.rgb / color.a;
- }
-
- return color;
-}
-
-vec4 workbench_sample_texture_array(sampler2DArray tile_array,
- sampler1DArray tile_data,
- vec2 coord,
- bool nearest_sampling,
- bool premultiplied)
-{
- vec2 tex_size = vec2(textureSize(tile_array, 0).xy);
-
- vec3 uv = vec3(coord, 0);
- if (!node_tex_tile_lookup(uv, tile_array, tile_data))
- return vec4(1.0, 0.0, 1.0, 1.0);
-
- /* TODO(fclem) We could do the same with sampler objects.
- * But this is a quick workaround instead of messing with the GPUTexture itself. */
- uv.xy = nearest_sampling ? (floor(uv.xy * tex_size) + 0.5) / tex_size : uv.xy;
- vec4 color = texture(tile_array, uv);
-
- /* Unpremultiply if stored multiplied, since straight alpha is expected by shaders. */
- if (premultiplied && !(color.a == 0.0 || color.a == 1.0)) {
- color.rgb = color.rgb / color.a;
- }
-
- return color;
-}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl
new file mode 100644
index 00000000000..effa0a8f4df
--- /dev/null
+++ b/source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl
@@ -0,0 +1,31 @@
+
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_common_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_world_light_lib.glsl)
+
+uniform sampler2D materialBuffer;
+uniform sampler2D normalBuffer;
+
+in vec4 uvcoordsvar;
+
+out vec4 fragColor;
+
+void main()
+{
+ vec3 normal = workbench_normal_decode(texture(normalBuffer, uvcoordsvar.st));
+ vec4 mat_data = texture(materialBuffer, uvcoordsvar.st);
+
+ vec3 I_vs = view_vector_from_screen_uv(uvcoordsvar.st, world_data.viewvecs, ProjectionMatrix);
+
+ vec3 base_color = mat_data.rgb;
+
+ float roughness, metallic;
+ workbench_float_pair_decode(mat_data.a, roughness, metallic);
+
+ vec3 specular_color = mix(vec3(0.05), base_color.rgb, metallic);
+ vec3 diffuse_color = mix(base_color.rgb, vec3(0.0), metallic);
+
+ fragColor.rgb = get_world_lighting(diffuse_color, specular_color, roughness, normal, I_vs);
+
+ fragColor.a = 1.0;
+}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl
index 0c984b094d3..008be393509 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl
@@ -5,6 +5,7 @@ struct LightData {
};
struct WorldData {
+ vec4 viewvecs[3];
vec4 object_outline_color;
vec4 shadow_direction_vs;
LightData lights[4];
@@ -14,3 +15,8 @@ struct WorldData {
float curvature_ridge;
float curvature_valley;
};
+
+layout(std140) uniform world_block
+{
+ WorldData world_data;
+};
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_image_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_image_lib.glsl
new file mode 100644
index 00000000000..f014804eecc
--- /dev/null
+++ b/source/blender/draw/engines/workbench/shaders/workbench_image_lib.glsl
@@ -0,0 +1,94 @@
+
+bool node_tex_tile_lookup(inout vec3 co, sampler2DArray ima, sampler1DArray map)
+{
+ vec2 tile_pos = floor(co.xy);
+
+ if (tile_pos.x < 0 || tile_pos.y < 0 || tile_pos.x >= 10)
+ return false;
+
+ float tile = 10.0 * tile_pos.y + tile_pos.x;
+ if (tile >= textureSize(map, 0).x)
+ return false;
+
+ /* Fetch tile information. */
+ float tile_layer = texelFetch(map, ivec2(tile, 0), 0).x;
+ if (tile_layer < 0.0)
+ return false;
+
+ vec4 tile_info = texelFetch(map, ivec2(tile, 1), 0);
+
+ co = vec3(((co.xy - tile_pos) * tile_info.zw) + tile_info.xy, tile_layer);
+ return true;
+}
+
+vec4 workbench_sample_texture(sampler2D image,
+ vec2 coord,
+ bool nearest_sampling,
+ bool premultiplied)
+{
+ vec2 tex_size = vec2(textureSize(image, 0).xy);
+ /* TODO(fclem) We could do the same with sampler objects.
+ * But this is a quick workaround instead of messing with the GPUTexture itself. */
+ vec2 uv = nearest_sampling ? (floor(coord * tex_size) + 0.5) / tex_size : coord;
+ vec4 color = texture(image, uv);
+
+ /* Unpremultiply if stored multiplied, since straight alpha is expected by shaders. */
+ if (premultiplied && !(color.a == 0.0 || color.a == 1.0)) {
+ color.rgb = color.rgb / color.a;
+ }
+
+ return color;
+}
+
+vec4 workbench_sample_texture_array(sampler2DArray tile_array,
+ sampler1DArray tile_data,
+ vec2 coord,
+ bool nearest_sampling,
+ bool premultiplied)
+{
+ vec2 tex_size = vec2(textureSize(tile_array, 0).xy);
+
+ vec3 uv = vec3(coord, 0);
+ if (!node_tex_tile_lookup(uv, tile_array, tile_data))
+ return vec4(1.0, 0.0, 1.0, 1.0);
+
+ /* TODO(fclem) We could do the same with sampler objects.
+ * But this is a quick workaround instead of messing with the GPUTexture itself. */
+ uv.xy = nearest_sampling ? (floor(uv.xy * tex_size) + 0.5) / tex_size : uv.xy;
+ vec4 color = texture(tile_array, uv);
+
+ /* Unpremultiply if stored multiplied, since straight alpha is expected by shaders. */
+ if (premultiplied && !(color.a == 0.0 || color.a == 1.0)) {
+ color.rgb = color.rgb / color.a;
+ }
+
+ return color;
+}
+
+uniform sampler2DArray image_tile_array;
+uniform sampler1DArray image_tile_data;
+uniform sampler2D image;
+
+uniform float imageTransparencyCutoff = 0.1;
+uniform bool imageNearest;
+uniform bool imagePremultiplied;
+
+vec3 workbench_image_color(vec2 uvs)
+{
+#if defined(V3D_SHADING_TEXTURE_COLOR)
+# ifdef TEXTURE_IMAGE_ARRAY
+ vec4 color = workbench_sample_texture_array(
+ image_tile_array, image_tile_data, uvs, imageNearest, imagePremultiplied);
+# else
+ vec4 color = workbench_sample_texture(image, uvs, imageNearest, imagePremultiplied);
+# endif
+
+ if (color.a < ImageTransparencyCutoff) {
+ discard;
+ }
+
+ return color.rgb;
+#else
+ return vec3(1.0);
+#endif
+}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl
index 94e41b4bcd4..e69de29bb2d 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl
@@ -1,92 +0,0 @@
-
-uniform vec4 materialColorAndMetal;
-uniform float materialRoughness;
-
-#ifdef TEXTURE_IMAGE_ARRAY
-uniform sampler2DArray image_tile_array;
-uniform sampler1DArray image_tile_data;
-#else
-uniform sampler2D image;
-#endif
-uniform float ImageTransparencyCutoff = 0.1;
-uniform bool imageNearest;
-uniform bool imagePremultiplied;
-
-#ifdef NORMAL_VIEWPORT_PASS_ENABLED
-in vec3 normal_viewport;
-#endif
-
-#ifdef V3D_SHADING_TEXTURE_COLOR
-in vec2 uv_interp;
-#endif
-#ifdef V3D_SHADING_VERTEX_COLOR
-in vec3 vertexColor;
-#endif
-
-#ifdef HAIR_SHADER
-flat in float hair_rand;
-#endif
-
-#ifdef MATDATA_PASS_ENABLED
-layout(location = 0) out vec4 materialData;
-#endif
-#ifdef OBJECT_ID_PASS_ENABLED
-layout(location = 1) out uint objectId;
-#endif
-#ifdef NORMAL_VIEWPORT_PASS_ENABLED
-layout(location = 2) out WB_Normal normalViewport;
-#endif
-
-void main()
-{
-#ifdef MATDATA_PASS_ENABLED
- float metallic, roughness;
- vec4 color;
-
-# if defined(V3D_SHADING_TEXTURE_COLOR)
-# ifdef TEXTURE_IMAGE_ARRAY
- color = workbench_sample_texture_array(
- image_tile_array, image_tile_data, uv_interp, imageNearest, imagePremultiplied);
-# else
- color = workbench_sample_texture(image, uv_interp, imageNearest, imagePremultiplied);
-# endif
- if (color.a < ImageTransparencyCutoff) {
- discard;
- }
-# elif defined(V3D_SHADING_VERTEX_COLOR)
- color.rgb = vertexColor;
-# else
- color.rgb = materialColorAndMetal.rgb;
-# endif
-
-# ifdef V3D_LIGHTING_MATCAP
- /* Encode front facing in metallic channel. */
- metallic = float(gl_FrontFacing);
- roughness = 0.0;
-# else
- metallic = materialColorAndMetal.a;
- roughness = materialRoughness;
-# endif
-
-# ifdef HAIR_SHADER
- /* Add some variation to the hairs to avoid uniform look. */
- float hair_variation = hair_rand * 0.1;
- color = clamp(color - hair_variation, 0.0, 1.0);
- metallic = clamp(materialColorAndMetal.a - hair_variation, 0.0, 1.0);
- roughness = clamp(materialRoughness - hair_variation, 0.0, 1.0);
-# endif
-
- materialData.rgb = color.rgb;
- materialData.a = workbench_float_pair_encode(roughness, metallic);
-#endif /* MATDATA_PASS_ENABLED */
-
-#ifdef OBJECT_ID_PASS_ENABLED
- objectId = uint(resource_id + 1) & 0xFFu;
-#endif
-
-#ifdef NORMAL_VIEWPORT_PASS_ENABLED
- vec3 n = (gl_FrontFacing) ? normal_viewport : -normal_viewport;
- n = normalize(n);
- normalViewport = workbench_normal_encode(n);
-#endif
-}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_hair_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_hair_vert.glsl
new file mode 100644
index 00000000000..4252c20a551
--- /dev/null
+++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_hair_vert.glsl
@@ -0,0 +1,129 @@
+
+#ifndef HAIR_SHADER
+in vec3 pos;
+in vec3 nor;
+in vec2 au; /* active texture layer */
+# ifdef V3D_SHADING_VERTEX_COLOR
+in vec4 ac; /* active color */
+# endif
+# define uv au
+#else /* HAIR_SHADER */
+
+# ifdef V3D_SHADING_TEXTURE_COLOR
+uniform samplerBuffer au; /* active texture layer */
+# endif
+# ifdef V3D_SHADING_VERTEX_COLOR
+uniform samplerBuffer ac; /* active color layer */
+# endif
+
+flat out float hair_rand;
+#endif /* HAIR_SHADER */
+
+#ifdef NORMAL_VIEWPORT_PASS_ENABLED
+out vec3 normal_viewport;
+#endif
+
+#ifdef V3D_SHADING_TEXTURE_COLOR
+out vec2 uv_interp;
+#endif
+#ifdef V3D_SHADING_VERTEX_COLOR
+out vec3 vertexColor;
+#endif
+
+#ifdef OBJECT_ID_PASS_ENABLED
+RESOURCE_ID_VARYING
+#endif
+
+/* From http://libnoise.sourceforge.net/noisegen/index.html */
+float integer_noise(int n)
+{
+ n = (n >> 13) ^ n;
+ int nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
+ return (float(nn) / 1073741824.0);
+}
+
+vec3 workbench_hair_hair_normal(vec3 tan, vec3 binor, float rand)
+{
+ /* To "simulate" anisotropic shading, randomize hair normal per strand. */
+ vec3 nor = cross(tan, binor);
+ nor = normalize(mix(nor, -tan, rand * 0.1));
+ float cos_theta = (rand * 2.0 - 1.0) * 0.2;
+ float sin_theta = sqrt(max(0.0, 1.0 - cos_theta * cos_theta));
+ nor = nor * sin_theta + binor * cos_theta;
+ return nor;
+}
+
+void main()
+{
+#ifdef HAIR_SHADER
+# ifdef V3D_SHADING_TEXTURE_COLOR
+ vec2 uv = hair_get_customdata_vec2(au);
+# endif
+ float time, thick_time, thickness;
+ vec3 world_pos, tan, binor;
+ hair_get_pos_tan_binor_time((ProjectionMatrix[3][3] == 0.0),
+ ModelMatrixInverse,
+ ViewMatrixInverse[3].xyz,
+ ViewMatrixInverse[2].xyz,
+ world_pos,
+ tan,
+ binor,
+ time,
+ thickness,
+ thick_time);
+
+ hair_rand = integer_noise(hair_get_strand_id());
+ vec3 nor = workbench_hair_hair_normal(tan, binor, hair_rand);
+#else
+ vec3 world_pos = point_object_to_world(pos);
+#endif
+ gl_Position = point_world_to_ndc(world_pos);
+
+#ifdef V3D_SHADING_TEXTURE_COLOR
+ uv_interp = uv;
+#endif
+
+#ifdef V3D_SHADING_VERTEX_COLOR
+# ifndef HAIR_SHADER
+ vertexColor = ac.rgb;
+# else
+ vertexColor = hair_get_customdata_vec4(ac).rgb;
+# endif
+#endif
+
+#ifdef NORMAL_VIEWPORT_PASS_ENABLED
+# ifndef HAIR_SHADER
+ normal_viewport = normal_object_to_view(nor);
+ normal_viewport = normalize(normal_viewport);
+# else
+ normal_viewport = normal_world_to_view(nor);
+# endif
+#endif
+
+#ifdef OBJECT_ID_PASS_ENABLED
+ PASS_RESOURCE_ID
+#endif
+
+#ifdef USE_WORLD_CLIP_PLANES
+ world_clip_planes_calc_clip_distance(world_pos);
+#endif
+
+#ifdef HAIR_SHADER
+ /* Add some variation to the hairs to avoid uniform look. */
+ float hair_variation = hair_rand * 0.1;
+ color = clamp(color - hair_variation, 0.0, 1.0);
+ metallic = clamp(materialColorAndMetal.a - hair_variation, 0.0, 1.0);
+ roughness = clamp(materialRoughness - hair_variation, 0.0, 1.0);
+#endif
+
+#ifdef V3D_LIGHTING_MATCAP
+ /* Encode front facing in metallic channel. */
+ metallic = float(gl_FrontFacing);
+ roughness = 0.0;
+#else
+ metallic = materialColorAndMetal.a;
+ roughness = materialRoughness;
+#endif
+
+ workbench_float_pair_encode(roughness, metallic)
+}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl
index 0a3252f0b9b..c7e74a789ac 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl
@@ -1,110 +1,74 @@
-#ifndef HAIR_SHADER
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_common_lib.glsl)
+
+IN_OUT ShaderStageInterface
+{
+ vec3 normal_interp;
+ vec3 color_interp;
+ vec2 uv_interp;
+ flat float packed_rough_metal;
+ flat int object_id;
+};
+
+#ifdef GPU_VERTEX_SHADER
+
in vec3 pos;
in vec3 nor;
-in vec2 au; /* active texture layer */
-# ifdef V3D_SHADING_VERTEX_COLOR
in vec4 ac; /* active color */
-# endif
-# define uv au
-#else /* HAIR_SHADER */
+in vec2 au; /* active texture layer */
-# ifdef V3D_SHADING_TEXTURE_COLOR
-uniform samplerBuffer au; /* active texture layer */
-# endif
-# ifdef V3D_SHADING_VERTEX_COLOR
-uniform samplerBuffer ac; /* active color layer */
+void main()
+{
+ vec3 world_pos = point_object_to_world(pos);
+ gl_Position = point_world_to_ndc(world_pos);
+
+# ifdef USE_WORLD_CLIP_PLANES
+ world_clip_planes_calc_clip_distance(world_pos);
# endif
-flat out float hair_rand;
-#endif /* HAIR_SHADER */
+ uv_interp = au;
+ color_interp = vec3(0.9); // ac.rgb;
-#ifdef NORMAL_VIEWPORT_PASS_ENABLED
-out vec3 normal_viewport;
-#endif
+ normal_interp = normalize(normal_object_to_view(nor));
-#ifdef V3D_SHADING_TEXTURE_COLOR
-out vec2 uv_interp;
-#endif
-#ifdef V3D_SHADING_VERTEX_COLOR
-out vec3 vertexColor;
-#endif
+ // float metallic = materialColorAndMetal.a;
+ // float roughness = materialRoughness;
-#ifdef OBJECT_ID_PASS_ENABLED
-RESOURCE_ID_VARYING
-#endif
+ float metallic = 0.0;
+ float roughness = 0.0;
-/* From http://libnoise.sourceforge.net/noisegen/index.html */
-float integer_noise(int n)
-{
- n = (n >> 13) ^ n;
- int nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
- return (float(nn) / 1073741824.0);
-}
+ if (metallic == -1.0) {
+ /* Matcap Case. */
+ packed_rough_metal = -1.0;
+ }
+ else {
+ packed_rough_metal = workbench_float_pair_encode(roughness, metallic);
+ }
-vec3 workbench_hair_hair_normal(vec3 tan, vec3 binor, float rand)
-{
- /* To "simulate" anisotropic shading, randomize hair normal per strand. */
- vec3 nor = cross(tan, binor);
- nor = normalize(mix(nor, -tan, rand * 0.1));
- float cos_theta = (rand * 2.0 - 1.0) * 0.2;
- float sin_theta = sqrt(max(0.0, 1.0 - cos_theta * cos_theta));
- nor = nor * sin_theta + binor * cos_theta;
- return nor;
+ object_id = int((uint(resource_id) + 1u) & 0xFFu);
}
+#else
+
+layout(location = 0) out vec4 materialData;
+layout(location = 1) out WB_Normal normalData;
+layout(location = 2) out uint objectId;
+
void main()
{
-#ifdef HAIR_SHADER
-# ifdef V3D_SHADING_TEXTURE_COLOR
- vec2 uv = hair_get_customdata_vec2(au);
-# endif
- float time, thick_time, thickness;
- vec3 world_pos, tan, binor;
- hair_get_pos_tan_binor_time((ProjectionMatrix[3][3] == 0.0),
- ModelMatrixInverse,
- ViewMatrixInverse[3].xyz,
- ViewMatrixInverse[2].xyz,
- world_pos,
- tan,
- binor,
- time,
- thickness,
- thick_time);
-
- hair_rand = integer_noise(hair_get_strand_id());
- vec3 nor = workbench_hair_hair_normal(tan, binor, hair_rand);
-#else
- vec3 world_pos = point_object_to_world(pos);
-#endif
- gl_Position = point_world_to_ndc(world_pos);
+ normalData = workbench_normal_encode(gl_FrontFacing, normal_interp);
-#ifdef V3D_SHADING_TEXTURE_COLOR
- uv_interp = uv;
-#endif
+ materialData = vec4(color_interp, packed_rough_metal);
-#ifdef V3D_SHADING_VERTEX_COLOR
-# ifndef HAIR_SHADER
- vertexColor = ac.rgb;
-# else
- vertexColor = hair_get_customdata_vec4(ac).rgb;
-# endif
-#endif
+ objectId = uint(object_id);
-#ifdef NORMAL_VIEWPORT_PASS_ENABLED
-# ifndef HAIR_SHADER
- normal_viewport = normal_object_to_view(nor);
- normal_viewport = normalize(normal_viewport);
-# else
- normal_viewport = normal_world_to_view(nor);
-# endif
-#endif
+ if (materialData.a == -1.0) {
+ /* For matcaps, save front facing in alpha channel. */
+ materialData.a = float(gl_FrontFacing);
+ }
-#ifdef OBJECT_ID_PASS_ENABLED
- PASS_RESOURCE_ID
-#endif
+ // materialData.rgb *= workbench_image_color(uv_interp);
+}
-#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance(world_pos);
#endif
-}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl
index 690ce5d527f..58e8370537a 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl
@@ -1,4 +1,6 @@
+#pragma BLENDER_REQUIRE(workbench_data_lib.glsl)
+
/* [Drobot2014a] Low Level Optimizations for GCN */
vec4 fast_rcp(vec4 v)
{
@@ -41,8 +43,7 @@ vec4 wrapped_lighting(vec4 NL, vec4 w)
return clamp((NL + w) * denom, 0.0, 1.0);
}
-vec3 get_world_lighting(
- WorldData world_data, vec3 diffuse_color, vec3 specular_color, float roughness, vec3 N, vec3 I)
+vec3 get_world_lighting(vec3 diffuse_color, vec3 specular_color, float roughness, vec3 N, vec3 I)
{
vec3 specular_light = world_data.ambient_color.rgb;
vec3 diffuse_light = world_data.ambient_color.rgb;
diff --git a/source/blender/draw/engines/workbench/workbench_data.c b/source/blender/draw/engines/workbench/workbench_data.c
index 056e6a6c364..a2cc2a52b7e 100644
--- a/source/blender/draw/engines/workbench/workbench_data.c
+++ b/source/blender/draw/engines/workbench/workbench_data.c
@@ -102,6 +102,43 @@ static void workbench_world_data_update_shadow_direction_vs(WORKBENCH_PrivateDat
/* \} */
+static void workbench_viewvecs_update(float r_viewvecs[3][4])
+{
+ float invproj[4][4];
+ const bool is_persp = DRW_view_is_persp_get(NULL);
+ DRW_view_winmat_get(NULL, invproj, true);
+
+ /* view vectors for the corners of the view frustum.
+ * Can be used to recreate the world space position easily */
+ copy_v4_fl4(r_viewvecs[0], -1.0f, -1.0f, -1.0f, 1.0f);
+ copy_v4_fl4(r_viewvecs[1], 1.0f, -1.0f, -1.0f, 1.0f);
+ copy_v4_fl4(r_viewvecs[2], -1.0f, 1.0f, -1.0f, 1.0f);
+
+ /* convert the view vectors to view space */
+ for (int i = 0; i < 3; i++) {
+ mul_m4_v4(invproj, r_viewvecs[i]);
+ /* normalized trick see:
+ * http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
+ mul_v3_fl(r_viewvecs[i], 1.0f / r_viewvecs[i][3]);
+ if (is_persp) {
+ mul_v3_fl(r_viewvecs[i], 1.0f / r_viewvecs[i][2]);
+ }
+ r_viewvecs[i][3] = 1.0;
+ }
+
+ /* we need to store the differences */
+ r_viewvecs[1][0] -= r_viewvecs[0][0];
+ r_viewvecs[1][1] = r_viewvecs[2][1] - r_viewvecs[0][1];
+
+ /* calculate a depth offset as well */
+ if (!is_persp) {
+ float vec_far[] = {-1.0f, -1.0f, 1.0f, 1.0f};
+ mul_m4_v4(invproj, vec_far);
+ mul_v3_fl(vec_far, 1.0f / vec_far[3]);
+ r_viewvecs[1][2] = vec_far[2] - r_viewvecs[0][2];
+ }
+}
+
void workbench_clear_color_get(float color[4])
{
const DRWContextState *draw_ctx = DRW_context_state_get();
@@ -130,9 +167,10 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
const Scene *scene = draw_ctx->scene;
- wpd->material_hash = BLI_ghash_ptr_new(__func__);
- wpd->material_transp_hash = BLI_ghash_ptr_new(__func__);
+ // wpd->material_hash = BLI_ghash_ptr_new(__func__);
+ // wpd->material_transp_hash = BLI_ghash_ptr_new(__func__);
wpd->preferences = &U;
+ wpd->sh_cfg = draw_ctx->sh_cfg;
View3D *v3d = draw_ctx->v3d;
RegionView3D *rv3d = draw_ctx->rv3d;
@@ -190,6 +228,7 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd)
workbench_world_data_update_shadow_direction_vs(wpd);
workbench_world_data_ubo_ensure(scene, wpd);
+ workbench_viewvecs_update(wpd->world_data.viewvecs);
/* Cavity settings */
{
diff --git a/source/blender/draw/engines/workbench/workbench_effect_cavity.c b/source/blender/draw/engines/workbench/workbench_effect_cavity.c
new file mode 100644
index 00000000000..42652cf4299
--- /dev/null
+++ b/source/blender/draw/engines/workbench/workbench_effect_cavity.c
@@ -0,0 +1,78 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2020, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ */
+
+#include "DRW_render.h"
+
+#include "workbench_engine.h"
+#include "workbench_private.h"
+
+#if 0
+{
+
+ {
+ /* AO Samples Tex */
+ int num_iterations = workbench_taa_calculate_num_iterations(vedata);
+
+ const int ssao_samples_single_iteration = scene->display.matcap_ssao_samples;
+ const int ssao_samples = MIN2(num_iterations * ssao_samples_single_iteration, 500);
+
+ if (e_data.sampling_ubo && (e_data.cached_sample_num != ssao_samples)) {
+ DRW_UBO_FREE_SAFE(e_data.sampling_ubo);
+ DRW_TEXTURE_FREE_SAFE(e_data.jitter_tx);
+ }
+
+ if (e_data.sampling_ubo == NULL) {
+ float *samples = create_disk_samples(ssao_samples_single_iteration, num_iterations);
+ e_data.jitter_tx = create_jitter_texture(ssao_samples);
+ e_data.sampling_ubo = DRW_uniformbuffer_create(sizeof(float[4]) * ssao_samples, samples);
+ e_data.cached_sample_num = ssao_samples;
+ MEM_freeN(samples);
+ }
+ }
+}
+
+ if (CAVITY_ENABLED(wpd)) {
+ int state = DRW_STATE_WRITE_COLOR;
+ GPUShader *shader = workbench_cavity_shader_get(SSAO_ENABLED(wpd), CURVATURE_ENABLED(wpd));
+ psl->cavity_pass = DRW_pass_create("Cavity", state);
+ DRWShadingGroup *grp = DRW_shgroup_create(shader, psl->cavity_pass);
+ DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &e_data.normal_buffer_tx);
+ DRW_shgroup_uniform_block(grp, "samples_block", e_data.sampling_ubo);
+
+ if (SSAO_ENABLED(wpd)) {
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
+ DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1);
+ DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)wpd->viewvecs, 3);
+ DRW_shgroup_uniform_vec4(grp, "ssao_params", wpd->ssao_params, 1);
+ DRW_shgroup_uniform_vec4(grp, "ssao_settings", wpd->ssao_settings, 1);
+ DRW_shgroup_uniform_mat4(grp, "WinMatrix", wpd->winmat);
+ DRW_shgroup_uniform_texture(grp, "ssao_jitter", e_data.jitter_tx);
+ }
+
+ if (CURVATURE_ENABLED(wpd)) {
+ DRW_shgroup_uniform_texture_ref(grp, "objectId", &e_data.object_id_tx);
+ DRW_shgroup_uniform_vec2(grp, "curvature_settings", &wpd->world_data.curvature_ridge, 1);
+ }
+
+ DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
+ }
+#endif \ No newline at end of file
diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c
index 62a192bbb25..68ef7b6ce60 100644
--- a/source/blender/draw/engines/workbench/workbench_engine.c
+++ b/source/blender/draw/engines/workbench/workbench_engine.c
@@ -19,8 +19,7 @@
/** \file
* \ingroup draw_engine
*
- * Simple engine for drawing color and/or depth.
- * When we only need simple flat shaders.
+ * Optimized engine to draw the working viewport with solid and transparent geometry.
*/
#include "DRW_render.h"
@@ -30,7 +29,137 @@
#define WORKBENCH_ENGINE "BLENDER_WORKBENCH"
-/* Note: currently unused, we may want to register so we can see this when debugging the view. */
+static void workbench_engine_init(void *ved)
+{
+ WORKBENCH_Data *vedata = ved;
+ WORKBENCH_StorageList *stl = vedata->stl;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ RegionView3D *rv3d = draw_ctx->rv3d;
+ View3D *v3d = draw_ctx->v3d;
+ Scene *scene = draw_ctx->scene;
+ Object *camera;
+
+ workbench_shader_library_ensure();
+
+ if (v3d && rv3d) {
+ camera = (rv3d->persp == RV3D_CAMOB) ? v3d->camera : NULL;
+ }
+ else {
+ camera = scene->camera;
+ }
+
+ if (!stl->wpd) {
+ stl->wpd = MEM_callocN(sizeof(*stl->wpd), __func__);
+ }
+
+ if (!stl->effects) {
+ stl->effects = MEM_callocN(sizeof(*stl->effects), __func__);
+ workbench_effect_info_init(stl->effects);
+ }
+
+ WORKBENCH_PrivateData *wpd = stl->wpd;
+ workbench_private_data_init(wpd);
+
+ workbench_opaque_engine_init(vedata);
+ // workbench_volume_engine_init();
+ // workbench_fxaa_engine_init();
+ // workbench_taa_engine_init(vedata);
+ // workbench_dof_engine_init(vedata, camera);
+}
+
+static void workbench_cache_init(void *ved)
+{
+ WORKBENCH_Data *vedata = ved;
+
+ workbench_opaque_cache_init(vedata);
+
+ return;
+
+ // workbench_aa_create_pass(vedata);
+ // workbench_dof_create_pass(vedata);
+}
+
+static void workbench_cache_populate(void *ved, Object *ob)
+{
+ WORKBENCH_Data *vedata = ved;
+ WORKBENCH_PassList *psl = vedata->psl;
+ WORKBENCH_StorageList *stl = vedata->stl;
+ WORKBENCH_PrivateData *wpd = stl->wpd;
+
+ if (!DRW_object_is_renderable(ob)) {
+ return;
+ }
+
+ // if (ob->type == OB_MESH) {
+ // workbench_cache_populate_particles(vedata, ob);
+ // }
+
+ /* TODO volume */
+
+ // if (!(DRW_object_visibility_in_active_context(ob) & OB_VISIBLE_SELF)) {
+ // return;
+ // }
+
+ if ((ob->dt < OB_SOLID) && !DRW_state_is_scene_render()) {
+ return;
+ }
+
+ if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) {
+ struct GPUBatch *geom = DRW_cache_object_surface_get(ob);
+
+ if (geom) {
+ DRW_shgroup_call(wpd->prepass_shgrp, geom, ob);
+ }
+ }
+}
+
+static void workbench_cache_finish(void *ved)
+{
+}
+
+static void workbench_draw_scene(void *ved)
+{
+ WORKBENCH_Data *vedata = ved;
+ WORKBENCH_FramebufferList *fbl = vedata->fbl;
+ WORKBENCH_PassList *psl = vedata->psl;
+ float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+
+ GPU_framebuffer_bind(fbl->prepass_fb);
+ DRW_draw_pass(psl->prepass_pass);
+
+ GPU_framebuffer_bind(fbl->composite_fb);
+ GPU_framebuffer_clear_color(fbl->composite_fb, clear_col);
+
+ DRW_draw_pass(psl->composite_pass);
+}
+
+static void workbench_engine_free(void)
+{
+ workbench_shader_free();
+}
+
+static void workbench_view_update(void *ved)
+{
+}
+
+static const DrawEngineDataSize workbench_data_size = DRW_VIEWPORT_DATA_SIZE(WORKBENCH_Data);
+
+DrawEngineType draw_engine_workbench = {
+ NULL,
+ NULL,
+ N_("Workbench"),
+ &workbench_data_size,
+ &workbench_engine_init,
+ &workbench_engine_free,
+ &workbench_cache_init,
+ &workbench_cache_populate,
+ &workbench_cache_finish,
+ &workbench_draw_scene,
+ &workbench_view_update,
+ NULL,
+ NULL,
+};
+
RenderEngineType DRW_engine_viewport_workbench_type = {
NULL,
NULL,
@@ -44,7 +173,7 @@ RenderEngineType DRW_engine_viewport_workbench_type = {
NULL,
NULL,
&workbench_render_update_passes,
- &draw_engine_workbench_solid,
+ &draw_engine_workbench,
{NULL, NULL, NULL},
};
diff --git a/source/blender/draw/engines/workbench/workbench_opaque.c b/source/blender/draw/engines/workbench/workbench_opaque.c
new file mode 100644
index 00000000000..32260623be8
--- /dev/null
+++ b/source/blender/draw/engines/workbench/workbench_opaque.c
@@ -0,0 +1,106 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2020, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ */
+
+#include "DRW_render.h"
+
+#include "GPU_extensions.h"
+
+#include "workbench_engine.h"
+#include "workbench_private.h"
+
+void workbench_opaque_engine_init(WORKBENCH_Data *data)
+{
+ WORKBENCH_FramebufferList *fbl = data->fbl;
+ WORKBENCH_PrivateData *wpd = data->stl->wpd;
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ const eGPUTextureFormat nor_tex_format = NORMAL_ENCODING_ENABLED() ? GPU_RG16 : GPU_RGBA32F;
+ const eGPUTextureFormat col_tex_format = workbench_color_texture_format(wpd);
+ const eGPUTextureFormat id_tex_format = OBJECT_ID_PASS_ENABLED(wpd) ? GPU_R32UI : GPU_R8;
+
+ wpd->composite_buffer_tx = dtxl->color;
+
+ wpd->material_buffer_tx = DRW_texture_pool_query_fullscreen(col_tex_format,
+ &draw_engine_workbench_solid);
+ wpd->object_id_tx = DRW_texture_pool_query_fullscreen(id_tex_format,
+ &draw_engine_workbench_solid);
+ wpd->normal_buffer_tx = DRW_texture_pool_query_fullscreen(nor_tex_format,
+ &draw_engine_workbench_solid);
+
+ GPU_framebuffer_ensure_config(&fbl->prepass_fb,
+ {
+ GPU_ATTACHMENT_TEXTURE(dtxl->depth),
+ GPU_ATTACHMENT_TEXTURE(wpd->material_buffer_tx),
+ GPU_ATTACHMENT_TEXTURE(wpd->normal_buffer_tx),
+ GPU_ATTACHMENT_TEXTURE(wpd->object_id_tx),
+ });
+
+ GPU_framebuffer_ensure_config(&fbl->composite_fb,
+ {
+ GPU_ATTACHMENT_TEXTURE(dtxl->depth),
+ GPU_ATTACHMENT_TEXTURE(dtxl->color),
+ });
+}
+
+void workbench_opaque_cache_init(WORKBENCH_Data *data)
+{
+ WORKBENCH_PassList *psl = data->psl;
+ WORKBENCH_PrivateData *wpd = data->stl->wpd;
+ struct GPUShader *sh;
+ DRWShadingGroup *grp;
+
+ {
+ DRWState clip_state = WORLD_CLIPPING_ENABLED(wpd) ? DRW_STATE_CLIP_PLANES : 0;
+ DRWState cull_state = CULL_BACKFACE_ENABLED(wpd) ? DRW_STATE_CULL_BACK : 0;
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
+
+ sh = workbench_shader_opaque_get(wpd);
+
+ DRW_PASS_CREATE(psl->prepass_pass, state | cull_state | clip_state);
+ wpd->prepass_shgrp = grp = DRW_shgroup_create(sh, psl->prepass_pass);
+
+ // DRW_PASS_CREATE(psl->ghost_prepass_pass, state | cull_state | clip_state);
+ // grp = DRW_shgroup_create(sh, psl->ghost_prepass_pass);
+
+ // sh = workbench_shader_opaque_hair_get(wpd);
+
+ // DRW_PASS_CREATE(psl->prepass_hair_pass, state | clip_state);
+ // DRW_PASS_CREATE(psl->ghost_prepass_hair_pass, state | clip_state);
+
+ // grp = DRW_shgroup_create(sh, psl->composite_pass);
+ // grp = DRW_shgroup_create(sh, psl->ghost_prepass_hair_pass);
+ }
+ {
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_GREATER;
+
+ DRW_PASS_CREATE(psl->composite_pass, state);
+
+ sh = workbench_shader_composite_get(wpd);
+
+ grp = DRW_shgroup_create(sh, psl->composite_pass);
+ DRW_shgroup_stencil_mask(grp, 0x00);
+ DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo);
+ DRW_shgroup_uniform_texture(grp, "materialBuffer", wpd->material_buffer_tx);
+ DRW_shgroup_uniform_texture(grp, "normalBuffer", wpd->normal_buffer_tx);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+ }
+}
diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h
index faf85e4a7de..87518137f8a 100644
--- a/source/blender/draw/engines/workbench/workbench_private.h
+++ b/source/blender/draw/engines/workbench/workbench_private.h
@@ -125,6 +125,7 @@ typedef struct WORKBENCH_TextureList {
typedef struct WORKBENCH_StorageList {
struct WORKBENCH_PrivateData *g_data;
+ struct WORKBENCH_PrivateData *wpd;
struct WORKBENCH_EffectInfo *effects;
float *dof_ubo_data;
} WORKBENCH_StorageList;
@@ -181,6 +182,7 @@ typedef struct WORKBENCH_UBO_Light {
} WORKBENCH_UBO_Light;
typedef struct WORKBENCH_UBO_World {
+ float viewvecs[3][4];
float object_outline_color[4];
float shadow_direction_vs[4];
WORKBENCH_UBO_Light lights[4];
@@ -243,6 +245,15 @@ typedef struct WORKBENCH_PrivateData {
float (*world_clip_planes)[4];
+ /* Opaque pipeline */
+ struct GPUTexture *object_id_tx;
+ struct GPUTexture *material_buffer_tx;
+ struct GPUTexture *composite_buffer_tx;
+ struct GPUTexture *normal_buffer_tx;
+ struct GPUTexture *cavity_buffer_tx;
+
+ struct DRWShadingGroup *prepass_shgrp;
+
/* Volumes */
bool volumes_do;
ListBase smoke_domains;
@@ -270,6 +281,8 @@ typedef struct WORKBENCH_PrivateData {
/* Color Management */
bool use_color_management;
bool use_color_render_settings;
+
+ eGPUShaderConfig sh_cfg;
} WORKBENCH_PrivateData; /* Transient data */
typedef struct WORKBENCH_EffectInfo {
@@ -431,6 +444,18 @@ BLI_INLINE eGPUTextureFormat workbench_color_texture_format(const WORKBENCH_Priv
return result;
}
+/* workbench_opaque.c */
+void workbench_opaque_engine_init(WORKBENCH_Data *data);
+void workbench_opaque_cache_init(WORKBENCH_Data *data);
+
+/* workbench_shader.c */
+GPUShader *workbench_shader_opaque_get(WORKBENCH_PrivateData *wpd);
+GPUShader *workbench_shader_opaque_hair_get(WORKBENCH_PrivateData *wpd);
+GPUShader *workbench_shader_composite_get(WORKBENCH_PrivateData *wpd);
+
+void workbench_shader_library_ensure(void);
+void workbench_shader_free(void);
+
/* workbench_deferred.c */
void workbench_deferred_engine_init(WORKBENCH_Data *vedata);
void workbench_deferred_engine_free(void);
diff --git a/source/blender/draw/engines/workbench/workbench_shader.c b/source/blender/draw/engines/workbench/workbench_shader.c
new file mode 100644
index 00000000000..378f621f319
--- /dev/null
+++ b/source/blender/draw/engines/workbench/workbench_shader.c
@@ -0,0 +1,174 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2020, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ */
+
+#include "DRW_render.h"
+
+#include "BLI_dynstr.h"
+
+#include "workbench_engine.h"
+#include "workbench_private.h"
+
+extern char datatoc_common_hair_lib_glsl[];
+extern char datatoc_common_view_lib_glsl[];
+
+extern char datatoc_workbench_prepass_vert_glsl[];
+extern char datatoc_workbench_prepass_frag_glsl[];
+// extern char datatoc_workbench_cavity_frag_glsl[];
+// extern char datatoc_workbench_forward_composite_frag_glsl[];
+// extern char datatoc_workbench_deferred_composite_frag_glsl[];
+// extern char datatoc_workbench_deferred_background_frag_glsl[];
+// extern char datatoc_workbench_ghost_resolve_frag_glsl[];
+
+extern char datatoc_workbench_composite_frag_glsl[];
+
+extern char datatoc_workbench_shadow_vert_glsl[];
+extern char datatoc_workbench_shadow_geom_glsl[];
+extern char datatoc_workbench_shadow_caps_geom_glsl[];
+extern char datatoc_workbench_shadow_debug_frag_glsl[];
+
+extern char datatoc_workbench_cavity_lib_glsl[];
+extern char datatoc_workbench_common_lib_glsl[];
+extern char datatoc_workbench_data_lib_glsl[];
+extern char datatoc_workbench_object_outline_lib_glsl[];
+extern char datatoc_workbench_curvature_lib_glsl[];
+extern char datatoc_workbench_world_light_lib_glsl[];
+
+extern char datatoc_gpu_shader_depth_only_frag_glsl[];
+
+static struct {
+ struct GPUShader *prepass_sh_cache[GPU_SHADER_CFG_LEN][MAX_PREPASS_SHADERS];
+
+ struct GPUShader *composite_sh[MAX_COMPOSITE_SHADERS];
+ struct GPUShader *cavity_sh[MAX_CAVITY_SHADERS];
+ struct GPUShader *ghost_resolve_sh;
+ struct GPUShader *oit_resolve_sh;
+
+ struct GPUShader *shadow_fail_sh[2];
+ struct GPUShader *shadow_pass_sh[2];
+ struct GPUShader *shadow_caps_sh[2];
+
+ struct DRWShaderLibrary *lib;
+} e_data = {{{NULL}}};
+
+void workbench_shader_library_ensure(void)
+{
+ if (e_data.lib == NULL) {
+ e_data.lib = DRW_shader_library_create();
+
+ DRW_SHADER_LIB_ADD(e_data.lib, common_hair_lib);
+ DRW_SHADER_LIB_ADD(e_data.lib, common_view_lib);
+ DRW_SHADER_LIB_ADD(e_data.lib, workbench_cavity_lib);
+ DRW_SHADER_LIB_ADD(e_data.lib, workbench_common_lib);
+ DRW_SHADER_LIB_ADD(e_data.lib, workbench_data_lib);
+ DRW_SHADER_LIB_ADD(e_data.lib, workbench_object_outline_lib);
+ DRW_SHADER_LIB_ADD(e_data.lib, workbench_curvature_lib);
+ DRW_SHADER_LIB_ADD(e_data.lib, workbench_world_light_lib);
+ }
+}
+
+static char *workbench_build_defines(WORKBENCH_PrivateData *UNUSED(wpd))
+{
+ char *str = NULL;
+
+ DynStr *ds = BLI_dynstr_new();
+
+ if (NORMAL_ENCODING_ENABLED()) {
+ BLI_dynstr_append(ds, "#define WORKBENCH_ENCODE_NORMALS\n");
+ }
+
+ str = BLI_dynstr_get_cstring(ds);
+ BLI_dynstr_free(ds);
+ return str;
+}
+
+GPUShader *workbench_shader_opaque_get(WORKBENCH_PrivateData *wpd)
+{
+ int index = 0;
+ if (e_data.prepass_sh_cache[wpd->sh_cfg][index] == NULL) {
+ char *defines = workbench_build_defines(wpd);
+ char *sh_src = DRW_shader_library_create_shader_string(e_data.lib,
+ datatoc_workbench_prepass_vert_glsl);
+ const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[wpd->sh_cfg];
+
+ e_data.prepass_sh_cache[wpd->sh_cfg][index] = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){sh_cfg_data->lib, sh_src, NULL},
+ .frag = (const char *[]){sh_src, NULL},
+ .defs = (const char *[]){sh_cfg_data->def, defines, NULL},
+ });
+
+ MEM_freeN(defines);
+ MEM_freeN(sh_src);
+ }
+ return e_data.prepass_sh_cache[wpd->sh_cfg][index];
+}
+
+GPUShader *workbench_shader_opaque_hair_get(WORKBENCH_PrivateData *wpd)
+{
+ // if (e_data.prepass_sh_cache[wpd->sh_cfg][index] == NULL) {
+ // char *vert = DRW_shader_library_create_shader_string(e_data.lib, char *shader_code);
+ // char *frag = DRW_shader_library_create_shader_string(e_data.lib, char *shader_code);
+ // char *defines = ;
+
+ // e_data.prepass_sh_cache[wpd->sh_cfg][index] = GPU_shader_create_from_arrays({
+ // .vert = (const char *[]){sh_cfg_data->lib, vert, NULL},
+ // .frag = (const char *[]){frag, NULL},
+ // .defs = (const char *[]){sh_cfg_data->def, defines, NULL},
+ // });
+
+ // MEM_freeN(vert);
+ // MEM_freeN(frag);
+ // MEM_freeN(defines);
+ // }
+ // return e_data.prepass_sh_cache[wpd->sh_cfg][index];
+ return NULL;
+}
+
+GPUShader *workbench_shader_composite_get(WORKBENCH_PrivateData *wpd)
+{
+ int index = 0;
+ if (e_data.composite_sh[index] == NULL) {
+ char *defines = workbench_build_defines(wpd);
+ char *frag = DRW_shader_library_create_shader_string(e_data.lib,
+ datatoc_workbench_composite_frag_glsl);
+
+ e_data.composite_sh[index] = DRW_shader_create_fullscreen(frag, defines);
+
+ MEM_freeN(defines);
+ MEM_freeN(frag);
+ }
+ return e_data.composite_sh[index];
+}
+
+void workbench_shader_free(void)
+{
+ for (int j = 0; j < ARRAY_SIZE(e_data.prepass_sh_cache); j++) {
+ for (int i = 0; i < MAX_PREPASS_SHADERS; i++) {
+ DRW_SHADER_FREE_SAFE(e_data.prepass_sh_cache[j][i]);
+ }
+ }
+
+ for (int i = 0; i < MAX_COMPOSITE_SHADERS; i++) {
+ DRW_SHADER_FREE_SAFE(e_data.composite_sh[i]);
+ }
+
+ DRW_SHADER_LIB_FREE_SAFE(e_data.lib);
+}
diff --git a/source/blender/draw/engines/workbench/workbench_shadow.c b/source/blender/draw/engines/workbench/workbench_shadow.c
new file mode 100644
index 00000000000..5be863e387d
--- /dev/null
+++ b/source/blender/draw/engines/workbench/workbench_shadow.c
@@ -0,0 +1,25 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2020, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ */
+
+#include "DRW_render.h"
+
+#include "workbench_engine.h" \ No newline at end of file
diff --git a/source/blender/draw/engines/workbench/workbench_transparent.c b/source/blender/draw/engines/workbench/workbench_transparent.c
new file mode 100644
index 00000000000..1ad3f41ef79
--- /dev/null
+++ b/source/blender/draw/engines/workbench/workbench_transparent.c
@@ -0,0 +1,26 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2020, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ */
+
+#include "DRW_render.h"
+
+#include "workbench_engine.h"
+#include "workbench_private.h" \ No newline at end of file
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 1eb4a903d90..cbd39331680 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -149,6 +149,8 @@ struct GPUTexture *DRW_texture_pool_query_2d(int w,
int h,
eGPUTextureFormat format,
DrawEngineType *engine_type);
+struct GPUTexture *DRW_texture_pool_query_fullscreen(eGPUTextureFormat format,
+ DrawEngineType *engine_type);
struct GPUTexture *DRW_texture_create_1d(int w,
eGPUTextureFormat format,
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 80001144cc0..5fedba246e7 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -1118,45 +1118,23 @@ static void use_drw_engine(DrawEngineType *engine)
BLI_addtail(&DST.enabled_engines, ld);
}
-/**
- * Use for external render engines.
- */
-static void drw_engines_enable_external(void)
-{
- use_drw_engine(DRW_engine_viewport_external_type.draw_engine);
-}
-
-/* TODO revisit this when proper layering is implemented */
/* Gather all draw engines needed and store them in DST.enabled_engines
* That also define the rendering order of engines */
-static void drw_engines_enable_from_engine(RenderEngineType *engine_type,
- int drawtype,
- bool use_xray)
+static void drw_engines_enable_from_engine(RenderEngineType *engine_type, int drawtype)
{
switch (drawtype) {
case OB_WIRE:
- use_drw_engine(&draw_engine_workbench_transparent);
- break;
-
case OB_SOLID:
- if (use_xray) {
- use_drw_engine(&draw_engine_workbench_transparent);
- }
- else {
- use_drw_engine(&draw_engine_workbench_solid);
- }
+ use_drw_engine(DRW_engine_viewport_workbench_type.draw_engine);
break;
-
case OB_MATERIAL:
case OB_RENDER:
default:
- /* TODO layers */
if (engine_type->draw_engine != NULL) {
use_drw_engine(engine_type->draw_engine);
}
-
- if ((engine_type->flag & RE_INTERNAL) == 0) {
- drw_engines_enable_external();
+ else if ((engine_type->flag & RE_INTERNAL) == 0) {
+ use_drw_engine(DRW_engine_viewport_external_type.draw_engine);
}
break;
}
@@ -1180,9 +1158,8 @@ static void drw_engines_enable(ViewLayer *UNUSED(view_layer),
{
View3D *v3d = DST.draw_ctx.v3d;
const int drawtype = v3d->shading.type;
- const bool use_xray = XRAY_ENABLED(v3d);
- drw_engines_enable_from_engine(engine_type, drawtype, use_xray);
+ drw_engines_enable_from_engine(engine_type, drawtype);
if (gpencil_engine_needed) {
use_drw_engine(&draw_engine_gpencil_type);
}
diff --git a/source/blender/draw/intern/draw_manager_texture.c b/source/blender/draw/intern/draw_manager_texture.c
index 373810b2f7f..c75299158a3 100644
--- a/source/blender/draw/intern/draw_manager_texture.c
+++ b/source/blender/draw/intern/draw_manager_texture.c
@@ -134,6 +134,13 @@ GPUTexture *DRW_texture_pool_query_2d(int w,
return tex;
}
+GPUTexture *DRW_texture_pool_query_fullscreen(eGPUTextureFormat format,
+ DrawEngineType *engine_type)
+{
+ const float *size = DRW_viewport_size_get();
+ return DRW_texture_pool_query_2d((int)size[0], (int)size[1], format, engine_type);
+}
+
void DRW_texture_ensure_fullscreen_2d(GPUTexture **tex,
eGPUTextureFormat format,
DRWTextureFlag flags)