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>2020-03-11 19:07:43 +0300
committerClément Foucault <foucault.clem@gmail.com>2020-03-11 19:12:16 +0300
commitc476c36e400883d929a7149def8dcb6ad6157a86 (patch)
treec19c43ad1ed82f333c08bee7d2096024fed812dd /source/blender/draw/engines/workbench/shaders
parentf01bc597a8e6bf5df19f1af0c422918c96b25e41 (diff)
Workbench Simplification Refactor
This patch is (almost) a complete rewrite of workbench engine. The features remain unchanged but the code quality is greatly improved. Hair shading is brighter but also more correct. This also introduce the concept of `DRWShaderLibrary` to make a simple include system inside the GLSL files. Differential Revision: https://developer.blender.org/D7060
Diffstat (limited to 'source/blender/draw/engines/workbench/shaders')
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_cavity_frag.glsl81
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl97
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl154
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl44
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_curvature_lib.glsl47
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl34
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_deferred_background_frag.glsl30
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl103
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_effect_cavity_frag.glsl31
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_effect_fxaa_frag.glsl14
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_effect_outline_frag.glsl24
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_effect_smaa_frag.glsl44
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_effect_smaa_vert.glsl21
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_effect_taa_frag.glsl11
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_forward_composite_frag.glsl36
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_forward_depth_frag.glsl20
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl118
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_ghost_resolve_frag.glsl13
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_image_lib.glsl83
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_matcap_lib.glsl30
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_material_lib.glsl21
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_merge_infront_frag.glsl18
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_object_outline_lib.glsl12
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl97
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_prepass_hair_vert.glsl94
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl114
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_shader_interface_lib.glsl21
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_shadow_debug_frag.glsl16
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_transparent_accum_frag.glsl89
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_transparent_resolve_frag.glsl26
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl37
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl3
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl88
33 files changed, 798 insertions, 873 deletions
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_cavity_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_cavity_frag.glsl
deleted file mode 100644
index a0e04f252e2..00000000000
--- a/source/blender/draw/engines/workbench/shaders/workbench_cavity_frag.glsl
+++ /dev/null
@@ -1,81 +0,0 @@
-out vec4 fragColor;
-
-uniform sampler2D depthBuffer;
-uniform sampler2D colorBuffer;
-uniform sampler2D normalBuffer;
-uniform usampler2D objectId;
-
-uniform vec2 invertedViewportSize;
-uniform mat4 WinMatrix; /* inverse WinMatrix */
-
-uniform vec4 viewvecs[3];
-uniform vec4 ssao_params;
-uniform vec4 ssao_settings;
-uniform vec2 curvature_settings;
-uniform sampler2D ssao_jitter;
-
-layout(std140) uniform samples_block
-{
- vec4 ssao_samples[500];
-};
-
-#define ssao_samples_num ssao_params.x
-#define jitter_tilling ssao_params.yz
-#define ssao_iteration ssao_params.w
-
-#define ssao_distance ssao_settings.x
-#define ssao_factor_cavity ssao_settings.y
-#define ssao_factor_edge ssao_settings.z
-#define ssao_attenuation ssao_settings.w
-
-vec3 get_view_space_from_depth(in vec2 uvcoords, in float depth)
-{
- if (WinMatrix[3][3] == 0.0) {
- /* Perspective */
- float d = 2.0 * depth - 1.0;
-
- float zview = -WinMatrix[3][2] / (d + WinMatrix[2][2]);
-
- return zview * (viewvecs[0].xyz + vec3(uvcoords, 0.0) * viewvecs[1].xyz);
- }
- else {
- /* Orthographic */
- vec3 offset = vec3(uvcoords, depth);
-
- return viewvecs[0].xyz + offset * viewvecs[1].xyz;
- }
-}
-
-/* forward declaration */
-void ssao_factors(in float depth,
- in vec3 normal,
- in vec3 position,
- in vec2 screenco,
- out float cavities,
- out float edges);
-
-void main()
-{
- vec2 screenco = vec2(gl_FragCoord.xy) * invertedViewportSize;
- ivec2 texel = ivec2(gl_FragCoord.xy);
-
- float cavity = 0.0, edges = 0.0, curvature = 0.0;
-
-#ifdef USE_CAVITY
- float depth = texelFetch(depthBuffer, texel, 0).x;
- vec3 position = get_view_space_from_depth(screenco, depth);
- vec3 normal_viewport = workbench_normal_decode(texelFetch(normalBuffer, texel, 0).rg);
-
- ssao_factors(depth, normal_viewport, position, screenco, cavity, edges);
-#endif
-
-#ifdef USE_CURVATURE
- curvature = calculate_curvature(
- objectId, normalBuffer, texel, curvature_settings.x, curvature_settings.y);
-#endif
-
- float final_cavity_factor = clamp((1.0 - cavity) * (1.0 + edges) * (1.0 + curvature), 0.0, 4.0);
-
- /* Using UNORM render target so compress the range. */
- fragColor = vec4(final_cavity_factor / CAVITY_BUFFER_RANGE);
-}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl
index 376b19cdd1b..87d04144cde 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl
@@ -1,77 +1,87 @@
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_data_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_common_lib.glsl)
-/* from The Alchemy screen-space ambient obscurance algorithm
+layout(std140) uniform samples_block
+{
+ vec4 samples_coords[512];
+};
+
+uniform sampler2D cavityJitter;
+
+/* From The Alchemy screen-space ambient obscurance algorithm
* http://graphics.cs.williams.edu/papers/AlchemyHPG11/VV11AlchemyAO.pdf */
-void ssao_factors(in float depth,
- in vec3 normal,
- in vec3 position,
- in vec2 screenco,
- out float cavities,
- out float edges)
+void cavity_compute(vec2 screenco,
+ sampler2D depthBuffer,
+ sampler2D normalBuffer,
+ out float cavities,
+ out float edges)
{
cavities = edges = 0.0;
- /* early out if there is no need for SSAO */
- if (ssao_factor_cavity == 0.0 && ssao_factor_edge == 0.0) {
+
+ float depth = texture(depthBuffer, screenco).x;
+
+ /* Early out if background and infront. */
+ if (depth == 1.0 || depth == 0.0) {
return;
}
- /* take the normalized ray direction here */
- vec3 noise = texture(ssao_jitter, screenco.xy * jitter_tilling).rgb;
+ vec3 position = view_position_from_depth(screenco, depth, world_data.viewvecs, ProjectionMatrix);
+ vec3 normal = workbench_normal_decode(texture(normalBuffer, screenco));
+
+ vec2 jitter_co = (screenco * world_data.viewport_size.xy) * world_data.cavity_jitter_scale;
+ vec3 noise = texture(cavityJitter, jitter_co).rgb;
/* find the offset in screen space by multiplying a point
* in camera space at the depth of the point by the projection matrix. */
vec2 offset;
- float homcoord = WinMatrix[2][3] * position.z + WinMatrix[3][3];
- offset.x = WinMatrix[0][0] * ssao_distance / homcoord;
- offset.y = WinMatrix[1][1] * ssao_distance / homcoord;
+ float homcoord = ProjectionMatrix[2][3] * position.z + ProjectionMatrix[3][3];
+ offset.x = ProjectionMatrix[0][0] * world_data.cavity_distance / homcoord;
+ offset.y = ProjectionMatrix[1][1] * world_data.cavity_distance / homcoord;
/* convert from -1.0...1.0 range to 0.0..1.0 for easy use with texture coordinates */
offset *= 0.5;
- int num_samples = int(ssao_samples_num);
-
/* Note. Putting noise usage here to put some ALU after texture fetch. */
vec2 rotX = noise.rg;
vec2 rotY = vec2(-rotX.y, rotX.x);
- for (int x = 0; x < num_samples; x++) {
- int sample_index = x + (int(ssao_iteration) * num_samples);
- if (sample_index > 500) {
- continue;
- }
- /* ssao_samples[x].xy is sample direction (normalized).
- * ssao_samples[x].z is sample distance from disk center. */
-
+ int sample_start = world_data.cavity_sample_start;
+ int sample_end = world_data.cavity_sample_end;
+ for (int i = sample_start; i < sample_end && i < 512; i++) {
+ /* sample_coord.xy is sample direction (normalized).
+ * sample_coord.z is sample distance from disk center. */
+ vec3 sample_coord = samples_coords[i].xyz;
/* Rotate with random direction to get jittered result. */
- vec2 dir_jittered = vec2(dot(ssao_samples[sample_index].xy, rotX),
- dot(ssao_samples[sample_index].xy, rotY));
- dir_jittered.xy *= ssao_samples[sample_index].z + noise.b;
+ vec2 dir_jittered = vec2(dot(sample_coord.xy, rotX), dot(sample_coord.xy, rotY));
+ dir_jittered.xy *= sample_coord.z + noise.b;
- vec2 uvcoords = screenco.xy + dir_jittered * offset;
-
- if (uvcoords.x > 1.0 || uvcoords.x < 0.0 || uvcoords.y > 1.0 || uvcoords.y < 0.0) {
+ vec2 uvcoords = screenco + dir_jittered * offset;
+ /* Out of screen case. */
+ if (any(greaterThan(abs(uvcoords - 0.5), vec2(0.5)))) {
continue;
}
-
- float depth_new = texture(depthBuffer, uvcoords).r;
-
+ /* Sample depth. */
+ float s_depth = texture(depthBuffer, uvcoords).r;
/* Handle Background case */
- bool is_background = (depth_new == 1.0);
-
+ bool is_background = (s_depth == 1.0);
/* This trick provide good edge effect even if no neighbor is found. */
- vec3 pos_new = get_view_space_from_depth(uvcoords, (is_background) ? depth : depth_new);
+ s_depth = (is_background) ? depth : s_depth;
+ vec3 s_pos = view_position_from_depth(
+ uvcoords, s_depth, world_data.viewvecs, ProjectionMatrix);
if (is_background) {
- pos_new.z -= ssao_distance;
+ s_pos.z -= world_data.cavity_distance;
}
- vec3 dir = pos_new - position;
+ vec3 dir = s_pos - position;
float len = length(dir);
float f_cavities = dot(dir, normal);
float f_edge = -f_cavities;
float f_bias = 0.05 * len + 0.0001;
- float attenuation = 1.0 / (len * (1.0 + len * len * ssao_attenuation));
+ float attenuation = 1.0 / (len * (1.0 + len * len * world_data.cavity_attenuation));
/* use minor bias here to avoid self shadowing */
if (f_cavities > -f_bias) {
@@ -82,11 +92,10 @@ void ssao_factors(in float depth,
edges += f_edge * attenuation;
}
}
-
- cavities /= ssao_samples_num;
- edges /= ssao_samples_num;
+ cavities *= world_data.cavity_sample_count_inv;
+ edges *= world_data.cavity_sample_count_inv;
/* don't let cavity wash out the surface appearance */
- cavities = clamp(cavities * ssao_factor_cavity, 0.0, 1.0);
- edges = edges * ssao_factor_edge;
+ cavities = clamp(cavities * world_data.cavity_valley_factor, 0.0, 1.0);
+ edges = edges * world_data.cavity_ridge_factor;
}
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..25eaf003e07 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl
@@ -1,30 +1,16 @@
-#define NO_OBJECT_ID uint(0)
+
#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)));
-
-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];
-}
-
#ifdef WORKBENCH_ENCODE_NORMALS
# define WB_Normal vec2
/* 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 +23,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,161 +34,64 @@ 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. */
+/* Encoding into the alpha of a RGBA16F texture. (10bit mantissa) */
#define TARGET_BITCOUNT 8u
#define METALLIC_BITS 3u /* Metallic channel is less important. */
#define ROUGHNESS_BITS (TARGET_BITCOUNT - METALLIC_BITS)
-#define TOTAL_BITS (METALLIC_BITS + ROUGHNESS_BITS)
/* Encode 2 float into 1 with the desired precision. */
float workbench_float_pair_encode(float v1, float v2)
{
- // const uint total_mask = ~(0xFFFFFFFFu << TOTAL_BITS);
// const uint v1_mask = ~(0xFFFFFFFFu << ROUGHNESS_BITS);
// const uint v2_mask = ~(0xFFFFFFFFu << METALLIC_BITS);
/* Same as above because some compiler are dumb af. and think we use mediump int. */
- const int total_mask = 0xFF;
const int v1_mask = 0x1F;
const int v2_mask = 0x7;
int iv1 = int(v1 * float(v1_mask));
int iv2 = int(v2 * float(v2_mask)) << int(ROUGHNESS_BITS);
- return float(iv1 | iv2) * (1.0 / float(total_mask));
+ return float(iv1 | iv2);
}
void workbench_float_pair_decode(float data, out float v1, out float v2)
{
- // const uint total_mask = ~(0xFFFFFFFFu << TOTAL_BITS);
// const uint v1_mask = ~(0xFFFFFFFFu << ROUGHNESS_BITS);
// const uint v2_mask = ~(0xFFFFFFFFu << METALLIC_BITS);
/* Same as above because some compiler are dumb af. and think we use mediump int. */
- const int total_mask = 0xFF;
const int v1_mask = 0x1F;
const int v2_mask = 0x7;
- int idata = int(data * float(total_mask));
+ int idata = int(data);
v1 = float(idata & v1_mask) * (1.0 / float(v1_mask));
v2 = float(idata >> int(ROUGHNESS_BITS)) * (1.0 / float(v2_mask));
}
-float calculate_transparent_weight(float z, float alpha)
-{
-#if 0
- /* Eq 10 : Good for surfaces with varying opacity (like particles) */
- float a = min(1.0, alpha * 10.0) + 0.01;
- float b = -gl_FragCoord.z * 0.95 + 1.0;
- float w = a * a * a * 3e2 * b * b * b;
-#else
- /* Eq 7 put more emphasis on surfaces closer to the view. */
- // float w = 10.0 / (1e-5 + pow(abs(z) / 5.0, 2.0) + pow(abs(z) / 200.0, 6.0)); /* Eq 7 */
- // float w = 10.0 / (1e-5 + pow(abs(z) / 10.0, 3.0) + pow(abs(z) / 200.0, 6.0)); /* Eq 8 */
- // float w = 10.0 / (1e-5 + pow(abs(z) / 200.0, 4.0)); /* Eq 9 */
- /* Same as eq 7, but optimized. */
- float a = abs(z) / 5.0;
- float b = abs(z) / 200.0;
- b *= b;
- float w = 10.0 / ((1e-5 + a * a) + b * (b * b)); /* Eq 7 */
-#endif
- return alpha * clamp(w, 1e-2, 3e2);
-}
-
-/* Special function only to be used with calculate_transparent_weight(). */
-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)
{
if (proj_mat[3][3] == 0.0) {
- float d = 2.0 * depth - 1.0;
- return -proj_mat[3][2] / (d + proj_mat[2][2]);
+ return normalize(viewvecs[0].xyz + vec3(uv, 0.0) * viewvecs[1].xyz);
}
else {
- /* Return depth from near plane. */
- return depth * viewvecs[1].z;
- }
-}
-
-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);
-}
-
-vec2 matcap_uv_compute(vec3 I, vec3 N, bool flipped)
-{
- /* Quick creation of an orthonormal basis */
- float a = 1.0 / (1.0 + I.z);
- float b = -I.x * I.y * a;
- vec3 b1 = vec3(1.0 - I.x * I.x * a, b, -I.x);
- vec3 b2 = vec3(b, 1.0 - I.y * I.y * a, -I.y);
- vec2 matcap_uv = vec2(dot(b1, N), dot(b2, N));
- if (flipped) {
- matcap_uv.x = -matcap_uv.x;
+ return vec3(0.0, 0.0, 1.0);
}
- return matcap_uv * 0.496 + 0.5;
}
-bool node_tex_tile_lookup(inout vec3 co, sampler2DArray ima, sampler1DArray map)
+vec3 view_position_from_depth(vec2 uvcoords, float depth, vec4 viewvecs[3], mat4 proj_mat)
{
- 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;
-}
+ if (proj_mat[3][3] == 0.0) {
+ /* Perspective */
+ float d = 2.0 * depth - 1.0;
-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);
+ float zview = -proj_mat[3][2] / (d + proj_mat[2][2]);
- /* 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 zview * (viewvecs[0].xyz + vec3(uvcoords, 0.0) * viewvecs[1].xyz);
}
+ else {
+ /* Orthographic */
+ vec3 offset = vec3(uvcoords, depth);
- 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 viewvecs[0].xyz + offset * viewvecs[1].xyz;
}
-
- 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..cdb9823096c
--- /dev/null
+++ b/source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl
@@ -0,0 +1,44 @@
+
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_common_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_matcap_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_world_light_lib.glsl)
+
+uniform sampler2D materialBuffer;
+uniform sampler2D normalBuffer;
+
+in vec4 uvcoordsvar;
+
+out vec4 fragColor;
+
+void main()
+{
+ /* Normal and Incident vector are in viewspace. Lighting is evaluated in viewspace. */
+ vec3 I = view_vector_from_screen_uv(uvcoordsvar.st, world_data.viewvecs, ProjectionMatrix);
+ vec3 N = workbench_normal_decode(texture(normalBuffer, uvcoordsvar.st));
+ vec4 mat_data = texture(materialBuffer, uvcoordsvar.st);
+
+ vec3 base_color = mat_data.rgb;
+
+ float roughness, metallic;
+ workbench_float_pair_decode(mat_data.a, roughness, metallic);
+
+#ifdef V3D_LIGHTING_MATCAP
+ /* When using matcaps, mat_data.a is the backface sign. */
+ N = (mat_data.a > 0.0) ? N : -N;
+
+ fragColor.rgb = get_matcap_lighting(base_color, N, I);
+#endif
+
+#ifdef V3D_LIGHTING_STUDIO
+ fragColor.rgb = get_world_lighting(base_color, roughness, metallic, N, I);
+#endif
+
+#ifdef V3D_LIGHTING_FLAT
+ fragColor.rgb = base_color;
+#endif
+
+ fragColor.rgb *= get_shadow(N);
+
+ fragColor.a = 1.0;
+}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_curvature_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_curvature_lib.glsl
index 22dc906be83..e6bc4c7bbc6 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_curvature_lib.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_curvature_lib.glsl
@@ -1,6 +1,5 @@
-#ifndef CURVATURE_OFFSET
-# define CURVATURE_OFFSET 1
-#endif
+
+#pragma BLENDER_REQUIRE(workbench_data_lib.glsl)
float curvature_soft_clamp(float curvature, float control)
{
@@ -10,33 +9,35 @@ float curvature_soft_clamp(float curvature, float control)
return 0.25 / control;
}
-float calculate_curvature(
- usampler2D objectId, sampler2D normalBuffer, ivec2 texel, float ridge, float valley)
+void curvature_compute(vec2 uv,
+ usampler2D objectIdBuffer,
+ sampler2D normalBuffer,
+ out float curvature)
{
- uint object_up = texelFetchOffset(objectId, texel, 0, ivec2(0, CURVATURE_OFFSET)).r;
- uint object_down = texelFetchOffset(objectId, texel, 0, ivec2(0, -CURVATURE_OFFSET)).r;
- uint object_left = texelFetchOffset(objectId, texel, 0, ivec2(-CURVATURE_OFFSET, 0)).r;
- uint object_right = texelFetchOffset(objectId, texel, 0, ivec2(CURVATURE_OFFSET, 0)).r;
+ curvature = 0.0;
+
+ vec3 offset = vec3(world_data.viewport_size_inv, 0.0) * world_data.ui_scale;
+ uint object_up = texture(objectIdBuffer, uv + offset.zy).r;
+ uint object_down = texture(objectIdBuffer, uv - offset.zy).r;
+ uint object_right = texture(objectIdBuffer, uv + offset.xz).r;
+ uint object_left = texture(objectIdBuffer, uv - offset.xz).r;
+ /* Remove object outlines. */
if ((object_up != object_down) || (object_right != object_left)) {
- return 0.0;
+ return;
}
- vec2 normal_up = texelFetchOffset(normalBuffer, texel, 0, ivec2(0, CURVATURE_OFFSET)).rg;
- vec2 normal_down = texelFetchOffset(normalBuffer, texel, 0, ivec2(0, -CURVATURE_OFFSET)).rg;
- vec2 normal_left = texelFetchOffset(normalBuffer, texel, 0, ivec2(-CURVATURE_OFFSET, 0)).rg;
- vec2 normal_right = texelFetchOffset(normalBuffer, texel, 0, ivec2(CURVATURE_OFFSET, 0)).rg;
-
- normal_up = workbench_normal_decode(normal_up).rg;
- normal_down = workbench_normal_decode(normal_down).rg;
- normal_left = workbench_normal_decode(normal_left).rg;
- normal_right = workbench_normal_decode(normal_right).rg;
+ float normal_up = workbench_normal_decode(texture(normalBuffer, uv + offset.zy)).g;
+ float normal_down = workbench_normal_decode(texture(normalBuffer, uv - offset.zy)).g;
+ float normal_right = workbench_normal_decode(texture(normalBuffer, uv + offset.xz)).r;
+ float normal_left = workbench_normal_decode(texture(normalBuffer, uv - offset.xz)).r;
- float normal_diff = ((normal_up.g - normal_down.g) + (normal_right.r - normal_left.r));
+ float normal_diff = (normal_up - normal_down) + (normal_right - normal_left);
if (normal_diff < 0) {
- return -2.0 * curvature_soft_clamp(-normal_diff, valley);
+ curvature = -2.0 * curvature_soft_clamp(-normal_diff, world_data.curvature_valley);
+ }
+ else {
+ curvature = 2.0 * curvature_soft_clamp(normal_diff, world_data.curvature_ridge);
}
-
- return 2.0 * curvature_soft_clamp(normal_diff, ridge);
}
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..5f3283e1643 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl
@@ -5,12 +5,42 @@ struct LightData {
};
struct WorldData {
+ vec4 viewvecs[3];
+ vec4 viewport_size;
vec4 object_outline_color;
vec4 shadow_direction_vs;
+ float shadow_focus;
+ float shadow_shift;
+ float shadow_mul;
+ float shadow_add;
+ /* - 16 bytes alignment- */
LightData lights[4];
vec4 ambient_color;
- int num_lights;
- int matcap_orientation;
+
+ int cavity_sample_start;
+ int cavity_sample_end;
+ float cavity_sample_count_inv;
+ float cavity_jitter_scale;
+
+ float cavity_valley_factor;
+ float cavity_ridge_factor;
+ float cavity_attenuation;
+ float cavity_distance;
+
float curvature_ridge;
float curvature_valley;
+ float ui_scale;
+ float _pad0;
+
+ int matcap_orientation;
+ bool use_specular;
+ int _pad1;
+ int _pad2;
+};
+
+#define viewport_size_inv viewport_size.zw
+
+layout(std140) uniform world_block
+{
+ WorldData world_data;
};
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_deferred_background_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_deferred_background_frag.glsl
deleted file mode 100644
index 22fa2babbbf..00000000000
--- a/source/blender/draw/engines/workbench/shaders/workbench_deferred_background_frag.glsl
+++ /dev/null
@@ -1,30 +0,0 @@
-
-uniform usampler2D objectId;
-
-uniform vec2 invertedViewportSize;
-
-out vec4 fragColor;
-
-layout(std140) uniform world_block
-{
- WorldData world_data;
-};
-
-void main()
-{
- vec2 uv_viewport = gl_FragCoord.xy * invertedViewportSize;
-
-#ifndef V3D_SHADING_OBJECT_OUTLINE
-
- fragColor = vec4(0.0);
-
-#else /* !V3D_SHADING_OBJECT_OUTLINE */
-
- ivec2 texel = ivec2(gl_FragCoord.xy);
- uint object_id = texelFetch(objectId, texel, 0).r;
- float object_outline = calculate_object_outline(objectId, texel, object_id);
-
- fragColor = vec4(world_data.object_outline_color.rgb, 1.0) * (1.0 - object_outline);
-
-#endif /* !V3D_SHADING_OBJECT_OUTLINE */
-}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl
deleted file mode 100644
index fd4cea4279a..00000000000
--- a/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl
+++ /dev/null
@@ -1,103 +0,0 @@
-out vec4 fragColor;
-
-uniform usampler2D objectId;
-uniform sampler2D materialBuffer;
-uniform sampler2D normalBuffer;
-/* normalBuffer contains viewport normals */
-uniform sampler2D cavityBuffer;
-uniform sampler2D matcapDiffuseImage;
-uniform sampler2D matcapSpecularImage;
-
-uniform vec2 invertedViewportSize;
-uniform vec4 viewvecs[3];
-uniform float shadowMultiplier;
-uniform float lightMultiplier;
-uniform float shadowShift = 0.1;
-uniform float shadowFocus = 1.0;
-
-uniform vec3 materialSingleColor;
-
-layout(std140) uniform world_block
-{
- WorldData world_data;
-};
-
-void main()
-{
- ivec2 texel = ivec2(gl_FragCoord.xy);
- vec2 uv_viewport = gl_FragCoord.xy * invertedViewportSize;
-
- float roughness, metallic;
- vec3 base_color;
-
-#ifndef MATDATA_PASS_ENABLED
- base_color = materialSingleColor;
- metallic = 0.0;
- roughness = 0.5;
-#else
- vec4 material_data = texelFetch(materialBuffer, texel, 0);
- base_color = material_data.rgb;
- workbench_float_pair_decode(material_data.a, roughness, metallic);
-#endif
-
-/* Do we need normals */
-#ifdef NORMAL_VIEWPORT_PASS_ENABLED
- vec3 normal_viewport = workbench_normal_decode(texelFetch(normalBuffer, texel, 0).rg);
-#endif
-
- vec3 I_vs = view_vector_from_screen_uv(uv_viewport, viewvecs, ProjectionMatrix);
-
- /* -------- SHADING --------- */
-#ifdef V3D_LIGHTING_FLAT
- vec3 shaded_color = base_color;
-
-#elif defined(V3D_LIGHTING_MATCAP)
- /* When using matcaps, the metallic is the backface sign. */
- normal_viewport = (metallic > 0.0) ? normal_viewport : -normal_viewport;
- bool flipped = world_data.matcap_orientation != 0;
- vec2 matcap_uv = matcap_uv_compute(I_vs, normal_viewport, flipped);
- vec3 matcap_diffuse = textureLod(matcapDiffuseImage, matcap_uv, 0.0).rgb;
-
-# ifdef V3D_SHADING_SPECULAR_HIGHLIGHT
- vec3 matcap_specular = textureLod(matcapSpecularImage, matcap_uv, 0.0).rgb;
-# else
- vec3 matcap_specular = vec3(0.0);
-# endif
-
- vec3 shaded_color = matcap_diffuse * base_color + matcap_specular;
-
-#elif defined(V3D_LIGHTING_STUDIO)
-
-# ifdef V3D_SHADING_SPECULAR_HIGHLIGHT
- vec3 specular_color = mix(vec3(0.05), base_color, metallic);
- vec3 diffuse_color = mix(base_color, vec3(0.0), metallic);
-# else
- roughness = 0.0;
- vec3 specular_color = vec3(0.0);
- vec3 diffuse_color = base_color;
-# endif
-
- vec3 shaded_color = get_world_lighting(
- world_data, diffuse_color, specular_color, roughness, normal_viewport, I_vs);
-#endif
-
- /* -------- POST EFFECTS --------- */
-#ifdef WB_CAVITY
- /* Using UNORM texture so decompress the range */
- shaded_color *= texelFetch(cavityBuffer, texel, 0).r * CAVITY_BUFFER_RANGE;
-#endif
-
-#ifdef V3D_SHADING_SHADOW
- float light_factor = -dot(normal_viewport, world_data.shadow_direction_vs.xyz);
- float shadow_mix = smoothstep(shadowFocus, shadowShift, light_factor);
- shaded_color *= mix(lightMultiplier, shadowMultiplier, shadow_mix);
-#endif
-
-#ifdef V3D_SHADING_OBJECT_OUTLINE
- uint object_id = texelFetch(objectId, texel, 0).r;
- float object_outline = calculate_object_outline(objectId, texel, object_id);
- shaded_color = mix(world_data.object_outline_color.rgb, shaded_color, object_outline);
-#endif
-
- fragColor = vec4(shaded_color, 1.0);
-}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_effect_cavity_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_effect_cavity_frag.glsl
new file mode 100644
index 00000000000..328d50e69e0
--- /dev/null
+++ b/source/blender/draw/engines/workbench/shaders/workbench_effect_cavity_frag.glsl
@@ -0,0 +1,31 @@
+
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_common_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_cavity_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_curvature_lib.glsl)
+
+uniform sampler2D depthBuffer;
+uniform sampler2D normalBuffer;
+uniform usampler2D objectIdBuffer;
+
+in vec4 uvcoordsvar;
+
+out vec4 fragColor;
+
+void main()
+{
+ float cavity = 0.0, edges = 0.0, curvature = 0.0;
+
+#ifdef USE_CAVITY
+ cavity_compute(uvcoordsvar.st, depthBuffer, normalBuffer, cavity, edges);
+#endif
+
+#ifdef USE_CURVATURE
+ curvature_compute(uvcoordsvar.st, objectIdBuffer, normalBuffer, curvature);
+#endif
+
+ float final_cavity_factor = clamp((1.0 - cavity) * (1.0 + edges) * (1.0 + curvature), 0.0, 4.0);
+
+ fragColor.rgb = vec3(final_cavity_factor);
+ fragColor.a = 1.0;
+}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_effect_fxaa_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_effect_fxaa_frag.glsl
deleted file mode 100644
index 95ca2c0c297..00000000000
--- a/source/blender/draw/engines/workbench/shaders/workbench_effect_fxaa_frag.glsl
+++ /dev/null
@@ -1,14 +0,0 @@
-
-in vec4 uvcoordsvar;
-
-out vec4 FragColor;
-
-uniform sampler2D colorBuffer;
-uniform vec2 invertedViewportSize;
-
-void main()
-{
- ivec2 texel = ivec2(gl_FragCoord.xy);
- FragColor = FxaaPixelShader(
- uvcoordsvar.st, colorBuffer, invertedViewportSize, 1.0, 0.166, 0.0833);
-}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_effect_outline_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_effect_outline_frag.glsl
new file mode 100644
index 00000000000..fb6fdb93462
--- /dev/null
+++ b/source/blender/draw/engines/workbench/shaders/workbench_effect_outline_frag.glsl
@@ -0,0 +1,24 @@
+
+#pragma BLENDER_REQUIRE(workbench_data_lib.glsl)
+
+uniform usampler2D objectIdBuffer;
+
+in vec4 uvcoordsvar;
+
+out vec4 fragColor;
+
+void main()
+{
+ vec3 offset = vec3(world_data.viewport_size_inv, 0.0) * world_data.ui_scale;
+ vec2 uv = uvcoordsvar.st;
+
+ uint center_id = texture(objectIdBuffer, uv).r;
+ uvec4 adjacent_ids = uvec4(texture(objectIdBuffer, uv + offset.zy).r,
+ texture(objectIdBuffer, uv - offset.zy).r,
+ texture(objectIdBuffer, uv + offset.xz).r,
+ texture(objectIdBuffer, uv - offset.xz).r);
+
+ float outline_opacity = 1.0 - dot(vec4(equal(uvec4(center_id), adjacent_ids)), vec4(0.25));
+
+ fragColor = world_data.object_outline_color * outline_opacity;
+}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_effect_smaa_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_effect_smaa_frag.glsl
new file mode 100644
index 00000000000..2dea2fc4883
--- /dev/null
+++ b/source/blender/draw/engines/workbench/shaders/workbench_effect_smaa_frag.glsl
@@ -0,0 +1,44 @@
+
+uniform sampler2D edgesTex;
+uniform sampler2D areaTex;
+uniform sampler2D searchTex;
+uniform sampler2D blendTex;
+uniform sampler2D colorTex;
+uniform float mixFactor;
+uniform float taaSampleCountInv;
+
+in vec2 uvs;
+in vec2 pixcoord;
+in vec4 offset[3];
+
+#if SMAA_STAGE == 0
+out vec2 fragColor;
+#else
+out vec4 fragColor;
+#endif
+
+void main()
+{
+#if SMAA_STAGE == 0
+ /* Detect edges in color and revealage buffer. */
+ fragColor = SMAALumaEdgeDetectionPS(uvs, offset, colorTex);
+ /* Discard if there is no edge. */
+ if (dot(fragColor, float2(1.0, 1.0)) == 0.0) {
+ discard;
+ }
+
+#elif SMAA_STAGE == 1
+ fragColor = SMAABlendingWeightCalculationPS(
+ uvs, pixcoord, offset, edgesTex, areaTex, searchTex, vec4(0));
+
+#elif SMAA_STAGE == 2
+ fragColor = vec4(0.0);
+ if (mixFactor > 0.0) {
+ fragColor += SMAANeighborhoodBlendingPS(uvs, offset[0], colorTex, blendTex) * mixFactor;
+ }
+ if (mixFactor < 1.0) {
+ fragColor += texture(colorTex, uvs) * (1.0 - mixFactor);
+ }
+ fragColor *= taaSampleCountInv;
+#endif
+}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_effect_smaa_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_effect_smaa_vert.glsl
new file mode 100644
index 00000000000..07734d19972
--- /dev/null
+++ b/source/blender/draw/engines/workbench/shaders/workbench_effect_smaa_vert.glsl
@@ -0,0 +1,21 @@
+
+out vec2 uvs;
+out vec2 pixcoord;
+out vec4 offset[3];
+
+void main()
+{
+ int v = gl_VertexID % 3;
+ float x = -1.0 + float((v & 1) << 2);
+ float y = -1.0 + float((v & 2) << 1);
+ gl_Position = vec4(x, y, 1.0, 1.0);
+ uvs = (gl_Position.xy + 1.0) * 0.5;
+
+#if SMAA_STAGE == 0
+ SMAAEdgeDetectionVS(uvs, offset);
+#elif SMAA_STAGE == 1
+ SMAABlendingWeightCalculationVS(uvs, pixcoord, offset);
+#elif SMAA_STAGE == 2
+ SMAANeighborhoodBlendingVS(uvs, offset[0]);
+#endif
+}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_effect_taa_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_effect_taa_frag.glsl
index 5795268f794..b877c2c3f76 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_effect_taa_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_effect_taa_frag.glsl
@@ -1,14 +1,11 @@
-uniform sampler2D historyBuffer;
+
uniform sampler2D colorBuffer;
-out vec4 colorOutput;
+in vec4 uvcoordsvar;
-uniform float mixFactor;
+out vec4 fragColor;
void main()
{
- ivec2 texel = ivec2(gl_FragCoord.xy);
- vec4 color_buffer = texelFetch(colorBuffer, texel, 0);
- vec4 history_buffer = texelFetch(historyBuffer, texel, 0);
- colorOutput = mix(history_buffer, color_buffer, mixFactor);
+ fragColor = texture(colorBuffer, uvcoordsvar.st);
}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_forward_composite_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_forward_composite_frag.glsl
deleted file mode 100644
index 0a4d64b37ad..00000000000
--- a/source/blender/draw/engines/workbench/shaders/workbench_forward_composite_frag.glsl
+++ /dev/null
@@ -1,36 +0,0 @@
-out vec4 fragColor;
-
-uniform usampler2D objectId;
-uniform sampler2D transparentAccum;
-uniform sampler2D transparentRevealage;
-uniform vec2 invertedViewportSize;
-
-#ifndef ALPHA_COMPOSITE
-layout(std140) uniform world_block
-{
- WorldData world_data;
-};
-#endif
-
-/* TODO: Bypass the whole shader if there is no xray pass and no outline pass. */
-void main()
-{
- ivec2 texel = ivec2(gl_FragCoord.xy);
- vec2 uv_viewport = gl_FragCoord.xy * invertedViewportSize;
-
- /* Listing 4 */
- vec4 trans_accum = texelFetch(transparentAccum, texel, 0);
- float trans_revealage = trans_accum.a;
- trans_accum.a = texelFetch(transparentRevealage, texel, 0).r;
-
- vec3 trans_color = trans_accum.rgb / clamp(trans_accum.a, 1e-4, 5e4);
-
- fragColor.a = 1.0 - trans_revealage;
- fragColor.rgb = trans_color * fragColor.a;
-
-#ifdef V3D_SHADING_OBJECT_OUTLINE
- uint object_id = texelFetch(objectId, texel, 0).r;
- float outline = calculate_object_outline(objectId, texel, object_id);
- fragColor = mix(vec4(world_data.object_outline_color.rgb, 1.0), fragColor, outline);
-#endif
-}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_forward_depth_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_forward_depth_frag.glsl
deleted file mode 100644
index abd8c1f6579..00000000000
--- a/source/blender/draw/engines/workbench/shaders/workbench_forward_depth_frag.glsl
+++ /dev/null
@@ -1,20 +0,0 @@
-
-layout(location = 0) out uint objectId;
-
-uniform float ImageTransparencyCutoff = 0.1;
-#ifdef V3D_SHADING_TEXTURE_COLOR
-uniform sampler2D image;
-
-in vec2 uv_interp;
-#endif
-
-void main()
-{
-#ifdef V3D_SHADING_TEXTURE_COLOR
- if (texture(image, uv_interp).a < ImageTransparencyCutoff) {
- discard;
- }
-#endif
-
- objectId = uint(resource_id + 1) & 0xFFu;
-}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl
deleted file mode 100644
index 559dc07c107..00000000000
--- a/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl
+++ /dev/null
@@ -1,118 +0,0 @@
-
-uniform float ImageTransparencyCutoff = 0.1;
-#ifdef TEXTURE_IMAGE_ARRAY
-uniform sampler2DArray image_tile_array;
-uniform sampler1DArray image_tile_data;
-#else
-uniform sampler2D image;
-#endif
-uniform bool imageNearest;
-uniform bool imagePremultiplied;
-
-uniform float alpha = 0.5;
-uniform vec2 invertedViewportSize;
-uniform vec4 viewvecs[3];
-
-uniform vec4 materialColorAndMetal;
-uniform float materialRoughness;
-
-uniform float shadowMultiplier = 0.5;
-uniform float lightMultiplier = 1.0;
-uniform float shadowShift = 0.1;
-uniform float shadowFocus = 1.0;
-
-#ifdef NORMAL_VIEWPORT_PASS_ENABLED
-in vec3 normal_viewport;
-#endif /* NORMAL_VIEWPORT_PASS_ENABLED */
-#ifdef V3D_SHADING_TEXTURE_COLOR
-in vec2 uv_interp;
-#endif
-#ifdef V3D_SHADING_VERTEX_COLOR
-in vec3 vertexColor;
-#endif
-#ifdef V3D_LIGHTING_MATCAP
-uniform sampler2D matcapDiffuseImage;
-uniform sampler2D matcapSpecularImage;
-#endif
-
-layout(std140) uniform world_block
-{
- WorldData world_data;
-};
-
-layout(location = 0) out vec4 transparentAccum;
-layout(location = 1) out
- float revealageAccum; /* revealage actually stored in transparentAccum.a */
-
-void main()
-{
- vec4 base_color;
-
-#if defined(V3D_SHADING_TEXTURE_COLOR)
-# ifdef TEXTURE_IMAGE_ARRAY
- base_color = workbench_sample_texture_array(
- image_tile_array, image_tile_data, uv_interp, imageNearest, imagePremultiplied);
-# else
- base_color = workbench_sample_texture(image, uv_interp, imageNearest, imagePremultiplied);
-# endif
- if (base_color.a < ImageTransparencyCutoff) {
- discard;
- }
-#elif defined(V3D_SHADING_VERTEX_COLOR)
- base_color.rgb = vertexColor;
-#else
- base_color.rgb = materialColorAndMetal.rgb;
-#endif /* V3D_SHADING_TEXTURE_COLOR */
-
- vec2 uv_viewport = gl_FragCoord.xy * invertedViewportSize;
- vec3 I_vs = view_vector_from_screen_uv(uv_viewport, viewvecs, ProjectionMatrix);
-
-#ifdef NORMAL_VIEWPORT_PASS_ENABLED
- vec3 nor = normalize(normal_viewport);
-#endif
-
- /* -------- SHADING --------- */
-#ifdef V3D_LIGHTING_FLAT
- vec3 shaded_color = base_color.rgb;
-
-#elif defined(V3D_LIGHTING_MATCAP)
- bool flipped = world_data.matcap_orientation != 0;
- vec2 matcap_uv = matcap_uv_compute(I_vs, nor, flipped);
- vec3 matcap_diffuse = textureLod(matcapDiffuseImage, matcap_uv, 0.0).rgb;
-# ifdef V3D_SHADING_SPECULAR_HIGHLIGHT
- vec3 matcap_specular = textureLod(matcapSpecularImage, matcap_uv, 0.0).rgb;
-# else
- vec3 matcap_specular = vec3(0.0);
-# endif
- vec3 shaded_color = matcap_diffuse * base_color.rgb + matcap_specular;
-
-#elif defined(V3D_LIGHTING_STUDIO)
-# ifdef V3D_SHADING_SPECULAR_HIGHLIGHT
- float metallic = materialColorAndMetal.a;
- vec3 specular_color = mix(vec3(0.05), base_color.rgb, metallic);
- vec3 diffuse_color = mix(base_color.rgb, vec3(0.0), metallic);
-# else
- vec3 specular_color = vec3(0.0);
- vec3 diffuse_color = base_color.rgb;
-# endif
-
- vec3 shaded_color = get_world_lighting(
- world_data, diffuse_color, specular_color, materialRoughness, nor, I_vs);
-#endif
-
-#ifdef V3D_SHADING_SHADOW
- float light_factor = -dot(nor, world_data.shadow_direction_vs.xyz);
- float shadow_mix = smoothstep(shadowFocus, shadowShift, light_factor);
- shaded_color *= mix(lightMultiplier, shadowMultiplier, shadow_mix);
-#endif
-
- /* Based on :
- * McGuire and Bavoil, Weighted Blended Order-Independent Transparency, Journal of
- * Computer Graphics Techniques (JCGT), vol. 2, no. 2, 122–141, 2013
- */
- /* Listing 4 */
- float z = linear_zdepth(gl_FragCoord.z, viewvecs, ProjectionMatrix);
- float weight = calculate_transparent_weight(z, alpha);
- transparentAccum = vec4(shaded_color * weight, alpha);
- revealageAccum = weight;
-}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_ghost_resolve_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_ghost_resolve_frag.glsl
deleted file mode 100644
index d223a7650c5..00000000000
--- a/source/blender/draw/engines/workbench/shaders/workbench_ghost_resolve_frag.glsl
+++ /dev/null
@@ -1,13 +0,0 @@
-uniform sampler2D depthBuffer;
-
-void main(void)
-{
- float depth = texelFetch(depthBuffer, ivec2(gl_FragCoord.xy), 0).r;
-
- /* background, discard */
- if (depth >= 1.0) {
- discard;
- }
-
- gl_FragDepth = depth;
-}
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..6f99739f259
--- /dev/null
+++ b/source/blender/draw/engines/workbench/shaders/workbench_image_lib.glsl
@@ -0,0 +1,83 @@
+
+/* TODO(fclem) deduplicate code. */
+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)
+{
+ 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;
+ return texture(image, uv);
+}
+
+vec4 workbench_sample_texture_array(sampler2DArray tile_array,
+ sampler1DArray tile_data,
+ vec2 coord,
+ bool nearest_sampling)
+{
+ 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;
+ return texture(tile_array, uv);
+}
+
+uniform sampler2DArray imageTileArray;
+uniform sampler1DArray imageTileData;
+uniform sampler2D imageTexture;
+
+uniform float imageTransparencyCutoff = 0.1;
+uniform bool imageNearest;
+uniform bool imagePremult;
+
+vec3 workbench_image_color(vec2 uvs)
+{
+#ifdef V3D_SHADING_TEXTURE_COLOR
+# ifdef TEXTURE_IMAGE_ARRAY
+ vec4 color = workbench_sample_texture_array(imageTileArray, imageTileData, uvs, imageNearest);
+# else
+ vec4 color = workbench_sample_texture(imageTexture, uvs, imageNearest);
+# endif
+
+ /* Unpremultiply if stored multiplied, since straight alpha is expected by shaders. */
+ if (imagePremult && !(color.a == 0.0 || color.a == 1.0)) {
+ color.rgb /= color.a;
+ }
+
+# ifdef GPU_FRAGMENT_SHADER
+ if (color.a < imageTransparencyCutoff) {
+ discard;
+ }
+# endif
+
+ return color.rgb;
+#else
+ return vec3(1.0);
+#endif
+}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_matcap_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_matcap_lib.glsl
new file mode 100644
index 00000000000..2d18cc1b014
--- /dev/null
+++ b/source/blender/draw/engines/workbench/shaders/workbench_matcap_lib.glsl
@@ -0,0 +1,30 @@
+
+#pragma BLENDER_REQUIRE(workbench_data_lib.glsl)
+
+vec2 matcap_uv_compute(vec3 I, vec3 N, bool flipped)
+{
+ /* Quick creation of an orthonormal basis */
+ float a = 1.0 / (1.0 + I.z);
+ float b = -I.x * I.y * a;
+ vec3 b1 = vec3(1.0 - I.x * I.x * a, b, -I.x);
+ vec3 b2 = vec3(b, 1.0 - I.y * I.y * a, -I.y);
+ vec2 matcap_uv = vec2(dot(b1, N), dot(b2, N));
+ if (flipped) {
+ matcap_uv.x = -matcap_uv.x;
+ }
+ return matcap_uv * 0.496 + 0.5;
+}
+
+uniform sampler2D matcapDiffuseImage;
+uniform sampler2D matcapSpecularImage;
+
+vec3 get_matcap_lighting(vec3 base_color, vec3 N, vec3 I)
+{
+ bool flipped = world_data.matcap_orientation != 0;
+ vec2 uv = matcap_uv_compute(I, N, flipped);
+
+ vec3 diffuse = textureLod(matcapDiffuseImage, uv, 0.0).rgb;
+ vec3 specular = textureLod(matcapSpecularImage, uv, 0.0).rgb;
+
+ return diffuse * base_color + specular * float(world_data.use_specular);
+}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_material_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_material_lib.glsl
new file mode 100644
index 00000000000..1d8950e34b3
--- /dev/null
+++ b/source/blender/draw/engines/workbench/shaders/workbench_material_lib.glsl
@@ -0,0 +1,21 @@
+
+layout(std140) uniform material_block
+{
+ vec4 mat_data[4096];
+};
+
+/* If set to -1, the resource handle is used instead. */
+uniform int materialIndex;
+
+void workbench_material_data_get(
+ int handle, out vec3 color, out float alpha, out float roughness, out float metallic)
+{
+ handle = (materialIndex != -1) ? materialIndex : handle;
+ vec4 data = mat_data[uint(handle) & 0xFFFu];
+ color = data.rgb;
+
+ uint encoded_data = floatBitsToUint(data.w);
+ alpha = float((encoded_data >> 16u) & 0xFFu) * (1.0 / 255.0);
+ roughness = float((encoded_data >> 8u) & 0xFFu) * (1.0 / 255.0);
+ metallic = float(encoded_data & 0xFFu) * (1.0 / 255.0);
+}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_merge_infront_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_merge_infront_frag.glsl
new file mode 100644
index 00000000000..58becb03290
--- /dev/null
+++ b/source/blender/draw/engines/workbench/shaders/workbench_merge_infront_frag.glsl
@@ -0,0 +1,18 @@
+
+uniform sampler2D depthBuffer;
+
+in vec4 uvcoordsvar;
+
+out vec4 fragColor;
+
+void main()
+{
+ float depth = texture(depthBuffer, uvcoordsvar.st).r;
+ /* Discard background pixels. */
+ if (depth == 1.0) {
+ discard;
+ }
+ /* Make this fragment occlude any fragment that will try to
+ * render over it in the normal passes. */
+ gl_FragDepth = 0.0;
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_object_outline_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_object_outline_lib.glsl
deleted file mode 100644
index a4a5d9c31a3..00000000000
--- a/source/blender/draw/engines/workbench/shaders/workbench_object_outline_lib.glsl
+++ /dev/null
@@ -1,12 +0,0 @@
-#define OBJECT_OUTLINE_OFFSET 1
-
-float calculate_object_outline(usampler2D objectId, ivec2 texel, uint object_id)
-{
- uvec4 oid_offset = uvec4(
- texelFetchOffset(objectId, texel, 0, ivec2(0, OBJECT_OUTLINE_OFFSET)).r,
- texelFetchOffset(objectId, texel, 0, ivec2(0, -OBJECT_OUTLINE_OFFSET)).r,
- texelFetchOffset(objectId, texel, 0, ivec2(-OBJECT_OUTLINE_OFFSET, 0)).r,
- texelFetchOffset(objectId, texel, 0, ivec2(OBJECT_OUTLINE_OFFSET, 0)).r);
-
- return dot(vec4(equal(uvec4(object_id), oid_offset)), vec4(0.25));
-}
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..6d24b001d4d 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 +1,29 @@
-uniform vec4 materialColorAndMetal;
-uniform float materialRoughness;
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_shader_interface_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_common_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_image_lib.glsl)
-#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
+layout(location = 1) out WB_Normal normalData;
+layout(location = 2) out uint objectId;
+
+uniform bool useMatcap = false;
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
+ normalData = workbench_normal_encode(gl_FrontFacing, normal_interp);
-# 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 = vec4(color_interp, packed_rough_metal);
- materialData.rgb = color.rgb;
- materialData.a = workbench_float_pair_encode(roughness, metallic);
-#endif /* MATDATA_PASS_ENABLED */
+ objectId = uint(object_id);
-#ifdef OBJECT_ID_PASS_ENABLED
- objectId = uint(resource_id + 1) & 0xFFu;
-#endif
+ if (useMatcap) {
+ /* For matcaps, save front facing in alpha channel. */
+ materialData.a = float(gl_FrontFacing);
+ }
-#ifdef NORMAL_VIEWPORT_PASS_ENABLED
- vec3 n = (gl_FrontFacing) ? normal_viewport : -normal_viewport;
- n = normalize(n);
- normalViewport = workbench_normal_encode(n);
+#ifdef V3D_SHADING_TEXTURE_COLOR
+ materialData.rgb = workbench_image_color(uv_interp);
#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..6a7bc185fe9
--- /dev/null
+++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_hair_vert.glsl
@@ -0,0 +1,94 @@
+#pragma BLENDER_REQUIRE(common_hair_lib.glsl)
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_shader_interface_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_common_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_material_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_image_lib.glsl)
+
+uniform samplerBuffer ac; /* active color layer */
+uniform samplerBuffer au; /* active texture layer */
+
+/* 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_random_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 workbench_hair_random_material(float rand,
+ inout vec3 color,
+ inout float roughness,
+ inout float metallic)
+{
+ /* Center noise around 0. */
+ rand -= 0.5;
+ rand *= 0.1;
+ /* Add some variation to the hairs to avoid uniform look. */
+ metallic = clamp(metallic + rand, 0.0, 1.0);
+ roughness = clamp(roughness + rand, 0.0, 1.0);
+ /* Modulate by color intensity to reduce very high contrast when color is dark. */
+ color = clamp(color + rand * (color + 0.05), 0.0, 1.0);
+}
+
+void main()
+{
+ bool is_persp = (ProjectionMatrix[3][3] == 0.0);
+ float time, thick_time, thickness;
+ vec3 world_pos, tan, binor;
+ hair_get_pos_tan_binor_time(is_persp,
+ ModelMatrixInverse,
+ ViewMatrixInverse[3].xyz,
+ ViewMatrixInverse[2].xyz,
+ world_pos,
+ tan,
+ binor,
+ time,
+ thickness,
+ thick_time);
+
+ gl_Position = point_world_to_ndc(world_pos);
+
+ float hair_rand = integer_noise(hair_get_strand_id());
+ vec3 nor = workbench_hair_random_normal(tan, binor, hair_rand);
+
+#ifdef USE_WORLD_CLIP_PLANES
+ world_clip_planes_calc_clip_distance(world_pos);
+#endif
+
+ uv_interp = hair_get_customdata_vec2(au);
+
+ normal_interp = normalize(normal_world_to_view(nor));
+
+#ifdef OPAQUE_MATERIAL
+ float metallic, roughness;
+#endif
+ workbench_material_data_get(resource_handle, color_interp, alpha_interp, roughness, metallic);
+
+ if (materialIndex == 0) {
+ color_interp = hair_get_customdata_vec3(ac);
+ }
+
+ /* Hairs have lots of layer and can rapidly become the most prominent surface.
+ * So we lower their alpha artificially. */
+ alpha_interp *= 0.3;
+
+ workbench_hair_random_material(hair_rand, color_interp, roughness, metallic);
+
+#ifdef OPAQUE_MATERIAL
+ packed_rough_metal = workbench_float_pair_encode(roughness, metallic);
+#endif
+
+ object_id = int((uint(resource_id) + 1u) & 0xFFu);
+}
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..31e298d1540 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,40 @@
-#ifndef HAIR_SHADER
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_shader_interface_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_common_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_material_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_image_lib.glsl)
+
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;
-}
+in vec2 au; /* active texture layer */
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;
+#ifdef USE_WORLD_CLIP_PLANES
+ world_clip_planes_calc_clip_distance(world_pos);
#endif
-#ifdef V3D_SHADING_VERTEX_COLOR
-# ifndef HAIR_SHADER
- vertexColor = ac.rgb;
-# else
- vertexColor = hair_get_customdata_vec4(ac).rgb;
-# endif
-#endif
+ uv_interp = au;
-#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
+ normal_interp = normalize(normal_object_to_view(nor));
-#ifdef OBJECT_ID_PASS_ENABLED
- PASS_RESOURCE_ID
+#ifdef OPAQUE_MATERIAL
+ float metallic, roughness;
#endif
+ workbench_material_data_get(resource_handle, color_interp, alpha_interp, roughness, metallic);
-#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance(world_pos);
+ if (materialIndex == 0) {
+ color_interp = ac.rgb;
+ }
+
+#ifdef OPAQUE_MATERIAL
+ packed_rough_metal = workbench_float_pair_encode(roughness, metallic);
#endif
+
+ object_id = int((uint(resource_id) + 1u) & 0xFFu);
}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_shader_interface_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_shader_interface_lib.glsl
new file mode 100644
index 00000000000..8e2f7ba4735
--- /dev/null
+++ b/source/blender/draw/engines/workbench/shaders/workbench_shader_interface_lib.glsl
@@ -0,0 +1,21 @@
+
+#ifdef GPU_VERTEX_SHADER
+# define IN_OUT out
+#else
+# define IN_OUT in
+#endif
+
+IN_OUT ShaderStageInterface
+{
+ vec3 normal_interp;
+ vec3 color_interp;
+ float alpha_interp;
+ vec2 uv_interp;
+#ifdef TRANSPARENT_MATERIAL
+ flat float roughness;
+ flat float metallic;
+#else
+ flat float packed_rough_metal;
+#endif
+ flat int object_id;
+};
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_shadow_debug_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_shadow_debug_frag.glsl
index 6b0741b6d1b..6fa76510e6e 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_shadow_debug_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_shadow_debug_frag.glsl
@@ -1,15 +1,19 @@
out vec4 fragColor;
+layout(location = 0) out vec4 materialData;
+layout(location = 1) out vec4 normalData;
+layout(location = 2) out uint objectId;
+
void main()
{
- const float intensity = 0.25;
+ const float a = 0.25;
#ifdef SHADOW_PASS
- fragColor = vec4(
- (gl_FrontFacing) ? vec3(intensity, -intensity, 0.0) : vec3(-intensity, intensity, 0.0), 1.0);
+ materialData.rgb = gl_FrontFacing ? vec3(a, -a, 0.0) : vec3(-a, a, 0.0);
#else
- fragColor = vec4((gl_FrontFacing) ? vec3(intensity, intensity, -intensity) :
- vec3(-intensity, -intensity, intensity),
- 1.0);
+ materialData.rgb = gl_FrontFacing ? vec3(a, a, -a) : vec3(-a, -a, a);
#endif
+ materialData.a = 0.0;
+ normalData = vec4(0.0);
+ objectId = 0u;
}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_transparent_accum_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_transparent_accum_frag.glsl
new file mode 100644
index 00000000000..3c2d1a9c0c7
--- /dev/null
+++ b/source/blender/draw/engines/workbench/shaders/workbench_transparent_accum_frag.glsl
@@ -0,0 +1,89 @@
+
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_shader_interface_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_common_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_image_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_matcap_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_world_light_lib.glsl)
+
+/* Revealage is actually stored in transparentAccum alpha channel.
+ * This is a workaround to older hardware not having separate blend equation per render target. */
+layout(location = 0) out vec4 transparentAccum;
+layout(location = 1) out vec4 revealageAccum;
+
+/* Note: Blending will be skipped on objectId because output is a non-normalized integer buffer. */
+layout(location = 2) out uint objectId;
+
+/* Special function only to be used with calculate_transparent_weight(). */
+float linear_zdepth(float depth, vec4 viewvecs[3], mat4 proj_mat)
+{
+ if (proj_mat[3][3] == 0.0) {
+ float d = 2.0 * depth - 1.0;
+ return -proj_mat[3][2] / (d + proj_mat[2][2]);
+ }
+ else {
+ /* Return depth from near plane. */
+ return depth * viewvecs[1].z;
+ }
+}
+
+/* Based on :
+ * McGuire and Bavoil, Weighted Blended Order-Independent Transparency, Journal of
+ * Computer Graphics Techniques (JCGT), vol. 2, no. 2, 122–141, 2013
+ */
+float calculate_transparent_weight(void)
+{
+ float z = linear_zdepth(gl_FragCoord.z, world_data.viewvecs, ProjectionMatrix);
+#if 0
+ /* Eq 10 : Good for surfaces with varying opacity (like particles) */
+ float a = min(1.0, alpha * 10.0) + 0.01;
+ float b = -gl_FragCoord.z * 0.95 + 1.0;
+ float w = a * a * a * 3e2 * b * b * b;
+#else
+ /* Eq 7 put more emphasis on surfaces closer to the view. */
+ // float w = 10.0 / (1e-5 + pow(abs(z) / 5.0, 2.0) + pow(abs(z) / 200.0, 6.0)); /* Eq 7 */
+ // float w = 10.0 / (1e-5 + pow(abs(z) / 10.0, 3.0) + pow(abs(z) / 200.0, 6.0)); /* Eq 8 */
+ // float w = 10.0 / (1e-5 + pow(abs(z) / 200.0, 4.0)); /* Eq 9 */
+ /* Same as eq 7, but optimized. */
+ float a = abs(z) / 5.0;
+ float b = abs(z) / 200.0;
+ b *= b;
+ float w = 10.0 / ((1e-5 + a * a) + b * (b * b)); /* Eq 7 */
+#endif
+ return clamp(w, 1e-2, 3e2);
+}
+
+void main()
+{
+ /* Normal and Incident vector are in viewspace. Lighting is evaluated in viewspace. */
+ vec2 uv_viewport = gl_FragCoord.xy * world_data.viewport_size_inv;
+ vec3 I = view_vector_from_screen_uv(uv_viewport, world_data.viewvecs, ProjectionMatrix);
+ vec3 N = normalize(normal_interp);
+
+ vec3 color = color_interp;
+
+#ifdef V3D_SHADING_TEXTURE_COLOR
+ color = workbench_image_color(uv_interp);
+#endif
+
+#ifdef V3D_LIGHTING_MATCAP
+ vec3 shaded_color = get_matcap_lighting(color, N, I);
+#endif
+
+#ifdef V3D_LIGHTING_STUDIO
+ vec3 shaded_color = get_world_lighting(color, roughness, metallic, N, I);
+#endif
+
+#ifdef V3D_LIGHTING_FLAT
+ vec3 shaded_color = color;
+#endif
+
+ shaded_color *= get_shadow(N);
+
+ /* Listing 4 */
+ float weight = calculate_transparent_weight() * alpha_interp;
+ transparentAccum = vec4(shaded_color * weight, alpha_interp);
+ revealageAccum = vec4(weight);
+
+ objectId = uint(object_id);
+}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_transparent_resolve_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_transparent_resolve_frag.glsl
new file mode 100644
index 00000000000..d985737a35b
--- /dev/null
+++ b/source/blender/draw/engines/workbench/shaders/workbench_transparent_resolve_frag.glsl
@@ -0,0 +1,26 @@
+
+uniform sampler2D transparentAccum;
+uniform sampler2D transparentRevealage;
+
+in vec4 uvcoordsvar;
+
+out vec4 fragColor;
+
+/* Based on :
+ * McGuire and Bavoil, Weighted Blended Order-Independent Transparency, Journal of
+ * Computer Graphics Techniques (JCGT), vol. 2, no. 2, 122–141, 2013
+ */
+
+void main()
+{
+ /* Revealage is actually stored in transparentAccum alpha channel.
+ * This is a workaround to older hardware not having separate blend equation per render target.
+ */
+ vec4 trans_accum = texture(transparentAccum, uvcoordsvar.st);
+ float trans_weight = texture(transparentRevealage, uvcoordsvar.st).r;
+ float trans_reveal = trans_accum.a;
+
+ /* Listing 4 */
+ fragColor.rgb = trans_accum.rgb / clamp(trans_weight, 1e-4, 5e4);
+ fragColor.a = 1.0 - trans_reveal;
+}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl
index 585e48ae7ec..e957f8bbe9c 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl
@@ -1,4 +1,9 @@
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+#pragma BLENDER_REQUIRE(gpu_shader_common_obinfos_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_data_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_common_lib.glsl)
+
uniform sampler2D depthBuffer;
uniform sampler3D densityTexture;
@@ -8,10 +13,9 @@ uniform sampler1D flameColorTexture;
uniform sampler1D transferTexture;
uniform int samplesLen = 256;
-uniform float noiseOfs = 0.0f;
+uniform float noiseOfs = 0.0;
uniform float stepLength; /* Step length in local space. */
uniform float densityScale; /* Simple Opacity multiplicator. */
-uniform vec4 viewvecs[3];
uniform vec3 activeColor;
uniform float slicePosition;
@@ -23,34 +27,11 @@ in vec3 localPos;
out vec4 fragColor;
-#define M_PI 3.1415926535897932 /* pi */
-
float phase_function_isotropic()
{
return 1.0 / (4.0 * M_PI);
}
-float get_view_z_from_depth(float depth)
-{
- if (ProjectionMatrix[3][3] == 0.0) {
- float d = 2.0 * depth - 1.0;
- return -ProjectionMatrix[3][2] / (d + ProjectionMatrix[2][2]);
- }
- else {
- return viewvecs[0].z + depth * viewvecs[1].z;
- }
-}
-
-vec3 get_view_space_from_depth(vec2 uvcoords, float depth)
-{
- if (ProjectionMatrix[3][3] == 0.0) {
- return vec3(viewvecs[0].xy + uvcoords * viewvecs[1].xy, 1.0) * get_view_z_from_depth(depth);
- }
- else {
- return viewvecs[0].xyz + vec3(uvcoords, depth) * viewvecs[1].xyz;
- }
-}
-
float max_v3(vec3 v)
{
return max(v.x, max(v.y, v.z));
@@ -209,8 +190,10 @@ void main()
float depth = texelFetch(depthBuffer, ivec2(gl_FragCoord.xy), 0).r;
float depth_end = min(depth, gl_FragCoord.z);
- vec3 vs_ray_end = get_view_space_from_depth(screen_uv, depth_end);
- vec3 vs_ray_ori = get_view_space_from_depth(screen_uv, 0.0);
+ vec3 vs_ray_end = view_position_from_depth(
+ screen_uv, depth_end, world_data.viewvecs, ProjectionMatrix);
+ vec3 vs_ray_ori = view_position_from_depth(
+ screen_uv, 0.0, world_data.viewvecs, ProjectionMatrix);
vec3 vs_ray_dir = (is_persp) ? (vs_ray_end - vs_ray_ori) : vec3(0.0, 0.0, -1.0);
vs_ray_dir /= abs(vs_ray_dir.z);
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl
index 3542a1a91fc..1a32a202290 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl
@@ -1,4 +1,7 @@
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+#pragma BLENDER_REQUIRE(gpu_shader_common_obinfos_lib.glsl)
+
uniform float slicePosition;
uniform int sliceAxis; /* -1 is no slice, 0 is X, 1 is Y, 2 is Z. */
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..81f6e651be0 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,9 +43,19 @@ 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 base_color, float roughness, float metallic, vec3 N, vec3 I)
{
+ vec3 specular_color, diffuse_color;
+
+ if (world_data.use_specular) {
+ diffuse_color = mix(base_color, vec3(0.0), metallic);
+ specular_color = mix(vec3(0.05), base_color, metallic);
+ }
+ else {
+ diffuse_color = base_color;
+ specular_color = vec3(0.0);
+ }
+
vec3 specular_light = world_data.ambient_color.rgb;
vec3 diffuse_light = world_data.ambient_color.rgb;
vec4 wrap = vec4(world_data.lights[0].diffuse_color_wrap.a,
@@ -51,37 +63,37 @@ vec3 get_world_lighting(
world_data.lights[2].diffuse_color_wrap.a,
world_data.lights[3].diffuse_color_wrap.a);
-#ifdef V3D_SHADING_SPECULAR_HIGHLIGHT
- /* Prepare Specular computation. Eval 4 lights at once. */
- vec3 R = -reflect(I, N);
- vec4 spec_angle, spec_NL, wrap_NL;
- prep_specular(world_data.lights[0].direction.xyz, I, N, R, spec_NL.x, wrap_NL.x, spec_angle.x);
- prep_specular(world_data.lights[1].direction.xyz, I, N, R, spec_NL.y, wrap_NL.y, spec_angle.y);
- prep_specular(world_data.lights[2].direction.xyz, I, N, R, spec_NL.z, wrap_NL.z, spec_angle.z);
- prep_specular(world_data.lights[3].direction.xyz, I, N, R, spec_NL.w, wrap_NL.w, spec_angle.w);
-
- vec4 gloss = vec4(1.0 - roughness);
- /* Reduce gloss for smooth light. (simulate bigger light) */
- gloss *= 1.0 - wrap;
- vec4 shininess = exp2(10.0 * gloss + 1.0);
-
- vec4 spec_light = blinn_specular(shininess, spec_angle, spec_NL);
-
- /* Simulate Env. light. */
- vec4 w = mix(wrap, vec4(1.0), roughness);
- vec4 spec_env = wrapped_lighting(wrap_NL, w);
-
- spec_light = mix(spec_light, spec_env, wrap * wrap);
-
- /* Multiply result by lights specular colors. */
- specular_light += spec_light.x * world_data.lights[0].specular_color.rgb;
- specular_light += spec_light.y * world_data.lights[1].specular_color.rgb;
- specular_light += spec_light.z * world_data.lights[2].specular_color.rgb;
- specular_light += spec_light.w * world_data.lights[3].specular_color.rgb;
-
- float NV = clamp(dot(N, I), 0.0, 1.0);
- specular_color = brdf_approx(specular_color, roughness, NV);
-#endif
+ if (world_data.use_specular) {
+ /* Prepare Specular computation. Eval 4 lights at once. */
+ vec3 R = -reflect(I, N);
+ vec4 spec_angle, spec_NL, wrap_NL;
+ prep_specular(world_data.lights[0].direction.xyz, I, N, R, spec_NL.x, wrap_NL.x, spec_angle.x);
+ prep_specular(world_data.lights[1].direction.xyz, I, N, R, spec_NL.y, wrap_NL.y, spec_angle.y);
+ prep_specular(world_data.lights[2].direction.xyz, I, N, R, spec_NL.z, wrap_NL.z, spec_angle.z);
+ prep_specular(world_data.lights[3].direction.xyz, I, N, R, spec_NL.w, wrap_NL.w, spec_angle.w);
+
+ vec4 gloss = vec4(1.0 - roughness);
+ /* Reduce gloss for smooth light. (simulate bigger light) */
+ gloss *= 1.0 - wrap;
+ vec4 shininess = exp2(10.0 * gloss + 1.0);
+
+ vec4 spec_light = blinn_specular(shininess, spec_angle, spec_NL);
+
+ /* Simulate Env. light. */
+ vec4 w = mix(wrap, vec4(1.0), roughness);
+ vec4 spec_env = wrapped_lighting(wrap_NL, w);
+
+ spec_light = mix(spec_light, spec_env, wrap * wrap);
+
+ /* Multiply result by lights specular colors. */
+ specular_light += spec_light.x * world_data.lights[0].specular_color.rgb;
+ specular_light += spec_light.y * world_data.lights[1].specular_color.rgb;
+ specular_light += spec_light.z * world_data.lights[2].specular_color.rgb;
+ specular_light += spec_light.w * world_data.lights[3].specular_color.rgb;
+
+ float NV = clamp(dot(N, I), 0.0, 1.0);
+ specular_color = brdf_approx(specular_color, roughness, NV);
+ }
specular_light *= specular_color;
/* Prepare diffuse computation. Eval 4 lights at once. */
@@ -107,3 +119,13 @@ vec3 get_world_lighting(
return diffuse_light + specular_light;
}
+
+uniform bool forceShadowing = false;
+
+float get_shadow(vec3 N)
+{
+ float light_factor = -dot(N, world_data.shadow_direction_vs.xyz);
+ float shadow_mix = smoothstep(world_data.shadow_shift, world_data.shadow_focus, light_factor);
+ shadow_mix *= forceShadowing ? 0.0 : world_data.shadow_mul;
+ return shadow_mix + world_data.shadow_add;
+} \ No newline at end of file