diff options
author | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:17:24 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:21:24 +0300 |
commit | e12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch) | |
tree | 8cf3453d12edb177a218ef8009357518ec6cab6a /source/blender/draw/engines/workbench | |
parent | b3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff) |
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211.
For details on usage and instructions for migrating branches
without conflicts, see:
https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'source/blender/draw/engines/workbench')
41 files changed, 4738 insertions, 4496 deletions
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_background_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_background_lib.glsl index fda2fc85460..a6d7c4b393b 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_background_lib.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_background_lib.glsl @@ -1,3 +1,5 @@ -vec3 background_color(WorldData world_data, float y) { - return mix(world_data.background_color_low, world_data.background_color_high, y).xyz + bayer_dither_noise(); +vec3 background_color(WorldData world_data, float y) +{ + return mix(world_data.background_color_low, world_data.background_color_high, y).xyz + + bayer_dither_noise(); } diff --git a/source/blender/draw/engines/workbench/shaders/workbench_cavity_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_cavity_frag.glsl index 769d453bb18..8d66cd7b26c 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_cavity_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_cavity_frag.glsl @@ -14,64 +14,68 @@ uniform vec4 ssao_settings; uniform vec2 curvature_settings; uniform sampler2D ssao_jitter; -layout(std140) uniform samples_block { - vec4 ssao_samples[500]; +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_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 +#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; + if (WinMatrix[3][3] == 0.0) { + /* Perspective */ + float d = 2.0 * depth - 1.0; - float zview = -WinMatrix[3][2] / (d + WinMatrix[2][2]); + 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 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; - } + return viewvecs[0].xyz + offset * viewvecs[1].xyz; + } } /* forward declartion */ -void ssao_factors( - in float depth, in vec3 normal, in vec3 position, in vec2 screenco, - out float cavities, out float edges); - +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); + vec2 screenco = vec2(gl_FragCoord.xy) * invertedViewportSize; + ivec2 texel = ivec2(gl_FragCoord.xy); - float cavity = 0.0, edges = 0.0, curvature = 0.0; + 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); + 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); + 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); + 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); + 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); + /* 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 998517e2e72..1af786b648c 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl @@ -3,87 +3,90 @@ /* 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 ssao_factors(in float depth, + in vec3 normal, + in vec3 position, + in vec2 screenco, + 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) { - return; - } - - /* take the normalized ray direction here */ - vec3 noise = texture(ssao_jitter, screenco.xy * jitter_tilling).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; - /* 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. */ - - /* 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 uvcoords = screenco.xy + dir_jittered * offset; - - if (uvcoords.x > 1.0 || uvcoords.x < 0.0 || uvcoords.y > 1.0 || uvcoords.y < 0.0) { - continue; - } - - float depth_new = texture(depthBuffer, uvcoords).r; - - /* Handle Background case */ - bool is_background = (depth_new == 1.0); - - /* This trick provide good edge effect even if no neighboor is found. */ - vec3 pos_new = get_view_space_from_depth(uvcoords, (is_background) ? depth : depth_new); - - if (is_background) { - pos_new.z -= ssao_distance; - } - - vec3 dir = pos_new - 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)); - - /* use minor bias here to avoid self shadowing */ - if (f_cavities > -f_bias) { - cavities += f_cavities * attenuation; - } - - if (f_edge > f_bias) { - edges += f_edge * attenuation; - } - } - - cavities /= ssao_samples_num; - edges /= ssao_samples_num; - - /* 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 = edges = 0.0; + /* early out if there is no need for SSAO */ + if (ssao_factor_cavity == 0.0 && ssao_factor_edge == 0.0) { + return; + } + + /* take the normalized ray direction here */ + vec3 noise = texture(ssao_jitter, screenco.xy * jitter_tilling).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; + /* 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. */ + + /* 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 uvcoords = screenco.xy + dir_jittered * offset; + + if (uvcoords.x > 1.0 || uvcoords.x < 0.0 || uvcoords.y > 1.0 || uvcoords.y < 0.0) { + continue; + } + + float depth_new = texture(depthBuffer, uvcoords).r; + + /* Handle Background case */ + bool is_background = (depth_new == 1.0); + + /* This trick provide good edge effect even if no neighboor is found. */ + vec3 pos_new = get_view_space_from_depth(uvcoords, (is_background) ? depth : depth_new); + + if (is_background) { + pos_new.z -= ssao_distance; + } + + vec3 dir = pos_new - 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)); + + /* use minor bias here to avoid self shadowing */ + if (f_cavities > -f_bias) { + cavities += f_cavities * attenuation; + } + + if (f_edge > f_bias) { + edges += f_edge * attenuation; + } + } + + cavities /= ssao_samples_num; + edges /= ssao_samples_num; + + /* don't let cavity wash out the surface appearance */ + cavities = clamp(cavities * ssao_factor_cavity, 0.0, 1.0); + edges = edges * ssao_factor_edge; } diff --git a/source/blender/draw/engines/workbench/shaders/workbench_checkerboard_depth_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_checkerboard_depth_frag.glsl index 94fa5d51229..c9711e9c7d6 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_checkerboard_depth_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_checkerboard_depth_frag.glsl @@ -1,12 +1,10 @@ /* 4x4 bayer matrix. */ #define P(x) ((x + 0.5) * (1.0 / 16.0)) -const vec4 dither_mat[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)) -); +const vec4 dither_mat[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))); uniform float threshold = 0.5; uniform float offset = 0.0; @@ -20,19 +18,21 @@ uniform float offset = 0.0; void main() { #if NOISE == 0 - ivec2 tx = ivec2(gl_FragCoord.xy) % 4; - float noise = dither_mat[tx.x][tx.y]; + ivec2 tx = ivec2(gl_FragCoord.xy) % 4; + float noise = dither_mat[tx.x][tx.y]; #elif NOISE == 1 - /* Interlieved gradient noise by Jorge Jimenez - * http://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare */ - float noise = fract(offset + 52.9829189 * fract(0.06711056 * gl_FragCoord.x + 0.00583715 * gl_FragCoord.y)); + /* Interlieved gradient noise by Jorge Jimenez + * http://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare */ + float noise = fract( + offset + 52.9829189 * fract(0.06711056 * gl_FragCoord.x + 0.00583715 * gl_FragCoord.y)); #else -#error +# error #endif - if (noise > threshold) { - discard; - } else { - gl_FragDepth = 1.0; - } + if (noise > threshold) { + discard; + } + else { + gl_FragDepth = 1.0; + } } 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 5f3dbd75b15..c76ad8c1d7b 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl @@ -6,47 +6,46 @@ /* 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]; +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 +# define WB_Normal vec2 /* From http://aras-p.info/texts/CompactNormalStorage.html * Using Method #4: Spheremap Transform */ vec3 workbench_normal_decode(WB_Normal enc) { - vec2 fenc = enc.xy * 4.0 - 2.0; - float f = dot(fenc, fenc); - float g = sqrt(1.0 - f / 4.0); - vec3 n; - n.xy = fenc*g; - n.z = 1 - f / 2; - return n; + vec2 fenc = enc.xy * 4.0 - 2.0; + float f = dot(fenc, fenc); + float g = sqrt(1.0 - f / 4.0); + vec3 n; + n.xy = fenc * g; + n.z = 1 - f / 2; + return n; } /* From http://aras-p.info/texts/CompactNormalStorage.html * Using Method #4: Spheremap Transform */ WB_Normal workbench_normal_encode(vec3 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; + float p = sqrt(n.z * 8.0 + 8.0); + n.xy = clamp(n.xy / p + 0.5, 0.0, 1.0); + return n.xy; } #else -#define WB_Normal vec3 +# define WB_Normal vec3 /* Well just do nothing... */ # define workbench_normal_encode(a) (a) # define workbench_normal_decode(a) (a) @@ -61,113 +60,112 @@ WB_Normal workbench_normal_encode(vec3 n) /* 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)); + // 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)); } 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)); - v1 = float(idata & v1_mask) * (1.0 / float(v1_mask)); - v2 = float(idata >> int(ROUGHNESS_BITS)) * (1.0 / float(v2_mask)); + // 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)); + 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; + /* 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 */ + /* 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); + 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) { - 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; - } + 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; + } } 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); + 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 matcap_uv * 0.496 + 0.5; + /* 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; } float srgb_to_linearrgb(float c) { - if (c < 0.04045) { - return (c < 0.0) ? 0.0 : c * (1.0 / 12.92); - } - else { - return pow((c + 0.055) * (1.0 / 1.055), 2.4); - } + if (c < 0.04045) { + return (c < 0.0) ? 0.0 : c * (1.0 / 12.92); + } + else { + return pow((c + 0.055) * (1.0 / 1.055), 2.4); + } } vec4 srgb_to_linearrgb(vec4 col_from) { - vec4 col_to; - col_to.r = srgb_to_linearrgb(col_from.r); - col_to.g = srgb_to_linearrgb(col_from.g); - col_to.b = srgb_to_linearrgb(col_from.b); - col_to.a = col_from.a; - return col_to; + vec4 col_to; + col_to.r = srgb_to_linearrgb(col_from.r); + col_to.g = srgb_to_linearrgb(col_from.g); + col_to.b = srgb_to_linearrgb(col_from.b); + col_to.a = col_from.a; + return col_to; } vec4 workbench_sample_texture(sampler2D image, vec2 coord, bool srgb, 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; - vec4 color = texture(image, uv); - return (srgb) ? srgb_to_linearrgb(color) : color; + 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); + return (srgb) ? srgb_to_linearrgb(color) : color; } 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 d0281f6c85c..22dc906be83 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_curvature_lib.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_curvature_lib.glsl @@ -4,38 +4,39 @@ float curvature_soft_clamp(float curvature, float control) { - if (curvature < 0.5 / control) { - return curvature * (1.0 - curvature * control); - } - return 0.25 / control; + if (curvature < 0.5 / control) { + return curvature * (1.0 - curvature * control); + } + return 0.25 / control; } -float calculate_curvature(usampler2D objectId, sampler2D normalBuffer, ivec2 texel, float ridge, float valley) +float calculate_curvature( + usampler2D objectId, sampler2D normalBuffer, ivec2 texel, float ridge, float valley) { - 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; + 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; - if((object_up != object_down) || (object_right != object_left)) { - return 0.0; - } + if ((object_up != object_down) || (object_right != object_left)) { + return 0.0; + } - 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; + 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; + 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_diff = ((normal_up.g - normal_down.g) + (normal_right.r - normal_left.r)); + float normal_diff = ((normal_up.g - normal_down.g) + (normal_right.r - normal_left.r)); - if (normal_diff < 0) { - return -2.0 * curvature_soft_clamp(-normal_diff, valley); - } + if (normal_diff < 0) { + return -2.0 * curvature_soft_clamp(-normal_diff, valley); + } - return 2.0 * curvature_soft_clamp(normal_diff, 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 6deb29f6bca..16df56b393a 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl @@ -1,20 +1,20 @@ struct LightData { - vec4 direction; - vec4 specular_color; - vec4 diffuse_color_wrap; /* rgb: diffuse col a: wrapped lighting factor */ + vec4 direction; + vec4 specular_color; + vec4 diffuse_color_wrap; /* rgb: diffuse col a: wrapped lighting factor */ }; struct WorldData { - vec4 background_color_low; - vec4 background_color_high; - vec4 object_outline_color; - vec4 shadow_direction_vs; - LightData lights[4]; - vec4 ambient_color; - int num_lights; - int matcap_orientation; - float background_alpha; - float curvature_ridge; - float curvature_valley; - int pad[3]; + vec4 background_color_low; + vec4 background_color_high; + vec4 object_outline_color; + vec4 shadow_direction_vs; + LightData lights[4]; + vec4 ambient_color; + int num_lights; + int matcap_orientation; + float background_alpha; + float curvature_ridge; + float curvature_valley; + int pad[3]; }; 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 index 9e4394238ff..45ebf09d623 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_deferred_background_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_deferred_background_frag.glsl @@ -5,35 +5,36 @@ uniform vec2 invertedViewportSize; out vec4 fragColor; -layout(std140) uniform world_block { - WorldData world_data; +layout(std140) uniform world_block +{ + WorldData world_data; }; void main() { - vec2 uv_viewport = gl_FragCoord.xy * invertedViewportSize; - vec3 background = background_color(world_data, uv_viewport.y); + vec2 uv_viewport = gl_FragCoord.xy * invertedViewportSize; + vec3 background = background_color(world_data, uv_viewport.y); #ifndef V3D_SHADING_OBJECT_OUTLINE - fragColor = vec4(background, world_data.background_alpha); + fragColor = vec4(background, world_data.background_alpha); #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); - - if (object_outline == 0.0) { - fragColor = vec4(background, world_data.background_alpha); - } - else { - /* Do correct alpha blending. */ - vec4 background_color = vec4(background, 1.0) * world_data.background_alpha; - vec4 outline_color = vec4(world_data.object_outline_color.rgb, 1.0); - fragColor = mix(outline_color, background_color, object_outline); - fragColor = vec4(fragColor.rgb / max(1e-8, fragColor.a), fragColor.a); - } + ivec2 texel = ivec2(gl_FragCoord.xy); + uint object_id = texelFetch(objectId, texel, 0).r; + float object_outline = calculate_object_outline(objectId, texel, object_id); + + if (object_outline == 0.0) { + fragColor = vec4(background, world_data.background_alpha); + } + else { + /* Do correct alpha blending. */ + vec4 background_color = vec4(background, 1.0) * world_data.background_alpha; + vec4 outline_color = vec4(world_data.object_outline_color.rgb, 1.0); + fragColor = mix(outline_color, background_color, object_outline); + fragColor = vec4(fragColor.rgb / max(1e-8, fragColor.a), fragColor.a); + } #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 index 40e166bc7ac..65196c1a836 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl @@ -19,80 +19,80 @@ uniform float shadowFocus = 1.0; uniform vec3 materialSingleColor; -layout(std140) uniform world_block { - WorldData world_data; +layout(std140) uniform world_block +{ + WorldData world_data; }; void main() { - ivec2 texel = ivec2(gl_FragCoord.xy); - vec2 uv_viewport = gl_FragCoord.xy * invertedViewportSize; + ivec2 texel = ivec2(gl_FragCoord.xy); + vec2 uv_viewport = gl_FragCoord.xy * invertedViewportSize; - float roughness, metallic; - vec3 base_color; + float roughness, metallic; + vec3 base_color; #ifndef MATDATA_PASS_ENABLED - base_color = materialSingleColor; - metallic = 0.0; - roughness = 0.5; + 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); + 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); + vec3 normal_viewport = workbench_normal_decode(texelFetch(normalBuffer, texel, 0).rg); #endif - vec3 I_vs = view_vector_from_screen_uv(uv_viewport, viewvecs, ProjectionMatrix); + vec3 I_vs = view_vector_from_screen_uv(uv_viewport, viewvecs, ProjectionMatrix); - /* -------- SHADING --------- */ + /* -------- SHADING --------- */ #ifdef V3D_LIGHTING_FLAT - vec3 shaded_color = base_color; + 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 = textureLod(matcapImage, matcap_uv, 0.0).rgb; - vec3 shaded_color = matcap * base_color; + /* 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 = textureLod(matcapImage, matcap_uv, 0.0).rgb; + vec3 shaded_color = matcap * base_color; #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); + 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; + 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); + vec3 shaded_color = get_world_lighting( + world_data, diffuse_color, specular_color, roughness, normal_viewport, I_vs); #endif - /* -------- POST EFFECTS --------- */ + /* -------- POST EFFECTS --------- */ #ifdef WB_CAVITY - /* Using UNORM texture so decompress the range */ - shaded_color *= texelFetch(cavityBuffer, texel, 0).r * CAVITY_BUFFER_RANGE; + /* 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); + 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); + 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); + fragColor = vec4(shaded_color, 1.0); } diff --git a/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl index 1fb7a9cec46..54440f7b120 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl @@ -18,29 +18,42 @@ uniform sampler2D halfResColorTex; uniform sampler2D blurTex; uniform sampler2D noiseTex; -#define dof_aperturesize dofParams.x -#define dof_distance dofParams.y -#define dof_invsensorsize dofParams.z +#define dof_aperturesize dofParams.x +#define dof_distance dofParams.y +#define dof_invsensorsize dofParams.z -#define M_PI 3.1415926535897932 /* pi */ +#define M_PI 3.1415926535897932 /* pi */ -float max_v4(vec4 v) { return max(max(v.x, v.y), max(v.z, v.w)); } +float max_v4(vec4 v) +{ + return max(max(v.x, v.y), max(v.z, v.w)); +} -#define weighted_sum(a, b, c, d, e, e_sum) ((a) * e.x + (b) * e.y + (c) * e.z + (d) * e.w) / max(1e-6, e_sum); +#define weighted_sum(a, b, c, d, e, e_sum) \ + ((a)*e.x + (b)*e.y + (c)*e.z + (d)*e.w) / max(1e-6, e_sum); /* divide by sensor size to get the normalized size */ -#define calculate_coc(zdepth) (dof_aperturesize * (dof_distance / zdepth - 1.0) * dof_invsensorsize) +#define calculate_coc(zdepth) \ + (dof_aperturesize * (dof_distance / zdepth - 1.0) * dof_invsensorsize) #define linear_depth(z) \ - ((ProjectionMatrix[3][3] == 0.0) ? \ - (nearFar.x * nearFar.y) / (z * (nearFar.x - nearFar.y) + nearFar.y) : \ - (z * 2.0 - 1.0) * nearFar.y) - + ((ProjectionMatrix[3][3] == 0.0) ? \ + (nearFar.x * nearFar.y) / (z * (nearFar.x - nearFar.y) + nearFar.y) : \ + (z * 2.0 - 1.0) * nearFar.y) const float MAX_COC_SIZE = 100.0; -vec2 encode_coc(float near, float far) { return vec2(near, far) / MAX_COC_SIZE; } -float decode_coc(vec2 cocs) { return max(cocs.x, cocs.y) * MAX_COC_SIZE; } -float decode_signed_coc(vec2 cocs) { return ((cocs.x > cocs.y) ? cocs.x : -cocs.y) * MAX_COC_SIZE; } +vec2 encode_coc(float near, float far) +{ + return vec2(near, far) / MAX_COC_SIZE; +} +float decode_coc(vec2 cocs) +{ + return max(cocs.x, cocs.y) * MAX_COC_SIZE; +} +float decode_signed_coc(vec2 cocs) +{ + return ((cocs.x > cocs.y) ? cocs.x : -cocs.y) * MAX_COC_SIZE; +} /** * ----------------- STEP 0 ------------------ @@ -53,39 +66,39 @@ layout(location = 1) out vec2 normalizedCoc; void main() { - ivec4 texel = ivec4(gl_FragCoord.xyxy) * 2 + ivec4(0, 0, 1, 1); - - vec4 color1 = texelFetch(sceneColorTex, texel.xy, 0); - vec4 color2 = texelFetch(sceneColorTex, texel.zw, 0); - vec4 color3 = texelFetch(sceneColorTex, texel.zy, 0); - vec4 color4 = texelFetch(sceneColorTex, texel.xw, 0); - - vec4 depths; - depths.x = texelFetch(sceneDepthTex, texel.xy, 0).x; - depths.y = texelFetch(sceneDepthTex, texel.zw, 0).x; - depths.z = texelFetch(sceneDepthTex, texel.zy, 0).x; - depths.w = texelFetch(sceneDepthTex, texel.xw, 0).x; - - vec4 zdepths = linear_depth(depths); - vec4 cocs_near = calculate_coc(zdepths); - vec4 cocs_far = -cocs_near; - - float coc_near = max(max_v4(cocs_near), 0.0); - float coc_far = max(max_v4(cocs_far), 0.0); - - /* now we need to write the near-far fields premultiplied by the coc - * also use bilateral weighting by each coc values to avoid bleeding. */ - vec4 near_weights = step(0.0, cocs_near) * clamp(1.0 - abs(coc_near - cocs_near), 0.0, 1.0); - vec4 far_weights = step(0.0, cocs_far) * clamp(1.0 - abs(coc_far - cocs_far), 0.0, 1.0); - - /* now write output to weighted buffers. */ - /* Take far plane pixels in priority. */ - vec4 w = any(notEqual(far_weights, vec4(0.0))) ? far_weights : near_weights; - float tot_weight = dot(w, vec4(1.0)); - halfResColor = weighted_sum(color1, color2, color3, color4, w, tot_weight); - halfResColor = clamp(halfResColor, 0.0, 3.0); - - normalizedCoc = encode_coc(coc_near, coc_far); + ivec4 texel = ivec4(gl_FragCoord.xyxy) * 2 + ivec4(0, 0, 1, 1); + + vec4 color1 = texelFetch(sceneColorTex, texel.xy, 0); + vec4 color2 = texelFetch(sceneColorTex, texel.zw, 0); + vec4 color3 = texelFetch(sceneColorTex, texel.zy, 0); + vec4 color4 = texelFetch(sceneColorTex, texel.xw, 0); + + vec4 depths; + depths.x = texelFetch(sceneDepthTex, texel.xy, 0).x; + depths.y = texelFetch(sceneDepthTex, texel.zw, 0).x; + depths.z = texelFetch(sceneDepthTex, texel.zy, 0).x; + depths.w = texelFetch(sceneDepthTex, texel.xw, 0).x; + + vec4 zdepths = linear_depth(depths); + vec4 cocs_near = calculate_coc(zdepths); + vec4 cocs_far = -cocs_near; + + float coc_near = max(max_v4(cocs_near), 0.0); + float coc_far = max(max_v4(cocs_far), 0.0); + + /* now we need to write the near-far fields premultiplied by the coc + * also use bilateral weighting by each coc values to avoid bleeding. */ + vec4 near_weights = step(0.0, cocs_near) * clamp(1.0 - abs(coc_near - cocs_near), 0.0, 1.0); + vec4 far_weights = step(0.0, cocs_far) * clamp(1.0 - abs(coc_far - cocs_far), 0.0, 1.0); + + /* now write output to weighted buffers. */ + /* Take far plane pixels in priority. */ + vec4 w = any(notEqual(far_weights, vec4(0.0))) ? far_weights : near_weights; + float tot_weight = dot(w, vec4(1.0)); + halfResColor = weighted_sum(color1, color2, color3, color4, w, tot_weight); + halfResColor = clamp(halfResColor, 0.0, 3.0); + + normalizedCoc = encode_coc(coc_near, coc_far); } #endif @@ -100,36 +113,36 @@ layout(location = 1) out vec2 outCocs; void main() { - ivec4 texel = ivec4(gl_FragCoord.xyxy) * 2 + ivec4(0, 0, 1, 1); + ivec4 texel = ivec4(gl_FragCoord.xyxy) * 2 + ivec4(0, 0, 1, 1); - vec4 color1 = texelFetch(sceneColorTex, texel.xy, 0); - vec4 color2 = texelFetch(sceneColorTex, texel.zw, 0); - vec4 color3 = texelFetch(sceneColorTex, texel.zy, 0); - vec4 color4 = texelFetch(sceneColorTex, texel.xw, 0); + vec4 color1 = texelFetch(sceneColorTex, texel.xy, 0); + vec4 color2 = texelFetch(sceneColorTex, texel.zw, 0); + vec4 color3 = texelFetch(sceneColorTex, texel.zy, 0); + vec4 color4 = texelFetch(sceneColorTex, texel.xw, 0); - vec4 depths; - vec2 cocs1 = texelFetch(inputCocTex, texel.xy, 0).rg; - vec2 cocs2 = texelFetch(inputCocTex, texel.zw, 0).rg; - vec2 cocs3 = texelFetch(inputCocTex, texel.zy, 0).rg; - vec2 cocs4 = texelFetch(inputCocTex, texel.xw, 0).rg; + vec4 depths; + vec2 cocs1 = texelFetch(inputCocTex, texel.xy, 0).rg; + vec2 cocs2 = texelFetch(inputCocTex, texel.zw, 0).rg; + vec2 cocs3 = texelFetch(inputCocTex, texel.zy, 0).rg; + vec2 cocs4 = texelFetch(inputCocTex, texel.xw, 0).rg; - vec4 cocs_near = vec4(cocs1.r, cocs2.r, cocs3.r, cocs4.r) * MAX_COC_SIZE; - vec4 cocs_far = vec4(cocs1.g, cocs2.g, cocs3.g, cocs4.g) * MAX_COC_SIZE; + vec4 cocs_near = vec4(cocs1.r, cocs2.r, cocs3.r, cocs4.r) * MAX_COC_SIZE; + vec4 cocs_far = vec4(cocs1.g, cocs2.g, cocs3.g, cocs4.g) * MAX_COC_SIZE; - float coc_near = max_v4(cocs_near); - float coc_far = max_v4(cocs_far); + float coc_near = max_v4(cocs_near); + float coc_far = max_v4(cocs_far); - /* now we need to write the near-far fields premultiplied by the coc - * also use bilateral weighting by each coc values to avoid bleeding. */ - vec4 near_weights = step(0.0, cocs_near) * clamp(1.0 - abs(coc_near - cocs_near), 0.0, 1.0); - vec4 far_weights = step(0.0, cocs_far) * clamp(1.0 - abs(coc_far - cocs_far), 0.0, 1.0); + /* now we need to write the near-far fields premultiplied by the coc + * also use bilateral weighting by each coc values to avoid bleeding. */ + vec4 near_weights = step(0.0, cocs_near) * clamp(1.0 - abs(coc_near - cocs_near), 0.0, 1.0); + vec4 far_weights = step(0.0, cocs_far) * clamp(1.0 - abs(coc_far - cocs_far), 0.0, 1.0); - /* now write output to weighted buffers. */ - vec4 w = any(notEqual(far_weights, vec4(0.0))) ? far_weights : near_weights; - float tot_weight = dot(w, vec4(1.0)); - outColor = weighted_sum(color1, color2, color3, color4, w, tot_weight); + /* now write output to weighted buffers. */ + vec4 w = any(notEqual(far_weights, vec4(0.0))) ? far_weights : near_weights; + float tot_weight = dot(w, vec4(1.0)); + outColor = weighted_sum(color1, color2, color3, color4, w, tot_weight); - outCocs = encode_coc(coc_near, coc_far); + outCocs = encode_coc(coc_near, coc_far); } #endif @@ -143,28 +156,29 @@ layout(location = 0) out vec2 flattenedCoc; void main() { -#ifdef FLATTEN_HORIZONTAL - ivec2 texel = ivec2(gl_FragCoord.xy) * ivec2(8, 1); - vec2 cocs1 = texelFetchOffset(inputCocTex, texel, 0, ivec2(0, 0)).rg; - vec2 cocs2 = texelFetchOffset(inputCocTex, texel, 0, ivec2(1, 0)).rg; - vec2 cocs3 = texelFetchOffset(inputCocTex, texel, 0, ivec2(2, 0)).rg; - vec2 cocs4 = texelFetchOffset(inputCocTex, texel, 0, ivec2(3, 0)).rg; - vec2 cocs5 = texelFetchOffset(inputCocTex, texel, 0, ivec2(4, 0)).rg; - vec2 cocs6 = texelFetchOffset(inputCocTex, texel, 0, ivec2(5, 0)).rg; - vec2 cocs7 = texelFetchOffset(inputCocTex, texel, 0, ivec2(6, 0)).rg; - vec2 cocs8 = texelFetchOffset(inputCocTex, texel, 0, ivec2(7, 0)).rg; -#else /* FLATTEN_VERTICAL */ - ivec2 texel = ivec2(gl_FragCoord.xy) * ivec2(1, 8); - vec2 cocs1 = texelFetchOffset(inputCocTex, texel, 0, ivec2(0, 0)).rg; - vec2 cocs2 = texelFetchOffset(inputCocTex, texel, 0, ivec2(0, 1)).rg; - vec2 cocs3 = texelFetchOffset(inputCocTex, texel, 0, ivec2(0, 2)).rg; - vec2 cocs4 = texelFetchOffset(inputCocTex, texel, 0, ivec2(0, 3)).rg; - vec2 cocs5 = texelFetchOffset(inputCocTex, texel, 0, ivec2(0, 4)).rg; - vec2 cocs6 = texelFetchOffset(inputCocTex, texel, 0, ivec2(0, 5)).rg; - vec2 cocs7 = texelFetchOffset(inputCocTex, texel, 0, ivec2(0, 6)).rg; - vec2 cocs8 = texelFetchOffset(inputCocTex, texel, 0, ivec2(0, 7)).rg; -#endif - flattenedCoc = max(max(max(cocs1, cocs2), max(cocs3, cocs4)), max(max(cocs5, cocs6), max(cocs7, cocs8))); +# ifdef FLATTEN_HORIZONTAL + ivec2 texel = ivec2(gl_FragCoord.xy) * ivec2(8, 1); + vec2 cocs1 = texelFetchOffset(inputCocTex, texel, 0, ivec2(0, 0)).rg; + vec2 cocs2 = texelFetchOffset(inputCocTex, texel, 0, ivec2(1, 0)).rg; + vec2 cocs3 = texelFetchOffset(inputCocTex, texel, 0, ivec2(2, 0)).rg; + vec2 cocs4 = texelFetchOffset(inputCocTex, texel, 0, ivec2(3, 0)).rg; + vec2 cocs5 = texelFetchOffset(inputCocTex, texel, 0, ivec2(4, 0)).rg; + vec2 cocs6 = texelFetchOffset(inputCocTex, texel, 0, ivec2(5, 0)).rg; + vec2 cocs7 = texelFetchOffset(inputCocTex, texel, 0, ivec2(6, 0)).rg; + vec2 cocs8 = texelFetchOffset(inputCocTex, texel, 0, ivec2(7, 0)).rg; +# else /* FLATTEN_VERTICAL */ + ivec2 texel = ivec2(gl_FragCoord.xy) * ivec2(1, 8); + vec2 cocs1 = texelFetchOffset(inputCocTex, texel, 0, ivec2(0, 0)).rg; + vec2 cocs2 = texelFetchOffset(inputCocTex, texel, 0, ivec2(0, 1)).rg; + vec2 cocs3 = texelFetchOffset(inputCocTex, texel, 0, ivec2(0, 2)).rg; + vec2 cocs4 = texelFetchOffset(inputCocTex, texel, 0, ivec2(0, 3)).rg; + vec2 cocs5 = texelFetchOffset(inputCocTex, texel, 0, ivec2(0, 4)).rg; + vec2 cocs6 = texelFetchOffset(inputCocTex, texel, 0, ivec2(0, 5)).rg; + vec2 cocs7 = texelFetchOffset(inputCocTex, texel, 0, ivec2(0, 6)).rg; + vec2 cocs8 = texelFetchOffset(inputCocTex, texel, 0, ivec2(0, 7)).rg; +# endif + flattenedCoc = max(max(max(cocs1, cocs2), max(cocs3, cocs4)), + max(max(cocs5, cocs6), max(cocs7, cocs8))); } #endif @@ -178,27 +192,27 @@ layout(location = 0) out vec2 dilatedCoc; void main() { - vec2 texel_size = 1.0 / vec2(textureSize(inputCocTex, 0)); - vec2 uv = gl_FragCoord.xy * texel_size; -#ifdef DILATE_VERTICAL - vec2 cocs1 = texture(inputCocTex, uv + texel_size * vec2(-3, 0)).rg; - vec2 cocs2 = texture(inputCocTex, uv + texel_size * vec2(-2, 0)).rg; - vec2 cocs3 = texture(inputCocTex, uv + texel_size * vec2(-1, 0)).rg; - vec2 cocs4 = texture(inputCocTex, uv + texel_size * vec2( 0, 0)).rg; - vec2 cocs5 = texture(inputCocTex, uv + texel_size * vec2( 1, 0)).rg; - vec2 cocs6 = texture(inputCocTex, uv + texel_size * vec2( 2, 0)).rg; - vec2 cocs7 = texture(inputCocTex, uv + texel_size * vec2( 3, 0)).rg; -#else /* DILATE_HORIZONTAL */ - vec2 cocs1 = texture(inputCocTex, uv + texel_size * vec2(0, -3)).rg; - vec2 cocs2 = texture(inputCocTex, uv + texel_size * vec2(0, -2)).rg; - vec2 cocs3 = texture(inputCocTex, uv + texel_size * vec2(0, -1)).rg; - vec2 cocs4 = texture(inputCocTex, uv + texel_size * vec2(0, 0)).rg; - vec2 cocs5 = texture(inputCocTex, uv + texel_size * vec2(0, 1)).rg; - vec2 cocs6 = texture(inputCocTex, uv + texel_size * vec2(0, 2)).rg; - vec2 cocs7 = texture(inputCocTex, uv + texel_size * vec2(0, 3)).rg; -#endif - // dilatedCoc = max(max(cocs3, cocs4), max(max(cocs5, cocs6), cocs2)); - dilatedCoc = max(max(max(cocs1, cocs2), max(cocs3, cocs4)), max(max(cocs5, cocs6), cocs7)); + vec2 texel_size = 1.0 / vec2(textureSize(inputCocTex, 0)); + vec2 uv = gl_FragCoord.xy * texel_size; +# ifdef DILATE_VERTICAL + vec2 cocs1 = texture(inputCocTex, uv + texel_size * vec2(-3, 0)).rg; + vec2 cocs2 = texture(inputCocTex, uv + texel_size * vec2(-2, 0)).rg; + vec2 cocs3 = texture(inputCocTex, uv + texel_size * vec2(-1, 0)).rg; + vec2 cocs4 = texture(inputCocTex, uv + texel_size * vec2(0, 0)).rg; + vec2 cocs5 = texture(inputCocTex, uv + texel_size * vec2(1, 0)).rg; + vec2 cocs6 = texture(inputCocTex, uv + texel_size * vec2(2, 0)).rg; + vec2 cocs7 = texture(inputCocTex, uv + texel_size * vec2(3, 0)).rg; +# else /* DILATE_HORIZONTAL */ + vec2 cocs1 = texture(inputCocTex, uv + texel_size * vec2(0, -3)).rg; + vec2 cocs2 = texture(inputCocTex, uv + texel_size * vec2(0, -2)).rg; + vec2 cocs3 = texture(inputCocTex, uv + texel_size * vec2(0, -1)).rg; + vec2 cocs4 = texture(inputCocTex, uv + texel_size * vec2(0, 0)).rg; + vec2 cocs5 = texture(inputCocTex, uv + texel_size * vec2(0, 1)).rg; + vec2 cocs6 = texture(inputCocTex, uv + texel_size * vec2(0, 2)).rg; + vec2 cocs7 = texture(inputCocTex, uv + texel_size * vec2(0, 3)).rg; +# endif + // dilatedCoc = max(max(cocs3, cocs4), max(max(cocs5, cocs6), cocs2)); + dilatedCoc = max(max(max(cocs1, cocs2), max(cocs3, cocs4)), max(max(cocs5, cocs6), cocs7)); } #endif @@ -210,53 +224,55 @@ void main() #ifdef BLUR1 layout(location = 0) out vec4 blurColor; -#define NUM_SAMPLES 49 +# define NUM_SAMPLES 49 -layout(std140) uniform dofSamplesBlock { - vec4 samples[NUM_SAMPLES]; +layout(std140) uniform dofSamplesBlock +{ + vec4 samples[NUM_SAMPLES]; }; vec2 get_random_vector(float offset) { - /* Interlieved gradient noise by Jorge Jimenez - * http://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare */ - float ign = fract(offset + 52.9829189 * fract(0.06711056 * gl_FragCoord.x + 0.00583715 * gl_FragCoord.y)); - float bn = texelFetch(noiseTex, ivec2(gl_FragCoord.xy) % 64, 0).a; - float ang = M_PI * 2.0 * fract(bn + offset); - return vec2(cos(ang), sin(ang)) * sqrt(ign); - // return noise.rg * sqrt(ign); + /* Interlieved gradient noise by Jorge Jimenez + * http://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare */ + float ign = fract(offset + + 52.9829189 * fract(0.06711056 * gl_FragCoord.x + 0.00583715 * gl_FragCoord.y)); + float bn = texelFetch(noiseTex, ivec2(gl_FragCoord.xy) % 64, 0).a; + float ang = M_PI * 2.0 * fract(bn + offset); + return vec2(cos(ang), sin(ang)) * sqrt(ign); + // return noise.rg * sqrt(ign); } void main() { - vec2 uv = gl_FragCoord.xy * invertedViewportSize * 2.0; + vec2 uv = gl_FragCoord.xy * invertedViewportSize * 2.0; - vec2 size = vec2(textureSize(halfResColorTex, 0).xy); - ivec2 texel = ivec2(uv * size); + vec2 size = vec2(textureSize(halfResColorTex, 0).xy); + ivec2 texel = ivec2(uv * size); - vec4 color = vec4(0.0); - float tot = 1e-4; + vec4 color = vec4(0.0); + float tot = 1e-4; - float coc = decode_coc(texelFetch(inputCocTex, texel, 0).rg); - float max_radius = coc; - vec2 noise = get_random_vector(noiseOffset) * 0.2 * clamp(max_radius * 0.2 - 4.0, 0.0, 1.0); - for (int i = 0; i < NUM_SAMPLES; ++i) { - vec2 tc = uv + (noise + samples[i].xy) * invertedViewportSize * max_radius; + float coc = decode_coc(texelFetch(inputCocTex, texel, 0).rg); + float max_radius = coc; + vec2 noise = get_random_vector(noiseOffset) * 0.2 * clamp(max_radius * 0.2 - 4.0, 0.0, 1.0); + for (int i = 0; i < NUM_SAMPLES; ++i) { + vec2 tc = uv + (noise + samples[i].xy) * invertedViewportSize * max_radius; - /* decode_signed_coc return biggest coc. */ - coc = abs(decode_signed_coc(texture(inputCocTex, tc).rg)); + /* decode_signed_coc return biggest coc. */ + coc = abs(decode_signed_coc(texture(inputCocTex, tc).rg)); - float lod = log2(clamp((coc + min(coc, max_radius)) * 0.5 - 21.0, 0.0, 16.0) * 0.25); - vec4 samp = textureLod(halfResColorTex, tc, lod); + float lod = log2(clamp((coc + min(coc, max_radius)) * 0.5 - 21.0, 0.0, 16.0) * 0.25); + vec4 samp = textureLod(halfResColorTex, tc, lod); - float radius = samples[i].z * max_radius; - float weight = abs(coc) * smoothstep(radius - 0.5, radius + 0.5, abs(coc)); + float radius = samples[i].z * max_radius; + float weight = abs(coc) * smoothstep(radius - 0.5, radius + 0.5, abs(coc)); - color += samp * weight; - tot += weight; - } + color += samp * weight; + tot += weight; + } - blurColor = color / tot; + blurColor = color / tot; } #endif @@ -297,48 +313,70 @@ out vec4 finalColor; void main() { - /* Half Res pass */ - vec2 pixel_size = 1.0 / vec2(textureSize(blurTex, 0).xy); - vec2 uv = gl_FragCoord.xy * pixel_size.xy; - float coc = decode_coc(texture(inputCocTex, uv).rg); - /* Only use this filter if coc is > 9.0 - * since this filter is not weighted by CoC - * and can bleed a bit. */ - float rad = clamp(coc - 9.0, 0.0, 1.0); - -#define vec vec4 -#define toVec(x) x.rgba - -#define s2(a, b) temp = a; a = min(a, b); b = max(temp, b); -#define mn3(a, b, c) s2(a, b); s2(a, c); -#define mx3(a, b, c) s2(b, c); s2(a, c); - -#define mnmx3(a, b, c) mx3(a, b, c); s2(a, b); // 3 exchanges -#define mnmx4(a, b, c, d) s2(a, b); s2(c, d); s2(a, c); s2(b, d); // 4 exchanges -#define mnmx5(a, b, c, d, e) s2(a, b); s2(c, d); mn3(a, c, e); mx3(b, d, e); // 6 exchanges -#define mnmx6(a, b, c, d, e, f) s2(a, d); s2(b, e); s2(c, f); mn3(a, b, c); mx3(d, e, f); // 7 exchanges - - vec v[9]; - - /* Add the pixels which make up our window to the pixel array. */ - for(int dX = -1; dX <= 1; ++dX) { - for(int dY = -1; dY <= 1; ++dY) { - vec2 offset = vec2(float(dX), float(dY)); - /* If a pixel in the window is located at (x+dX, y+dY), put it at index (dX + R)(2R + 1) + (dY + R) of the - * pixel array. This will fill the pixel array, with the top left pixel of the window at pixel[0] and the - * bottom right pixel of the window at pixel[N-1]. */ - v[(dX + 1) * 3 + (dY + 1)] = toVec(texture(blurTex, uv + offset * pixel_size * rad)); - } - } - - vec temp; - - /* Starting with a subset of size 6, remove the min and max each time */ - mnmx6(v[0], v[1], v[2], v[3], v[4], v[5]); - mnmx5(v[1], v[2], v[3], v[4], v[6]); - mnmx4(v[2], v[3], v[4], v[7]); - mnmx3(v[3], v[4], v[8]); - toVec(finalColor) = v[4]; + /* Half Res pass */ + vec2 pixel_size = 1.0 / vec2(textureSize(blurTex, 0).xy); + vec2 uv = gl_FragCoord.xy * pixel_size.xy; + float coc = decode_coc(texture(inputCocTex, uv).rg); + /* Only use this filter if coc is > 9.0 + * since this filter is not weighted by CoC + * and can bleed a bit. */ + float rad = clamp(coc - 9.0, 0.0, 1.0); + +# define vec vec4 +# define toVec(x) x.rgba + +# define s2(a, b) \ + temp = a; \ + a = min(a, b); \ + b = max(temp, b); +# define mn3(a, b, c) \ + s2(a, b); \ + s2(a, c); +# define mx3(a, b, c) \ + s2(b, c); \ + s2(a, c); + +# define mnmx3(a, b, c) \ + mx3(a, b, c); \ + s2(a, b); // 3 exchanges +# define mnmx4(a, b, c, d) \ + s2(a, b); \ + s2(c, d); \ + s2(a, c); \ + s2(b, d); // 4 exchanges +# define mnmx5(a, b, c, d, e) \ + s2(a, b); \ + s2(c, d); \ + mn3(a, c, e); \ + mx3(b, d, e); // 6 exchanges +# define mnmx6(a, b, c, d, e, f) \ + s2(a, d); \ + s2(b, e); \ + s2(c, f); \ + mn3(a, b, c); \ + mx3(d, e, f); // 7 exchanges + + vec v[9]; + + /* Add the pixels which make up our window to the pixel array. */ + for (int dX = -1; dX <= 1; ++dX) { + for (int dY = -1; dY <= 1; ++dY) { + vec2 offset = vec2(float(dX), float(dY)); + /* If a pixel in the window is located at (x+dX, y+dY), put it at index (dX + R)(2R + 1) + (dY + R) of the + * pixel array. This will fill the pixel array, with the top left pixel of the window at pixel[0] and the + * bottom right pixel of the window at pixel[N-1]. */ + v[(dX + 1) * 3 + (dY + 1)] = toVec(texture(blurTex, uv + offset * pixel_size * rad)); + } + } + + vec temp; + + /* Starting with a subset of size 6, remove the min and max each time */ + mnmx6(v[0], v[1], v[2], v[3], v[4], v[5]); + mnmx5(v[1], v[2], v[3], v[4], v[6]); + mnmx4(v[2], v[3], v[4], v[7]); + mnmx3(v[3], v[4], v[8]); + toVec(finalColor) = v[4]; } #endif @@ -351,16 +389,16 @@ out vec4 finalColor; void main() { - /* Fullscreen pass */ - vec2 pixel_size = 0.5 / vec2(textureSize(halfResColorTex, 0).xy); - vec2 uv = gl_FragCoord.xy * pixel_size; + /* Fullscreen pass */ + vec2 pixel_size = 0.5 / vec2(textureSize(halfResColorTex, 0).xy); + vec2 uv = gl_FragCoord.xy * pixel_size; - /* TODO MAKE SURE TO ALIGN SAMPLE POSITION TO AVOID OFFSET IN THE BOKEH */ - float depth = texelFetch(sceneDepthTex, ivec2(gl_FragCoord.xy), 0).r; - float zdepth = linear_depth(depth); - float coc = calculate_coc(zdepth); + /* TODO MAKE SURE TO ALIGN SAMPLE POSITION TO AVOID OFFSET IN THE BOKEH */ + float depth = texelFetch(sceneDepthTex, ivec2(gl_FragCoord.xy), 0).r; + float zdepth = linear_depth(depth); + float coc = calculate_coc(zdepth); - finalColor = texture(halfResColorTex, uv); - finalColor.a = smoothstep(1.0, 3.0, abs(coc)); + finalColor = texture(halfResColorTex, uv); + finalColor.a = smoothstep(1.0, 3.0, abs(coc)); } #endif 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 index 4ffd20c2839..46b0361245b 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_effect_fxaa_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_effect_fxaa_frag.glsl @@ -8,12 +8,6 @@ uniform vec2 invertedViewportSize; void main() { - FragColor = FxaaPixelShader( - uvcoordsvar.st, - colorBuffer, - invertedViewportSize, - 1.0, - 0.166, - 0.0833 - ); + FragColor = FxaaPixelShader( + uvcoordsvar.st, colorBuffer, invertedViewportSize, 1.0, 0.166, 0.0833); } 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 1da1b2ad13c..5795268f794 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 @@ -7,8 +7,8 @@ uniform float mixFactor; 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); + 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); } 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 index 576a5e81c0d..6915055e356 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_forward_composite_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_forward_composite_frag.glsl @@ -6,38 +6,40 @@ uniform sampler2D transparentRevealage; uniform vec2 invertedViewportSize; #ifndef ALPHA_COMPOSITE -layout(std140) uniform world_block { - WorldData world_data; +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; + 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; + /* 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); + vec3 trans_color = trans_accum.rgb / clamp(trans_accum.a, 1e-4, 5e4); #ifndef ALPHA_COMPOSITE - vec3 bg_color = background_color(world_data, uv_viewport.y); + vec3 bg_color = background_color(world_data, uv_viewport.y); - bg_color = (world_data.background_alpha == 0.0) ? trans_color : bg_color; - vec4 color = mix(vec4(trans_color, 1.0), vec4(bg_color, world_data.background_alpha), trans_revealage); + bg_color = (world_data.background_alpha == 0.0) ? trans_color : bg_color; + vec4 color = mix( + vec4(trans_color, 1.0), vec4(bg_color, world_data.background_alpha), trans_revealage); # ifdef V3D_SHADING_OBJECT_OUTLINE - uint object_id = texelFetch(objectId, texel, 0).r; - float outline = calculate_object_outline(objectId, texel, object_id); - color = mix(vec4(world_data.object_outline_color.rgb, 1.0), color, outline); + uint object_id = texelFetch(objectId, texel, 0).r; + float outline = calculate_object_outline(objectId, texel, object_id); + color = mix(vec4(world_data.object_outline_color.rgb, 1.0), color, outline); # endif - fragColor = color; + fragColor = color; #else - fragColor = vec4(trans_color, 1.0 - trans_revealage); + fragColor = vec4(trans_color, 1.0 - trans_revealage); #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 index 9380044f2b9..505b4822ad6 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_forward_depth_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_forward_depth_frag.glsl @@ -1,5 +1,5 @@ uniform int object_id = 0; -layout(location=0) out uint objectId; +layout(location = 0) out uint objectId; uniform float ImageTransparencyCutoff = 0.1; #ifdef V3D_SHADING_TEXTURE_COLOR uniform sampler2D image; @@ -10,11 +10,11 @@ in vec2 uv_interp; void main() { #ifdef V3D_SHADING_TEXTURE_COLOR - vec4 diffuse_color = texture(image, uv_interp); - if (diffuse_color.a < ImageTransparencyCutoff) { - discard; - } + vec4 diffuse_color = texture(image, uv_interp); + if (diffuse_color.a < ImageTransparencyCutoff) { + discard; + } #endif - objectId = uint(object_id); + objectId = uint(object_id); } 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 index b3642b7beb3..e654141df5c 100644 --- 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 @@ -29,62 +29,63 @@ in vec2 uv_interp; uniform sampler2D matcapImage; #endif -layout(std140) uniform world_block { - WorldData world_data; +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 */ +layout(location = 0) out vec4 transparentAccum; +layout(location = 1) out + float revealageAccum; /* revealage actually stored in transparentAccum.a */ void main() { - vec4 diffuse_color; + vec4 diffuse_color; #ifdef V3D_SHADING_TEXTURE_COLOR - diffuse_color = workbench_sample_texture(image, uv_interp, imageSrgb, imageNearest); - if (diffuse_color.a < ImageTransparencyCutoff) { - discard; - } + diffuse_color = workbench_sample_texture(image, uv_interp, imageSrgb, imageNearest); + if (diffuse_color.a < ImageTransparencyCutoff) { + discard; + } #else - diffuse_color = vec4(materialDiffuseColor, 1.0); + diffuse_color = vec4(materialDiffuseColor, 1.0); #endif /* V3D_SHADING_TEXTURE_COLOR */ - vec2 uv_viewport = gl_FragCoord.xy * invertedViewportSize; - vec3 I_vs = view_vector_from_screen_uv(uv_viewport, viewvecs, ProjectionMatrix); + 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); + vec3 nor = normalize(normal_viewport); #endif - /* -------- SHADING --------- */ + /* -------- SHADING --------- */ #ifdef V3D_LIGHTING_FLAT - vec3 shaded_color = diffuse_color.rgb; + vec3 shaded_color = diffuse_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 = textureLod(matcapImage, matcap_uv, 0.0).rgb; - vec3 shaded_color = matcap * diffuse_color.rgb; + bool flipped = world_data.matcap_orientation != 0; + vec2 matcap_uv = matcap_uv_compute(I_vs, nor, flipped); + vec3 matcap = textureLod(matcapImage, matcap_uv, 0.0).rgb; + vec3 shaded_color = matcap * diffuse_color.rgb; #elif defined(V3D_LIGHTING_STUDIO) - vec3 shaded_color = get_world_lighting(world_data, - diffuse_color.rgb, materialSpecularColor, materialRoughness, - nor, I_vs); + vec3 shaded_color = get_world_lighting( + world_data, diffuse_color.rgb, materialSpecularColor, 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); + 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; + /* 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 index 59f2df11086..d223a7650c5 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_ghost_resolve_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_ghost_resolve_frag.glsl @@ -2,12 +2,12 @@ uniform sampler2D depthBuffer; void main(void) { - float depth = texelFetch(depthBuffer, ivec2(gl_FragCoord.xy), 0).r; + float depth = texelFetch(depthBuffer, ivec2(gl_FragCoord.xy), 0).r; - /* background, discard */ - if (depth >= 1.0) { - discard; - } + /* background, discard */ + if (depth >= 1.0) { + discard; + } - gl_FragDepth = depth; + gl_FragDepth = depth; } 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 index 3e925ba023f..a4a5d9c31a3 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_object_outline_lib.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_object_outline_lib.glsl @@ -2,11 +2,11 @@ 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); + 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)); + 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 db51d3da15f..6b2962a66da 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl @@ -22,58 +22,58 @@ flat in float hair_rand; #endif #ifdef MATDATA_PASS_ENABLED -layout(location=0) out vec4 materialData; +layout(location = 0) out vec4 materialData; #endif #ifdef OBJECT_ID_PASS_ENABLED -layout(location=1) out uint objectId; +layout(location = 1) out uint objectId; #endif #ifdef NORMAL_VIEWPORT_PASS_ENABLED -layout(location=2) out WB_Normal normalViewport; +layout(location = 2) out WB_Normal normalViewport; #endif void main() { #ifdef MATDATA_PASS_ENABLED - float metallic, roughness; - vec4 color; + float metallic, roughness; + vec4 color; # ifdef V3D_SHADING_TEXTURE_COLOR - color = workbench_sample_texture(image, uv_interp, imageSrgb, imageNearest); - if (color.a < ImageTransparencyCutoff) { - discard; - } + color = workbench_sample_texture(image, uv_interp, imageSrgb, imageNearest); + if (color.a < ImageTransparencyCutoff) { + discard; + } # else - color.rgb = materialDiffuseColor; + color.rgb = materialDiffuseColor; # endif # ifdef V3D_LIGHTING_MATCAP - /* Encode front facing in metallic channel. */ - metallic = float(gl_FrontFacing); - roughness = 0.0; + /* Encode front facing in metallic channel. */ + metallic = float(gl_FrontFacing); + roughness = 0.0; # else - metallic = materialMetallic; - roughness = materialRoughness; + metallic = materialMetallic; + 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(materialMetallic - hair_variation, 0.0, 1.0); - roughness = clamp(materialRoughness - hair_variation, 0.0, 1.0); + /* 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(materialMetallic - 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); + materialData.rgb = color.rgb; + materialData.a = workbench_float_pair_encode(roughness, metallic); #endif /* MATDATA_PASS_ENABLED */ #ifdef OBJECT_ID_PASS_ENABLED - objectId = uint(object_id); + objectId = uint(object_id); #endif #ifdef NORMAL_VIEWPORT_PASS_ENABLED - vec3 n = (gl_FrontFacing) ? normal_viewport : -normal_viewport; - n = normalize(n); - normalViewport = workbench_normal_encode(n); + 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_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl index 66372f82b89..dd737063f61 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl @@ -10,7 +10,7 @@ uniform mat3 NormalMatrix; in vec3 pos; in vec3 nor; in vec2 u; /* active texture layer */ -#define uv u +# define uv u #else /* HAIR_SHADER */ # ifdef V3D_SHADING_TEXTURE_COLOR uniform samplerBuffer u; /* active texture layer */ @@ -29,49 +29,53 @@ out vec2 uv_interp; /* 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); + n = (n >> 13) ^ n; + int nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff; + return (float(nn) / 1073741824.0); } void main() { #ifdef HAIR_SHADER # ifdef V3D_SHADING_TEXTURE_COLOR - vec2 uv = hair_get_customdata_vec2(u); + vec2 uv = hair_get_customdata_vec2(u); # endif - float time, thick_time, thickness; - vec3 pos, tan, binor; - hair_get_pos_tan_binor_time( - (ProjectionMatrix[3][3] == 0.0), - ModelMatrixInverse, - ViewMatrixInverse[3].xyz, ViewMatrixInverse[2].xyz, - pos, tan, binor, time, thickness, thick_time); - /* To "simulate" anisotropic shading, randomize hair normal per strand. */ - hair_rand = integer_noise(hair_get_strand_id()); - tan = normalize(tan); - vec3 nor = normalize(cross(binor, tan)); - nor = normalize(mix(nor, -tan, hair_rand * 0.10)); - float cos_theta = (hair_rand*2.0 - 1.0) * 0.20; - float sin_theta = sqrt(max(0.0, 1.0f - cos_theta*cos_theta)); - nor = nor * sin_theta + binor * cos_theta; - gl_Position = ViewProjectionMatrix * vec4(pos, 1.0); + float time, thick_time, thickness; + vec3 pos, tan, binor; + hair_get_pos_tan_binor_time((ProjectionMatrix[3][3] == 0.0), + ModelMatrixInverse, + ViewMatrixInverse[3].xyz, + ViewMatrixInverse[2].xyz, + pos, + tan, + binor, + time, + thickness, + thick_time); + /* To "simulate" anisotropic shading, randomize hair normal per strand. */ + hair_rand = integer_noise(hair_get_strand_id()); + tan = normalize(tan); + vec3 nor = normalize(cross(binor, tan)); + nor = normalize(mix(nor, -tan, hair_rand * 0.10)); + float cos_theta = (hair_rand * 2.0 - 1.0) * 0.20; + float sin_theta = sqrt(max(0.0, 1.0f - cos_theta * cos_theta)); + nor = nor * sin_theta + binor * cos_theta; + gl_Position = ViewProjectionMatrix * vec4(pos, 1.0); #else - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); #endif #ifdef V3D_SHADING_TEXTURE_COLOR - uv_interp = uv; + uv_interp = uv; #endif #ifdef NORMAL_VIEWPORT_PASS_ENABLED - normal_viewport = NormalMatrix * nor; + normal_viewport = NormalMatrix * nor; # ifndef HAIR_SHADER - normal_viewport = normalize(normal_viewport); + normal_viewport = normalize(normal_viewport); # endif #endif #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); #endif - } diff --git a/source/blender/draw/engines/workbench/shaders/workbench_shadow_caps_geom.glsl b/source/blender/draw/engines/workbench/shaders/workbench_shadow_caps_geom.glsl index d8c8f22ed1c..09bafb8ff11 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_shadow_caps_geom.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_shadow_caps_geom.glsl @@ -1,7 +1,7 @@ #extension GL_ARB_gpu_shader5 : enable #ifdef GL_ARB_gpu_shader5 -#define USE_INVOC_EXT +# define USE_INVOC_EXT #endif #ifdef DOUBLE_MANIFOLD @@ -28,58 +28,66 @@ layout(triangle_strip, max_vertices = vert_len) out; uniform vec3 lightDirection = vec3(0.57, 0.57, -0.57); -in VertexData { - vec3 pos; /* local position */ - vec4 frontPosition; /* final ndc position */ - vec4 backPosition; -} vData[]; +in VertexData +{ + vec3 pos; /* local position */ + vec4 frontPosition; /* final ndc position */ + vec4 backPosition; +} +vData[]; vec4 get_pos(int v, bool backface) { - return (backface) ? vData[v].backPosition : vData[v].frontPosition; + return (backface) ? vData[v].backPosition : vData[v].frontPosition; } void emit_cap(const bool front, bool reversed) { - if (front) { - gl_Position = vData[0].frontPosition; EmitVertex(); - gl_Position = vData[reversed ? 2 : 1].frontPosition; EmitVertex(); - gl_Position = vData[reversed ? 1 : 2].frontPosition; EmitVertex(); - } - else { - gl_Position = vData[0].backPosition; EmitVertex(); - gl_Position = vData[reversed ? 1 : 2].backPosition; EmitVertex(); - gl_Position = vData[reversed ? 2 : 1].backPosition; EmitVertex(); - } - EndPrimitive(); + if (front) { + gl_Position = vData[0].frontPosition; + EmitVertex(); + gl_Position = vData[reversed ? 2 : 1].frontPosition; + EmitVertex(); + gl_Position = vData[reversed ? 1 : 2].frontPosition; + EmitVertex(); + } + else { + gl_Position = vData[0].backPosition; + EmitVertex(); + gl_Position = vData[reversed ? 1 : 2].backPosition; + EmitVertex(); + gl_Position = vData[reversed ? 2 : 1].backPosition; + EmitVertex(); + } + EndPrimitive(); } void main() { - vec3 v10 = vData[0].pos - vData[1].pos; - vec3 v12 = vData[2].pos - vData[1].pos; + vec3 v10 = vData[0].pos - vData[1].pos; + vec3 v12 = vData[2].pos - vData[1].pos; - vec3 n = cross(v12, v10); - float facing = dot(n, lightDirection); + vec3 n = cross(v12, v10); + float facing = dot(n, lightDirection); - bool backface = facing > 0.0; + bool backface = facing > 0.0; #ifdef DOUBLE_MANIFOLD - /* In case of non manifold geom, we only increase/decrease - * the stencil buffer by one but do every faces as they were facing the light. */ - bool invert = backface; + /* In case of non manifold geom, we only increase/decrease + * the stencil buffer by one but do every faces as they were facing the light. */ + bool invert = backface; #else - const bool invert = false; - if (!backface) { + const bool invert = false; + if (!backface) { #endif #ifdef USE_INVOC_EXT - bool do_front = (gl_InvocationID & 1) == 0; - emit_cap(do_front, invert); + bool do_front = (gl_InvocationID & 1) == 0; + emit_cap(do_front, invert); #else - emit_cap(true, invert); - emit_cap(false, invert); + emit_cap(true, invert); + emit_cap(false, invert); #endif #ifndef DOUBLE_MANIFOLD - } +} #endif } 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 ceb33e77f2b..6b0741b6d1b 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 @@ -3,12 +3,13 @@ out vec4 fragColor; void main() { - const float intensity = 0.25; + const float intensity = 0.25; #ifdef SHADOW_PASS - fragColor = vec4((gl_FrontFacing) ? vec3(intensity, -intensity, 0.0) - : vec3(-intensity, intensity, 0.0), 1.0); + fragColor = vec4( + (gl_FrontFacing) ? vec3(intensity, -intensity, 0.0) : vec3(-intensity, intensity, 0.0), 1.0); #else - fragColor = vec4((gl_FrontFacing) ? vec3(intensity, intensity, -intensity) - : vec3(-intensity, -intensity, intensity), 1.0); + fragColor = vec4((gl_FrontFacing) ? vec3(intensity, intensity, -intensity) : + vec3(-intensity, -intensity, intensity), + 1.0); #endif } diff --git a/source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl b/source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl index 00213260df0..5373648d4e4 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl @@ -1,7 +1,7 @@ #extension GL_ARB_gpu_shader5 : enable #ifdef GL_ARB_gpu_shader5 -#define USE_INVOC_EXT +# define USE_INVOC_EXT #endif #ifdef DOUBLE_MANIFOLD @@ -28,11 +28,13 @@ layout(triangle_strip, max_vertices = vert_len) out; uniform vec3 lightDirection = vec3(0.57, 0.57, -0.57); -in VertexData { - vec3 pos; /* local position */ - vec4 frontPosition; /* final ndc position */ - vec4 backPosition; -} vData[]; +in VertexData +{ + vec3 pos; /* local position */ + vec4 frontPosition; /* final ndc position */ + vec4 backPosition; +} +vData[]; #define DEGENERATE_TRIS_WORKAROUND @@ -40,80 +42,82 @@ in VertexData { void extrude_edge(bool invert) { - /* Reverse order if backfacing the light. */ - ivec2 idx = (invert) ? ivec2(1, 2) : ivec2(2, 1); - gl_Position = vData[idx.x].frontPosition; EmitVertex(); - gl_Position = vData[idx.y].frontPosition; EmitVertex(); - gl_Position = vData[idx.x].backPosition; EmitVertex(); - gl_Position = vData[idx.y].backPosition; EmitVertex(); - EndPrimitive(); + /* Reverse order if backfacing the light. */ + ivec2 idx = (invert) ? ivec2(1, 2) : ivec2(2, 1); + gl_Position = vData[idx.x].frontPosition; + EmitVertex(); + gl_Position = vData[idx.y].frontPosition; + EmitVertex(); + gl_Position = vData[idx.x].backPosition; + EmitVertex(); + gl_Position = vData[idx.y].backPosition; + EmitVertex(); + EndPrimitive(); } void main() { - vec3 v10 = vData[0].pos - vData[1].pos; - vec3 v12 = vData[2].pos - vData[1].pos; - vec3 v13 = vData[3].pos - vData[1].pos; + vec3 v10 = vData[0].pos - vData[1].pos; + vec3 v12 = vData[2].pos - vData[1].pos; + vec3 v13 = vData[3].pos - vData[1].pos; - vec3 n1 = cross(v12, v10); - vec3 n2 = cross(v13, v12); + vec3 n1 = cross(v12, v10); + vec3 n2 = cross(v13, v12); #ifdef DEGENERATE_TRIS_WORKAROUND - /* Check if area is null */ - vec2 faces_area = vec2(len_sqr(n1), len_sqr(n2)); - bvec2 degen_faces = equal(abs(faces_area), vec2(0.0)); - - /* Both triangles are degenerate, abort. */ - if (all(degen_faces)) { - return; - } + /* Check if area is null */ + vec2 faces_area = vec2(len_sqr(n1), len_sqr(n2)); + bvec2 degen_faces = equal(abs(faces_area), vec2(0.0)); + + /* Both triangles are degenerate, abort. */ + if (all(degen_faces)) { + return; + } #endif - vec2 facing = vec2(dot(n1, lightDirection), - dot(n2, lightDirection)); + vec2 facing = vec2(dot(n1, lightDirection), dot(n2, lightDirection)); - /* WATCH: maybe unpredictable in some cases. */ - bool is_manifold = any(notEqual(vData[0].pos, vData[3].pos)); + /* WATCH: maybe unpredictable in some cases. */ + bool is_manifold = any(notEqual(vData[0].pos, vData[3].pos)); - bvec2 backface = greaterThan(facing, vec2(0.0)); + bvec2 backface = greaterThan(facing, vec2(0.0)); #ifdef DEGENERATE_TRIS_WORKAROUND # ifndef DOUBLE_MANIFOLD - /* If the mesh is known to be manifold and we don't use double count, - * only create an quad if the we encounter a facing geom. */ - if ((degen_faces.x && backface.y) || - (degen_faces.y && backface.x)) - return; + /* If the mesh is known to be manifold and we don't use double count, + * only create an quad if the we encounter a facing geom. */ + if ((degen_faces.x && backface.y) || (degen_faces.y && backface.x)) + return; # endif - /* If one of the 2 triangles is degenerate, replace edge by a non-manifold one. */ - backface.x = (degen_faces.x) ? !backface.y : backface.x; - backface.y = (degen_faces.y) ? !backface.x : backface.y; - is_manifold = (any(degen_faces)) ? false : is_manifold; + /* If one of the 2 triangles is degenerate, replace edge by a non-manifold one. */ + backface.x = (degen_faces.x) ? !backface.y : backface.x; + backface.y = (degen_faces.y) ? !backface.x : backface.y; + is_manifold = (any(degen_faces)) ? false : is_manifold; #endif - /* If both faces face the same direction it's not an outline edge. */ - if (backface.x == backface.y) { - return; - } + /* If both faces face the same direction it's not an outline edge. */ + if (backface.x == backface.y) { + return; + } #ifdef USE_INVOC_EXT - if (gl_InvocationID == 0) { - extrude_edge(backface.x); - } - else if (is_manifold) { + if (gl_InvocationID == 0) { + extrude_edge(backface.x); + } + else if (is_manifold) { # ifdef DOUBLE_MANIFOLD - /* Increment/Decrement twice for manifold edges. */ - extrude_edge(backface.x); + /* Increment/Decrement twice for manifold edges. */ + extrude_edge(backface.x); # endif - } + } #else - extrude_edge(backface.x); - if (is_manifold) { + extrude_edge(backface.x); + if (is_manifold) { # ifdef DOUBLE_MANIFOLD - /* Increment/Decrement twice for manifold edges. */ - extrude_edge(backface.x); + /* Increment/Decrement twice for manifold edges. */ + extrude_edge(backface.x); # endif - } + } #endif } diff --git a/source/blender/draw/engines/workbench/shaders/workbench_shadow_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_shadow_vert.glsl index 50a721f948f..afd704a7d3a 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_shadow_vert.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_shadow_vert.glsl @@ -7,15 +7,17 @@ uniform float lightDistance = 1e4; in vec3 pos; -out VertexData { - vec3 pos; /* local position */ - vec4 frontPosition; /* final ndc position */ - vec4 backPosition; -} vData; +out VertexData +{ + vec3 pos; /* local position */ + vec4 frontPosition; /* final ndc position */ + vec4 backPosition; +} +vData; void main() { - vData.pos = pos; - vData.frontPosition = ModelViewProjectionMatrix * vec4(pos, 1.0); - vData.backPosition = ModelViewProjectionMatrix * vec4(pos + lightDirection * lightDistance, 1.0); + vData.pos = pos; + vData.frontPosition = ModelViewProjectionMatrix * vec4(pos, 1.0); + vData.backPosition = ModelViewProjectionMatrix * vec4(pos + lightDirection * lightDistance, 1.0); } 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 c99787eaee8..26ebe7a4553 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl @@ -15,7 +15,7 @@ uniform sampler1D transferTexture; uniform int samplesLen = 256; uniform float noiseOfs = 0.0f; -uniform float stepLength; /* Step length in local space. */ +uniform float stepLength; /* Step length in local space. */ uniform float densityScale; /* Simple Opacity multiplicator. */ uniform vec4 viewvecs[3]; uniform vec3 activeColor; @@ -29,90 +29,93 @@ in vec3 localPos; out vec4 fragColor; -#define M_PI 3.1415926535897932 /* pi */ +#define M_PI 3.1415926535897932 /* pi */ float phase_function_isotropic() { - return 1.0 / (4.0 * M_PI); + 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; - } + 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; - } + 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)); } +float max_v3(vec3 v) +{ + return max(v.x, max(v.y, v.z)); +} float line_unit_box_intersect_dist(vec3 lineorigin, vec3 linedirection) { - /* https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/ */ - vec3 firstplane = (vec3( 1.0) - lineorigin) / linedirection; - vec3 secondplane = (vec3(-1.0) - lineorigin) / linedirection; - vec3 furthestplane = min(firstplane, secondplane); - return max_v3(furthestplane); + /* https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/ */ + vec3 firstplane = (vec3(1.0) - lineorigin) / linedirection; + vec3 secondplane = (vec3(-1.0) - lineorigin) / linedirection; + vec3 furthestplane = min(firstplane, secondplane); + return max_v3(furthestplane); } #define sample_trilinear(ima, co) texture(ima, co) vec4 sample_tricubic(sampler3D ima, vec3 co) { - vec3 tex_size = vec3(textureSize(ima, 0).xyz); - - co *= tex_size; - /* texel center */ - vec3 tc = floor(co - 0.5) + 0.5; - vec3 f = co - tc; - vec3 f2 = f * f; - vec3 f3 = f2 * f; - /* Bspline coefs (optimized) */ - vec3 w3 = f3 / 6.0; - vec3 w0 = -w3 + f2 * 0.5 - f * 0.5 + 1.0 / 6.0; - vec3 w1 = f3 * 0.5 - f2 + 2.0 / 3.0; - vec3 w2 = 1.0 - w0 - w1 - w3; - - vec3 s0 = w0 + w1; - vec3 s1 = w2 + w3; - - vec3 f0 = w1 / (w0 + w1); - vec3 f1 = w3 / (w2 + w3); - - vec2 final_z; - vec4 final_co; - final_co.xy = tc.xy - 1.0 + f0.xy; - final_co.zw = tc.xy + 1.0 + f1.xy; - final_z = tc.zz + vec2(-1.0, 1.0) + vec2(f0.z, f1.z); - - final_co /= tex_size.xyxy; - final_z /= tex_size.zz; - - vec4 color; - color = texture(ima, vec3(final_co.xy, final_z.x)) * s0.x * s0.y * s0.z; - color += texture(ima, vec3(final_co.zy, final_z.x)) * s1.x * s0.y * s0.z; - color += texture(ima, vec3(final_co.xw, final_z.x)) * s0.x * s1.y * s0.z; - color += texture(ima, vec3(final_co.zw, final_z.x)) * s1.x * s1.y * s0.z; - - color += texture(ima, vec3(final_co.xy, final_z.y)) * s0.x * s0.y * s1.z; - color += texture(ima, vec3(final_co.zy, final_z.y)) * s1.x * s0.y * s1.z; - color += texture(ima, vec3(final_co.xw, final_z.y)) * s0.x * s1.y * s1.z; - color += texture(ima, vec3(final_co.zw, final_z.y)) * s1.x * s1.y * s1.z; - - return color; + vec3 tex_size = vec3(textureSize(ima, 0).xyz); + + co *= tex_size; + /* texel center */ + vec3 tc = floor(co - 0.5) + 0.5; + vec3 f = co - tc; + vec3 f2 = f * f; + vec3 f3 = f2 * f; + /* Bspline coefs (optimized) */ + vec3 w3 = f3 / 6.0; + vec3 w0 = -w3 + f2 * 0.5 - f * 0.5 + 1.0 / 6.0; + vec3 w1 = f3 * 0.5 - f2 + 2.0 / 3.0; + vec3 w2 = 1.0 - w0 - w1 - w3; + + vec3 s0 = w0 + w1; + vec3 s1 = w2 + w3; + + vec3 f0 = w1 / (w0 + w1); + vec3 f1 = w3 / (w2 + w3); + + vec2 final_z; + vec4 final_co; + final_co.xy = tc.xy - 1.0 + f0.xy; + final_co.zw = tc.xy + 1.0 + f1.xy; + final_z = tc.zz + vec2(-1.0, 1.0) + vec2(f0.z, f1.z); + + final_co /= tex_size.xyxy; + final_z /= tex_size.zz; + + vec4 color; + color = texture(ima, vec3(final_co.xy, final_z.x)) * s0.x * s0.y * s0.z; + color += texture(ima, vec3(final_co.zy, final_z.x)) * s1.x * s0.y * s0.z; + color += texture(ima, vec3(final_co.xw, final_z.x)) * s0.x * s1.y * s0.z; + color += texture(ima, vec3(final_co.zw, final_z.x)) * s1.x * s1.y * s0.z; + + color += texture(ima, vec3(final_co.xy, final_z.y)) * s0.x * s0.y * s1.z; + color += texture(ima, vec3(final_co.zy, final_z.y)) * s1.x * s0.y * s1.z; + color += texture(ima, vec3(final_co.xw, final_z.y)) * s0.x * s1.y * s1.z; + color += texture(ima, vec3(final_co.zw, final_z.y)) * s1.x * s1.y * s1.z; + + return color; } #ifdef USE_TRICUBIC @@ -123,127 +126,126 @@ vec4 sample_tricubic(sampler3D ima, vec3 co) void volume_properties(vec3 ls_pos, out vec3 scattering, out float extinction) { - vec3 co = ls_pos * 0.5 + 0.5; + vec3 co = ls_pos * 0.5 + 0.5; #ifdef USE_COBA - float val = sample_volume_texture(densityTexture, co).r; - vec4 tval = texture(transferTexture, val) * densityScale; - tval.rgb = pow(tval.rgb, vec3(2.2)); - scattering = tval.rgb * 1500.0; - extinction = max(1e-4, tval.a * 50.0); + float val = sample_volume_texture(densityTexture, co).r; + vec4 tval = texture(transferTexture, val) * densityScale; + tval.rgb = pow(tval.rgb, vec3(2.2)); + scattering = tval.rgb * 1500.0; + extinction = max(1e-4, tval.a * 50.0); #else - float flame = sample_volume_texture(flameTexture, co).r; - vec4 emission = texture(flameColorTexture, flame); - float shadows = sample_volume_texture(shadowTexture, co).r; - vec4 density = sample_volume_texture(densityTexture, co); /* rgb: color, a: density */ + float flame = sample_volume_texture(flameTexture, co).r; + vec4 emission = texture(flameColorTexture, flame); + float shadows = sample_volume_texture(shadowTexture, co).r; + vec4 density = sample_volume_texture(densityTexture, co); /* rgb: color, a: density */ - scattering = density.rgb * (density.a * densityScale) * activeColor; - extinction = max(1e-4, dot(scattering, vec3(0.33333))); + scattering = density.rgb * (density.a * densityScale) * activeColor; + extinction = max(1e-4, dot(scattering, vec3(0.33333))); - /* Scale shadows in log space and clamp them to avoid completely black shadows. */ - scattering *= exp(clamp(log(shadows) * densityScale * 0.1, -2.5, 0.0)) * M_PI; + /* Scale shadows in log space and clamp them to avoid completely black shadows. */ + scattering *= exp(clamp(log(shadows) * densityScale * 0.1, -2.5, 0.0)) * M_PI; - /* 800 is arbitrary and here to mimic old viewport. TODO make it a parameter */ - scattering += pow(emission.rgb, vec3(2.2)) * emission.a * 800.0; + /* 800 is arbitrary and here to mimic old viewport. TODO make it a parameter */ + scattering += pow(emission.rgb, vec3(2.2)) * emission.a * 800.0; #endif } void eval_volume_step(inout vec3 Lscat, float extinction, float step_len, out float Tr) { - Lscat *= phase_function_isotropic(); - /* Evaluate Scattering */ - Tr = exp(-extinction * step_len); - /* integrate along the current step segment */ - Lscat = (Lscat - Lscat * Tr) / extinction; + Lscat *= phase_function_isotropic(); + /* Evaluate Scattering */ + Tr = exp(-extinction * step_len); + /* integrate along the current step segment */ + Lscat = (Lscat - Lscat * Tr) / extinction; } #define P(x) ((x + 0.5) * (1.0 / 16.0)) -const vec4 dither_mat[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)) -); - -vec4 volume_integration( - vec3 ray_ori, vec3 ray_dir, float ray_inc, float ray_max, float step_len) +const vec4 dither_mat[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))); + +vec4 volume_integration(vec3 ray_ori, vec3 ray_dir, float ray_inc, float ray_max, float step_len) { - /* Start with full transmittance and no scattered light. */ - vec3 final_scattering = vec3(0.0); - float final_transmittance = 1.0; - - ivec2 tx = ivec2(gl_FragCoord.xy) % 4; - float noise = fract(dither_mat[tx.x][tx.y] + noiseOfs); - - float ray_len = noise * ray_inc; - for (int i = 0; i < samplesLen && ray_len < ray_max; ++i, ray_len += ray_inc) { - vec3 ls_pos = ray_ori + ray_dir * ray_len; - - vec3 Lscat; - float s_extinction, Tr; - volume_properties(ls_pos, Lscat, s_extinction); - eval_volume_step(Lscat, s_extinction, step_len, Tr); - /* accumulate and also take into account the transmittance from previous steps */ - final_scattering += final_transmittance * Lscat; - final_transmittance *= Tr; - } - - return vec4(final_scattering, final_transmittance); + /* Start with full transmittance and no scattered light. */ + vec3 final_scattering = vec3(0.0); + float final_transmittance = 1.0; + + ivec2 tx = ivec2(gl_FragCoord.xy) % 4; + float noise = fract(dither_mat[tx.x][tx.y] + noiseOfs); + + float ray_len = noise * ray_inc; + for (int i = 0; i < samplesLen && ray_len < ray_max; ++i, ray_len += ray_inc) { + vec3 ls_pos = ray_ori + ray_dir * ray_len; + + vec3 Lscat; + float s_extinction, Tr; + volume_properties(ls_pos, Lscat, s_extinction); + eval_volume_step(Lscat, s_extinction, step_len, Tr); + /* accumulate and also take into account the transmittance from previous steps */ + final_scattering += final_transmittance * Lscat; + final_transmittance *= Tr; + } + + return vec4(final_scattering, final_transmittance); } void main() { #ifdef VOLUME_SLICE - /* Manual depth test. TODO remove. */ - float depth = texelFetch(depthBuffer, ivec2(gl_FragCoord.xy), 0).r; - if (gl_FragCoord.z >= depth) { - discard; - } - - vec3 Lscat; - float s_extinction, Tr; - volume_properties(localPos, Lscat, s_extinction); - eval_volume_step(Lscat, s_extinction, stepLength, Tr); - - fragColor = vec4(Lscat, Tr); + /* Manual depth test. TODO remove. */ + float depth = texelFetch(depthBuffer, ivec2(gl_FragCoord.xy), 0).r; + if (gl_FragCoord.z >= depth) { + discard; + } + + vec3 Lscat; + float s_extinction, Tr; + volume_properties(localPos, Lscat, s_extinction); + eval_volume_step(Lscat, s_extinction, stepLength, Tr); + + fragColor = vec4(Lscat, Tr); #else - vec2 screen_uv = gl_FragCoord.xy / vec2(textureSize(depthBuffer, 0).xy); - bool is_persp = ProjectionMatrix[3][3] == 0.0; - - vec3 volume_center = ModelMatrix[3].xyz; - - 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_dir = (is_persp) ? (vs_ray_end - vs_ray_ori) : vec3(0.0, 0.0, -1.0); - vs_ray_dir /= abs(vs_ray_dir.z); - - vec3 ls_ray_dir = mat3(ModelViewMatrixInverse) * vs_ray_dir * OrcoTexCoFactors[1] * 2.0; - vec3 ls_ray_ori = (ModelViewMatrixInverse * vec4(vs_ray_ori, 1.0)).xyz; - vec3 ls_ray_end = (ModelViewMatrixInverse * vec4(vs_ray_end, 1.0)).xyz; - - ls_ray_ori = (OrcoTexCoFactors[0] + ls_ray_ori * OrcoTexCoFactors[1]) * 2.0 - 1.0; - ls_ray_end = (OrcoTexCoFactors[0] + ls_ray_end * OrcoTexCoFactors[1]) * 2.0 - 1.0; - - /* TODO: Align rays to volume center so that it mimics old behaviour of slicing the volume. */ - - float dist = line_unit_box_intersect_dist(ls_ray_ori, ls_ray_dir); - if (dist > 0.0) { - ls_ray_ori = ls_ray_dir * dist + ls_ray_ori; - } - - vec3 ls_vol_isect = ls_ray_end - ls_ray_ori; - if (dot(ls_ray_dir, ls_vol_isect) < 0.0) { - /* Start is further away than the end. - * That means no volume is intersected. */ - discard; - } - - fragColor = volume_integration(ls_ray_ori, ls_ray_dir, stepLength, - length(ls_vol_isect) / length(ls_ray_dir), - length(vs_ray_dir) * stepLength); + vec2 screen_uv = gl_FragCoord.xy / vec2(textureSize(depthBuffer, 0).xy); + bool is_persp = ProjectionMatrix[3][3] == 0.0; + + vec3 volume_center = ModelMatrix[3].xyz; + + 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_dir = (is_persp) ? (vs_ray_end - vs_ray_ori) : vec3(0.0, 0.0, -1.0); + vs_ray_dir /= abs(vs_ray_dir.z); + + vec3 ls_ray_dir = mat3(ModelViewMatrixInverse) * vs_ray_dir * OrcoTexCoFactors[1] * 2.0; + vec3 ls_ray_ori = (ModelViewMatrixInverse * vec4(vs_ray_ori, 1.0)).xyz; + vec3 ls_ray_end = (ModelViewMatrixInverse * vec4(vs_ray_end, 1.0)).xyz; + + ls_ray_ori = (OrcoTexCoFactors[0] + ls_ray_ori * OrcoTexCoFactors[1]) * 2.0 - 1.0; + ls_ray_end = (OrcoTexCoFactors[0] + ls_ray_end * OrcoTexCoFactors[1]) * 2.0 - 1.0; + + /* TODO: Align rays to volume center so that it mimics old behaviour of slicing the volume. */ + + float dist = line_unit_box_intersect_dist(ls_ray_ori, ls_ray_dir); + if (dist > 0.0) { + ls_ray_ori = ls_ray_dir * dist + ls_ray_ori; + } + + vec3 ls_vol_isect = ls_ray_end - ls_ray_ori; + if (dot(ls_ray_dir, ls_vol_isect) < 0.0) { + /* Start is further away than the end. + * That means no volume is intersected. */ + discard; + } + + fragColor = volume_integration(ls_ray_ori, + ls_ray_dir, + stepLength, + length(ls_vol_isect) / length(ls_ray_dir), + length(vs_ray_dir) * stepLength); #endif - /* Convert transmitance to alpha so we can use premul blending. */ - fragColor.a = 1.0 - fragColor.a; + /* Convert transmitance to alpha so we can use premul blending. */ + fragColor.a = 1.0 - fragColor.a; } 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 7ce21c3d5ca..7a418243fd3 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl @@ -15,19 +15,19 @@ out vec3 localPos; void main() { #ifdef VOLUME_SLICE - if (sliceAxis == 0) { - localPos = vec3(slicePosition * 2.0 - 1.0, pos.xy); - } - else if (sliceAxis == 1) { - localPos = vec3(pos.x, slicePosition * 2.0 - 1.0, pos.y); - } - else { - localPos = vec3(pos.xy, slicePosition * 2.0 - 1.0); - } - vec3 final_pos = localPos; + if (sliceAxis == 0) { + localPos = vec3(slicePosition * 2.0 - 1.0, pos.xy); + } + else if (sliceAxis == 1) { + localPos = vec3(pos.x, slicePosition * 2.0 - 1.0, pos.y); + } + else { + localPos = vec3(pos.xy, slicePosition * 2.0 - 1.0); + } + vec3 final_pos = localPos; #else - vec3 final_pos = pos; + vec3 final_pos = pos; #endif - final_pos = ((final_pos * 0.5 + 0.5) - OrcoTexCoFactors[0]) / OrcoTexCoFactors[1]; - gl_Position = ModelViewProjectionMatrix * vec4(final_pos, 1.0); + final_pos = ((final_pos * 0.5 + 0.5) - OrcoTexCoFactors[0]) / OrcoTexCoFactors[1]; + gl_Position = ModelViewProjectionMatrix * vec4(final_pos, 1.0); } 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 8792c646ec1..690ce5d527f 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 @@ -2,113 +2,108 @@ /* [Drobot2014a] Low Level Optimizations for GCN */ vec4 fast_rcp(vec4 v) { - return intBitsToFloat(0x7eef370b - floatBitsToInt(v)); + return intBitsToFloat(0x7eef370b - floatBitsToInt(v)); } vec3 brdf_approx(vec3 spec_color, float roughness, float NV) { - /* Very rough own approx. We don't need it to be correct, just fast. - * Just simulate fresnel effect with roughness attenuation. */ - float fresnel = exp2(-8.35 * NV) * (1.0 - roughness); - return mix(spec_color, vec3(1.0), fresnel); + /* Very rough own approx. We don't need it to be correct, just fast. + * Just simulate fresnel effect with roughness attenuation. */ + float fresnel = exp2(-8.35 * NV) * (1.0 - roughness); + return mix(spec_color, vec3(1.0), fresnel); } void prep_specular( - vec3 L, vec3 I, vec3 N, vec3 R, - out float NL, out float wrapped_NL, out float spec_angle) + vec3 L, vec3 I, vec3 N, vec3 R, out float NL, out float wrapped_NL, out float spec_angle) { - wrapped_NL = dot(L, R); - vec3 half_dir = normalize(L + I); - spec_angle = clamp(dot(half_dir, N), 0.0, 1.0); - NL = clamp(dot(L, N), 0.0, 1.0); + wrapped_NL = dot(L, R); + vec3 half_dir = normalize(L + I); + spec_angle = clamp(dot(half_dir, N), 0.0, 1.0); + NL = clamp(dot(L, N), 0.0, 1.0); } /* Normalized Blinn shading */ vec4 blinn_specular(vec4 shininess, vec4 spec_angle, vec4 NL) { - /* Pi is already divided in the light power. - * normalization_factor = (shininess + 8.0) / (8.0 * M_PI) */ - vec4 normalization_factor = shininess * 0.125 + 1.0; - vec4 spec_light = pow(spec_angle, shininess) * NL * normalization_factor; + /* Pi is already divided in the light power. + * normalization_factor = (shininess + 8.0) / (8.0 * M_PI) */ + vec4 normalization_factor = shininess * 0.125 + 1.0; + vec4 spec_light = pow(spec_angle, shininess) * NL * normalization_factor; - return spec_light; + return spec_light; } /* NL need to be unclamped. w in [0..1] range. */ vec4 wrapped_lighting(vec4 NL, vec4 w) { - vec4 w_1 = w + 1.0; - vec4 denom = fast_rcp(w_1 * w_1); - return clamp((NL + w) * denom, 0.0, 1.0); + vec4 w_1 = w + 1.0; + vec4 denom = fast_rcp(w_1 * w_1); + 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) + WorldData world_data, 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; - vec4 wrap = vec4( - world_data.lights[0].diffuse_color_wrap.a, - world_data.lights[1].diffuse_color_wrap.a, - world_data.lights[2].diffuse_color_wrap.a, - world_data.lights[3].diffuse_color_wrap.a - ); + 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, + world_data.lights[1].diffuse_color_wrap.a, + 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); + /* 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 - specular_light *= specular_color; + specular_light *= specular_color; - /* Prepare diffuse computation. Eval 4 lights at once. */ - vec4 diff_NL; - diff_NL.x = dot(world_data.lights[0].direction.xyz, N); - diff_NL.y = dot(world_data.lights[1].direction.xyz, N); - diff_NL.z = dot(world_data.lights[2].direction.xyz, N); - diff_NL.w = dot(world_data.lights[3].direction.xyz, N); + /* Prepare diffuse computation. Eval 4 lights at once. */ + vec4 diff_NL; + diff_NL.x = dot(world_data.lights[0].direction.xyz, N); + diff_NL.y = dot(world_data.lights[1].direction.xyz, N); + diff_NL.z = dot(world_data.lights[2].direction.xyz, N); + diff_NL.w = dot(world_data.lights[3].direction.xyz, N); - vec4 diff_light = wrapped_lighting(diff_NL, wrap); + vec4 diff_light = wrapped_lighting(diff_NL, wrap); - /* Multiply result by lights diffuse colors. */ - diffuse_light += diff_light.x * world_data.lights[0].diffuse_color_wrap.rgb; - diffuse_light += diff_light.y * world_data.lights[1].diffuse_color_wrap.rgb; - diffuse_light += diff_light.z * world_data.lights[2].diffuse_color_wrap.rgb; - diffuse_light += diff_light.w * world_data.lights[3].diffuse_color_wrap.rgb; + /* Multiply result by lights diffuse colors. */ + diffuse_light += diff_light.x * world_data.lights[0].diffuse_color_wrap.rgb; + diffuse_light += diff_light.y * world_data.lights[1].diffuse_color_wrap.rgb; + diffuse_light += diff_light.z * world_data.lights[2].diffuse_color_wrap.rgb; + diffuse_light += diff_light.w * world_data.lights[3].diffuse_color_wrap.rgb; - /* Energy conservation with colored specular look strange. - * Limit this strangeness by using mono-chromatic specular intensity. */ - float spec_energy = dot(specular_color, vec3(0.33333)); + /* Energy conservation with colored specular look strange. + * Limit this strangeness by using mono-chromatic specular intensity. */ + float spec_energy = dot(specular_color, vec3(0.33333)); - diffuse_light *= diffuse_color * (1.0 - spec_energy); + diffuse_light *= diffuse_color * (1.0 - spec_energy); - return diffuse_light + specular_light; + return diffuse_light + specular_light; } diff --git a/source/blender/draw/engines/workbench/solid_mode.c b/source/blender/draw/engines/workbench/solid_mode.c index 4e69788457a..a01b14f17fb 100644 --- a/source/blender/draw/engines/workbench/solid_mode.c +++ b/source/blender/draw/engines/workbench/solid_mode.c @@ -35,78 +35,83 @@ static void workbench_solid_engine_init(void *vedata) { - WORKBENCH_Data *data = vedata; - workbench_deferred_engine_init(data); + WORKBENCH_Data *data = vedata; + workbench_deferred_engine_init(data); } static void workbench_solid_cache_init(void *vedata) { - WORKBENCH_Data *data = vedata; - workbench_deferred_cache_init(data); + WORKBENCH_Data *data = vedata; + workbench_deferred_cache_init(data); } static void workbench_solid_cache_populate(void *vedata, Object *ob) { - WORKBENCH_Data *data = vedata; - workbench_deferred_solid_cache_populate(data, ob); + WORKBENCH_Data *data = vedata; + workbench_deferred_solid_cache_populate(data, ob); } static void workbench_solid_cache_finish(void *vedata) { - WORKBENCH_Data *data = vedata; - workbench_deferred_cache_finish(data); + WORKBENCH_Data *data = vedata; + workbench_deferred_cache_finish(data); } static void workbench_solid_draw_background(void *vedata) { - WORKBENCH_Data *data = vedata; - workbench_deferred_draw_background(data); - workbench_deferred_draw_scene(data); - workbench_deferred_draw_finish(data); + WORKBENCH_Data *data = vedata; + workbench_deferred_draw_background(data); + workbench_deferred_draw_scene(data); + workbench_deferred_draw_finish(data); } static void workbench_solid_engine_free(void) { - workbench_deferred_engine_free(); + workbench_deferred_engine_free(); } static void workbench_solid_view_update(void *vedata) { - WORKBENCH_Data *data = vedata; - workbench_taa_view_updated(data); + WORKBENCH_Data *data = vedata; + workbench_taa_view_updated(data); } static void workbench_solid_id_update(void *UNUSED(vedata), struct ID *id) { - if (GS(id->name) == ID_OB) { - WORKBENCH_ObjectData *oed = (WORKBENCH_ObjectData *)DRW_drawdata_get(id, &draw_engine_workbench_solid); - if (oed != NULL && oed->dd.recalc != 0) { - oed->shadow_bbox_dirty = (oed->dd.recalc & ID_RECALC_ALL) != 0; - oed->dd.recalc = 0; - } - } + if (GS(id->name) == ID_OB) { + WORKBENCH_ObjectData *oed = (WORKBENCH_ObjectData *)DRW_drawdata_get( + id, &draw_engine_workbench_solid); + if (oed != NULL && oed->dd.recalc != 0) { + oed->shadow_bbox_dirty = (oed->dd.recalc & ID_RECALC_ALL) != 0; + oed->dd.recalc = 0; + } + } } -static void workbench_render_to_image(void *vedata, RenderEngine *engine, RenderLayer *render_layer, const rcti *rect) +static void workbench_render_to_image(void *vedata, + RenderEngine *engine, + RenderLayer *render_layer, + const rcti *rect) { - workbench_render(vedata, engine, render_layer, rect); + workbench_render(vedata, engine, render_layer, rect); } static const DrawEngineDataSize workbench_data_size = DRW_VIEWPORT_DATA_SIZE(WORKBENCH_Data); DrawEngineType draw_engine_workbench_solid = { - NULL, NULL, - N_("Workbench"), - &workbench_data_size, - &workbench_solid_engine_init, - &workbench_solid_engine_free, - &workbench_solid_cache_init, - &workbench_solid_cache_populate, - &workbench_solid_cache_finish, - &workbench_solid_draw_background, - NULL, - &workbench_solid_view_update, - &workbench_solid_id_update, - &workbench_render_to_image, + NULL, + NULL, + N_("Workbench"), + &workbench_data_size, + &workbench_solid_engine_init, + &workbench_solid_engine_free, + &workbench_solid_cache_init, + &workbench_solid_cache_populate, + &workbench_solid_cache_finish, + &workbench_solid_draw_background, + NULL, + &workbench_solid_view_update, + &workbench_solid_id_update, + &workbench_render_to_image, }; diff --git a/source/blender/draw/engines/workbench/transparent_mode.c b/source/blender/draw/engines/workbench/transparent_mode.c index c3b118d4660..0f4150ff986 100644 --- a/source/blender/draw/engines/workbench/transparent_mode.c +++ b/source/blender/draw/engines/workbench/transparent_mode.c @@ -33,62 +33,63 @@ static void workbench_transparent_engine_init(void *vedata) { - WORKBENCH_Data *data = vedata; - workbench_forward_engine_init(data); + WORKBENCH_Data *data = vedata; + workbench_forward_engine_init(data); } static void workbench_transparent_cache_init(void *vedata) { - WORKBENCH_Data *data = vedata; - workbench_forward_cache_init(data); + WORKBENCH_Data *data = vedata; + workbench_forward_cache_init(data); } static void workbench_transparent_cache_populate(void *vedata, Object *ob) { - WORKBENCH_Data *data = vedata; - workbench_forward_cache_populate(data, ob); + WORKBENCH_Data *data = vedata; + workbench_forward_cache_populate(data, ob); } static void workbench_transparent_cache_finish(void *vedata) { - WORKBENCH_Data *data = vedata; - workbench_forward_cache_finish(data); + WORKBENCH_Data *data = vedata; + workbench_forward_cache_finish(data); } static void workbench_transparent_draw_background(void *vedata) { - WORKBENCH_Data *data = vedata; - workbench_forward_draw_background(data); - workbench_forward_draw_scene(data); - workbench_forward_draw_finish(data); + WORKBENCH_Data *data = vedata; + workbench_forward_draw_background(data); + workbench_forward_draw_scene(data); + workbench_forward_draw_finish(data); } static void workbench_transparent_engine_free(void) { - workbench_forward_engine_free(); + workbench_forward_engine_free(); } static void workbench_transparent_view_update(void *vedata) { - WORKBENCH_Data *data = vedata; - workbench_taa_view_updated(data); + WORKBENCH_Data *data = vedata; + workbench_taa_view_updated(data); } static const DrawEngineDataSize workbench_data_size = DRW_VIEWPORT_DATA_SIZE(WORKBENCH_Data); DrawEngineType draw_engine_workbench_transparent = { - NULL, NULL, - N_("Workbench"), - &workbench_data_size, - &workbench_transparent_engine_init, - &workbench_transparent_engine_free, - &workbench_transparent_cache_init, - &workbench_transparent_cache_populate, - &workbench_transparent_cache_finish, - &workbench_transparent_draw_background, - NULL, - &workbench_transparent_view_update, - NULL, - NULL, + NULL, + NULL, + N_("Workbench"), + &workbench_data_size, + &workbench_transparent_engine_init, + &workbench_transparent_engine_free, + &workbench_transparent_cache_init, + &workbench_transparent_cache_populate, + &workbench_transparent_cache_finish, + &workbench_transparent_draw_background, + NULL, + &workbench_transparent_view_update, + NULL, + NULL, }; diff --git a/source/blender/draw/engines/workbench/workbench_data.c b/source/blender/draw/engines/workbench/workbench_data.c index 38b05133487..7728b3f998b 100644 --- a/source/blender/draw/engines/workbench/workbench_data.c +++ b/source/blender/draw/engines/workbench/workbench_data.c @@ -28,214 +28,209 @@ #include "GPU_batch.h" - void workbench_effect_info_init(WORKBENCH_EffectInfo *effect_info) { - effect_info->jitter_index = 0; - effect_info->view_updated = true; + effect_info->jitter_index = 0; + effect_info->view_updated = true; } 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->preferences = &U; - - View3D *v3d = draw_ctx->v3d; - if (!v3d) { - wpd->shading = scene->display.shading; - wpd->use_color_render_settings = true; - } - else if (v3d->shading.type == OB_RENDER && - BKE_scene_uses_blender_workbench(scene)) - { - wpd->shading = scene->display.shading; - wpd->use_color_render_settings = true; - } - else { - wpd->shading = v3d->shading; - wpd->use_color_render_settings = false; - } - - wpd->use_color_management = BKE_scene_check_color_management_enabled(scene); - - if (wpd->shading.light == V3D_LIGHTING_MATCAP) { - wpd->studio_light = BKE_studiolight_find( - wpd->shading.matcap, STUDIOLIGHT_TYPE_MATCAP); - } - else { - wpd->studio_light = BKE_studiolight_find( - wpd->shading.studio_light, STUDIOLIGHT_TYPE_STUDIO); - } - - /* If matcaps are missing, use this as fallback. */ - if (UNLIKELY(wpd->studio_light == NULL)) { - wpd->studio_light = BKE_studiolight_find( - wpd->shading.studio_light, STUDIOLIGHT_TYPE_STUDIO); - } - - - float shadow_focus = scene->display.shadow_focus; - /* Clamp to avoid overshadowing and shading errors. */ - CLAMP(shadow_focus, 0.0001f, 0.99999f); - wpd->shadow_shift = scene->display.shadow_shift; - wpd->shadow_focus = 1.0f - shadow_focus * (1.0f - wpd->shadow_shift); - wpd->shadow_multiplier = 1.0 - wpd->shading.shadow_intensity; - - WORKBENCH_UBO_World *wd = &wpd->world_data; - wd->matcap_orientation = (wpd->shading.flag & V3D_SHADING_MATCAP_FLIP_X) != 0; - wd->background_alpha = (DRW_state_is_image_render() && scene->r.alphamode == R_ALPHAPREMUL) ? 0.0f : 1.0f; - - if ((scene->world != NULL) && - (!v3d || (v3d && ((v3d->shading.background_type == V3D_SHADING_BACKGROUND_WORLD) || - (v3d->shading.type == OB_RENDER))))) - { - copy_v3_v3(wd->background_color_low, &scene->world->horr); - copy_v3_v3(wd->background_color_high, &scene->world->horr); - } - else if (v3d && (v3d->shading.background_type == V3D_SHADING_BACKGROUND_VIEWPORT)) { - copy_v3_v3(wd->background_color_low, v3d->shading.background_color); - copy_v3_v3(wd->background_color_high, v3d->shading.background_color); - } - else if (v3d) { - UI_GetThemeColor3fv(UI_GetThemeValue(TH_SHOW_BACK_GRAD) ? TH_BACK_GRAD : TH_BACK, wd->background_color_low); - UI_GetThemeColor3fv(TH_BACK, wd->background_color_high); - - /* XXX: Really quick conversion to avoid washed out background. - * Needs to be addressed properly (color managed using ocio). */ - if (wpd->use_color_management) { - srgb_to_linearrgb_v3_v3(wd->background_color_high, wd->background_color_high); - srgb_to_linearrgb_v3_v3(wd->background_color_low, wd->background_color_low); - } - else { - copy_v3_v3(wd->background_color_high, wd->background_color_high); - copy_v3_v3(wd->background_color_low, wd->background_color_low); - } - } - else { - zero_v3(wd->background_color_low); - zero_v3(wd->background_color_high); - } - - studiolight_update_world(wpd, wpd->studio_light, wd); - - copy_v3_v3(wd->object_outline_color, wpd->shading.object_outline_color); - wd->object_outline_color[3] = 1.0f; - - wd->curvature_ridge = 0.5f / max_ff(SQUARE(wpd->shading.curvature_ridge_factor), 1e-4f); - wd->curvature_valley = 0.7f / max_ff(SQUARE(wpd->shading.curvature_valley_factor), 1e-4f); - - /* Will be NULL when rendering. */ - if (draw_ctx->rv3d != NULL) { - RegionView3D *rv3d = draw_ctx->rv3d; - if (rv3d->rflag & RV3D_CLIPPING) { - wpd->world_clip_planes = rv3d->clip; - DRW_state_clip_planes_set_from_rv3d(rv3d); - UI_GetThemeColor4fv(TH_V3D_CLIPPING_BORDER, wpd->world_clip_planes_color); - if (wpd->use_color_management) { - srgb_to_linearrgb_v3_v3(wpd->world_clip_planes_color, wpd->world_clip_planes_color); - } - else { - copy_v3_v3(wpd->world_clip_planes_color, wpd->world_clip_planes_color); - } - } - else { - wpd->world_clip_planes = NULL; - } - } - - wpd->world_ubo = DRW_uniformbuffer_create(sizeof(WORKBENCH_UBO_World), &wpd->world_data); - - /* Cavity settings */ - { - const int ssao_samples = scene->display.matcap_ssao_samples; - - float invproj[4][4]; - const bool is_persp = DRW_viewport_is_persp_get(); - /* view vectors for the corners of the view frustum. - * Can be used to recreate the world space position easily */ - float viewvecs[3][4] = { - {-1.0f, -1.0f, -1.0f, 1.0f}, - {1.0f, -1.0f, -1.0f, 1.0f}, - {-1.0f, 1.0f, -1.0f, 1.0f}, - }; - int i; - const float *size = DRW_viewport_size_get(); - - wpd->ssao_params[0] = ssao_samples; - wpd->ssao_params[1] = size[0] / 64.0; - wpd->ssao_params[2] = size[1] / 64.0; - wpd->ssao_params[3] = 0; - - /* distance, factor, factor, attenuation */ - copy_v4_fl4( - wpd->ssao_settings, - scene->display.matcap_ssao_distance, - wpd->shading.cavity_valley_factor, - wpd->shading.cavity_ridge_factor, - scene->display.matcap_ssao_attenuation); - - /* invert the view matrix */ - DRW_viewport_matrix_get(wpd->winmat, DRW_MAT_WIN); - invert_m4_m4(invproj, wpd->winmat); - - /* convert the view vectors to view space */ - for (i = 0; i < 3; i++) { - mul_m4_v4(invproj, viewvecs[i]); - /* normalized trick see: - * http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */ - mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][3]); - if (is_persp) { - mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]); - } - viewvecs[i][3] = 1.0; - - copy_v4_v4(wpd->viewvecs[i], viewvecs[i]); - } - - /* we need to store the differences */ - wpd->viewvecs[1][0] -= wpd->viewvecs[0][0]; - wpd->viewvecs[1][1] = wpd->viewvecs[2][1] - wpd->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]); - wpd->viewvecs[1][2] = vec_far[2] - wpd->viewvecs[0][2]; - } - } - - wpd->volumes_do = false; - BLI_listbase_clear(&wpd->smoke_domains); + 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->preferences = &U; + + View3D *v3d = draw_ctx->v3d; + if (!v3d) { + wpd->shading = scene->display.shading; + wpd->use_color_render_settings = true; + } + else if (v3d->shading.type == OB_RENDER && BKE_scene_uses_blender_workbench(scene)) { + wpd->shading = scene->display.shading; + wpd->use_color_render_settings = true; + } + else { + wpd->shading = v3d->shading; + wpd->use_color_render_settings = false; + } + + wpd->use_color_management = BKE_scene_check_color_management_enabled(scene); + + if (wpd->shading.light == V3D_LIGHTING_MATCAP) { + wpd->studio_light = BKE_studiolight_find(wpd->shading.matcap, STUDIOLIGHT_TYPE_MATCAP); + } + else { + wpd->studio_light = BKE_studiolight_find(wpd->shading.studio_light, STUDIOLIGHT_TYPE_STUDIO); + } + + /* If matcaps are missing, use this as fallback. */ + if (UNLIKELY(wpd->studio_light == NULL)) { + wpd->studio_light = BKE_studiolight_find(wpd->shading.studio_light, STUDIOLIGHT_TYPE_STUDIO); + } + + float shadow_focus = scene->display.shadow_focus; + /* Clamp to avoid overshadowing and shading errors. */ + CLAMP(shadow_focus, 0.0001f, 0.99999f); + wpd->shadow_shift = scene->display.shadow_shift; + wpd->shadow_focus = 1.0f - shadow_focus * (1.0f - wpd->shadow_shift); + wpd->shadow_multiplier = 1.0 - wpd->shading.shadow_intensity; + + WORKBENCH_UBO_World *wd = &wpd->world_data; + wd->matcap_orientation = (wpd->shading.flag & V3D_SHADING_MATCAP_FLIP_X) != 0; + wd->background_alpha = (DRW_state_is_image_render() && scene->r.alphamode == R_ALPHAPREMUL) ? + 0.0f : + 1.0f; + + if ((scene->world != NULL) && + (!v3d || (v3d && ((v3d->shading.background_type == V3D_SHADING_BACKGROUND_WORLD) || + (v3d->shading.type == OB_RENDER))))) { + copy_v3_v3(wd->background_color_low, &scene->world->horr); + copy_v3_v3(wd->background_color_high, &scene->world->horr); + } + else if (v3d && (v3d->shading.background_type == V3D_SHADING_BACKGROUND_VIEWPORT)) { + copy_v3_v3(wd->background_color_low, v3d->shading.background_color); + copy_v3_v3(wd->background_color_high, v3d->shading.background_color); + } + else if (v3d) { + UI_GetThemeColor3fv(UI_GetThemeValue(TH_SHOW_BACK_GRAD) ? TH_BACK_GRAD : TH_BACK, + wd->background_color_low); + UI_GetThemeColor3fv(TH_BACK, wd->background_color_high); + + /* XXX: Really quick conversion to avoid washed out background. + * Needs to be addressed properly (color managed using ocio). */ + if (wpd->use_color_management) { + srgb_to_linearrgb_v3_v3(wd->background_color_high, wd->background_color_high); + srgb_to_linearrgb_v3_v3(wd->background_color_low, wd->background_color_low); + } + else { + copy_v3_v3(wd->background_color_high, wd->background_color_high); + copy_v3_v3(wd->background_color_low, wd->background_color_low); + } + } + else { + zero_v3(wd->background_color_low); + zero_v3(wd->background_color_high); + } + + studiolight_update_world(wpd, wpd->studio_light, wd); + + copy_v3_v3(wd->object_outline_color, wpd->shading.object_outline_color); + wd->object_outline_color[3] = 1.0f; + + wd->curvature_ridge = 0.5f / max_ff(SQUARE(wpd->shading.curvature_ridge_factor), 1e-4f); + wd->curvature_valley = 0.7f / max_ff(SQUARE(wpd->shading.curvature_valley_factor), 1e-4f); + + /* Will be NULL when rendering. */ + if (draw_ctx->rv3d != NULL) { + RegionView3D *rv3d = draw_ctx->rv3d; + if (rv3d->rflag & RV3D_CLIPPING) { + wpd->world_clip_planes = rv3d->clip; + DRW_state_clip_planes_set_from_rv3d(rv3d); + UI_GetThemeColor4fv(TH_V3D_CLIPPING_BORDER, wpd->world_clip_planes_color); + if (wpd->use_color_management) { + srgb_to_linearrgb_v3_v3(wpd->world_clip_planes_color, wpd->world_clip_planes_color); + } + else { + copy_v3_v3(wpd->world_clip_planes_color, wpd->world_clip_planes_color); + } + } + else { + wpd->world_clip_planes = NULL; + } + } + + wpd->world_ubo = DRW_uniformbuffer_create(sizeof(WORKBENCH_UBO_World), &wpd->world_data); + + /* Cavity settings */ + { + const int ssao_samples = scene->display.matcap_ssao_samples; + + float invproj[4][4]; + const bool is_persp = DRW_viewport_is_persp_get(); + /* view vectors for the corners of the view frustum. + * Can be used to recreate the world space position easily */ + float viewvecs[3][4] = { + {-1.0f, -1.0f, -1.0f, 1.0f}, + {1.0f, -1.0f, -1.0f, 1.0f}, + {-1.0f, 1.0f, -1.0f, 1.0f}, + }; + int i; + const float *size = DRW_viewport_size_get(); + + wpd->ssao_params[0] = ssao_samples; + wpd->ssao_params[1] = size[0] / 64.0; + wpd->ssao_params[2] = size[1] / 64.0; + wpd->ssao_params[3] = 0; + + /* distance, factor, factor, attenuation */ + copy_v4_fl4(wpd->ssao_settings, + scene->display.matcap_ssao_distance, + wpd->shading.cavity_valley_factor, + wpd->shading.cavity_ridge_factor, + scene->display.matcap_ssao_attenuation); + + /* invert the view matrix */ + DRW_viewport_matrix_get(wpd->winmat, DRW_MAT_WIN); + invert_m4_m4(invproj, wpd->winmat); + + /* convert the view vectors to view space */ + for (i = 0; i < 3; i++) { + mul_m4_v4(invproj, viewvecs[i]); + /* normalized trick see: + * http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */ + mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][3]); + if (is_persp) { + mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]); + } + viewvecs[i][3] = 1.0; + + copy_v4_v4(wpd->viewvecs[i], viewvecs[i]); + } + + /* we need to store the differences */ + wpd->viewvecs[1][0] -= wpd->viewvecs[0][0]; + wpd->viewvecs[1][1] = wpd->viewvecs[2][1] - wpd->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]); + wpd->viewvecs[1][2] = vec_far[2] - wpd->viewvecs[0][2]; + } + } + + wpd->volumes_do = false; + BLI_listbase_clear(&wpd->smoke_domains); } -void workbench_private_data_get_light_direction(WORKBENCH_PrivateData *wpd, float r_light_direction[3]) +void workbench_private_data_get_light_direction(WORKBENCH_PrivateData *wpd, + float r_light_direction[3]) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - Scene *scene = draw_ctx->scene; - WORKBENCH_UBO_World *wd = &wpd->world_data; - float view_matrix[4][4]; - DRW_viewport_matrix_get(view_matrix, DRW_MAT_VIEW); + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + WORKBENCH_UBO_World *wd = &wpd->world_data; + float view_matrix[4][4]; + DRW_viewport_matrix_get(view_matrix, DRW_MAT_VIEW); - copy_v3_v3(r_light_direction, scene->display.light_direction); - SWAP(float, r_light_direction[2], r_light_direction[1]); - r_light_direction[2] = -r_light_direction[2]; - r_light_direction[0] = -r_light_direction[0]; + copy_v3_v3(r_light_direction, scene->display.light_direction); + SWAP(float, r_light_direction[2], r_light_direction[1]); + r_light_direction[2] = -r_light_direction[2]; + r_light_direction[0] = -r_light_direction[0]; - /* Shadow direction. */ - mul_v3_mat3_m4v3(wd->shadow_direction_vs, view_matrix, r_light_direction); + /* Shadow direction. */ + mul_v3_mat3_m4v3(wd->shadow_direction_vs, view_matrix, r_light_direction); - DRW_uniformbuffer_update(wpd->world_ubo, wd); + DRW_uniformbuffer_update(wpd->world_ubo, wd); } void workbench_private_data_free(WORKBENCH_PrivateData *wpd) { - BLI_ghash_free(wpd->material_hash, NULL, MEM_freeN); - BLI_ghash_free(wpd->material_transp_hash, NULL, MEM_freeN); - DRW_UBO_FREE_SAFE(wpd->world_ubo); - DRW_UBO_FREE_SAFE(wpd->dof_ubo); - GPU_BATCH_DISCARD_SAFE(wpd->world_clip_planes_batch); + BLI_ghash_free(wpd->material_hash, NULL, MEM_freeN); + BLI_ghash_free(wpd->material_transp_hash, NULL, MEM_freeN); + DRW_UBO_FREE_SAFE(wpd->world_ubo); + DRW_UBO_FREE_SAFE(wpd->dof_ubo); + GPU_BATCH_DISCARD_SAFE(wpd->world_clip_planes_batch); } diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c index 482d7178cb7..91f4f351c7b 100644 --- a/source/blender/draw/engines/workbench/workbench_deferred.c +++ b/source/blender/draw/engines/workbench/workbench_deferred.c @@ -22,7 +22,6 @@ #include "workbench_private.h" - #include "BLI_alloca.h" #include "BLI_dynstr.h" #include "BLI_utildefines.h" @@ -38,7 +37,6 @@ #include "DNA_modifier_types.h" #include "DNA_node_types.h" - #include "GPU_shader.h" #include "GPU_texture.h" #include "GPU_extensions.h" @@ -54,41 +52,41 @@ #endif typedef struct WORKBENCH_DEFERRED_Shaders { - struct GPUShader *prepass_sh_cache[MAX_PREPASS_SHADERS]; + struct GPUShader *prepass_sh_cache[MAX_PREPASS_SHADERS]; } WORKBENCH_DEFERRED_Shaders; static struct { - WORKBENCH_DEFERRED_Shaders sh_data[GPU_SHADER_CFG_LEN]; - - struct GPUShader *composite_sh_cache[MAX_COMPOSITE_SHADERS]; - struct GPUShader *cavity_sh[MAX_CAVITY_SHADERS]; - struct GPUShader *background_sh[2]; - struct GPUShader *ghost_resolve_sh; - struct GPUShader *shadow_fail_sh; - struct GPUShader *shadow_fail_manifold_sh; - struct GPUShader *shadow_pass_sh; - struct GPUShader *shadow_pass_manifold_sh; - struct GPUShader *shadow_caps_sh; - struct GPUShader *shadow_caps_manifold_sh; - struct GPUShader *oit_resolve_sh; - - /* TODO(fclem) move everything below to wpd and custom viewlayer data. */ - struct GPUTexture *oit_accum_tx; /* ref only, not alloced */ - struct GPUTexture *oit_revealage_tx; /* ref only, not alloced */ - struct GPUTexture *ghost_depth_tx; /* ref only, not alloced */ - struct GPUTexture *object_id_tx; /* ref only, not alloced */ - struct GPUTexture *color_buffer_tx; /* ref only, not alloced */ - struct GPUTexture *cavity_buffer_tx; /* ref only, not alloced */ - struct GPUTexture *metallic_buffer_tx; /* ref only, not alloced */ - struct GPUTexture *normal_buffer_tx; /* ref only, not alloced */ - struct GPUTexture *composite_buffer_tx; /* ref only, not alloced */ - - SceneDisplay display; /* world light direction for shadows */ - int next_object_id; - - struct GPUUniformBuffer *sampling_ubo; - struct GPUTexture *jitter_tx; - int cached_sample_num; + WORKBENCH_DEFERRED_Shaders sh_data[GPU_SHADER_CFG_LEN]; + + struct GPUShader *composite_sh_cache[MAX_COMPOSITE_SHADERS]; + struct GPUShader *cavity_sh[MAX_CAVITY_SHADERS]; + struct GPUShader *background_sh[2]; + struct GPUShader *ghost_resolve_sh; + struct GPUShader *shadow_fail_sh; + struct GPUShader *shadow_fail_manifold_sh; + struct GPUShader *shadow_pass_sh; + struct GPUShader *shadow_pass_manifold_sh; + struct GPUShader *shadow_caps_sh; + struct GPUShader *shadow_caps_manifold_sh; + struct GPUShader *oit_resolve_sh; + + /* TODO(fclem) move everything below to wpd and custom viewlayer data. */ + struct GPUTexture *oit_accum_tx; /* ref only, not alloced */ + struct GPUTexture *oit_revealage_tx; /* ref only, not alloced */ + struct GPUTexture *ghost_depth_tx; /* ref only, not alloced */ + struct GPUTexture *object_id_tx; /* ref only, not alloced */ + struct GPUTexture *color_buffer_tx; /* ref only, not alloced */ + struct GPUTexture *cavity_buffer_tx; /* ref only, not alloced */ + struct GPUTexture *metallic_buffer_tx; /* ref only, not alloced */ + struct GPUTexture *normal_buffer_tx; /* ref only, not alloced */ + struct GPUTexture *composite_buffer_tx; /* ref only, not alloced */ + + SceneDisplay display; /* world light direction for shadows */ + int next_object_id; + + struct GPUUniformBuffer *sampling_ubo; + struct GPUTexture *jitter_tx; + int cached_sample_num; } e_data = {{{{NULL}}}}; /* Shaders */ @@ -119,947 +117,999 @@ extern char datatoc_gpu_shader_depth_only_frag_glsl[]; static char *workbench_build_composite_frag(WORKBENCH_PrivateData *wpd) { - DynStr *ds = BLI_dynstr_new(); - - BLI_dynstr_append(ds, datatoc_workbench_data_lib_glsl); - BLI_dynstr_append(ds, datatoc_workbench_common_lib_glsl); - BLI_dynstr_append(ds, datatoc_workbench_background_lib_glsl); - - if (!FLAT_ENABLED(wpd)) { - BLI_dynstr_append(ds, datatoc_workbench_world_light_lib_glsl); - } - if (OBJECT_OUTLINE_ENABLED(wpd)) { - BLI_dynstr_append(ds, datatoc_workbench_object_outline_lib_glsl); - } - if (CURVATURE_ENABLED(wpd)) { - BLI_dynstr_append(ds, datatoc_workbench_curvature_lib_glsl); - } - - BLI_dynstr_append(ds, datatoc_workbench_deferred_composite_frag_glsl); - - char *str = BLI_dynstr_get_cstring(ds); - BLI_dynstr_free(ds); - return str; + DynStr *ds = BLI_dynstr_new(); + + BLI_dynstr_append(ds, datatoc_workbench_data_lib_glsl); + BLI_dynstr_append(ds, datatoc_workbench_common_lib_glsl); + BLI_dynstr_append(ds, datatoc_workbench_background_lib_glsl); + + if (!FLAT_ENABLED(wpd)) { + BLI_dynstr_append(ds, datatoc_workbench_world_light_lib_glsl); + } + if (OBJECT_OUTLINE_ENABLED(wpd)) { + BLI_dynstr_append(ds, datatoc_workbench_object_outline_lib_glsl); + } + if (CURVATURE_ENABLED(wpd)) { + BLI_dynstr_append(ds, datatoc_workbench_curvature_lib_glsl); + } + + BLI_dynstr_append(ds, datatoc_workbench_deferred_composite_frag_glsl); + + char *str = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); + return str; } static char *workbench_build_prepass_frag(void) { - DynStr *ds = BLI_dynstr_new(); + DynStr *ds = BLI_dynstr_new(); - BLI_dynstr_append(ds, datatoc_workbench_data_lib_glsl); - BLI_dynstr_append(ds, datatoc_workbench_common_lib_glsl); - BLI_dynstr_append(ds, datatoc_workbench_prepass_frag_glsl); + BLI_dynstr_append(ds, datatoc_workbench_data_lib_glsl); + BLI_dynstr_append(ds, datatoc_workbench_common_lib_glsl); + BLI_dynstr_append(ds, datatoc_workbench_prepass_frag_glsl); - char *str = BLI_dynstr_get_cstring(ds); - BLI_dynstr_free(ds); - return str; + char *str = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); + return str; } static char *workbench_build_prepass_vert(bool is_hair) { - DynStr *ds = BLI_dynstr_new(); - if (is_hair) { - BLI_dynstr_append(ds, datatoc_common_hair_lib_glsl); - } - BLI_dynstr_append(ds, datatoc_workbench_prepass_vert_glsl); - char *str = BLI_dynstr_get_cstring(ds); - BLI_dynstr_free(ds); - return str; + DynStr *ds = BLI_dynstr_new(); + if (is_hair) { + BLI_dynstr_append(ds, datatoc_common_hair_lib_glsl); + } + BLI_dynstr_append(ds, datatoc_workbench_prepass_vert_glsl); + char *str = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); + return str; } static char *workbench_build_cavity_frag(bool cavity, bool curvature, bool high_dpi) { - DynStr *ds = BLI_dynstr_new(); - - if (cavity) { - BLI_dynstr_append(ds, "#define USE_CAVITY\n"); - } - if (curvature) { - BLI_dynstr_append(ds, "#define USE_CURVATURE\n"); - } - if (high_dpi) { - BLI_dynstr_append(ds, "#define CURVATURE_OFFSET 2\n"); - } - if (NORMAL_ENCODING_ENABLED()) { - BLI_dynstr_append(ds, "#define WORKBENCH_ENCODE_NORMALS\n"); - } - BLI_dynstr_append(ds, datatoc_workbench_common_lib_glsl); - BLI_dynstr_append(ds, datatoc_workbench_curvature_lib_glsl); - BLI_dynstr_append(ds, datatoc_workbench_cavity_frag_glsl); - BLI_dynstr_append(ds, datatoc_workbench_cavity_lib_glsl); - - char *str = BLI_dynstr_get_cstring(ds); - BLI_dynstr_free(ds); - return str; + DynStr *ds = BLI_dynstr_new(); + + if (cavity) { + BLI_dynstr_append(ds, "#define USE_CAVITY\n"); + } + if (curvature) { + BLI_dynstr_append(ds, "#define USE_CURVATURE\n"); + } + if (high_dpi) { + BLI_dynstr_append(ds, "#define CURVATURE_OFFSET 2\n"); + } + if (NORMAL_ENCODING_ENABLED()) { + BLI_dynstr_append(ds, "#define WORKBENCH_ENCODE_NORMALS\n"); + } + BLI_dynstr_append(ds, datatoc_workbench_common_lib_glsl); + BLI_dynstr_append(ds, datatoc_workbench_curvature_lib_glsl); + BLI_dynstr_append(ds, datatoc_workbench_cavity_frag_glsl); + BLI_dynstr_append(ds, datatoc_workbench_cavity_lib_glsl); + + char *str = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); + return str; } static GPUShader *workbench_cavity_shader_get(bool cavity, bool curvature) { - const bool high_dpi = (U.pixelsize > 1.5f); - int index = 0; - SET_FLAG_FROM_TEST(index, cavity, 1 << 0); - SET_FLAG_FROM_TEST(index, curvature, 1 << 1); - SET_FLAG_FROM_TEST(index, high_dpi, 1 << 2); - - GPUShader **sh = &e_data.cavity_sh[index]; - if (*sh == NULL) { - char *cavity_frag = workbench_build_cavity_frag(cavity, curvature, high_dpi); - *sh = DRW_shader_create_fullscreen(cavity_frag, NULL); - MEM_freeN(cavity_frag); - } - return *sh; + const bool high_dpi = (U.pixelsize > 1.5f); + int index = 0; + SET_FLAG_FROM_TEST(index, cavity, 1 << 0); + SET_FLAG_FROM_TEST(index, curvature, 1 << 1); + SET_FLAG_FROM_TEST(index, high_dpi, 1 << 2); + + GPUShader **sh = &e_data.cavity_sh[index]; + if (*sh == NULL) { + char *cavity_frag = workbench_build_cavity_frag(cavity, curvature, high_dpi); + *sh = DRW_shader_create_fullscreen(cavity_frag, NULL); + MEM_freeN(cavity_frag); + } + return *sh; } -static GPUShader *ensure_deferred_prepass_shader( - WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair, eGPUShaderConfig sh_cfg) +static GPUShader *ensure_deferred_prepass_shader(WORKBENCH_PrivateData *wpd, + bool use_textures, + bool is_hair, + eGPUShaderConfig sh_cfg) { - WORKBENCH_DEFERRED_Shaders *sh_data = &e_data.sh_data[sh_cfg]; - int index = workbench_material_get_prepass_shader_index(wpd, use_textures, is_hair); - if (sh_data->prepass_sh_cache[index] == NULL) { - const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg]; - char *defines = workbench_material_build_defines(wpd, use_textures, is_hair); - char *prepass_vert = workbench_build_prepass_vert(is_hair); - char *prepass_frag = workbench_build_prepass_frag(); - sh_data->prepass_sh_cache[index] = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, prepass_vert, NULL}, - .frag = (const char *[]){prepass_frag, NULL}, - .defs = (const char *[]){sh_cfg_data->def, defines, NULL}, - }); - MEM_freeN(prepass_vert); - MEM_freeN(prepass_frag); - MEM_freeN(defines); - } - return sh_data->prepass_sh_cache[index]; + WORKBENCH_DEFERRED_Shaders *sh_data = &e_data.sh_data[sh_cfg]; + int index = workbench_material_get_prepass_shader_index(wpd, use_textures, is_hair); + if (sh_data->prepass_sh_cache[index] == NULL) { + const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg]; + char *defines = workbench_material_build_defines(wpd, use_textures, is_hair); + char *prepass_vert = workbench_build_prepass_vert(is_hair); + char *prepass_frag = workbench_build_prepass_frag(); + sh_data->prepass_sh_cache[index] = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, prepass_vert, NULL}, + .frag = (const char *[]){prepass_frag, NULL}, + .defs = (const char *[]){sh_cfg_data->def, defines, NULL}, + }); + MEM_freeN(prepass_vert); + MEM_freeN(prepass_frag); + MEM_freeN(defines); + } + return sh_data->prepass_sh_cache[index]; } static GPUShader *ensure_deferred_composite_shader(WORKBENCH_PrivateData *wpd) { - int index = workbench_material_get_composite_shader_index(wpd); - if (e_data.composite_sh_cache[index] == NULL) { - char *defines = workbench_material_build_defines(wpd, false, false); - char *composite_frag = workbench_build_composite_frag(wpd); - e_data.composite_sh_cache[index] = DRW_shader_create_fullscreen(composite_frag, defines); - MEM_freeN(composite_frag); - MEM_freeN(defines); - } - return e_data.composite_sh_cache[index]; + int index = workbench_material_get_composite_shader_index(wpd); + if (e_data.composite_sh_cache[index] == NULL) { + char *defines = workbench_material_build_defines(wpd, false, false); + char *composite_frag = workbench_build_composite_frag(wpd); + e_data.composite_sh_cache[index] = DRW_shader_create_fullscreen(composite_frag, defines); + MEM_freeN(composite_frag); + MEM_freeN(defines); + } + return e_data.composite_sh_cache[index]; } static GPUShader *ensure_background_shader(WORKBENCH_PrivateData *wpd) { - const int index = OBJECT_OUTLINE_ENABLED(wpd) ? 1 : 0; - if (e_data.background_sh[index] == NULL) { - const char *defines = (index) ? "#define V3D_SHADING_OBJECT_OUTLINE\n" : NULL; - char *frag = BLI_string_joinN( - datatoc_workbench_data_lib_glsl, - datatoc_workbench_common_lib_glsl, - datatoc_workbench_background_lib_glsl, - datatoc_workbench_object_outline_lib_glsl, - datatoc_workbench_deferred_background_frag_glsl); - e_data.background_sh[index] = DRW_shader_create_fullscreen(frag, defines); - MEM_freeN(frag); - } - return e_data.background_sh[index]; + const int index = OBJECT_OUTLINE_ENABLED(wpd) ? 1 : 0; + if (e_data.background_sh[index] == NULL) { + const char *defines = (index) ? "#define V3D_SHADING_OBJECT_OUTLINE\n" : NULL; + char *frag = BLI_string_joinN(datatoc_workbench_data_lib_glsl, + datatoc_workbench_common_lib_glsl, + datatoc_workbench_background_lib_glsl, + datatoc_workbench_object_outline_lib_glsl, + datatoc_workbench_deferred_background_frag_glsl); + e_data.background_sh[index] = DRW_shader_create_fullscreen(frag, defines); + MEM_freeN(frag); + } + return e_data.background_sh[index]; } static void select_deferred_shaders(WORKBENCH_PrivateData *wpd, eGPUShaderConfig sh_cfg) { - wpd->prepass_solid_sh = ensure_deferred_prepass_shader(wpd, false, false, sh_cfg); - wpd->prepass_solid_hair_sh = ensure_deferred_prepass_shader(wpd, false, true, sh_cfg); - wpd->prepass_texture_sh = ensure_deferred_prepass_shader(wpd, true, false, sh_cfg); - wpd->prepass_texture_hair_sh = ensure_deferred_prepass_shader(wpd, true, true, sh_cfg); - wpd->composite_sh = ensure_deferred_composite_shader(wpd); - wpd->background_sh = ensure_background_shader(wpd); + wpd->prepass_solid_sh = ensure_deferred_prepass_shader(wpd, false, false, sh_cfg); + wpd->prepass_solid_hair_sh = ensure_deferred_prepass_shader(wpd, false, true, sh_cfg); + wpd->prepass_texture_sh = ensure_deferred_prepass_shader(wpd, true, false, sh_cfg); + wpd->prepass_texture_hair_sh = ensure_deferred_prepass_shader(wpd, true, true, sh_cfg); + wpd->composite_sh = ensure_deferred_composite_shader(wpd); + wpd->background_sh = ensure_background_shader(wpd); } /* Using Hammersley distribution */ static float *create_disk_samples(int num_samples, int num_iterations) { - /* vec4 to ensure memory alignment. */ - const int total_samples = num_samples * num_iterations; - float(*texels)[4] = MEM_mallocN(sizeof(float[4]) * total_samples, __func__); - const float num_samples_inv = 1.0f / num_samples; - - for (int i = 0; i < total_samples; i++) { - float it_add = (i / num_samples) * 0.499f; - float r = fmodf((i + 0.5f + it_add) * num_samples_inv, 1.0f); - double dphi; - BLI_hammersley_1d(i, &dphi); - - float phi = (float)dphi * 2.0f * M_PI + it_add; - texels[i][0] = cosf(phi); - texels[i][1] = sinf(phi); - /* This deliberately distribute more samples - * at the center of the disk (and thus the shadow). */ - texels[i][2] = r; - } - - return (float *)texels; + /* vec4 to ensure memory alignment. */ + const int total_samples = num_samples * num_iterations; + float(*texels)[4] = MEM_mallocN(sizeof(float[4]) * total_samples, __func__); + const float num_samples_inv = 1.0f / num_samples; + + for (int i = 0; i < total_samples; i++) { + float it_add = (i / num_samples) * 0.499f; + float r = fmodf((i + 0.5f + it_add) * num_samples_inv, 1.0f); + double dphi; + BLI_hammersley_1d(i, &dphi); + + float phi = (float)dphi * 2.0f * M_PI + it_add; + texels[i][0] = cosf(phi); + texels[i][1] = sinf(phi); + /* This deliberately distribute more samples + * at the center of the disk (and thus the shadow). */ + texels[i][2] = r; + } + + return (float *)texels; } static struct GPUTexture *create_jitter_texture(int num_samples) { - float jitter[64 * 64][4]; - const float num_samples_inv = 1.0f / num_samples; - - for (int i = 0; i < 64 * 64; i++) { - float phi = blue_noise[i][0] * 2.0f * M_PI; - /* This rotate the sample per pixels */ - jitter[i][0] = cosf(phi); - jitter[i][1] = sinf(phi); - /* This offset the sample along it's direction axis (reduce banding) */ - float bn = blue_noise[i][1] - 0.5f; - CLAMP(bn, -0.499f, 0.499f); /* fix fireflies */ - jitter[i][2] = bn * num_samples_inv; - jitter[i][3] = blue_noise[i][1]; - } - - UNUSED_VARS(bsdf_split_sum_ggx, btdf_split_sum_ggx, ltc_mag_ggx, ltc_mat_ggx, ltc_disk_integral); - - return DRW_texture_create_2d(64, 64, GPU_RGBA16F, DRW_TEX_FILTER | DRW_TEX_WRAP, &jitter[0][0]); + float jitter[64 * 64][4]; + const float num_samples_inv = 1.0f / num_samples; + + for (int i = 0; i < 64 * 64; i++) { + float phi = blue_noise[i][0] * 2.0f * M_PI; + /* This rotate the sample per pixels */ + jitter[i][0] = cosf(phi); + jitter[i][1] = sinf(phi); + /* This offset the sample along it's direction axis (reduce banding) */ + float bn = blue_noise[i][1] - 0.5f; + CLAMP(bn, -0.499f, 0.499f); /* fix fireflies */ + jitter[i][2] = bn * num_samples_inv; + jitter[i][3] = blue_noise[i][1]; + } + + UNUSED_VARS(bsdf_split_sum_ggx, btdf_split_sum_ggx, ltc_mag_ggx, ltc_mat_ggx, ltc_disk_integral); + + return DRW_texture_create_2d(64, 64, GPU_RGBA16F, DRW_TEX_FILTER | DRW_TEX_WRAP, &jitter[0][0]); } /* Functions */ - static void workbench_init_object_data(DrawData *dd) { - WORKBENCH_ObjectData *data = (WORKBENCH_ObjectData *)dd; - data->object_id = ((e_data.next_object_id++) & 0xff) + 1; - data->shadow_bbox_dirty = true; + WORKBENCH_ObjectData *data = (WORKBENCH_ObjectData *)dd; + data->object_id = ((e_data.next_object_id++) & 0xff) + 1; + data->shadow_bbox_dirty = true; } -static void workbench_init_oit_framebuffer(WORKBENCH_FramebufferList *fbl, DefaultTextureList *dtxl) +static void workbench_init_oit_framebuffer(WORKBENCH_FramebufferList *fbl, + DefaultTextureList *dtxl) { - const float *size = DRW_viewport_size_get(); - e_data.oit_accum_tx = DRW_texture_pool_query_2d(size[0], size[1], GPU_RGBA16F, &draw_engine_workbench_solid); - e_data.oit_revealage_tx = DRW_texture_pool_query_2d(size[0], size[1], GPU_R16F, &draw_engine_workbench_solid); - - GPU_framebuffer_ensure_config(&fbl->transparent_accum_fb, { - GPU_ATTACHMENT_TEXTURE(dtxl->depth), - GPU_ATTACHMENT_TEXTURE(e_data.oit_accum_tx), - GPU_ATTACHMENT_TEXTURE(e_data.oit_revealage_tx), - }); + const float *size = DRW_viewport_size_get(); + e_data.oit_accum_tx = DRW_texture_pool_query_2d( + size[0], size[1], GPU_RGBA16F, &draw_engine_workbench_solid); + e_data.oit_revealage_tx = DRW_texture_pool_query_2d( + size[0], size[1], GPU_R16F, &draw_engine_workbench_solid); + + GPU_framebuffer_ensure_config(&fbl->transparent_accum_fb, + { + GPU_ATTACHMENT_TEXTURE(dtxl->depth), + GPU_ATTACHMENT_TEXTURE(e_data.oit_accum_tx), + GPU_ATTACHMENT_TEXTURE(e_data.oit_revealage_tx), + }); } void workbench_deferred_engine_init(WORKBENCH_Data *vedata) { - WORKBENCH_FramebufferList *fbl = vedata->fbl; - WORKBENCH_StorageList *stl = vedata->stl; - WORKBENCH_PassList *psl = vedata->psl; - DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - 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; - - if (v3d && rv3d) { - camera = (rv3d->persp == RV3D_CAMOB) ? v3d->camera : NULL; - } - else { - camera = scene->camera; - } - - if (!stl->g_data) { - /* Alloc transient pointers */ - stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__); - } - if (!stl->effects) { - stl->effects = MEM_callocN(sizeof(*stl->effects), __func__); - workbench_effect_info_init(stl->effects); - } - - if (!e_data.next_object_id) { - WORKBENCH_DEFERRED_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; - memset(sh_data->prepass_sh_cache, 0, sizeof(sh_data->prepass_sh_cache)); - memset(e_data.composite_sh_cache, 0, sizeof(e_data.composite_sh_cache)); - e_data.next_object_id = 1; + WORKBENCH_FramebufferList *fbl = vedata->fbl; + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_PassList *psl = vedata->psl; + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + 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; + + if (v3d && rv3d) { + camera = (rv3d->persp == RV3D_CAMOB) ? v3d->camera : NULL; + } + else { + camera = scene->camera; + } + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__); + } + if (!stl->effects) { + stl->effects = MEM_callocN(sizeof(*stl->effects), __func__); + workbench_effect_info_init(stl->effects); + } + + if (!e_data.next_object_id) { + WORKBENCH_DEFERRED_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; + memset(sh_data->prepass_sh_cache, 0, sizeof(sh_data->prepass_sh_cache)); + memset(e_data.composite_sh_cache, 0, sizeof(e_data.composite_sh_cache)); + e_data.next_object_id = 1; #ifdef DEBUG_SHADOW_VOLUME - const char *shadow_frag = datatoc_workbench_shadow_debug_frag_glsl; + const char *shadow_frag = datatoc_workbench_shadow_debug_frag_glsl; #else - const char *shadow_frag = datatoc_gpu_shader_depth_only_frag_glsl; + const char *shadow_frag = datatoc_gpu_shader_depth_only_frag_glsl; #endif - /* TODO only compile on demand */ - e_data.shadow_pass_sh = DRW_shader_create( - datatoc_workbench_shadow_vert_glsl, - datatoc_workbench_shadow_geom_glsl, - shadow_frag, - "#define SHADOW_PASS\n" - "#define DOUBLE_MANIFOLD\n"); - e_data.shadow_pass_manifold_sh = DRW_shader_create( - datatoc_workbench_shadow_vert_glsl, - datatoc_workbench_shadow_geom_glsl, - shadow_frag, - "#define SHADOW_PASS\n"); - e_data.shadow_fail_sh = DRW_shader_create( - datatoc_workbench_shadow_vert_glsl, - datatoc_workbench_shadow_geom_glsl, - shadow_frag, - "#define SHADOW_FAIL\n" - "#define DOUBLE_MANIFOLD\n"); - e_data.shadow_fail_manifold_sh = DRW_shader_create( - datatoc_workbench_shadow_vert_glsl, - datatoc_workbench_shadow_geom_glsl, - shadow_frag, - "#define SHADOW_FAIL\n"); - e_data.shadow_caps_sh = DRW_shader_create( - datatoc_workbench_shadow_vert_glsl, - datatoc_workbench_shadow_caps_geom_glsl, - shadow_frag, - "#define SHADOW_FAIL\n" - "#define DOUBLE_MANIFOLD\n"); - e_data.shadow_caps_manifold_sh = DRW_shader_create( - datatoc_workbench_shadow_vert_glsl, - datatoc_workbench_shadow_caps_geom_glsl, - shadow_frag, - "#define SHADOW_FAIL\n"); - - e_data.ghost_resolve_sh = DRW_shader_create_fullscreen(datatoc_workbench_ghost_resolve_frag_glsl, NULL); - } - workbench_volume_engine_init(); - workbench_fxaa_engine_init(); - workbench_taa_engine_init(vedata); - - WORKBENCH_PrivateData *wpd = stl->g_data; - workbench_private_data_init(wpd); - - workbench_dof_engine_init(vedata, camera); - - if (OIT_ENABLED(wpd)) { - if (e_data.oit_resolve_sh == NULL) { - e_data.oit_resolve_sh = DRW_shader_create_fullscreen( - datatoc_workbench_forward_composite_frag_glsl, - "#define ALPHA_COMPOSITE\n"); - } - - workbench_forward_choose_shaders(wpd, draw_ctx->sh_cfg); - workbench_forward_outline_shaders_ensure(wpd, draw_ctx->sh_cfg); - } - - { - const float *viewport_size = DRW_viewport_size_get(); - const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; - const eGPUTextureFormat nor_tex_format = NORMAL_ENCODING_ENABLED() ? GPU_RG16 : GPU_RGBA32F; - const eGPUTextureFormat comp_tex_format = DRW_state_is_image_render() ? GPU_RGBA16F : GPU_R11F_G11F_B10F; - const eGPUTextureFormat col_tex_format = DRW_state_is_image_render() ? GPU_RGBA16F : GPU_RGBA8; - const eGPUTextureFormat id_tex_format = OBJECT_ID_PASS_ENABLED(wpd) ? GPU_R32UI : GPU_R8; - - e_data.object_id_tx = NULL; - e_data.color_buffer_tx = NULL; - e_data.composite_buffer_tx = NULL; - e_data.normal_buffer_tx = NULL; - e_data.cavity_buffer_tx = NULL; - - e_data.composite_buffer_tx = DRW_texture_pool_query_2d(size[0], size[1], comp_tex_format, &draw_engine_workbench_solid); - - if (MATDATA_PASS_ENABLED(wpd) || GPU_unused_fb_slot_workaround()) { - e_data.color_buffer_tx = DRW_texture_pool_query_2d(size[0], size[1], col_tex_format, &draw_engine_workbench_solid); - } - if (OBJECT_ID_PASS_ENABLED(wpd) || GPU_unused_fb_slot_workaround()) { - e_data.object_id_tx = DRW_texture_pool_query_2d(size[0], size[1], id_tex_format, &draw_engine_workbench_solid); - } - if (NORMAL_VIEWPORT_PASS_ENABLED(wpd)) { - e_data.normal_buffer_tx = DRW_texture_pool_query_2d(size[0], size[1], nor_tex_format, &draw_engine_workbench_solid); - } - if (CAVITY_ENABLED(wpd)) { - e_data.cavity_buffer_tx = DRW_texture_pool_query_2d(size[0], size[1], GPU_R16, &draw_engine_workbench_solid); - } - - GPU_framebuffer_ensure_config(&fbl->prepass_fb, { - GPU_ATTACHMENT_TEXTURE(dtxl->depth), - GPU_ATTACHMENT_TEXTURE(e_data.color_buffer_tx), - GPU_ATTACHMENT_TEXTURE(e_data.object_id_tx), - GPU_ATTACHMENT_TEXTURE(e_data.normal_buffer_tx), - }); - GPU_framebuffer_ensure_config(&fbl->cavity_fb, { - GPU_ATTACHMENT_NONE, - GPU_ATTACHMENT_TEXTURE(e_data.cavity_buffer_tx), - }); - GPU_framebuffer_ensure_config(&fbl->composite_fb, { - GPU_ATTACHMENT_TEXTURE(dtxl->depth), - GPU_ATTACHMENT_TEXTURE(e_data.composite_buffer_tx), - }); - GPU_framebuffer_ensure_config(&fbl->color_only_fb, { - GPU_ATTACHMENT_NONE, - GPU_ATTACHMENT_TEXTURE(e_data.composite_buffer_tx), - }); - - if (!MATDATA_PASS_ENABLED(wpd) && !GPU_unused_fb_slot_workaround()) { - e_data.color_buffer_tx = DRW_texture_pool_query_2d(size[0], size[1], col_tex_format, &draw_engine_workbench_solid); - } - - GPU_framebuffer_ensure_config(&fbl->effect_fb, { - GPU_ATTACHMENT_NONE, - GPU_ATTACHMENT_TEXTURE(e_data.color_buffer_tx), - }); - - if (OBJECT_ID_PASS_ENABLED(wpd)) { - GPU_framebuffer_ensure_config(&fbl->id_clear_fb, { - GPU_ATTACHMENT_NONE, - GPU_ATTACHMENT_TEXTURE(e_data.object_id_tx), - }); - } - } - - { - /* 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); - } - } - - /* Prepass */ - { - DRWShadingGroup *grp; - const bool do_cull = CULL_BACKFACE_ENABLED(wpd); - - int state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; - psl->prepass_pass = DRW_pass_create("Prepass", (do_cull) ? state | DRW_STATE_CULL_BACK : state); - psl->prepass_hair_pass = DRW_pass_create("Prepass", state); - - psl->ghost_prepass_pass = DRW_pass_create("Prepass Ghost", (do_cull) ? state | DRW_STATE_CULL_BACK : state); - psl->ghost_prepass_hair_pass = DRW_pass_create("Prepass Ghost", state); - - psl->ghost_resolve_pass = DRW_pass_create("Resolve Ghost Depth", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS); - grp = DRW_shgroup_create(e_data.ghost_resolve_sh, psl->ghost_resolve_pass); - DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.ghost_depth_tx); - DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); - } - - { - workbench_aa_create_pass(vedata, &e_data.color_buffer_tx); - } - - { - workbench_dof_create_pass(vedata, &e_data.composite_buffer_tx, e_data.jitter_tx); - } - - 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_add(grp, DRW_cache_fullscreen_quad_get(), NULL); - } + /* TODO only compile on demand */ + e_data.shadow_pass_sh = DRW_shader_create(datatoc_workbench_shadow_vert_glsl, + datatoc_workbench_shadow_geom_glsl, + shadow_frag, + "#define SHADOW_PASS\n" + "#define DOUBLE_MANIFOLD\n"); + e_data.shadow_pass_manifold_sh = DRW_shader_create(datatoc_workbench_shadow_vert_glsl, + datatoc_workbench_shadow_geom_glsl, + shadow_frag, + "#define SHADOW_PASS\n"); + e_data.shadow_fail_sh = DRW_shader_create(datatoc_workbench_shadow_vert_glsl, + datatoc_workbench_shadow_geom_glsl, + shadow_frag, + "#define SHADOW_FAIL\n" + "#define DOUBLE_MANIFOLD\n"); + e_data.shadow_fail_manifold_sh = DRW_shader_create(datatoc_workbench_shadow_vert_glsl, + datatoc_workbench_shadow_geom_glsl, + shadow_frag, + "#define SHADOW_FAIL\n"); + e_data.shadow_caps_sh = DRW_shader_create(datatoc_workbench_shadow_vert_glsl, + datatoc_workbench_shadow_caps_geom_glsl, + shadow_frag, + "#define SHADOW_FAIL\n" + "#define DOUBLE_MANIFOLD\n"); + e_data.shadow_caps_manifold_sh = DRW_shader_create(datatoc_workbench_shadow_vert_glsl, + datatoc_workbench_shadow_caps_geom_glsl, + shadow_frag, + "#define SHADOW_FAIL\n"); + + e_data.ghost_resolve_sh = DRW_shader_create_fullscreen( + datatoc_workbench_ghost_resolve_frag_glsl, NULL); + } + workbench_volume_engine_init(); + workbench_fxaa_engine_init(); + workbench_taa_engine_init(vedata); + + WORKBENCH_PrivateData *wpd = stl->g_data; + workbench_private_data_init(wpd); + + workbench_dof_engine_init(vedata, camera); + + if (OIT_ENABLED(wpd)) { + if (e_data.oit_resolve_sh == NULL) { + e_data.oit_resolve_sh = DRW_shader_create_fullscreen( + datatoc_workbench_forward_composite_frag_glsl, "#define ALPHA_COMPOSITE\n"); + } + + workbench_forward_choose_shaders(wpd, draw_ctx->sh_cfg); + workbench_forward_outline_shaders_ensure(wpd, draw_ctx->sh_cfg); + } + + { + const float *viewport_size = DRW_viewport_size_get(); + const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; + const eGPUTextureFormat nor_tex_format = NORMAL_ENCODING_ENABLED() ? GPU_RG16 : GPU_RGBA32F; + const eGPUTextureFormat comp_tex_format = DRW_state_is_image_render() ? GPU_RGBA16F : + GPU_R11F_G11F_B10F; + const eGPUTextureFormat col_tex_format = DRW_state_is_image_render() ? GPU_RGBA16F : GPU_RGBA8; + const eGPUTextureFormat id_tex_format = OBJECT_ID_PASS_ENABLED(wpd) ? GPU_R32UI : GPU_R8; + + e_data.object_id_tx = NULL; + e_data.color_buffer_tx = NULL; + e_data.composite_buffer_tx = NULL; + e_data.normal_buffer_tx = NULL; + e_data.cavity_buffer_tx = NULL; + + e_data.composite_buffer_tx = DRW_texture_pool_query_2d( + size[0], size[1], comp_tex_format, &draw_engine_workbench_solid); + + if (MATDATA_PASS_ENABLED(wpd) || GPU_unused_fb_slot_workaround()) { + e_data.color_buffer_tx = DRW_texture_pool_query_2d( + size[0], size[1], col_tex_format, &draw_engine_workbench_solid); + } + if (OBJECT_ID_PASS_ENABLED(wpd) || GPU_unused_fb_slot_workaround()) { + e_data.object_id_tx = DRW_texture_pool_query_2d( + size[0], size[1], id_tex_format, &draw_engine_workbench_solid); + } + if (NORMAL_VIEWPORT_PASS_ENABLED(wpd)) { + e_data.normal_buffer_tx = DRW_texture_pool_query_2d( + size[0], size[1], nor_tex_format, &draw_engine_workbench_solid); + } + if (CAVITY_ENABLED(wpd)) { + e_data.cavity_buffer_tx = DRW_texture_pool_query_2d( + size[0], size[1], GPU_R16, &draw_engine_workbench_solid); + } + + GPU_framebuffer_ensure_config(&fbl->prepass_fb, + { + GPU_ATTACHMENT_TEXTURE(dtxl->depth), + GPU_ATTACHMENT_TEXTURE(e_data.color_buffer_tx), + GPU_ATTACHMENT_TEXTURE(e_data.object_id_tx), + GPU_ATTACHMENT_TEXTURE(e_data.normal_buffer_tx), + }); + GPU_framebuffer_ensure_config(&fbl->cavity_fb, + { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(e_data.cavity_buffer_tx), + }); + GPU_framebuffer_ensure_config(&fbl->composite_fb, + { + GPU_ATTACHMENT_TEXTURE(dtxl->depth), + GPU_ATTACHMENT_TEXTURE(e_data.composite_buffer_tx), + }); + GPU_framebuffer_ensure_config(&fbl->color_only_fb, + { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(e_data.composite_buffer_tx), + }); + + if (!MATDATA_PASS_ENABLED(wpd) && !GPU_unused_fb_slot_workaround()) { + e_data.color_buffer_tx = DRW_texture_pool_query_2d( + size[0], size[1], col_tex_format, &draw_engine_workbench_solid); + } + + GPU_framebuffer_ensure_config(&fbl->effect_fb, + { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(e_data.color_buffer_tx), + }); + + if (OBJECT_ID_PASS_ENABLED(wpd)) { + GPU_framebuffer_ensure_config(&fbl->id_clear_fb, + { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(e_data.object_id_tx), + }); + } + } + + { + /* 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); + } + } + + /* Prepass */ + { + DRWShadingGroup *grp; + const bool do_cull = CULL_BACKFACE_ENABLED(wpd); + + int state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; + psl->prepass_pass = DRW_pass_create("Prepass", + (do_cull) ? state | DRW_STATE_CULL_BACK : state); + psl->prepass_hair_pass = DRW_pass_create("Prepass", state); + + psl->ghost_prepass_pass = DRW_pass_create("Prepass Ghost", + (do_cull) ? state | DRW_STATE_CULL_BACK : state); + psl->ghost_prepass_hair_pass = DRW_pass_create("Prepass Ghost", state); + + psl->ghost_resolve_pass = DRW_pass_create("Resolve Ghost Depth", + DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS); + grp = DRW_shgroup_create(e_data.ghost_resolve_sh, psl->ghost_resolve_pass); + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.ghost_depth_tx); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + } + + { + workbench_aa_create_pass(vedata, &e_data.color_buffer_tx); + } + + { + workbench_dof_create_pass(vedata, &e_data.composite_buffer_tx, e_data.jitter_tx); + } + + 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_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + } } static void workbench_setup_ghost_framebuffer(WORKBENCH_FramebufferList *fbl) { - const float *viewport_size = DRW_viewport_size_get(); - const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; - - e_data.ghost_depth_tx = DRW_texture_pool_query_2d(size[0], size[1], GPU_DEPTH_COMPONENT24, &draw_engine_workbench_solid); - - GPU_framebuffer_ensure_config(&fbl->ghost_prepass_fb, { - GPU_ATTACHMENT_TEXTURE(e_data.ghost_depth_tx), - GPU_ATTACHMENT_TEXTURE(e_data.color_buffer_tx), - GPU_ATTACHMENT_TEXTURE(e_data.object_id_tx), - GPU_ATTACHMENT_TEXTURE(e_data.normal_buffer_tx), - }); + const float *viewport_size = DRW_viewport_size_get(); + const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; + + e_data.ghost_depth_tx = DRW_texture_pool_query_2d( + size[0], size[1], GPU_DEPTH_COMPONENT24, &draw_engine_workbench_solid); + + GPU_framebuffer_ensure_config(&fbl->ghost_prepass_fb, + { + GPU_ATTACHMENT_TEXTURE(e_data.ghost_depth_tx), + GPU_ATTACHMENT_TEXTURE(e_data.color_buffer_tx), + GPU_ATTACHMENT_TEXTURE(e_data.object_id_tx), + GPU_ATTACHMENT_TEXTURE(e_data.normal_buffer_tx), + }); } void workbench_deferred_engine_free(void) { - for (int sh_data_index = 0; sh_data_index < ARRAY_SIZE(e_data.sh_data); sh_data_index++) { - WORKBENCH_DEFERRED_Shaders *sh_data = &e_data.sh_data[sh_data_index]; - for (int index = 0; index < MAX_PREPASS_SHADERS; index++) { - DRW_SHADER_FREE_SAFE(sh_data->prepass_sh_cache[index]); - } - } - for (int index = 0; index < MAX_COMPOSITE_SHADERS; index++) { - DRW_SHADER_FREE_SAFE(e_data.composite_sh_cache[index]); - } - for (int index = 0; index < MAX_CAVITY_SHADERS; ++index) { - DRW_SHADER_FREE_SAFE(e_data.cavity_sh[index]); - } - DRW_SHADER_FREE_SAFE(e_data.ghost_resolve_sh); - DRW_UBO_FREE_SAFE(e_data.sampling_ubo); - DRW_TEXTURE_FREE_SAFE(e_data.jitter_tx); - DRW_SHADER_FREE_SAFE(e_data.background_sh[0]); - DRW_SHADER_FREE_SAFE(e_data.background_sh[1]); - - DRW_SHADER_FREE_SAFE(e_data.oit_resolve_sh); - - DRW_SHADER_FREE_SAFE(e_data.shadow_pass_sh); - DRW_SHADER_FREE_SAFE(e_data.shadow_pass_manifold_sh); - DRW_SHADER_FREE_SAFE(e_data.shadow_fail_sh); - DRW_SHADER_FREE_SAFE(e_data.shadow_fail_manifold_sh); - DRW_SHADER_FREE_SAFE(e_data.shadow_caps_sh); - DRW_SHADER_FREE_SAFE(e_data.shadow_caps_manifold_sh); - - workbench_volume_engine_free(); - workbench_fxaa_engine_free(); - workbench_taa_engine_free(); - workbench_dof_engine_free(); + for (int sh_data_index = 0; sh_data_index < ARRAY_SIZE(e_data.sh_data); sh_data_index++) { + WORKBENCH_DEFERRED_Shaders *sh_data = &e_data.sh_data[sh_data_index]; + for (int index = 0; index < MAX_PREPASS_SHADERS; index++) { + DRW_SHADER_FREE_SAFE(sh_data->prepass_sh_cache[index]); + } + } + for (int index = 0; index < MAX_COMPOSITE_SHADERS; index++) { + DRW_SHADER_FREE_SAFE(e_data.composite_sh_cache[index]); + } + for (int index = 0; index < MAX_CAVITY_SHADERS; ++index) { + DRW_SHADER_FREE_SAFE(e_data.cavity_sh[index]); + } + DRW_SHADER_FREE_SAFE(e_data.ghost_resolve_sh); + DRW_UBO_FREE_SAFE(e_data.sampling_ubo); + DRW_TEXTURE_FREE_SAFE(e_data.jitter_tx); + DRW_SHADER_FREE_SAFE(e_data.background_sh[0]); + DRW_SHADER_FREE_SAFE(e_data.background_sh[1]); + + DRW_SHADER_FREE_SAFE(e_data.oit_resolve_sh); + + DRW_SHADER_FREE_SAFE(e_data.shadow_pass_sh); + DRW_SHADER_FREE_SAFE(e_data.shadow_pass_manifold_sh); + DRW_SHADER_FREE_SAFE(e_data.shadow_fail_sh); + DRW_SHADER_FREE_SAFE(e_data.shadow_fail_manifold_sh); + DRW_SHADER_FREE_SAFE(e_data.shadow_caps_sh); + DRW_SHADER_FREE_SAFE(e_data.shadow_caps_manifold_sh); + + workbench_volume_engine_free(); + workbench_fxaa_engine_free(); + workbench_taa_engine_free(); + workbench_dof_engine_free(); } static void workbench_composite_uniforms(WORKBENCH_PrivateData *wpd, DRWShadingGroup *grp) { - DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo); - if (MATDATA_PASS_ENABLED(wpd)) { - DRW_shgroup_uniform_texture_ref(grp, "materialBuffer", &e_data.color_buffer_tx); - } - else { - DRW_shgroup_uniform_vec3(grp, "materialSingleColor", wpd->shading.single_color, 1); - } - if (OBJECT_OUTLINE_ENABLED(wpd)) { - DRW_shgroup_uniform_texture_ref(grp, "objectId", &e_data.object_id_tx); - } - if (NORMAL_VIEWPORT_COMP_PASS_ENABLED(wpd)) { - DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &e_data.normal_buffer_tx); - } - if (CAVITY_ENABLED(wpd)) { - DRW_shgroup_uniform_texture_ref(grp, "cavityBuffer", &e_data.cavity_buffer_tx); - } - if (SPECULAR_HIGHLIGHT_ENABLED(wpd) || STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) { - DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)wpd->viewvecs, 3); - } - if (SPECULAR_HIGHLIGHT_ENABLED(wpd) || STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) { - DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); - } - if (STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) { - BKE_studiolight_ensure_flag(wpd->studio_light, STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE); - DRW_shgroup_uniform_texture(grp, "matcapImage", wpd->studio_light->equirect_radiance_gputexture); - } + DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo); + if (MATDATA_PASS_ENABLED(wpd)) { + DRW_shgroup_uniform_texture_ref(grp, "materialBuffer", &e_data.color_buffer_tx); + } + else { + DRW_shgroup_uniform_vec3(grp, "materialSingleColor", wpd->shading.single_color, 1); + } + if (OBJECT_OUTLINE_ENABLED(wpd)) { + DRW_shgroup_uniform_texture_ref(grp, "objectId", &e_data.object_id_tx); + } + if (NORMAL_VIEWPORT_COMP_PASS_ENABLED(wpd)) { + DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &e_data.normal_buffer_tx); + } + if (CAVITY_ENABLED(wpd)) { + DRW_shgroup_uniform_texture_ref(grp, "cavityBuffer", &e_data.cavity_buffer_tx); + } + if (SPECULAR_HIGHLIGHT_ENABLED(wpd) || STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) { + DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)wpd->viewvecs, 3); + } + if (SPECULAR_HIGHLIGHT_ENABLED(wpd) || STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) { + DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); + } + if (STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) { + BKE_studiolight_ensure_flag(wpd->studio_light, STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE); + DRW_shgroup_uniform_texture( + grp, "matcapImage", wpd->studio_light->equirect_radiance_gputexture); + } } void workbench_deferred_cache_init(WORKBENCH_Data *vedata) { - WORKBENCH_StorageList *stl = vedata->stl; - WORKBENCH_PassList *psl = vedata->psl; - WORKBENCH_PrivateData *wpd = stl->g_data; - DRWShadingGroup *grp; - const DRWContextState *draw_ctx = DRW_context_state_get(); - - Scene *scene = draw_ctx->scene; - - workbench_volume_cache_init(vedata); - - select_deferred_shaders(wpd, draw_ctx->sh_cfg); - - /* Background Pass */ - { - psl->background_pass = DRW_pass_create( - "Background", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL); - grp = DRW_shgroup_create(wpd->background_sh, psl->background_pass); - DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo); - DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); - if (OBJECT_OUTLINE_ENABLED(wpd)) { - DRW_shgroup_uniform_texture_ref(grp, "objectId", &e_data.object_id_tx); - } - DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); - - if (draw_ctx->rv3d && (draw_ctx->rv3d->rflag & RV3D_CLIPPING) && draw_ctx->rv3d->clipbb) { - GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR_BACKGROUND); - grp = DRW_shgroup_create(shader, psl->background_pass); - wpd->world_clip_planes_batch = DRW_draw_background_clipping_batch_from_rv3d(draw_ctx->rv3d); - DRW_shgroup_call_add(grp, wpd->world_clip_planes_batch, NULL); - DRW_shgroup_uniform_vec4(grp, "color", &wpd->world_clip_planes_color[0], 1); - } - } - - /* Deferred Mix Pass */ - { - workbench_private_data_get_light_direction(wpd, e_data.display.light_direction); - studiolight_update_light(wpd, e_data.display.light_direction); - - if (SHADOW_ENABLED(wpd)) { - psl->composite_pass = DRW_pass_create( - "Composite", DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_EQUAL | DRW_STATE_DEPTH_GREATER); - grp = DRW_shgroup_create(wpd->composite_sh, psl->composite_pass); - workbench_composite_uniforms(wpd, grp); - DRW_shgroup_stencil_mask(grp, 0x00); - DRW_shgroup_uniform_float_copy(grp, "lightMultiplier", 1.0f); - DRW_shgroup_uniform_float(grp, "shadowMultiplier", &wpd->shadow_multiplier, 1); - DRW_shgroup_uniform_float_copy(grp, "shadowShift", scene->display.shadow_shift); - DRW_shgroup_uniform_float_copy(grp, "shadowFocus", wpd->shadow_focus); - DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); - - /* Stencil Shadow passes. */ + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_PassList *psl = vedata->psl; + WORKBENCH_PrivateData *wpd = stl->g_data; + DRWShadingGroup *grp; + const DRWContextState *draw_ctx = DRW_context_state_get(); + + Scene *scene = draw_ctx->scene; + + workbench_volume_cache_init(vedata); + + select_deferred_shaders(wpd, draw_ctx->sh_cfg); + + /* Background Pass */ + { + psl->background_pass = DRW_pass_create("Background", + DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL); + grp = DRW_shgroup_create(wpd->background_sh, psl->background_pass); + DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo); + DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); + if (OBJECT_OUTLINE_ENABLED(wpd)) { + DRW_shgroup_uniform_texture_ref(grp, "objectId", &e_data.object_id_tx); + } + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + + if (draw_ctx->rv3d && (draw_ctx->rv3d->rflag & RV3D_CLIPPING) && draw_ctx->rv3d->clipbb) { + GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR_BACKGROUND); + grp = DRW_shgroup_create(shader, psl->background_pass); + wpd->world_clip_planes_batch = DRW_draw_background_clipping_batch_from_rv3d(draw_ctx->rv3d); + DRW_shgroup_call_add(grp, wpd->world_clip_planes_batch, NULL); + DRW_shgroup_uniform_vec4(grp, "color", &wpd->world_clip_planes_color[0], 1); + } + } + + /* Deferred Mix Pass */ + { + workbench_private_data_get_light_direction(wpd, e_data.display.light_direction); + studiolight_update_light(wpd, e_data.display.light_direction); + + if (SHADOW_ENABLED(wpd)) { + psl->composite_pass = DRW_pass_create( + "Composite", DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_EQUAL | DRW_STATE_DEPTH_GREATER); + grp = DRW_shgroup_create(wpd->composite_sh, psl->composite_pass); + workbench_composite_uniforms(wpd, grp); + DRW_shgroup_stencil_mask(grp, 0x00); + DRW_shgroup_uniform_float_copy(grp, "lightMultiplier", 1.0f); + DRW_shgroup_uniform_float(grp, "shadowMultiplier", &wpd->shadow_multiplier, 1); + DRW_shgroup_uniform_float_copy(grp, "shadowShift", scene->display.shadow_shift); + DRW_shgroup_uniform_float_copy(grp, "shadowFocus", wpd->shadow_focus); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + + /* Stencil Shadow passes. */ #ifdef DEBUG_SHADOW_VOLUME - DRWState depth_pass_state = DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE; - DRWState depth_fail_state = DRW_STATE_DEPTH_GREATER_EQUAL | DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE; + DRWState depth_pass_state = DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_COLOR | + DRW_STATE_ADDITIVE; + DRWState depth_fail_state = DRW_STATE_DEPTH_GREATER_EQUAL | DRW_STATE_WRITE_COLOR | + DRW_STATE_ADDITIVE; #else - DRWState depth_pass_state = DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_STENCIL_SHADOW_PASS; - DRWState depth_fail_state = DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_STENCIL_SHADOW_FAIL; + DRWState depth_pass_state = DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_STENCIL_SHADOW_PASS; + DRWState depth_fail_state = DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_STENCIL_SHADOW_FAIL; #endif - psl->shadow_depth_pass_pass = DRW_pass_create("Shadow Pass", depth_pass_state); - psl->shadow_depth_pass_mani_pass = DRW_pass_create("Shadow Pass Mani", depth_pass_state); - psl->shadow_depth_fail_pass = DRW_pass_create("Shadow Fail", depth_fail_state); - psl->shadow_depth_fail_mani_pass = DRW_pass_create("Shadow Fail Mani", depth_fail_state); - psl->shadow_depth_fail_caps_pass = DRW_pass_create("Shadow Fail Caps", depth_fail_state); - psl->shadow_depth_fail_caps_mani_pass = DRW_pass_create("Shadow Fail Caps Mani", depth_fail_state); + psl->shadow_depth_pass_pass = DRW_pass_create("Shadow Pass", depth_pass_state); + psl->shadow_depth_pass_mani_pass = DRW_pass_create("Shadow Pass Mani", depth_pass_state); + psl->shadow_depth_fail_pass = DRW_pass_create("Shadow Fail", depth_fail_state); + psl->shadow_depth_fail_mani_pass = DRW_pass_create("Shadow Fail Mani", depth_fail_state); + psl->shadow_depth_fail_caps_pass = DRW_pass_create("Shadow Fail Caps", depth_fail_state); + psl->shadow_depth_fail_caps_mani_pass = DRW_pass_create("Shadow Fail Caps Mani", + depth_fail_state); #ifndef DEBUG_SHADOW_VOLUME - grp = DRW_shgroup_create(e_data.shadow_pass_sh, psl->shadow_depth_pass_pass); - DRW_shgroup_stencil_mask(grp, 0xFF); - grp = DRW_shgroup_create(e_data.shadow_pass_manifold_sh, psl->shadow_depth_pass_mani_pass); - DRW_shgroup_stencil_mask(grp, 0xFF); - grp = DRW_shgroup_create(e_data.shadow_fail_sh, psl->shadow_depth_fail_pass); - DRW_shgroup_stencil_mask(grp, 0xFF); - grp = DRW_shgroup_create(e_data.shadow_fail_manifold_sh, psl->shadow_depth_fail_mani_pass); - DRW_shgroup_stencil_mask(grp, 0xFF); - grp = DRW_shgroup_create(e_data.shadow_caps_sh, psl->shadow_depth_fail_caps_pass); - DRW_shgroup_stencil_mask(grp, 0xFF); - grp = DRW_shgroup_create(e_data.shadow_caps_manifold_sh, psl->shadow_depth_fail_caps_mani_pass); - DRW_shgroup_stencil_mask(grp, 0xFF); - - psl->composite_shadow_pass = DRW_pass_create( - "Composite Shadow", DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_NEQUAL | DRW_STATE_DEPTH_GREATER); - grp = DRW_shgroup_create(wpd->composite_sh, psl->composite_shadow_pass); - DRW_shgroup_stencil_mask(grp, 0x00); - workbench_composite_uniforms(wpd, grp); - DRW_shgroup_uniform_float(grp, "lightMultiplier", &wpd->shadow_multiplier, 1); - DRW_shgroup_uniform_float(grp, "shadowMultiplier", &wpd->shadow_multiplier, 1); - DRW_shgroup_uniform_float_copy(grp, "shadowShift", scene->display.shadow_shift); - DRW_shgroup_uniform_float_copy(grp, "shadowFocus", wpd->shadow_focus); - DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + grp = DRW_shgroup_create(e_data.shadow_pass_sh, psl->shadow_depth_pass_pass); + DRW_shgroup_stencil_mask(grp, 0xFF); + grp = DRW_shgroup_create(e_data.shadow_pass_manifold_sh, psl->shadow_depth_pass_mani_pass); + DRW_shgroup_stencil_mask(grp, 0xFF); + grp = DRW_shgroup_create(e_data.shadow_fail_sh, psl->shadow_depth_fail_pass); + DRW_shgroup_stencil_mask(grp, 0xFF); + grp = DRW_shgroup_create(e_data.shadow_fail_manifold_sh, psl->shadow_depth_fail_mani_pass); + DRW_shgroup_stencil_mask(grp, 0xFF); + grp = DRW_shgroup_create(e_data.shadow_caps_sh, psl->shadow_depth_fail_caps_pass); + DRW_shgroup_stencil_mask(grp, 0xFF); + grp = DRW_shgroup_create(e_data.shadow_caps_manifold_sh, + psl->shadow_depth_fail_caps_mani_pass); + DRW_shgroup_stencil_mask(grp, 0xFF); + + psl->composite_shadow_pass = DRW_pass_create( + "Composite Shadow", + DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_NEQUAL | DRW_STATE_DEPTH_GREATER); + grp = DRW_shgroup_create(wpd->composite_sh, psl->composite_shadow_pass); + DRW_shgroup_stencil_mask(grp, 0x00); + workbench_composite_uniforms(wpd, grp); + DRW_shgroup_uniform_float(grp, "lightMultiplier", &wpd->shadow_multiplier, 1); + DRW_shgroup_uniform_float(grp, "shadowMultiplier", &wpd->shadow_multiplier, 1); + DRW_shgroup_uniform_float_copy(grp, "shadowShift", scene->display.shadow_shift); + DRW_shgroup_uniform_float_copy(grp, "shadowFocus", wpd->shadow_focus); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); #endif - } - else { - psl->composite_pass = DRW_pass_create( - "Composite", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_GREATER); - grp = DRW_shgroup_create(wpd->composite_sh, psl->composite_pass); - workbench_composite_uniforms(wpd, grp); - DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); - } - } - - /** - * Order Independant Transparency. - * Similar to workbench forward. Duplicated code to avoid - * spaghetti with workbench forward. It would be great if we unify - * this in a clean way. - */ - if (OIT_ENABLED(wpd)) { - const bool do_cull = CULL_BACKFACE_ENABLED(wpd); - const int cull_state = (do_cull) ? DRW_STATE_CULL_BACK : 0; - /* Transparency Accum */ - { - /* Same as forward but here we use depth test to - * not bleed through other solid objects. */ - int state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_OIT | DRW_STATE_DEPTH_LESS | cull_state; - psl->transparent_accum_pass = DRW_pass_create("Transparent Accum", state); - } - /* Depth */ - { - int state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | cull_state; - psl->object_outline_pass = DRW_pass_create("Transparent Depth", state); - } - /* OIT Composite */ - { - int state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND; - psl->oit_composite_pass = DRW_pass_create("OIT Composite", state); - - grp = DRW_shgroup_create(e_data.oit_resolve_sh, psl->oit_composite_pass); - DRW_shgroup_uniform_texture_ref(grp, "transparentAccum", &e_data.oit_accum_tx); - DRW_shgroup_uniform_texture_ref(grp, "transparentRevealage", &e_data.oit_revealage_tx); - DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); - DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); - } - } + } + else { + psl->composite_pass = DRW_pass_create("Composite", + DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_GREATER); + grp = DRW_shgroup_create(wpd->composite_sh, psl->composite_pass); + workbench_composite_uniforms(wpd, grp); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + } + } + + /** + * Order Independant Transparency. + * Similar to workbench forward. Duplicated code to avoid + * spaghetti with workbench forward. It would be great if we unify + * this in a clean way. + */ + if (OIT_ENABLED(wpd)) { + const bool do_cull = CULL_BACKFACE_ENABLED(wpd); + const int cull_state = (do_cull) ? DRW_STATE_CULL_BACK : 0; + /* Transparency Accum */ + { + /* Same as forward but here we use depth test to + * not bleed through other solid objects. */ + int state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_OIT | DRW_STATE_DEPTH_LESS | cull_state; + psl->transparent_accum_pass = DRW_pass_create("Transparent Accum", state); + } + /* Depth */ + { + int state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | cull_state; + psl->object_outline_pass = DRW_pass_create("Transparent Depth", state); + } + /* OIT Composite */ + { + int state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND; + psl->oit_composite_pass = DRW_pass_create("OIT Composite", state); + + grp = DRW_shgroup_create(e_data.oit_resolve_sh, psl->oit_composite_pass); + DRW_shgroup_uniform_texture_ref(grp, "transparentAccum", &e_data.oit_accum_tx); + DRW_shgroup_uniform_texture_ref(grp, "transparentRevealage", &e_data.oit_revealage_tx); + DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + } + } } -static WORKBENCH_MaterialData *get_or_create_material_data( - WORKBENCH_Data *vedata, Object *ob, Material *mat, Image *ima, ImageUser *iuser, int color_type, int interp) +static WORKBENCH_MaterialData *get_or_create_material_data(WORKBENCH_Data *vedata, + Object *ob, + Material *mat, + Image *ima, + ImageUser *iuser, + int color_type, + int interp) { - WORKBENCH_StorageList *stl = vedata->stl; - WORKBENCH_PassList *psl = vedata->psl; - WORKBENCH_PrivateData *wpd = stl->g_data; - WORKBENCH_MaterialData *material; - WORKBENCH_ObjectData *engine_object_data = (WORKBENCH_ObjectData *)DRW_drawdata_ensure( - &ob->id, &draw_engine_workbench_solid, sizeof(WORKBENCH_ObjectData), &workbench_init_object_data, NULL); - WORKBENCH_MaterialData material_template; - const bool is_ghost = (ob->dtx & OB_DRAWXRAY); - - /* Solid */ - workbench_material_update_data(wpd, ob, mat, &material_template); - material_template.object_id = OBJECT_ID_PASS_ENABLED(wpd) ? engine_object_data->object_id : 1; - material_template.color_type = color_type; - material_template.ima = ima; - material_template.iuser = iuser; - material_template.interp = interp; - uint hash = workbench_material_get_hash(&material_template, is_ghost); - - material = BLI_ghash_lookup(wpd->material_hash, POINTER_FROM_UINT(hash)); - if (material == NULL) { - material = MEM_mallocN(sizeof(WORKBENCH_MaterialData), __func__); - material->shgrp = DRW_shgroup_create( - (color_type == V3D_SHADING_TEXTURE_COLOR) ? wpd->prepass_texture_sh: wpd->prepass_solid_sh, - (ob->dtx & OB_DRAWXRAY) ? psl->ghost_prepass_pass : psl->prepass_pass); - workbench_material_copy(material, &material_template); - DRW_shgroup_stencil_mask(material->shgrp, (ob->dtx & OB_DRAWXRAY) ? 0x00 : 0xFF); - DRW_shgroup_uniform_int(material->shgrp, "object_id", &material->object_id, 1); - workbench_material_shgroup_uniform(wpd, material->shgrp, material, ob, true, true, interp); - BLI_ghash_insert(wpd->material_hash, POINTER_FROM_UINT(hash), material); - } - return material; + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_PassList *psl = vedata->psl; + WORKBENCH_PrivateData *wpd = stl->g_data; + WORKBENCH_MaterialData *material; + WORKBENCH_ObjectData *engine_object_data = (WORKBENCH_ObjectData *)DRW_drawdata_ensure( + &ob->id, + &draw_engine_workbench_solid, + sizeof(WORKBENCH_ObjectData), + &workbench_init_object_data, + NULL); + WORKBENCH_MaterialData material_template; + const bool is_ghost = (ob->dtx & OB_DRAWXRAY); + + /* Solid */ + workbench_material_update_data(wpd, ob, mat, &material_template); + material_template.object_id = OBJECT_ID_PASS_ENABLED(wpd) ? engine_object_data->object_id : 1; + material_template.color_type = color_type; + material_template.ima = ima; + material_template.iuser = iuser; + material_template.interp = interp; + uint hash = workbench_material_get_hash(&material_template, is_ghost); + + material = BLI_ghash_lookup(wpd->material_hash, POINTER_FROM_UINT(hash)); + if (material == NULL) { + material = MEM_mallocN(sizeof(WORKBENCH_MaterialData), __func__); + material->shgrp = DRW_shgroup_create( + (color_type == V3D_SHADING_TEXTURE_COLOR) ? wpd->prepass_texture_sh : + wpd->prepass_solid_sh, + (ob->dtx & OB_DRAWXRAY) ? psl->ghost_prepass_pass : psl->prepass_pass); + workbench_material_copy(material, &material_template); + DRW_shgroup_stencil_mask(material->shgrp, (ob->dtx & OB_DRAWXRAY) ? 0x00 : 0xFF); + DRW_shgroup_uniform_int(material->shgrp, "object_id", &material->object_id, 1); + workbench_material_shgroup_uniform(wpd, material->shgrp, material, ob, true, true, interp); + BLI_ghash_insert(wpd->material_hash, POINTER_FROM_UINT(hash), material); + } + return material; } static void workbench_cache_populate_particles(WORKBENCH_Data *vedata, Object *ob) { - WORKBENCH_StorageList *stl = vedata->stl; - WORKBENCH_PassList *psl = vedata->psl; - WORKBENCH_PrivateData *wpd = stl->g_data; - - for (ModifierData *md = ob->modifiers.first; md; md = md->next) { - if (md->type != eModifierType_ParticleSystem) { - continue; - } - ParticleSystem *psys = ((ParticleSystemModifierData *)md)->psys; - if (!DRW_object_is_visible_psys_in_active_context(ob, psys)) { - continue; - } - ParticleSettings *part = psys->part; - const int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as; - - if (draw_as == PART_DRAW_PATH) { - Material *mat; - Image *image; - ImageUser *iuser; - int interp; - workbench_material_get_image_and_mat(ob, part->omat, &image, &iuser, &interp, &mat); - int color_type = workbench_material_determine_color_type(wpd, image, ob); - WORKBENCH_MaterialData *material = get_or_create_material_data(vedata, ob, mat, image, iuser, color_type, interp); - - struct GPUShader *shader = (color_type != V3D_SHADING_TEXTURE_COLOR) ? - wpd->prepass_solid_hair_sh : - wpd->prepass_texture_hair_sh; - DRWShadingGroup *shgrp = DRW_shgroup_hair_create( - ob, psys, md, - (ob->dtx & OB_DRAWXRAY) ? psl->ghost_prepass_hair_pass : psl->prepass_hair_pass, - shader); - DRW_shgroup_stencil_mask(shgrp, (ob->dtx & OB_DRAWXRAY) ? 0x00 : 0xFF); - DRW_shgroup_uniform_int(shgrp, "object_id", &material->object_id, 1); - workbench_material_shgroup_uniform(wpd, shgrp, material, ob, true, true, interp); - } - } + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_PassList *psl = vedata->psl; + WORKBENCH_PrivateData *wpd = stl->g_data; + + for (ModifierData *md = ob->modifiers.first; md; md = md->next) { + if (md->type != eModifierType_ParticleSystem) { + continue; + } + ParticleSystem *psys = ((ParticleSystemModifierData *)md)->psys; + if (!DRW_object_is_visible_psys_in_active_context(ob, psys)) { + continue; + } + ParticleSettings *part = psys->part; + const int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as; + + if (draw_as == PART_DRAW_PATH) { + Material *mat; + Image *image; + ImageUser *iuser; + int interp; + workbench_material_get_image_and_mat(ob, part->omat, &image, &iuser, &interp, &mat); + int color_type = workbench_material_determine_color_type(wpd, image, ob); + WORKBENCH_MaterialData *material = get_or_create_material_data( + vedata, ob, mat, image, iuser, color_type, interp); + + struct GPUShader *shader = (color_type != V3D_SHADING_TEXTURE_COLOR) ? + wpd->prepass_solid_hair_sh : + wpd->prepass_texture_hair_sh; + DRWShadingGroup *shgrp = DRW_shgroup_hair_create( + ob, + psys, + md, + (ob->dtx & OB_DRAWXRAY) ? psl->ghost_prepass_hair_pass : psl->prepass_hair_pass, + shader); + DRW_shgroup_stencil_mask(shgrp, (ob->dtx & OB_DRAWXRAY) ? 0x00 : 0xFF); + DRW_shgroup_uniform_int(shgrp, "object_id", &material->object_id, 1); + workbench_material_shgroup_uniform(wpd, shgrp, material, ob, true, true, interp); + } + } } void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob) { - WORKBENCH_StorageList *stl = vedata->stl; - WORKBENCH_PassList *psl = vedata->psl; - WORKBENCH_PrivateData *wpd = stl->g_data; - const DRWContextState *draw_ctx = DRW_context_state_get(); - Scene *scene = draw_ctx->scene; - - if (!DRW_object_is_renderable(ob)) { - return; - } - - if (ob->type == OB_MESH) { - workbench_cache_populate_particles(vedata, ob); - } - - ModifierData *md; - if (((ob->base_flag & BASE_FROM_DUPLI) == 0) && - (md = modifiers_findByType(ob, eModifierType_Smoke)) && - (modifier_isEnabled(scene, md, eModifierMode_Realtime)) && - (((SmokeModifierData *)md)->domain != NULL)) - { - workbench_volume_cache_populate(vedata, scene, ob, md); - return; /* Do not draw solid in this case. */ - } - - if (!(DRW_object_visibility_in_active_context(ob) & OB_VISIBLE_SELF)) { - return; - } - if ((ob->dt < OB_SOLID) && !DRW_state_is_image_render()) { - return; - } - - WORKBENCH_MaterialData *material; - if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) { - const bool is_active = (ob == draw_ctx->obact); - const bool is_sculpt_mode = is_active && (draw_ctx->object_mode & OB_MODE_SCULPT) != 0; - const bool use_hide = is_active && DRW_object_use_hide_faces(ob); - const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol)); - const Mesh *me = (ob->type == OB_MESH) ? ob->data : NULL; - bool has_transp_mat = false; - - if (!is_sculpt_mode && me && me->mloopuv && TEXTURE_DRAWING_ENABLED(wpd)) { - /* Draw textured */ - struct GPUBatch **geom_array = DRW_cache_mesh_surface_texpaint_get(ob); - for (int i = 0; i < materials_len; i++) { - if (geom_array != NULL && geom_array[i] != NULL) { - Material *mat; - Image *image; - ImageUser *iuser; - int interp; - workbench_material_get_image_and_mat(ob, i + 1, &image, &iuser, &interp, &mat); - int color_type = workbench_material_determine_color_type(wpd, image, ob); - if (color_type == V3D_SHADING_MATERIAL_COLOR && mat && mat->a < 1.0) { - material = workbench_forward_get_or_create_material_data(vedata, ob, mat, image, iuser, color_type, 0); - has_transp_mat = true; - } - else { - material = get_or_create_material_data(vedata, ob, mat, image, iuser, color_type, interp); - } - DRW_shgroup_call_object_add(material->shgrp, geom_array[i], ob); - } - } - } - else if (ELEM(wpd->shading.color_type, - V3D_SHADING_SINGLE_COLOR, V3D_SHADING_OBJECT_COLOR, V3D_SHADING_RANDOM_COLOR)) - { - if ((ob->color[3] < 1.0f) && - (wpd->shading.color_type == V3D_SHADING_OBJECT_COLOR)) - { - /* Hack */ - wpd->shading.xray_alpha = ob->color[3]; - material = workbench_forward_get_or_create_material_data(vedata, ob, NULL, NULL, NULL, wpd->shading.color_type, 0); - has_transp_mat = true; - } - else { - /* Draw solid color */ - material = get_or_create_material_data(vedata, ob, NULL, NULL, NULL, wpd->shading.color_type, 0); - } - if (is_sculpt_mode) { - DRW_shgroup_call_sculpt_add(material->shgrp, ob, ob->obmat); - } - else { - struct GPUBatch *geom = DRW_cache_object_surface_get(ob); - if (geom) { - DRW_shgroup_call_object_add(material->shgrp, geom, ob); - } - } - } - else { - /* Draw material color */ - if (is_sculpt_mode) { - /* Multiple materials are not supported in sculpt mode yet. */ - Material *mat = give_current_material(ob, 1); - material = get_or_create_material_data(vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0); - DRW_shgroup_call_sculpt_add(material->shgrp, ob, ob->obmat); - } - else { - struct GPUBatch **geoms; - struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len); - memset(gpumat_array, 0, sizeof(*gpumat_array) * materials_len); - - geoms = DRW_cache_object_surface_material_get(ob, gpumat_array, materials_len, NULL, NULL, NULL); - for (int i = 0; i < materials_len; ++i) { - if (geoms != NULL && geoms[i] != NULL) { - Material *mat = give_current_material(ob, i + 1); - if (mat != NULL && mat->a < 1.0f) { - /* Hack */ - wpd->shading.xray_alpha = mat->a; - material = workbench_forward_get_or_create_material_data(vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0); - has_transp_mat = true; - } - else { - material = get_or_create_material_data(vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0); - } - DRW_shgroup_call_object_add(material->shgrp, geoms[i], ob); - } - } - } - } - - if (SHADOW_ENABLED(wpd) && !(ob->dtx & OB_DRAW_NO_SHADOW_CAST)) { - bool is_manifold; - struct GPUBatch *geom_shadow = DRW_cache_object_edge_detection_get(ob, &is_manifold); - if (geom_shadow) { - if (is_sculpt_mode || use_hide) { - /* Currently unsupported in sculpt mode. We could revert to the slow - * method in this case but I'm not sure if it's a good idea given that - * sculpted meshes are heavy to begin with. */ - // DRW_shgroup_call_sculpt_add(wpd->shadow_shgrp, ob, ob->obmat); - } - else { - WORKBENCH_ObjectData *engine_object_data = (WORKBENCH_ObjectData *)DRW_drawdata_ensure( - &ob->id, &draw_engine_workbench_solid, sizeof(WORKBENCH_ObjectData), &workbench_init_object_data, NULL); - - if (studiolight_object_cast_visible_shadow(wpd, ob, engine_object_data)) { - - invert_m4_m4(ob->imat, ob->obmat); - mul_v3_mat3_m4v3(engine_object_data->shadow_dir, ob->imat, e_data.display.light_direction); - - DRWShadingGroup *grp; - bool use_shadow_pass_technique = !studiolight_camera_in_object_shadow(wpd, ob, engine_object_data); - - if (use_shadow_pass_technique && !has_transp_mat) { - if (is_manifold) { - grp = DRW_shgroup_create(e_data.shadow_pass_manifold_sh, psl->shadow_depth_pass_mani_pass); - } - else { - grp = DRW_shgroup_create(e_data.shadow_pass_sh, psl->shadow_depth_pass_pass); - } - DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1); - DRW_shgroup_uniform_float_copy(grp, "lightDistance", 1e5f); - DRW_shgroup_call_add(grp, geom_shadow, ob->obmat); + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_PassList *psl = vedata->psl; + WORKBENCH_PrivateData *wpd = stl->g_data; + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + + if (!DRW_object_is_renderable(ob)) { + return; + } + + if (ob->type == OB_MESH) { + workbench_cache_populate_particles(vedata, ob); + } + + ModifierData *md; + if (((ob->base_flag & BASE_FROM_DUPLI) == 0) && + (md = modifiers_findByType(ob, eModifierType_Smoke)) && + (modifier_isEnabled(scene, md, eModifierMode_Realtime)) && + (((SmokeModifierData *)md)->domain != NULL)) { + workbench_volume_cache_populate(vedata, scene, ob, md); + return; /* Do not draw solid in this case. */ + } + + if (!(DRW_object_visibility_in_active_context(ob) & OB_VISIBLE_SELF)) { + return; + } + if ((ob->dt < OB_SOLID) && !DRW_state_is_image_render()) { + return; + } + + WORKBENCH_MaterialData *material; + if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) { + const bool is_active = (ob == draw_ctx->obact); + const bool is_sculpt_mode = is_active && (draw_ctx->object_mode & OB_MODE_SCULPT) != 0; + const bool use_hide = is_active && DRW_object_use_hide_faces(ob); + const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol)); + const Mesh *me = (ob->type == OB_MESH) ? ob->data : NULL; + bool has_transp_mat = false; + + if (!is_sculpt_mode && me && me->mloopuv && TEXTURE_DRAWING_ENABLED(wpd)) { + /* Draw textured */ + struct GPUBatch **geom_array = DRW_cache_mesh_surface_texpaint_get(ob); + for (int i = 0; i < materials_len; i++) { + if (geom_array != NULL && geom_array[i] != NULL) { + Material *mat; + Image *image; + ImageUser *iuser; + int interp; + workbench_material_get_image_and_mat(ob, i + 1, &image, &iuser, &interp, &mat); + int color_type = workbench_material_determine_color_type(wpd, image, ob); + if (color_type == V3D_SHADING_MATERIAL_COLOR && mat && mat->a < 1.0) { + material = workbench_forward_get_or_create_material_data( + vedata, ob, mat, image, iuser, color_type, 0); + has_transp_mat = true; + } + else { + material = get_or_create_material_data( + vedata, ob, mat, image, iuser, color_type, interp); + } + DRW_shgroup_call_object_add(material->shgrp, geom_array[i], ob); + } + } + } + else if (ELEM(wpd->shading.color_type, + V3D_SHADING_SINGLE_COLOR, + V3D_SHADING_OBJECT_COLOR, + V3D_SHADING_RANDOM_COLOR)) { + if ((ob->color[3] < 1.0f) && (wpd->shading.color_type == V3D_SHADING_OBJECT_COLOR)) { + /* Hack */ + wpd->shading.xray_alpha = ob->color[3]; + material = workbench_forward_get_or_create_material_data( + vedata, ob, NULL, NULL, NULL, wpd->shading.color_type, 0); + has_transp_mat = true; + } + else { + /* Draw solid color */ + material = get_or_create_material_data( + vedata, ob, NULL, NULL, NULL, wpd->shading.color_type, 0); + } + if (is_sculpt_mode) { + DRW_shgroup_call_sculpt_add(material->shgrp, ob, ob->obmat); + } + else { + struct GPUBatch *geom = DRW_cache_object_surface_get(ob); + if (geom) { + DRW_shgroup_call_object_add(material->shgrp, geom, ob); + } + } + } + else { + /* Draw material color */ + if (is_sculpt_mode) { + /* Multiple materials are not supported in sculpt mode yet. */ + Material *mat = give_current_material(ob, 1); + material = get_or_create_material_data( + vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0); + DRW_shgroup_call_sculpt_add(material->shgrp, ob, ob->obmat); + } + else { + struct GPUBatch **geoms; + struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len); + memset(gpumat_array, 0, sizeof(*gpumat_array) * materials_len); + + geoms = DRW_cache_object_surface_material_get( + ob, gpumat_array, materials_len, NULL, NULL, NULL); + for (int i = 0; i < materials_len; ++i) { + if (geoms != NULL && geoms[i] != NULL) { + Material *mat = give_current_material(ob, i + 1); + if (mat != NULL && mat->a < 1.0f) { + /* Hack */ + wpd->shading.xray_alpha = mat->a; + material = workbench_forward_get_or_create_material_data( + vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0); + has_transp_mat = true; + } + else { + material = get_or_create_material_data( + vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0); + } + DRW_shgroup_call_object_add(material->shgrp, geoms[i], ob); + } + } + } + } + + if (SHADOW_ENABLED(wpd) && !(ob->dtx & OB_DRAW_NO_SHADOW_CAST)) { + bool is_manifold; + struct GPUBatch *geom_shadow = DRW_cache_object_edge_detection_get(ob, &is_manifold); + if (geom_shadow) { + if (is_sculpt_mode || use_hide) { + /* Currently unsupported in sculpt mode. We could revert to the slow + * method in this case but I'm not sure if it's a good idea given that + * sculpted meshes are heavy to begin with. */ + // DRW_shgroup_call_sculpt_add(wpd->shadow_shgrp, ob, ob->obmat); + } + else { + WORKBENCH_ObjectData *engine_object_data = (WORKBENCH_ObjectData *)DRW_drawdata_ensure( + &ob->id, + &draw_engine_workbench_solid, + sizeof(WORKBENCH_ObjectData), + &workbench_init_object_data, + NULL); + + if (studiolight_object_cast_visible_shadow(wpd, ob, engine_object_data)) { + + invert_m4_m4(ob->imat, ob->obmat); + mul_v3_mat3_m4v3( + engine_object_data->shadow_dir, ob->imat, e_data.display.light_direction); + + DRWShadingGroup *grp; + bool use_shadow_pass_technique = !studiolight_camera_in_object_shadow( + wpd, ob, engine_object_data); + + if (use_shadow_pass_technique && !has_transp_mat) { + if (is_manifold) { + grp = DRW_shgroup_create(e_data.shadow_pass_manifold_sh, + psl->shadow_depth_pass_mani_pass); + } + else { + grp = DRW_shgroup_create(e_data.shadow_pass_sh, psl->shadow_depth_pass_pass); + } + DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1); + DRW_shgroup_uniform_float_copy(grp, "lightDistance", 1e5f); + DRW_shgroup_call_add(grp, geom_shadow, ob->obmat); #ifdef DEBUG_SHADOW_VOLUME - DRW_debug_bbox(&engine_object_data->shadow_bbox, (float[4]){1.0f, 0.0f, 0.0f, 1.0f}); + DRW_debug_bbox(&engine_object_data->shadow_bbox, (float[4]){1.0f, 0.0f, 0.0f, 1.0f}); #endif - } - else { - float extrude_distance = studiolight_object_shadow_distance(wpd, ob, engine_object_data); - - /* TODO(fclem): only use caps if they are in the view frustum. */ - const bool need_caps = true; - if (need_caps) { - if (is_manifold) { - grp = DRW_shgroup_create(e_data.shadow_caps_manifold_sh, psl->shadow_depth_fail_caps_mani_pass); - } - else { - grp = DRW_shgroup_create(e_data.shadow_caps_sh, psl->shadow_depth_fail_caps_pass); - } - DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1); - DRW_shgroup_uniform_float_copy(grp, "lightDistance", extrude_distance); - DRW_shgroup_call_add(grp, DRW_cache_object_surface_get(ob), ob->obmat); - } - - if (is_manifold) { - grp = DRW_shgroup_create(e_data.shadow_fail_manifold_sh, psl->shadow_depth_fail_mani_pass); - } - else { - grp = DRW_shgroup_create(e_data.shadow_fail_sh, psl->shadow_depth_fail_pass); - } - DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1); - DRW_shgroup_uniform_float_copy(grp, "lightDistance", extrude_distance); - DRW_shgroup_call_add(grp, geom_shadow, ob->obmat); + } + else { + float extrude_distance = studiolight_object_shadow_distance( + wpd, ob, engine_object_data); + + /* TODO(fclem): only use caps if they are in the view frustum. */ + const bool need_caps = true; + if (need_caps) { + if (is_manifold) { + grp = DRW_shgroup_create(e_data.shadow_caps_manifold_sh, + psl->shadow_depth_fail_caps_mani_pass); + } + else { + grp = DRW_shgroup_create(e_data.shadow_caps_sh, + psl->shadow_depth_fail_caps_pass); + } + DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1); + DRW_shgroup_uniform_float_copy(grp, "lightDistance", extrude_distance); + DRW_shgroup_call_add(grp, DRW_cache_object_surface_get(ob), ob->obmat); + } + + if (is_manifold) { + grp = DRW_shgroup_create(e_data.shadow_fail_manifold_sh, + psl->shadow_depth_fail_mani_pass); + } + else { + grp = DRW_shgroup_create(e_data.shadow_fail_sh, psl->shadow_depth_fail_pass); + } + DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1); + DRW_shgroup_uniform_float_copy(grp, "lightDistance", extrude_distance); + DRW_shgroup_call_add(grp, geom_shadow, ob->obmat); #ifdef DEBUG_SHADOW_VOLUME - DRW_debug_bbox(&engine_object_data->shadow_bbox, (float[4]){0.0f, 1.0f, 0.0f, 1.0f}); + DRW_debug_bbox(&engine_object_data->shadow_bbox, (float[4]){0.0f, 1.0f, 0.0f, 1.0f}); #endif - } - } - } - } - } - } + } + } + } + } + } + } } void workbench_deferred_cache_finish(WORKBENCH_Data *UNUSED(vedata)) @@ -1068,144 +1118,146 @@ void workbench_deferred_cache_finish(WORKBENCH_Data *UNUSED(vedata)) void workbench_deferred_draw_background(WORKBENCH_Data *vedata) { - WORKBENCH_StorageList *stl = vedata->stl; - WORKBENCH_FramebufferList *fbl = vedata->fbl; - WORKBENCH_PrivateData *wpd = stl->g_data; - const float clear_depth = 1.0f; - const float clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - uint clear_stencil = 0x00; - - DRW_stats_group_start("Clear Background"); - - if (OBJECT_ID_PASS_ENABLED(wpd)) { - /* From all the color buffers, only object id needs to be cleared. */ - GPU_framebuffer_bind(fbl->id_clear_fb); - GPU_framebuffer_clear_color(fbl->id_clear_fb, clear_color); - } - - GPU_framebuffer_bind(fbl->prepass_fb); - int clear_bits = GPU_DEPTH_BIT; - SET_FLAG_FROM_TEST(clear_bits, SHADOW_ENABLED(wpd), GPU_STENCIL_BIT); - GPU_framebuffer_clear(fbl->prepass_fb, clear_bits, clear_color, clear_depth, clear_stencil); - DRW_stats_group_end(); + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_FramebufferList *fbl = vedata->fbl; + WORKBENCH_PrivateData *wpd = stl->g_data; + const float clear_depth = 1.0f; + const float clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + uint clear_stencil = 0x00; + + DRW_stats_group_start("Clear Background"); + + if (OBJECT_ID_PASS_ENABLED(wpd)) { + /* From all the color buffers, only object id needs to be cleared. */ + GPU_framebuffer_bind(fbl->id_clear_fb); + GPU_framebuffer_clear_color(fbl->id_clear_fb, clear_color); + } + + GPU_framebuffer_bind(fbl->prepass_fb); + int clear_bits = GPU_DEPTH_BIT; + SET_FLAG_FROM_TEST(clear_bits, SHADOW_ENABLED(wpd), GPU_STENCIL_BIT); + GPU_framebuffer_clear(fbl->prepass_fb, clear_bits, clear_color, clear_depth, clear_stencil); + DRW_stats_group_end(); } void workbench_deferred_draw_scene(WORKBENCH_Data *vedata) { - WORKBENCH_PassList *psl = vedata->psl; - WORKBENCH_StorageList *stl = vedata->stl; - WORKBENCH_FramebufferList *fbl = vedata->fbl; - WORKBENCH_PrivateData *wpd = stl->g_data; - DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); - - if (TAA_ENABLED(wpd)) { - workbench_taa_draw_scene_start(vedata); - } - - /* clear in background */ - GPU_framebuffer_bind(fbl->prepass_fb); - DRW_draw_pass(psl->prepass_pass); - DRW_draw_pass(psl->prepass_hair_pass); - - if (GHOST_ENABLED(psl)) { - /* meh, late init to not request a depth buffer we won't use. */ - workbench_setup_ghost_framebuffer(fbl); - - GPU_framebuffer_bind(fbl->ghost_prepass_fb); - GPU_framebuffer_clear_depth(fbl->ghost_prepass_fb, 1.0f); - DRW_draw_pass(psl->ghost_prepass_pass); - DRW_draw_pass(psl->ghost_prepass_hair_pass); - - GPU_framebuffer_bind(dfbl->depth_only_fb); - DRW_draw_pass(psl->ghost_resolve_pass); - } - - if (CAVITY_ENABLED(wpd)) { - GPU_framebuffer_bind(fbl->cavity_fb); - DRW_draw_pass(psl->cavity_pass); - } - - if (SHADOW_ENABLED(wpd)) { + WORKBENCH_PassList *psl = vedata->psl; + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_FramebufferList *fbl = vedata->fbl; + WORKBENCH_PrivateData *wpd = stl->g_data; + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + + if (TAA_ENABLED(wpd)) { + workbench_taa_draw_scene_start(vedata); + } + + /* clear in background */ + GPU_framebuffer_bind(fbl->prepass_fb); + DRW_draw_pass(psl->prepass_pass); + DRW_draw_pass(psl->prepass_hair_pass); + + if (GHOST_ENABLED(psl)) { + /* meh, late init to not request a depth buffer we won't use. */ + workbench_setup_ghost_framebuffer(fbl); + + GPU_framebuffer_bind(fbl->ghost_prepass_fb); + GPU_framebuffer_clear_depth(fbl->ghost_prepass_fb, 1.0f); + DRW_draw_pass(psl->ghost_prepass_pass); + DRW_draw_pass(psl->ghost_prepass_hair_pass); + + GPU_framebuffer_bind(dfbl->depth_only_fb); + DRW_draw_pass(psl->ghost_resolve_pass); + } + + if (CAVITY_ENABLED(wpd)) { + GPU_framebuffer_bind(fbl->cavity_fb); + DRW_draw_pass(psl->cavity_pass); + } + + if (SHADOW_ENABLED(wpd)) { #ifdef DEBUG_SHADOW_VOLUME - GPU_framebuffer_bind(fbl->composite_fb); - DRW_draw_pass(psl->composite_pass); + GPU_framebuffer_bind(fbl->composite_fb); + DRW_draw_pass(psl->composite_pass); #else - GPU_framebuffer_bind(dfbl->depth_only_fb); + GPU_framebuffer_bind(dfbl->depth_only_fb); #endif - DRW_draw_pass(psl->shadow_depth_pass_pass); - DRW_draw_pass(psl->shadow_depth_pass_mani_pass); - DRW_draw_pass(psl->shadow_depth_fail_pass); - DRW_draw_pass(psl->shadow_depth_fail_mani_pass); - DRW_draw_pass(psl->shadow_depth_fail_caps_pass); - DRW_draw_pass(psl->shadow_depth_fail_caps_mani_pass); - - if (GHOST_ENABLED(psl)) { - /* We need to set the stencil buffer to 0 where Ghost objects - * else they will get shadow and even badly shadowed. */ - DRW_pass_state_set(psl->ghost_prepass_pass, DRW_STATE_DEPTH_EQUAL | DRW_STATE_WRITE_STENCIL); - DRW_pass_state_set(psl->ghost_prepass_hair_pass, DRW_STATE_DEPTH_EQUAL | DRW_STATE_WRITE_STENCIL); - - DRW_draw_pass(psl->ghost_prepass_pass); - DRW_draw_pass(psl->ghost_prepass_hair_pass); - } + DRW_draw_pass(psl->shadow_depth_pass_pass); + DRW_draw_pass(psl->shadow_depth_pass_mani_pass); + DRW_draw_pass(psl->shadow_depth_fail_pass); + DRW_draw_pass(psl->shadow_depth_fail_mani_pass); + DRW_draw_pass(psl->shadow_depth_fail_caps_pass); + DRW_draw_pass(psl->shadow_depth_fail_caps_mani_pass); + + if (GHOST_ENABLED(psl)) { + /* We need to set the stencil buffer to 0 where Ghost objects + * else they will get shadow and even badly shadowed. */ + DRW_pass_state_set(psl->ghost_prepass_pass, DRW_STATE_DEPTH_EQUAL | DRW_STATE_WRITE_STENCIL); + DRW_pass_state_set(psl->ghost_prepass_hair_pass, + DRW_STATE_DEPTH_EQUAL | DRW_STATE_WRITE_STENCIL); + + DRW_draw_pass(psl->ghost_prepass_pass); + DRW_draw_pass(psl->ghost_prepass_hair_pass); + } #ifndef DEBUG_SHADOW_VOLUME - GPU_framebuffer_bind(fbl->composite_fb); - DRW_draw_pass(psl->composite_pass); - DRW_draw_pass(psl->composite_shadow_pass); + GPU_framebuffer_bind(fbl->composite_fb); + DRW_draw_pass(psl->composite_pass); + DRW_draw_pass(psl->composite_shadow_pass); #endif - } - else { - GPU_framebuffer_bind(fbl->composite_fb); - DRW_draw_pass(psl->composite_pass); - } - - /* TODO(fclem): only enable when needed (when there is overlays). */ - if (GHOST_ENABLED(psl)) { - /* In order to not draw on top of ghost objects, we clear the stencil - * to 0xFF and the ghost object to 0x00 and only draw overlays on top if - * stencil is not 0. */ - GPU_framebuffer_bind(dfbl->depth_only_fb); - GPU_framebuffer_clear_stencil(dfbl->depth_only_fb, 0xFF); - - DRW_pass_state_set(psl->ghost_prepass_pass, DRW_STATE_DEPTH_EQUAL | DRW_STATE_WRITE_STENCIL); - DRW_pass_state_set(psl->ghost_prepass_hair_pass, DRW_STATE_DEPTH_EQUAL | DRW_STATE_WRITE_STENCIL); - - DRW_draw_pass(psl->ghost_prepass_pass); - DRW_draw_pass(psl->ghost_prepass_hair_pass); - } - - GPU_framebuffer_bind(fbl->composite_fb); - DRW_draw_pass(psl->background_pass); - - if (OIT_ENABLED(wpd) && !DRW_pass_is_empty(psl->transparent_accum_pass)) { - DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - /* meh, late init to not request buffers we won't use. */ - workbench_init_oit_framebuffer(fbl, dtxl); - - const float clear_color[4] = {0.0f, 0.0f, 0.0f, 1.0f}; - GPU_framebuffer_bind(fbl->transparent_accum_fb); - GPU_framebuffer_clear_color(fbl->transparent_accum_fb, clear_color); - DRW_draw_pass(psl->transparent_accum_pass); - - GPU_framebuffer_bind(fbl->composite_fb); - DRW_draw_pass(psl->oit_composite_pass); - } - - if (wpd->volumes_do) { - GPU_framebuffer_bind(fbl->color_only_fb); - DRW_draw_pass(psl->volume_pass); - } - - workbench_dof_draw_pass(vedata); - workbench_aa_draw_pass(vedata, e_data.composite_buffer_tx); + } + else { + GPU_framebuffer_bind(fbl->composite_fb); + DRW_draw_pass(psl->composite_pass); + } + + /* TODO(fclem): only enable when needed (when there is overlays). */ + if (GHOST_ENABLED(psl)) { + /* In order to not draw on top of ghost objects, we clear the stencil + * to 0xFF and the ghost object to 0x00 and only draw overlays on top if + * stencil is not 0. */ + GPU_framebuffer_bind(dfbl->depth_only_fb); + GPU_framebuffer_clear_stencil(dfbl->depth_only_fb, 0xFF); + + DRW_pass_state_set(psl->ghost_prepass_pass, DRW_STATE_DEPTH_EQUAL | DRW_STATE_WRITE_STENCIL); + DRW_pass_state_set(psl->ghost_prepass_hair_pass, + DRW_STATE_DEPTH_EQUAL | DRW_STATE_WRITE_STENCIL); + + DRW_draw_pass(psl->ghost_prepass_pass); + DRW_draw_pass(psl->ghost_prepass_hair_pass); + } + + GPU_framebuffer_bind(fbl->composite_fb); + DRW_draw_pass(psl->background_pass); + + if (OIT_ENABLED(wpd) && !DRW_pass_is_empty(psl->transparent_accum_pass)) { + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + /* meh, late init to not request buffers we won't use. */ + workbench_init_oit_framebuffer(fbl, dtxl); + + const float clear_color[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + GPU_framebuffer_bind(fbl->transparent_accum_fb); + GPU_framebuffer_clear_color(fbl->transparent_accum_fb, clear_color); + DRW_draw_pass(psl->transparent_accum_pass); + + GPU_framebuffer_bind(fbl->composite_fb); + DRW_draw_pass(psl->oit_composite_pass); + } + + if (wpd->volumes_do) { + GPU_framebuffer_bind(fbl->color_only_fb); + DRW_draw_pass(psl->volume_pass); + } + + workbench_dof_draw_pass(vedata); + workbench_aa_draw_pass(vedata, e_data.composite_buffer_tx); } void workbench_deferred_draw_finish(WORKBENCH_Data *vedata) { - WORKBENCH_StorageList *stl = vedata->stl; - WORKBENCH_PrivateData *wpd = stl->g_data; + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_PrivateData *wpd = stl->g_data; - /* XXX TODO(fclem) do not discard UBOS after drawing! Store them per viewport. */ - workbench_private_data_free(wpd); - workbench_volume_smoke_textures_free(wpd); + /* XXX TODO(fclem) do not discard UBOS after drawing! Store them per viewport. */ + workbench_private_data_free(wpd); + workbench_volume_smoke_textures_free(wpd); } diff --git a/source/blender/draw/engines/workbench/workbench_effect_aa.c b/source/blender/draw/engines/workbench/workbench_effect_aa.c index 226f1746e50..a80f6ce338b 100644 --- a/source/blender/draw/engines/workbench/workbench_effect_aa.c +++ b/source/blender/draw/engines/workbench/workbench_effect_aa.c @@ -24,83 +24,82 @@ #include "workbench_private.h" - void workbench_aa_create_pass(WORKBENCH_Data *vedata, GPUTexture **tx) { - WORKBENCH_StorageList *stl = vedata->stl; - WORKBENCH_PrivateData *wpd = stl->g_data; - WORKBENCH_PassList *psl = vedata->psl; - WORKBENCH_EffectInfo *effect_info = stl->effects; - const DRWContextState *draw_ctx = DRW_context_state_get(); + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_PrivateData *wpd = stl->g_data; + WORKBENCH_PassList *psl = vedata->psl; + WORKBENCH_EffectInfo *effect_info = stl->effects; + const DRWContextState *draw_ctx = DRW_context_state_get(); - if (draw_ctx->evil_C != NULL) { - struct wmWindowManager *wm = CTX_wm_manager(draw_ctx->evil_C); - wpd->is_playback = ED_screen_animation_playing(wm) != NULL; - } - else { - wpd->is_playback = false; - } + if (draw_ctx->evil_C != NULL) { + struct wmWindowManager *wm = CTX_wm_manager(draw_ctx->evil_C); + wpd->is_playback = ED_screen_animation_playing(wm) != NULL; + } + else { + wpd->is_playback = false; + } - if (TAA_ENABLED(wpd)) { - psl->effect_aa_pass = workbench_taa_create_pass(vedata, tx); - } - else if (FXAA_ENABLED(wpd)) { - psl->effect_aa_pass = workbench_fxaa_create_pass(tx); - effect_info->jitter_index = 0; - } - else { - psl->effect_aa_pass = NULL; - } + if (TAA_ENABLED(wpd)) { + psl->effect_aa_pass = workbench_taa_create_pass(vedata, tx); + } + else if (FXAA_ENABLED(wpd)) { + psl->effect_aa_pass = workbench_fxaa_create_pass(tx); + effect_info->jitter_index = 0; + } + else { + psl->effect_aa_pass = NULL; + } } static void workspace_aa_draw_transform(GPUTexture *tx, WORKBENCH_PrivateData *wpd) { - if (DRW_state_is_image_render()) { - /* Linear result for render. */ - DRW_transform_none(tx); - } - else { - /* Display space result for viewport. */ - DRW_transform_to_display(tx, wpd->use_color_render_settings, wpd->use_color_render_settings); - } + if (DRW_state_is_image_render()) { + /* Linear result for render. */ + DRW_transform_none(tx); + } + else { + /* Display space result for viewport. */ + DRW_transform_to_display(tx, wpd->use_color_render_settings, wpd->use_color_render_settings); + } } void workbench_aa_draw_pass(WORKBENCH_Data *vedata, GPUTexture *tx) { - WORKBENCH_StorageList *stl = vedata->stl; - WORKBENCH_PrivateData *wpd = stl->g_data; - WORKBENCH_FramebufferList *fbl = vedata->fbl; - WORKBENCH_PassList *psl = vedata->psl; - WORKBENCH_EffectInfo *effect_info = stl->effects; + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_PrivateData *wpd = stl->g_data; + WORKBENCH_FramebufferList *fbl = vedata->fbl; + WORKBENCH_PassList *psl = vedata->psl; + WORKBENCH_EffectInfo *effect_info = stl->effects; - DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); - if (FXAA_ENABLED(wpd)) { - GPU_framebuffer_bind(fbl->effect_fb); - workspace_aa_draw_transform(tx, wpd); - GPU_framebuffer_bind(dfbl->color_only_fb); - DRW_draw_pass(psl->effect_aa_pass); - } - else if (TAA_ENABLED(wpd)) { - /* - * when drawing the first TAA frame, we transform directly to the - * color_only_fb as the TAA shader is just performing a direct copy. - * the workbench_taa_draw_screen_end will fill the history buffer - * for the other iterations. - */ - if (effect_info->jitter_index == 1) { - GPU_framebuffer_bind(dfbl->color_only_fb); - workspace_aa_draw_transform(tx, wpd); - } - else { - GPU_framebuffer_bind(fbl->effect_fb); - workspace_aa_draw_transform(tx, wpd); - GPU_framebuffer_bind(dfbl->color_only_fb); - DRW_draw_pass(psl->effect_aa_pass); - } - workbench_taa_draw_scene_end(vedata); - } - else { - GPU_framebuffer_bind(dfbl->color_only_fb); - workspace_aa_draw_transform(tx, wpd); - } + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + if (FXAA_ENABLED(wpd)) { + GPU_framebuffer_bind(fbl->effect_fb); + workspace_aa_draw_transform(tx, wpd); + GPU_framebuffer_bind(dfbl->color_only_fb); + DRW_draw_pass(psl->effect_aa_pass); + } + else if (TAA_ENABLED(wpd)) { + /* + * when drawing the first TAA frame, we transform directly to the + * color_only_fb as the TAA shader is just performing a direct copy. + * the workbench_taa_draw_screen_end will fill the history buffer + * for the other iterations. + */ + if (effect_info->jitter_index == 1) { + GPU_framebuffer_bind(dfbl->color_only_fb); + workspace_aa_draw_transform(tx, wpd); + } + else { + GPU_framebuffer_bind(fbl->effect_fb); + workspace_aa_draw_transform(tx, wpd); + GPU_framebuffer_bind(dfbl->color_only_fb); + DRW_draw_pass(psl->effect_aa_pass); + } + workbench_taa_draw_scene_end(vedata); + } + else { + GPU_framebuffer_bind(dfbl->color_only_fb); + workspace_aa_draw_transform(tx, wpd); + } } diff --git a/source/blender/draw/engines/workbench/workbench_effect_dof.c b/source/blender/draw/engines/workbench/workbench_effect_dof.c index dca65355c8f..3e35f8120d7 100644 --- a/source/blender/draw/engines/workbench/workbench_effect_dof.c +++ b/source/blender/draw/engines/workbench/workbench_effect_dof.c @@ -29,15 +29,15 @@ /* *********** STATIC *********** */ static struct { - struct GPUShader *effect_dof_prepare_sh; - struct GPUShader *effect_dof_downsample_sh; - struct GPUShader *effect_dof_flatten_v_sh; - struct GPUShader *effect_dof_flatten_h_sh; - struct GPUShader *effect_dof_dilate_v_sh; - struct GPUShader *effect_dof_dilate_h_sh; - struct GPUShader *effect_dof_blur1_sh; - struct GPUShader *effect_dof_blur2_sh; - struct GPUShader *effect_dof_resolve_sh; + struct GPUShader *effect_dof_prepare_sh; + struct GPUShader *effect_dof_downsample_sh; + struct GPUShader *effect_dof_flatten_v_sh; + struct GPUShader *effect_dof_flatten_h_sh; + struct GPUShader *effect_dof_dilate_v_sh; + struct GPUShader *effect_dof_dilate_h_sh; + struct GPUShader *effect_dof_blur1_sh; + struct GPUShader *effect_dof_blur2_sh; + struct GPUShader *effect_dof_resolve_sh; } e_data = {NULL}; /* Shaders */ @@ -50,385 +50,384 @@ extern char datatoc_workbench_effect_dof_frag_glsl[]; */ static void square_to_circle(float x, float y, float *r, float *T) { - if (x > -y) { - if (x > y) { - *r = x; - *T = (M_PI / 4.0f) * (y / x); - } - else { - *r = y; - *T = (M_PI / 4.0f) * (2 - (x / y)); - } - } - else { - if (x < y) { - *r = -x; - *T = (M_PI / 4.0f) * (4 + (y / x)); - } - else { - *r = -y; - if (y != 0) { - *T = (M_PI / 4.0f) * (6 - (x / y)); - } - else { - *T = 0.0f; - } - } - } + if (x > -y) { + if (x > y) { + *r = x; + *T = (M_PI / 4.0f) * (y / x); + } + else { + *r = y; + *T = (M_PI / 4.0f) * (2 - (x / y)); + } + } + else { + if (x < y) { + *r = -x; + *T = (M_PI / 4.0f) * (4 + (y / x)); + } + else { + *r = -y; + if (y != 0) { + *T = (M_PI / 4.0f) * (6 - (x / y)); + } + else { + *T = 0.0f; + } + } + } } #define KERNEL_RAD 3 -#define SAMP_LEN SQUARE(KERNEL_RAD * 2 + 1) +#define SAMP_LEN SQUARE(KERNEL_RAD * 2 + 1) -static void workbench_dof_setup_samples( - struct GPUUniformBuffer **ubo, float **data, - float bokeh_sides, float bokeh_rotation, float bokeh_ratio) +static void workbench_dof_setup_samples(struct GPUUniformBuffer **ubo, + float **data, + float bokeh_sides, + float bokeh_rotation, + float bokeh_ratio) { - if (*data == NULL) { - *data = MEM_callocN(sizeof(float) * 4 * SAMP_LEN, "workbench dof samples"); - } - if (*ubo == NULL) { - *ubo = DRW_uniformbuffer_create(sizeof(float) * 4 * SAMP_LEN, NULL); - } - - float *samp = *data; - for (int i = 0; i <= KERNEL_RAD; ++i) { - for (int j = -KERNEL_RAD; j <= KERNEL_RAD; ++j) { - for (int k = -KERNEL_RAD; k <= KERNEL_RAD; ++k) { - if (abs(j) > i || abs(k) > i) { - continue; - } - if (abs(j) < i && abs(k) < i) { - continue; - } - float x = ((float)j) / KERNEL_RAD; - float y = ((float)k) / KERNEL_RAD; - - float r, T; - square_to_circle(x, y, &r, &T); - samp[2] = r; - - /* Bokeh shape parametrisation */ - if (bokeh_sides > 1.0f) { - float denom = T - (2.0 * M_PI / bokeh_sides) * floorf((bokeh_sides * T + M_PI) / (2.0 * M_PI)); - r *= cosf(M_PI / bokeh_sides) / cosf(denom); - } - - T += bokeh_rotation; - - samp[0] = r * cosf(T) * bokeh_ratio; - samp[1] = r * sinf(T); - samp += 4; - } - } - } - - DRW_uniformbuffer_update(*ubo, *data); + if (*data == NULL) { + *data = MEM_callocN(sizeof(float) * 4 * SAMP_LEN, "workbench dof samples"); + } + if (*ubo == NULL) { + *ubo = DRW_uniformbuffer_create(sizeof(float) * 4 * SAMP_LEN, NULL); + } + + float *samp = *data; + for (int i = 0; i <= KERNEL_RAD; ++i) { + for (int j = -KERNEL_RAD; j <= KERNEL_RAD; ++j) { + for (int k = -KERNEL_RAD; k <= KERNEL_RAD; ++k) { + if (abs(j) > i || abs(k) > i) { + continue; + } + if (abs(j) < i && abs(k) < i) { + continue; + } + float x = ((float)j) / KERNEL_RAD; + float y = ((float)k) / KERNEL_RAD; + + float r, T; + square_to_circle(x, y, &r, &T); + samp[2] = r; + + /* Bokeh shape parametrisation */ + if (bokeh_sides > 1.0f) { + float denom = T - (2.0 * M_PI / bokeh_sides) * + floorf((bokeh_sides * T + M_PI) / (2.0 * M_PI)); + r *= cosf(M_PI / bokeh_sides) / cosf(denom); + } + + T += bokeh_rotation; + + samp[0] = r * cosf(T) * bokeh_ratio; + samp[1] = r * sinf(T); + samp += 4; + } + } + } + + DRW_uniformbuffer_update(*ubo, *data); } void workbench_dof_engine_init(WORKBENCH_Data *vedata, Object *camera) { - WORKBENCH_TextureList *txl = vedata->txl; - WORKBENCH_StorageList *stl = vedata->stl; - WORKBENCH_PrivateData *wpd = stl->g_data; - WORKBENCH_FramebufferList *fbl = vedata->fbl; - - if ((wpd->shading.flag & V3D_SHADING_DEPTH_OF_FIELD) == 0 || - (camera == NULL)) - { - wpd->dof_enabled = false; - return; - } - - if (e_data.effect_dof_prepare_sh == NULL) { - e_data.effect_dof_prepare_sh = DRW_shader_create_fullscreen( - datatoc_workbench_effect_dof_frag_glsl, - "#define PREPARE\n"); - - e_data.effect_dof_downsample_sh = DRW_shader_create_fullscreen( - datatoc_workbench_effect_dof_frag_glsl, - "#define DOWNSAMPLE\n"); - - e_data.effect_dof_flatten_v_sh = DRW_shader_create_fullscreen( - datatoc_workbench_effect_dof_frag_glsl, - "#define FLATTEN_VERTICAL\n"); - - e_data.effect_dof_flatten_h_sh = DRW_shader_create_fullscreen( - datatoc_workbench_effect_dof_frag_glsl, - "#define FLATTEN_HORIZONTAL\n"); - - e_data.effect_dof_dilate_v_sh = DRW_shader_create_fullscreen( - datatoc_workbench_effect_dof_frag_glsl, - "#define DILATE_VERTICAL\n"); - - e_data.effect_dof_dilate_h_sh = DRW_shader_create_fullscreen( - datatoc_workbench_effect_dof_frag_glsl, - "#define DILATE_HORIZONTAL\n"); - - e_data.effect_dof_blur1_sh = DRW_shader_create_fullscreen( - datatoc_workbench_effect_dof_frag_glsl, - "#define BLUR1\n"); - - e_data.effect_dof_blur2_sh = DRW_shader_create_fullscreen( - datatoc_workbench_effect_dof_frag_glsl, - "#define BLUR2\n"); - - e_data.effect_dof_resolve_sh = DRW_shader_create_fullscreen( - datatoc_workbench_effect_dof_frag_glsl, - "#define RESOLVE\n"); - } - - const float *full_size = DRW_viewport_size_get(); - int size[2] = {full_size[0] / 2, full_size[1] / 2}; + WORKBENCH_TextureList *txl = vedata->txl; + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_PrivateData *wpd = stl->g_data; + WORKBENCH_FramebufferList *fbl = vedata->fbl; + + if ((wpd->shading.flag & V3D_SHADING_DEPTH_OF_FIELD) == 0 || (camera == NULL)) { + wpd->dof_enabled = false; + return; + } + + if (e_data.effect_dof_prepare_sh == NULL) { + e_data.effect_dof_prepare_sh = DRW_shader_create_fullscreen( + datatoc_workbench_effect_dof_frag_glsl, "#define PREPARE\n"); + + e_data.effect_dof_downsample_sh = DRW_shader_create_fullscreen( + datatoc_workbench_effect_dof_frag_glsl, "#define DOWNSAMPLE\n"); + + e_data.effect_dof_flatten_v_sh = DRW_shader_create_fullscreen( + datatoc_workbench_effect_dof_frag_glsl, "#define FLATTEN_VERTICAL\n"); + + e_data.effect_dof_flatten_h_sh = DRW_shader_create_fullscreen( + datatoc_workbench_effect_dof_frag_glsl, "#define FLATTEN_HORIZONTAL\n"); + + e_data.effect_dof_dilate_v_sh = DRW_shader_create_fullscreen( + datatoc_workbench_effect_dof_frag_glsl, "#define DILATE_VERTICAL\n"); + + e_data.effect_dof_dilate_h_sh = DRW_shader_create_fullscreen( + datatoc_workbench_effect_dof_frag_glsl, "#define DILATE_HORIZONTAL\n"); + + e_data.effect_dof_blur1_sh = DRW_shader_create_fullscreen( + datatoc_workbench_effect_dof_frag_glsl, "#define BLUR1\n"); + + e_data.effect_dof_blur2_sh = DRW_shader_create_fullscreen( + datatoc_workbench_effect_dof_frag_glsl, "#define BLUR2\n"); + + e_data.effect_dof_resolve_sh = DRW_shader_create_fullscreen( + datatoc_workbench_effect_dof_frag_glsl, "#define RESOLVE\n"); + } + + const float *full_size = DRW_viewport_size_get(); + int size[2] = {full_size[0] / 2, full_size[1] / 2}; #if 0 - /* NOTE: We Ceil here in order to not miss any edge texel if using a NPO2 texture. */ - int shrink_h_size[2] = {ceilf(size[0] / 8.0f), size[1]}; - int shrink_w_size[2] = {shrink_h_size[0], ceilf(size[1] / 8.0f)}; + /* NOTE: We Ceil here in order to not miss any edge texel if using a NPO2 texture. */ + int shrink_h_size[2] = {ceilf(size[0] / 8.0f), size[1]}; + int shrink_w_size[2] = {shrink_h_size[0], ceilf(size[1] / 8.0f)}; #endif - DRW_texture_ensure_2d(&txl->dof_source_tx, size[0], size[1], GPU_R11F_G11F_B10F, DRW_TEX_FILTER | DRW_TEX_MIPMAP); - DRW_texture_ensure_2d(&txl->coc_halfres_tx, size[0], size[1], GPU_RG8, DRW_TEX_FILTER | DRW_TEX_MIPMAP); - wpd->dof_blur_tx = DRW_texture_pool_query_2d(size[0], size[1], GPU_R11F_G11F_B10F, &draw_engine_workbench_solid); + DRW_texture_ensure_2d( + &txl->dof_source_tx, size[0], size[1], GPU_R11F_G11F_B10F, DRW_TEX_FILTER | DRW_TEX_MIPMAP); + DRW_texture_ensure_2d( + &txl->coc_halfres_tx, size[0], size[1], GPU_RG8, DRW_TEX_FILTER | DRW_TEX_MIPMAP); + wpd->dof_blur_tx = DRW_texture_pool_query_2d( + size[0], size[1], GPU_R11F_G11F_B10F, &draw_engine_workbench_solid); #if 0 - wpd->coc_temp_tx = DRW_texture_pool_query_2d(shrink_h_size[0], shrink_h_size[1], GPU_RG8, &draw_engine_workbench_solid); - wpd->coc_tiles_tx[0] = DRW_texture_pool_query_2d(shrink_w_size[0], shrink_w_size[1], GPU_RG8, &draw_engine_workbench_solid); - wpd->coc_tiles_tx[1] = DRW_texture_pool_query_2d(shrink_w_size[0], shrink_w_size[1], GPU_RG8, &draw_engine_workbench_solid); + wpd->coc_temp_tx = DRW_texture_pool_query_2d(shrink_h_size[0], shrink_h_size[1], GPU_RG8, &draw_engine_workbench_solid); + wpd->coc_tiles_tx[0] = DRW_texture_pool_query_2d(shrink_w_size[0], shrink_w_size[1], GPU_RG8, &draw_engine_workbench_solid); + wpd->coc_tiles_tx[1] = DRW_texture_pool_query_2d(shrink_w_size[0], shrink_w_size[1], GPU_RG8, &draw_engine_workbench_solid); #endif - GPU_framebuffer_ensure_config(&fbl->dof_downsample_fb, { - GPU_ATTACHMENT_NONE, - GPU_ATTACHMENT_TEXTURE(txl->dof_source_tx), - GPU_ATTACHMENT_TEXTURE(txl->coc_halfres_tx), - }); + GPU_framebuffer_ensure_config(&fbl->dof_downsample_fb, + { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(txl->dof_source_tx), + GPU_ATTACHMENT_TEXTURE(txl->coc_halfres_tx), + }); #if 0 - GPU_framebuffer_ensure_config(&fbl->dof_coc_tile_h_fb, { - GPU_ATTACHMENT_NONE, - GPU_ATTACHMENT_TEXTURE(wpd->coc_temp_tx), - }); - GPU_framebuffer_ensure_config(&fbl->dof_coc_tile_v_fb, { - GPU_ATTACHMENT_NONE, - GPU_ATTACHMENT_TEXTURE(wpd->coc_tiles_tx[0]), - }); - GPU_framebuffer_ensure_config(&fbl->dof_coc_dilate_fb, { - GPU_ATTACHMENT_NONE, - GPU_ATTACHMENT_TEXTURE(wpd->coc_tiles_tx[1]), - }); + GPU_framebuffer_ensure_config(&fbl->dof_coc_tile_h_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(wpd->coc_temp_tx), + }); + GPU_framebuffer_ensure_config(&fbl->dof_coc_tile_v_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(wpd->coc_tiles_tx[0]), + }); + GPU_framebuffer_ensure_config(&fbl->dof_coc_dilate_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(wpd->coc_tiles_tx[1]), + }); #endif - GPU_framebuffer_ensure_config(&fbl->dof_blur1_fb, { - GPU_ATTACHMENT_NONE, - GPU_ATTACHMENT_TEXTURE(wpd->dof_blur_tx), - }); - GPU_framebuffer_ensure_config(&fbl->dof_blur2_fb, { - GPU_ATTACHMENT_NONE, - GPU_ATTACHMENT_TEXTURE(txl->dof_source_tx), - }); - - { - const DRWContextState *draw_ctx = DRW_context_state_get(); - const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); - RegionView3D *rv3d = draw_ctx->rv3d; - Camera *cam = (Camera *)camera->data; - - /* Parameters */ - /* TODO UI Options */ - float fstop = cam->gpu_dof.fstop; - float sensor = BKE_camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y); - float focus_dist = BKE_camera_object_dof_distance(camera); - float focal_len = cam->lens; - - /* TODO(fclem) deduplicate with eevee */ - - /* this is factor that converts to the scene scale. focal length and sensor are expressed in mm - * unit.scale_length is how many meters per blender unit we have. We want to convert to blender units though - * because the shader reads coordinates in world space, which is in blender units. - * Note however that focus_distance is already in blender units and shall not be scaled here (see T48157). */ - float scale = (scene_eval->unit.system) ? scene_eval->unit.scale_length : 1.0f; - float scale_camera = 0.001f / scale; - /* we want radius here for the aperture number */ - float aperture = 0.5f * scale_camera * focal_len / fstop; - float focal_len_scaled = scale_camera * focal_len; - float sensor_scaled = scale_camera * sensor; - - if (rv3d != NULL) { - sensor_scaled *= rv3d->viewcamtexcofac[0]; - } - - wpd->dof_aperturesize = aperture * fabsf(focal_len_scaled / (focus_dist - focal_len_scaled)); - wpd->dof_distance = -focus_dist; - wpd->dof_invsensorsize = full_size[0] / sensor_scaled; - - wpd->dof_near_far[0] = -cam->clip_start; - wpd->dof_near_far[1] = -cam->clip_end; - - float blades = cam->gpu_dof.num_blades; - float rotation = cam->gpu_dof.rotation; - float ratio = 1.0f / cam->gpu_dof.ratio; - - if (wpd->dof_ubo == NULL || - blades != wpd->dof_blades || - rotation != wpd->dof_rotation || - ratio != wpd->dof_ratio) - { - wpd->dof_blades = blades; - wpd->dof_rotation = rotation; - wpd->dof_ratio = ratio; - workbench_dof_setup_samples(&wpd->dof_ubo, &stl->dof_ubo_data, blades, rotation, ratio); - } - } - - wpd->dof_enabled = true; + GPU_framebuffer_ensure_config(&fbl->dof_blur1_fb, + { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(wpd->dof_blur_tx), + }); + GPU_framebuffer_ensure_config(&fbl->dof_blur2_fb, + { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(txl->dof_source_tx), + }); + + { + const DRWContextState *draw_ctx = DRW_context_state_get(); + const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); + RegionView3D *rv3d = draw_ctx->rv3d; + Camera *cam = (Camera *)camera->data; + + /* Parameters */ + /* TODO UI Options */ + float fstop = cam->gpu_dof.fstop; + float sensor = BKE_camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y); + float focus_dist = BKE_camera_object_dof_distance(camera); + float focal_len = cam->lens; + + /* TODO(fclem) deduplicate with eevee */ + + /* this is factor that converts to the scene scale. focal length and sensor are expressed in mm + * unit.scale_length is how many meters per blender unit we have. We want to convert to blender units though + * because the shader reads coordinates in world space, which is in blender units. + * Note however that focus_distance is already in blender units and shall not be scaled here (see T48157). */ + float scale = (scene_eval->unit.system) ? scene_eval->unit.scale_length : 1.0f; + float scale_camera = 0.001f / scale; + /* we want radius here for the aperture number */ + float aperture = 0.5f * scale_camera * focal_len / fstop; + float focal_len_scaled = scale_camera * focal_len; + float sensor_scaled = scale_camera * sensor; + + if (rv3d != NULL) { + sensor_scaled *= rv3d->viewcamtexcofac[0]; + } + + wpd->dof_aperturesize = aperture * fabsf(focal_len_scaled / (focus_dist - focal_len_scaled)); + wpd->dof_distance = -focus_dist; + wpd->dof_invsensorsize = full_size[0] / sensor_scaled; + + wpd->dof_near_far[0] = -cam->clip_start; + wpd->dof_near_far[1] = -cam->clip_end; + + float blades = cam->gpu_dof.num_blades; + float rotation = cam->gpu_dof.rotation; + float ratio = 1.0f / cam->gpu_dof.ratio; + + if (wpd->dof_ubo == NULL || blades != wpd->dof_blades || rotation != wpd->dof_rotation || + ratio != wpd->dof_ratio) { + wpd->dof_blades = blades; + wpd->dof_rotation = rotation; + wpd->dof_ratio = ratio; + workbench_dof_setup_samples(&wpd->dof_ubo, &stl->dof_ubo_data, blades, rotation, ratio); + } + } + + wpd->dof_enabled = true; } -void workbench_dof_create_pass(WORKBENCH_Data *vedata, GPUTexture **dof_input, GPUTexture *noise_tex) +void workbench_dof_create_pass(WORKBENCH_Data *vedata, + GPUTexture **dof_input, + GPUTexture *noise_tex) { - WORKBENCH_PassList *psl = vedata->psl; - WORKBENCH_TextureList *txl = vedata->txl; - WORKBENCH_StorageList *stl = vedata->stl; - WORKBENCH_PrivateData *wpd = stl->g_data; - struct GPUBatch *quad = DRW_cache_fullscreen_quad_get(); - - if (!wpd->dof_enabled) { - return; - } - - DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - - psl->dof_down_ps = DRW_pass_create("DoF DownSample", DRW_STATE_WRITE_COLOR); - psl->dof_down2_ps = DRW_pass_create("DoF DownSample", DRW_STATE_WRITE_COLOR); - psl->dof_flatten_h_ps = DRW_pass_create("DoF Flatten Coc H", DRW_STATE_WRITE_COLOR); - psl->dof_flatten_v_ps = DRW_pass_create("DoF Flatten Coc V", DRW_STATE_WRITE_COLOR); - psl->dof_dilate_h_ps = DRW_pass_create("DoF Dilate Coc H", DRW_STATE_WRITE_COLOR); - psl->dof_dilate_v_ps = DRW_pass_create("DoF Dilate Coc V", DRW_STATE_WRITE_COLOR); - psl->dof_blur1_ps = DRW_pass_create("DoF Blur 1", DRW_STATE_WRITE_COLOR); - psl->dof_blur2_ps = DRW_pass_create("DoF Blur 2", DRW_STATE_WRITE_COLOR); - psl->dof_resolve_ps = DRW_pass_create("DoF Resolve", DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND); - - { - DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_prepare_sh, psl->dof_down_ps); - DRW_shgroup_uniform_texture_ref(grp, "sceneColorTex", dof_input); - DRW_shgroup_uniform_texture(grp, "sceneDepthTex", dtxl->depth); - DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); - DRW_shgroup_uniform_vec3(grp, "dofParams", &wpd->dof_aperturesize, 1); - DRW_shgroup_uniform_vec2(grp, "nearFar", wpd->dof_near_far, 1); - DRW_shgroup_call_add(grp, quad, NULL); - } - - { - DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_downsample_sh, psl->dof_down2_ps); - DRW_shgroup_uniform_texture(grp, "sceneColorTex", txl->dof_source_tx); - DRW_shgroup_uniform_texture(grp, "inputCocTex", txl->coc_halfres_tx); - DRW_shgroup_call_add(grp, quad, NULL); - } + WORKBENCH_PassList *psl = vedata->psl; + WORKBENCH_TextureList *txl = vedata->txl; + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_PrivateData *wpd = stl->g_data; + struct GPUBatch *quad = DRW_cache_fullscreen_quad_get(); + + if (!wpd->dof_enabled) { + return; + } + + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + psl->dof_down_ps = DRW_pass_create("DoF DownSample", DRW_STATE_WRITE_COLOR); + psl->dof_down2_ps = DRW_pass_create("DoF DownSample", DRW_STATE_WRITE_COLOR); + psl->dof_flatten_h_ps = DRW_pass_create("DoF Flatten Coc H", DRW_STATE_WRITE_COLOR); + psl->dof_flatten_v_ps = DRW_pass_create("DoF Flatten Coc V", DRW_STATE_WRITE_COLOR); + psl->dof_dilate_h_ps = DRW_pass_create("DoF Dilate Coc H", DRW_STATE_WRITE_COLOR); + psl->dof_dilate_v_ps = DRW_pass_create("DoF Dilate Coc V", DRW_STATE_WRITE_COLOR); + psl->dof_blur1_ps = DRW_pass_create("DoF Blur 1", DRW_STATE_WRITE_COLOR); + psl->dof_blur2_ps = DRW_pass_create("DoF Blur 2", DRW_STATE_WRITE_COLOR); + psl->dof_resolve_ps = DRW_pass_create("DoF Resolve", DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND); + + { + DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_prepare_sh, psl->dof_down_ps); + DRW_shgroup_uniform_texture_ref(grp, "sceneColorTex", dof_input); + DRW_shgroup_uniform_texture(grp, "sceneDepthTex", dtxl->depth); + DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); + DRW_shgroup_uniform_vec3(grp, "dofParams", &wpd->dof_aperturesize, 1); + DRW_shgroup_uniform_vec2(grp, "nearFar", wpd->dof_near_far, 1); + DRW_shgroup_call_add(grp, quad, NULL); + } + + { + DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_downsample_sh, psl->dof_down2_ps); + DRW_shgroup_uniform_texture(grp, "sceneColorTex", txl->dof_source_tx); + DRW_shgroup_uniform_texture(grp, "inputCocTex", txl->coc_halfres_tx); + DRW_shgroup_call_add(grp, quad, NULL); + } #if 0 - { - DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_flatten_h_sh, psl->dof_flatten_h_ps); - DRW_shgroup_uniform_texture(grp, "inputCocTex", txl->coc_halfres_tx); - DRW_shgroup_call_add(grp, quad, NULL); - } - { - DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_flatten_v_sh, psl->dof_flatten_v_ps); - DRW_shgroup_uniform_texture(grp, "inputCocTex", wpd->coc_temp_tx); - DRW_shgroup_call_add(grp, quad, NULL); - } - { - DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_dilate_v_sh, psl->dof_dilate_v_ps); - DRW_shgroup_uniform_texture(grp, "inputCocTex", wpd->coc_tiles_tx[0]); - DRW_shgroup_call_add(grp, quad, NULL); - } - { - DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_dilate_h_sh, psl->dof_dilate_h_ps); - DRW_shgroup_uniform_texture(grp, "inputCocTex", wpd->coc_tiles_tx[1]); - DRW_shgroup_call_add(grp, quad, NULL); - } + { + DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_flatten_h_sh, psl->dof_flatten_h_ps); + DRW_shgroup_uniform_texture(grp, "inputCocTex", txl->coc_halfres_tx); + DRW_shgroup_call_add(grp, quad, NULL); + } + { + DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_flatten_v_sh, psl->dof_flatten_v_ps); + DRW_shgroup_uniform_texture(grp, "inputCocTex", wpd->coc_temp_tx); + DRW_shgroup_call_add(grp, quad, NULL); + } + { + DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_dilate_v_sh, psl->dof_dilate_v_ps); + DRW_shgroup_uniform_texture(grp, "inputCocTex", wpd->coc_tiles_tx[0]); + DRW_shgroup_call_add(grp, quad, NULL); + } + { + DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_dilate_h_sh, psl->dof_dilate_h_ps); + DRW_shgroup_uniform_texture(grp, "inputCocTex", wpd->coc_tiles_tx[1]); + DRW_shgroup_call_add(grp, quad, NULL); + } #endif - { - float offset = stl->effects->jitter_index / (float)workbench_taa_calculate_num_iterations(vedata); - DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_blur1_sh, psl->dof_blur1_ps); - DRW_shgroup_uniform_block(grp, "dofSamplesBlock", wpd->dof_ubo); - DRW_shgroup_uniform_texture(grp, "noiseTex", noise_tex); - DRW_shgroup_uniform_texture(grp, "inputCocTex", txl->coc_halfres_tx); - DRW_shgroup_uniform_texture(grp, "halfResColorTex", txl->dof_source_tx); - DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); - DRW_shgroup_uniform_float_copy(grp, "noiseOffset", offset); - DRW_shgroup_call_add(grp, quad, NULL); - } - { - DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_blur2_sh, psl->dof_blur2_ps); - DRW_shgroup_uniform_texture(grp, "inputCocTex", txl->coc_halfres_tx); - DRW_shgroup_uniform_texture(grp, "blurTex", wpd->dof_blur_tx); - DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); - DRW_shgroup_call_add(grp, quad, NULL); - } - { - DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_resolve_sh, psl->dof_resolve_ps); - DRW_shgroup_uniform_texture(grp, "halfResColorTex", txl->dof_source_tx); - DRW_shgroup_uniform_texture(grp, "sceneDepthTex", dtxl->depth); - DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); - DRW_shgroup_uniform_vec3(grp, "dofParams", &wpd->dof_aperturesize, 1); - DRW_shgroup_uniform_vec2(grp, "nearFar", wpd->dof_near_far, 1); - DRW_shgroup_call_add(grp, quad, NULL); - } + { + float offset = stl->effects->jitter_index / + (float)workbench_taa_calculate_num_iterations(vedata); + DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_blur1_sh, psl->dof_blur1_ps); + DRW_shgroup_uniform_block(grp, "dofSamplesBlock", wpd->dof_ubo); + DRW_shgroup_uniform_texture(grp, "noiseTex", noise_tex); + DRW_shgroup_uniform_texture(grp, "inputCocTex", txl->coc_halfres_tx); + DRW_shgroup_uniform_texture(grp, "halfResColorTex", txl->dof_source_tx); + DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); + DRW_shgroup_uniform_float_copy(grp, "noiseOffset", offset); + DRW_shgroup_call_add(grp, quad, NULL); + } + { + DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_blur2_sh, psl->dof_blur2_ps); + DRW_shgroup_uniform_texture(grp, "inputCocTex", txl->coc_halfres_tx); + DRW_shgroup_uniform_texture(grp, "blurTex", wpd->dof_blur_tx); + DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); + DRW_shgroup_call_add(grp, quad, NULL); + } + { + DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_resolve_sh, psl->dof_resolve_ps); + DRW_shgroup_uniform_texture(grp, "halfResColorTex", txl->dof_source_tx); + DRW_shgroup_uniform_texture(grp, "sceneDepthTex", dtxl->depth); + DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); + DRW_shgroup_uniform_vec3(grp, "dofParams", &wpd->dof_aperturesize, 1); + DRW_shgroup_uniform_vec2(grp, "nearFar", wpd->dof_near_far, 1); + DRW_shgroup_call_add(grp, quad, NULL); + } } void workbench_dof_engine_free(void) { - DRW_SHADER_FREE_SAFE(e_data.effect_dof_prepare_sh); - DRW_SHADER_FREE_SAFE(e_data.effect_dof_downsample_sh); - DRW_SHADER_FREE_SAFE(e_data.effect_dof_flatten_v_sh); - DRW_SHADER_FREE_SAFE(e_data.effect_dof_flatten_h_sh); - DRW_SHADER_FREE_SAFE(e_data.effect_dof_dilate_v_sh); - DRW_SHADER_FREE_SAFE(e_data.effect_dof_dilate_h_sh); - DRW_SHADER_FREE_SAFE(e_data.effect_dof_blur1_sh); - DRW_SHADER_FREE_SAFE(e_data.effect_dof_blur2_sh); - DRW_SHADER_FREE_SAFE(e_data.effect_dof_resolve_sh); + DRW_SHADER_FREE_SAFE(e_data.effect_dof_prepare_sh); + DRW_SHADER_FREE_SAFE(e_data.effect_dof_downsample_sh); + DRW_SHADER_FREE_SAFE(e_data.effect_dof_flatten_v_sh); + DRW_SHADER_FREE_SAFE(e_data.effect_dof_flatten_h_sh); + DRW_SHADER_FREE_SAFE(e_data.effect_dof_dilate_v_sh); + DRW_SHADER_FREE_SAFE(e_data.effect_dof_dilate_h_sh); + DRW_SHADER_FREE_SAFE(e_data.effect_dof_blur1_sh); + DRW_SHADER_FREE_SAFE(e_data.effect_dof_blur2_sh); + DRW_SHADER_FREE_SAFE(e_data.effect_dof_resolve_sh); } static void workbench_dof_downsample_level(void *userData, int UNUSED(level)) { - WORKBENCH_PassList *psl = (WORKBENCH_PassList *)userData; - DRW_draw_pass(psl->dof_down2_ps); + WORKBENCH_PassList *psl = (WORKBENCH_PassList *)userData; + DRW_draw_pass(psl->dof_down2_ps); } void workbench_dof_draw_pass(WORKBENCH_Data *vedata) { - WORKBENCH_FramebufferList *fbl = vedata->fbl; - WORKBENCH_StorageList *stl = vedata->stl; - WORKBENCH_PassList *psl = vedata->psl; - WORKBENCH_PrivateData *wpd = stl->g_data; + WORKBENCH_FramebufferList *fbl = vedata->fbl; + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_PassList *psl = vedata->psl; + WORKBENCH_PrivateData *wpd = stl->g_data; - if (!wpd->dof_enabled) { - return; - } + if (!wpd->dof_enabled) { + return; + } - DRW_stats_group_start("Depth Of Field"); + DRW_stats_group_start("Depth Of Field"); - GPU_framebuffer_bind(fbl->dof_downsample_fb); - DRW_draw_pass(psl->dof_down_ps); + GPU_framebuffer_bind(fbl->dof_downsample_fb); + DRW_draw_pass(psl->dof_down_ps); - GPU_framebuffer_recursive_downsample(fbl->dof_downsample_fb, 2, workbench_dof_downsample_level, psl); + GPU_framebuffer_recursive_downsample( + fbl->dof_downsample_fb, 2, workbench_dof_downsample_level, psl); #if 0 - GPU_framebuffer_bind(fbl->dof_coc_tile_h_fb); - DRW_draw_pass(psl->dof_flatten_h_ps); + GPU_framebuffer_bind(fbl->dof_coc_tile_h_fb); + DRW_draw_pass(psl->dof_flatten_h_ps); - GPU_framebuffer_bind(fbl->dof_coc_tile_v_fb); - DRW_draw_pass(psl->dof_flatten_v_ps); + GPU_framebuffer_bind(fbl->dof_coc_tile_v_fb); + DRW_draw_pass(psl->dof_flatten_v_ps); - GPU_framebuffer_bind(fbl->dof_coc_dilate_fb); - DRW_draw_pass(psl->dof_dilate_v_ps); + GPU_framebuffer_bind(fbl->dof_coc_dilate_fb); + DRW_draw_pass(psl->dof_dilate_v_ps); - GPU_framebuffer_bind(fbl->dof_coc_tile_v_fb); - DRW_draw_pass(psl->dof_dilate_h_ps); + GPU_framebuffer_bind(fbl->dof_coc_tile_v_fb); + DRW_draw_pass(psl->dof_dilate_h_ps); #endif - GPU_framebuffer_bind(fbl->dof_blur1_fb); - DRW_draw_pass(psl->dof_blur1_ps); + GPU_framebuffer_bind(fbl->dof_blur1_fb); + DRW_draw_pass(psl->dof_blur1_ps); - GPU_framebuffer_bind(fbl->dof_blur2_fb); - DRW_draw_pass(psl->dof_blur2_ps); + GPU_framebuffer_bind(fbl->dof_blur2_fb); + DRW_draw_pass(psl->dof_blur2_ps); - GPU_framebuffer_bind(fbl->color_only_fb); - DRW_draw_pass(psl->dof_resolve_ps); + GPU_framebuffer_bind(fbl->color_only_fb); + DRW_draw_pass(psl->dof_resolve_ps); - DRW_stats_group_end(); + DRW_stats_group_end(); } diff --git a/source/blender/draw/engines/workbench/workbench_effect_fxaa.c b/source/blender/draw/engines/workbench/workbench_effect_fxaa.c index 6e2ebff854e..47355f324a8 100644 --- a/source/blender/draw/engines/workbench/workbench_effect_fxaa.c +++ b/source/blender/draw/engines/workbench/workbench_effect_fxaa.c @@ -23,7 +23,7 @@ /* *********** STATIC *********** */ static struct { - struct GPUShader *effect_fxaa_sh; + struct GPUShader *effect_fxaa_sh; } e_data = {NULL}; /* Shaders */ @@ -34,26 +34,26 @@ extern char datatoc_workbench_effect_fxaa_frag_glsl[]; /* *********** Functions *********** */ void workbench_fxaa_engine_init(void) { - if (e_data.effect_fxaa_sh == NULL) { - e_data.effect_fxaa_sh = DRW_shader_create_with_lib( - datatoc_common_fullscreen_vert_glsl, NULL, - datatoc_workbench_effect_fxaa_frag_glsl, - datatoc_common_fxaa_lib_glsl, - NULL); - } + if (e_data.effect_fxaa_sh == NULL) { + e_data.effect_fxaa_sh = DRW_shader_create_with_lib(datatoc_common_fullscreen_vert_glsl, + NULL, + datatoc_workbench_effect_fxaa_frag_glsl, + datatoc_common_fxaa_lib_glsl, + NULL); + } } DRWPass *workbench_fxaa_create_pass(GPUTexture **color_buffer_tx) { - DRWPass *pass = DRW_pass_create("Effect FXAA", DRW_STATE_WRITE_COLOR); - DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_fxaa_sh, pass); - DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", color_buffer_tx); - DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); - DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); - return pass; + DRWPass *pass = DRW_pass_create("Effect FXAA", DRW_STATE_WRITE_COLOR); + DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_fxaa_sh, pass); + DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", color_buffer_tx); + DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + return pass; } void workbench_fxaa_engine_free(void) { - DRW_SHADER_FREE_SAFE(e_data.effect_fxaa_sh); + DRW_SHADER_FREE_SAFE(e_data.effect_fxaa_sh); } diff --git a/source/blender/draw/engines/workbench/workbench_effect_taa.c b/source/blender/draw/engines/workbench/workbench_effect_taa.c index cbc0e347d7d..0435a804fab 100644 --- a/source/blender/draw/engines/workbench/workbench_effect_taa.c +++ b/source/blender/draw/engines/workbench/workbench_effect_taa.c @@ -20,290 +20,288 @@ * \ingroup draw_engine */ - #include "workbench_private.h" #include "BLI_jitter_2d.h" static struct { - struct GPUShader *effect_taa_sh; - float jitter_5[5][2]; - float jitter_8[8][2]; - float jitter_11[11][2]; - float jitter_16[16][2]; - float jitter_32[32][2]; + struct GPUShader *effect_taa_sh; + float jitter_5[5][2]; + float jitter_8[8][2]; + float jitter_11[11][2]; + float jitter_16[16][2]; + float jitter_32[32][2]; } e_data = {NULL}; extern char datatoc_workbench_effect_taa_frag_glsl[]; - static void workbench_taa_jitter_init_order(float (*table)[2], int num) { - BLI_jitter_init(table, num); - - /* find closest element to center */ - int closest_index = 0; - float closest_squared_distance = 1.0f; - - for (int index = 0; index < num; index++) { - const float squared_dist = SQUARE(table[index][0]) + SQUARE(table[index][1]); - if (squared_dist < closest_squared_distance) { - closest_squared_distance = squared_dist; - closest_index = index; - } - } - - /* move jitter table so that closest sample is in center */ - for (int index = 0; index < num; index++) { - sub_v2_v2(table[index], table[closest_index]); - mul_v2_fl(table[index], 2.0f); - } - - /* swap center sample to the start of the table */ - if (closest_index != 0) { - swap_v2_v2(table[0], table[closest_index]); - } - - /* sort list based on furtest distance with previous */ - for (int i = 0; i < num - 2; i++) { - float f_squared_dist = 0.0; - int f_index = i; - for (int j = i + 1; j < num; j++) { - const float squared_dist = SQUARE(table[i][0] - table[j][0]) + SQUARE(table[i][1] - table[j][1]); - if (squared_dist > f_squared_dist) { - f_squared_dist = squared_dist; - f_index = j; - } - } - swap_v2_v2(table[i + 1], table[f_index]); - } + BLI_jitter_init(table, num); + + /* find closest element to center */ + int closest_index = 0; + float closest_squared_distance = 1.0f; + + for (int index = 0; index < num; index++) { + const float squared_dist = SQUARE(table[index][0]) + SQUARE(table[index][1]); + if (squared_dist < closest_squared_distance) { + closest_squared_distance = squared_dist; + closest_index = index; + } + } + + /* move jitter table so that closest sample is in center */ + for (int index = 0; index < num; index++) { + sub_v2_v2(table[index], table[closest_index]); + mul_v2_fl(table[index], 2.0f); + } + + /* swap center sample to the start of the table */ + if (closest_index != 0) { + swap_v2_v2(table[0], table[closest_index]); + } + + /* sort list based on furtest distance with previous */ + for (int i = 0; i < num - 2; i++) { + float f_squared_dist = 0.0; + int f_index = i; + for (int j = i + 1; j < num; j++) { + const float squared_dist = SQUARE(table[i][0] - table[j][0]) + + SQUARE(table[i][1] - table[j][1]); + if (squared_dist > f_squared_dist) { + f_squared_dist = squared_dist; + f_index = j; + } + } + swap_v2_v2(table[i + 1], table[f_index]); + } } - static void workbench_taa_jitter_init(void) { - workbench_taa_jitter_init_order(e_data.jitter_5, 5); - workbench_taa_jitter_init_order(e_data.jitter_8, 8); - workbench_taa_jitter_init_order(e_data.jitter_11, 11); - workbench_taa_jitter_init_order(e_data.jitter_16, 16); - workbench_taa_jitter_init_order(e_data.jitter_32, 32); + workbench_taa_jitter_init_order(e_data.jitter_5, 5); + workbench_taa_jitter_init_order(e_data.jitter_8, 8); + workbench_taa_jitter_init_order(e_data.jitter_11, 11); + workbench_taa_jitter_init_order(e_data.jitter_16, 16); + workbench_taa_jitter_init_order(e_data.jitter_32, 32); } int workbench_taa_calculate_num_iterations(WORKBENCH_Data *vedata) { - WORKBENCH_StorageList *stl = vedata->stl; - WORKBENCH_PrivateData *wpd = stl->g_data; - int result = 1; - if (TAA_ENABLED(wpd)) { - if (DRW_state_is_image_render()) { - const Scene *scene = DRW_context_state_get()->scene; - result = (scene->r.mode & R_OSA) ? scene->r.osa : 1; - } - else if (IN_RANGE_INCL( - wpd->preferences->gpu_viewport_quality, - GPU_VIEWPORT_QUALITY_TAA8, GPU_VIEWPORT_QUALITY_TAA16)) - { - result = 8; - } - else if (IN_RANGE_INCL( - wpd->preferences->gpu_viewport_quality, - GPU_VIEWPORT_QUALITY_TAA16, GPU_VIEWPORT_QUALITY_TAA32)) - { - result = 16; - } - else { - result = 32; - } - } - return result; + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_PrivateData *wpd = stl->g_data; + int result = 1; + if (TAA_ENABLED(wpd)) { + if (DRW_state_is_image_render()) { + const Scene *scene = DRW_context_state_get()->scene; + result = (scene->r.mode & R_OSA) ? scene->r.osa : 1; + } + else if (IN_RANGE_INCL(wpd->preferences->gpu_viewport_quality, + GPU_VIEWPORT_QUALITY_TAA8, + GPU_VIEWPORT_QUALITY_TAA16)) { + result = 8; + } + else if (IN_RANGE_INCL(wpd->preferences->gpu_viewport_quality, + GPU_VIEWPORT_QUALITY_TAA16, + GPU_VIEWPORT_QUALITY_TAA32)) { + result = 16; + } + else { + result = 32; + } + } + return result; } void workbench_taa_engine_init(WORKBENCH_Data *vedata) { - WORKBENCH_EffectInfo *effect_info = vedata->stl->effects; - const DRWContextState *draw_ctx = DRW_context_state_get(); - RegionView3D *rv3d = draw_ctx->rv3d; - - if (e_data.effect_taa_sh == NULL) { - e_data.effect_taa_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_taa_frag_glsl, NULL); - workbench_taa_jitter_init(); - } - - /* reset complete drawing when navigating. */ - if (effect_info->jitter_index != 0) { - if (rv3d && rv3d->rflag & RV3D_NAVIGATING) { - effect_info->jitter_index = 0; - } - } - - if (effect_info->view_updated) { - effect_info->jitter_index = 0; - effect_info->view_updated = false; - } - - { - float view[4][4]; - float win[4][4]; - DRW_viewport_matrix_get(view, DRW_MAT_VIEW); - DRW_viewport_matrix_get(win, DRW_MAT_WIN); - mul_m4_m4m4(effect_info->curr_mat, view, win); - if (!equals_m4m4(effect_info->curr_mat, effect_info->last_mat)) { - effect_info->jitter_index = 0; - } - } + WORKBENCH_EffectInfo *effect_info = vedata->stl->effects; + const DRWContextState *draw_ctx = DRW_context_state_get(); + RegionView3D *rv3d = draw_ctx->rv3d; + + if (e_data.effect_taa_sh == NULL) { + e_data.effect_taa_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_taa_frag_glsl, + NULL); + workbench_taa_jitter_init(); + } + + /* reset complete drawing when navigating. */ + if (effect_info->jitter_index != 0) { + if (rv3d && rv3d->rflag & RV3D_NAVIGATING) { + effect_info->jitter_index = 0; + } + } + + if (effect_info->view_updated) { + effect_info->jitter_index = 0; + effect_info->view_updated = false; + } + + { + float view[4][4]; + float win[4][4]; + DRW_viewport_matrix_get(view, DRW_MAT_VIEW); + DRW_viewport_matrix_get(win, DRW_MAT_WIN); + mul_m4_m4m4(effect_info->curr_mat, view, win); + if (!equals_m4m4(effect_info->curr_mat, effect_info->last_mat)) { + effect_info->jitter_index = 0; + } + } } void workbench_taa_engine_free(void) { - DRW_SHADER_FREE_SAFE(e_data.effect_taa_sh); + DRW_SHADER_FREE_SAFE(e_data.effect_taa_sh); } - DRWPass *workbench_taa_create_pass(WORKBENCH_Data *vedata, GPUTexture **color_buffer_tx) { - WORKBENCH_StorageList *stl = vedata->stl; - WORKBENCH_TextureList *txl = vedata->txl; - WORKBENCH_EffectInfo *effect_info = stl->effects; - WORKBENCH_FramebufferList *fbl = vedata->fbl; - WORKBENCH_PrivateData *wpd = stl->g_data; - /* - * jitter_index is not updated yet. This will be done in during draw phase. - * so for now it is inversed. - */ - int previous_jitter_index = effect_info->jitter_index; - - { - const eGPUTextureFormat hist_buffer_format = DRW_state_is_image_render() ? GPU_RGBA16F : GPU_RGBA8; - DRW_texture_ensure_fullscreen_2d(&txl->history_buffer_tx, hist_buffer_format, 0); - DRW_texture_ensure_fullscreen_2d(&txl->depth_buffer_tx, GPU_DEPTH24_STENCIL8, 0); - } - - { - GPU_framebuffer_ensure_config(&fbl->effect_taa_fb, { - GPU_ATTACHMENT_NONE, - GPU_ATTACHMENT_TEXTURE(txl->history_buffer_tx), - }); - GPU_framebuffer_ensure_config(&fbl->depth_buffer_fb, { - GPU_ATTACHMENT_TEXTURE(txl->depth_buffer_tx), - }); - } - - - DRWPass *pass = DRW_pass_create("Effect TAA", DRW_STATE_WRITE_COLOR); - DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_taa_sh, pass); - DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", color_buffer_tx); - DRW_shgroup_uniform_texture_ref(grp, "historyBuffer", &txl->history_buffer_tx); - DRW_shgroup_uniform_float(grp, "mixFactor", &effect_info->taa_mix_factor, 1); - DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); - - /* - * Set the offset for the cavity shader so every iteration different - * samples will be selected - */ - wpd->ssao_params[3] = previous_jitter_index; - - return pass; + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_TextureList *txl = vedata->txl; + WORKBENCH_EffectInfo *effect_info = stl->effects; + WORKBENCH_FramebufferList *fbl = vedata->fbl; + WORKBENCH_PrivateData *wpd = stl->g_data; + /* + * jitter_index is not updated yet. This will be done in during draw phase. + * so for now it is inversed. + */ + int previous_jitter_index = effect_info->jitter_index; + + { + const eGPUTextureFormat hist_buffer_format = DRW_state_is_image_render() ? GPU_RGBA16F : + GPU_RGBA8; + DRW_texture_ensure_fullscreen_2d(&txl->history_buffer_tx, hist_buffer_format, 0); + DRW_texture_ensure_fullscreen_2d(&txl->depth_buffer_tx, GPU_DEPTH24_STENCIL8, 0); + } + + { + GPU_framebuffer_ensure_config(&fbl->effect_taa_fb, + { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(txl->history_buffer_tx), + }); + GPU_framebuffer_ensure_config(&fbl->depth_buffer_fb, + { + GPU_ATTACHMENT_TEXTURE(txl->depth_buffer_tx), + }); + } + + DRWPass *pass = DRW_pass_create("Effect TAA", DRW_STATE_WRITE_COLOR); + DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_taa_sh, pass); + DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", color_buffer_tx); + DRW_shgroup_uniform_texture_ref(grp, "historyBuffer", &txl->history_buffer_tx); + DRW_shgroup_uniform_float(grp, "mixFactor", &effect_info->taa_mix_factor, 1); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + + /* + * Set the offset for the cavity shader so every iteration different + * samples will be selected + */ + wpd->ssao_params[3] = previous_jitter_index; + + return pass; } void workbench_taa_draw_scene_start(WORKBENCH_Data *vedata) { - WORKBENCH_StorageList *stl = vedata->stl; - WORKBENCH_EffectInfo *effect_info = stl->effects; - const float *viewport_size = DRW_viewport_size_get(); - int num_samples = 8; - float (*samples)[2]; - float mix_factor; - - num_samples = workbench_taa_calculate_num_iterations(vedata); - switch (num_samples) { - default: - case 5: - samples = e_data.jitter_5; - break; - case 8: - samples = e_data.jitter_8; - break; - case 11: - samples = e_data.jitter_11; - break; - case 16: - samples = e_data.jitter_16; - break; - case 32: - samples = e_data.jitter_32; - break; - } - - mix_factor = 1.0f / (effect_info->jitter_index + 1); - - const int jitter_index = effect_info->jitter_index; - const float *transform_offset = samples[jitter_index]; - effect_info->jitter_index = (jitter_index + 1) % num_samples; - - /* construct new matrices from transform delta */ - float viewmat[4][4]; - float persmat[4][4]; - DRW_viewport_matrix_get(viewmat, DRW_MAT_VIEW); - DRW_viewport_matrix_get(persmat, DRW_MAT_PERS); - DRW_viewport_matrix_get(effect_info->override_winmat, DRW_MAT_WIN); - - window_translate_m4( - effect_info->override_winmat, persmat, - transform_offset[0] / viewport_size[0], - transform_offset[1] / viewport_size[1]); - - mul_m4_m4m4(effect_info->override_persmat, effect_info->override_winmat, viewmat); - invert_m4_m4(effect_info->override_persinv, effect_info->override_persmat); - invert_m4_m4(effect_info->override_wininv, effect_info->override_winmat); - - DRW_viewport_matrix_override_set(effect_info->override_persmat, DRW_MAT_PERS); - DRW_viewport_matrix_override_set(effect_info->override_persinv, DRW_MAT_PERSINV); - DRW_viewport_matrix_override_set(effect_info->override_winmat, DRW_MAT_WIN); - DRW_viewport_matrix_override_set(effect_info->override_wininv, DRW_MAT_WININV); - - /* weight the mix factor by the jitter index */ - effect_info->taa_mix_factor = mix_factor; + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_EffectInfo *effect_info = stl->effects; + const float *viewport_size = DRW_viewport_size_get(); + int num_samples = 8; + float(*samples)[2]; + float mix_factor; + + num_samples = workbench_taa_calculate_num_iterations(vedata); + switch (num_samples) { + default: + case 5: + samples = e_data.jitter_5; + break; + case 8: + samples = e_data.jitter_8; + break; + case 11: + samples = e_data.jitter_11; + break; + case 16: + samples = e_data.jitter_16; + break; + case 32: + samples = e_data.jitter_32; + break; + } + + mix_factor = 1.0f / (effect_info->jitter_index + 1); + + const int jitter_index = effect_info->jitter_index; + const float *transform_offset = samples[jitter_index]; + effect_info->jitter_index = (jitter_index + 1) % num_samples; + + /* construct new matrices from transform delta */ + float viewmat[4][4]; + float persmat[4][4]; + DRW_viewport_matrix_get(viewmat, DRW_MAT_VIEW); + DRW_viewport_matrix_get(persmat, DRW_MAT_PERS); + DRW_viewport_matrix_get(effect_info->override_winmat, DRW_MAT_WIN); + + window_translate_m4(effect_info->override_winmat, + persmat, + transform_offset[0] / viewport_size[0], + transform_offset[1] / viewport_size[1]); + + mul_m4_m4m4(effect_info->override_persmat, effect_info->override_winmat, viewmat); + invert_m4_m4(effect_info->override_persinv, effect_info->override_persmat); + invert_m4_m4(effect_info->override_wininv, effect_info->override_winmat); + + DRW_viewport_matrix_override_set(effect_info->override_persmat, DRW_MAT_PERS); + DRW_viewport_matrix_override_set(effect_info->override_persinv, DRW_MAT_PERSINV); + DRW_viewport_matrix_override_set(effect_info->override_winmat, DRW_MAT_WIN); + DRW_viewport_matrix_override_set(effect_info->override_wininv, DRW_MAT_WININV); + + /* weight the mix factor by the jitter index */ + effect_info->taa_mix_factor = mix_factor; } void workbench_taa_draw_scene_end(WORKBENCH_Data *vedata) { - /* - * If first frame than the offset is 0.0 and its depth is the depth buffer to use - * for the rest of the draw engines. We store it in a persistent buffer. - * - * If it is not the first frame we copy the persistent buffer back to the - * default depth buffer - */ - const WORKBENCH_StorageList *stl = vedata->stl; - const WORKBENCH_FramebufferList *fbl = vedata->fbl; - const DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); - WORKBENCH_EffectInfo *effect_info = stl->effects; - - if (effect_info->jitter_index == 1) { - GPU_framebuffer_blit(dfbl->depth_only_fb, 0, fbl->depth_buffer_fb, 0, GPU_DEPTH_BIT); - } - else { - GPU_framebuffer_blit(fbl->depth_buffer_fb, 0, dfbl->depth_only_fb, 0, GPU_DEPTH_BIT); - } - - GPU_framebuffer_blit(dfbl->color_only_fb, 0, fbl->effect_taa_fb, 0, GPU_COLOR_BIT); - - if (!DRW_state_is_image_render()) { - DRW_viewport_matrix_override_unset_all(); - } - - copy_m4_m4(effect_info->last_mat, effect_info->curr_mat); - if (effect_info->jitter_index != 0 && !DRW_state_is_image_render()) { - DRW_viewport_request_redraw(); - } + /* + * If first frame than the offset is 0.0 and its depth is the depth buffer to use + * for the rest of the draw engines. We store it in a persistent buffer. + * + * If it is not the first frame we copy the persistent buffer back to the + * default depth buffer + */ + const WORKBENCH_StorageList *stl = vedata->stl; + const WORKBENCH_FramebufferList *fbl = vedata->fbl; + const DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + WORKBENCH_EffectInfo *effect_info = stl->effects; + + if (effect_info->jitter_index == 1) { + GPU_framebuffer_blit(dfbl->depth_only_fb, 0, fbl->depth_buffer_fb, 0, GPU_DEPTH_BIT); + } + else { + GPU_framebuffer_blit(fbl->depth_buffer_fb, 0, dfbl->depth_only_fb, 0, GPU_DEPTH_BIT); + } + + GPU_framebuffer_blit(dfbl->color_only_fb, 0, fbl->effect_taa_fb, 0, GPU_COLOR_BIT); + + if (!DRW_state_is_image_render()) { + DRW_viewport_matrix_override_unset_all(); + } + + copy_m4_m4(effect_info->last_mat, effect_info->curr_mat); + if (effect_info->jitter_index != 0 && !DRW_state_is_image_render()) { + DRW_viewport_request_redraw(); + } } void workbench_taa_view_updated(WORKBENCH_Data *vedata) { - WORKBENCH_StorageList *stl = vedata->stl; - if (stl) { - WORKBENCH_EffectInfo *effect_info = stl->effects; - if (effect_info) { - effect_info->view_updated = true; - } - } + WORKBENCH_StorageList *stl = vedata->stl; + if (stl) { + WORKBENCH_EffectInfo *effect_info = stl->effects; + if (effect_info) { + effect_info->view_updated = true; + } + } } diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c index 8aa21e92082..62a192bbb25 100644 --- a/source/blender/draw/engines/workbench/workbench_engine.c +++ b/source/blender/draw/engines/workbench/workbench_engine.c @@ -32,13 +32,20 @@ /* Note: currently unused, we may want to register so we can see this when debugging the view. */ RenderEngineType DRW_engine_viewport_workbench_type = { - NULL, NULL, - WORKBENCH_ENGINE, N_("Workbench"), RE_INTERNAL, - NULL, &DRW_render_to_image, NULL, NULL, NULL, NULL, - &workbench_render_update_passes, - &draw_engine_workbench_solid, - {NULL, NULL, NULL}, + NULL, + NULL, + WORKBENCH_ENGINE, + N_("Workbench"), + RE_INTERNAL, + NULL, + &DRW_render_to_image, + NULL, + NULL, + NULL, + NULL, + &workbench_render_update_passes, + &draw_engine_workbench_solid, + {NULL, NULL, NULL}, }; - #undef WORKBENCH_ENGINE diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c index f86a263406a..782e85597d7 100644 --- a/source/blender/draw/engines/workbench/workbench_forward.c +++ b/source/blender/draw/engines/workbench/workbench_forward.c @@ -43,28 +43,27 @@ #include "GPU_shader.h" #include "GPU_texture.h" - /* *********** STATIC *********** */ typedef struct WORKBENCH_FORWARD_Shaders { - struct GPUShader *transparent_accum_sh_cache[MAX_ACCUM_SHADERS]; - struct GPUShader *object_outline_sh; - struct GPUShader *object_outline_texture_sh; - struct GPUShader *object_outline_hair_sh; + struct GPUShader *transparent_accum_sh_cache[MAX_ACCUM_SHADERS]; + struct GPUShader *object_outline_sh; + struct GPUShader *object_outline_texture_sh; + struct GPUShader *object_outline_hair_sh; } WORKBENCH_FORWARD_Shaders; static struct { - WORKBENCH_FORWARD_Shaders sh_data[GPU_SHADER_CFG_LEN]; + WORKBENCH_FORWARD_Shaders sh_data[GPU_SHADER_CFG_LEN]; - struct GPUShader *composite_sh_cache[2]; - struct GPUShader *checker_depth_sh; + struct GPUShader *composite_sh_cache[2]; + struct GPUShader *checker_depth_sh; - struct GPUTexture *object_id_tx; /* ref only, not alloced */ - struct GPUTexture *transparent_accum_tx; /* ref only, not alloced */ - struct GPUTexture *transparent_revealage_tx; /* ref only, not alloced */ - struct GPUTexture *composite_buffer_tx; /* ref only, not alloced */ + struct GPUTexture *object_id_tx; /* ref only, not alloced */ + struct GPUTexture *transparent_accum_tx; /* ref only, not alloced */ + struct GPUTexture *transparent_revealage_tx; /* ref only, not alloced */ + struct GPUTexture *composite_buffer_tx; /* ref only, not alloced */ - int next_object_id; + int next_object_id; } e_data = {{{{NULL}}}}; /* Shaders */ @@ -85,370 +84,389 @@ extern char datatoc_workbench_world_light_lib_glsl[]; /* static functions */ static char *workbench_build_forward_vert(bool is_hair) { - DynStr *ds = BLI_dynstr_new(); - if (is_hair) { - BLI_dynstr_append(ds, datatoc_common_hair_lib_glsl); - } - BLI_dynstr_append(ds, datatoc_workbench_prepass_vert_glsl); - - char *str = BLI_dynstr_get_cstring(ds); - BLI_dynstr_free(ds); - return str; + DynStr *ds = BLI_dynstr_new(); + if (is_hair) { + BLI_dynstr_append(ds, datatoc_common_hair_lib_glsl); + } + BLI_dynstr_append(ds, datatoc_workbench_prepass_vert_glsl); + + char *str = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); + return str; } static char *workbench_build_forward_transparent_accum_frag(void) { - DynStr *ds = BLI_dynstr_new(); + DynStr *ds = BLI_dynstr_new(); - BLI_dynstr_append(ds, datatoc_workbench_data_lib_glsl); - BLI_dynstr_append(ds, datatoc_workbench_common_lib_glsl); - BLI_dynstr_append(ds, datatoc_workbench_world_light_lib_glsl); - BLI_dynstr_append(ds, datatoc_workbench_forward_transparent_accum_frag_glsl); + BLI_dynstr_append(ds, datatoc_workbench_data_lib_glsl); + BLI_dynstr_append(ds, datatoc_workbench_common_lib_glsl); + BLI_dynstr_append(ds, datatoc_workbench_world_light_lib_glsl); + BLI_dynstr_append(ds, datatoc_workbench_forward_transparent_accum_frag_glsl); - char *str = BLI_dynstr_get_cstring(ds); - BLI_dynstr_free(ds); - return str; + char *str = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); + return str; } static char *workbench_build_forward_composite_frag(void) { - DynStr *ds = BLI_dynstr_new(); - - BLI_dynstr_append(ds, datatoc_workbench_data_lib_glsl); - BLI_dynstr_append(ds, datatoc_workbench_common_lib_glsl); - BLI_dynstr_append(ds, datatoc_workbench_background_lib_glsl); - BLI_dynstr_append(ds, datatoc_workbench_object_outline_lib_glsl); - BLI_dynstr_append(ds, datatoc_workbench_curvature_lib_glsl); - BLI_dynstr_append(ds, datatoc_workbench_forward_composite_frag_glsl); - - char *str = BLI_dynstr_get_cstring(ds); - BLI_dynstr_free(ds); - return str; + DynStr *ds = BLI_dynstr_new(); + + BLI_dynstr_append(ds, datatoc_workbench_data_lib_glsl); + BLI_dynstr_append(ds, datatoc_workbench_common_lib_glsl); + BLI_dynstr_append(ds, datatoc_workbench_background_lib_glsl); + BLI_dynstr_append(ds, datatoc_workbench_object_outline_lib_glsl); + BLI_dynstr_append(ds, datatoc_workbench_curvature_lib_glsl); + BLI_dynstr_append(ds, datatoc_workbench_forward_composite_frag_glsl); + + char *str = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); + return str; } static void workbench_init_object_data(DrawData *dd) { - WORKBENCH_ObjectData *data = (WORKBENCH_ObjectData *)dd; - data->object_id = ((e_data.next_object_id++) & 0xff) + 1; + WORKBENCH_ObjectData *data = (WORKBENCH_ObjectData *)dd; + data->object_id = ((e_data.next_object_id++) & 0xff) + 1; } -WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data( - WORKBENCH_Data *vedata, Object *ob, Material *mat, Image *ima, ImageUser *iuser, int color_type, int interp) +WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_Data *vedata, + Object *ob, + Material *mat, + Image *ima, + ImageUser *iuser, + int color_type, + int interp) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - WORKBENCH_FORWARD_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; - WORKBENCH_StorageList *stl = vedata->stl; - WORKBENCH_PassList *psl = vedata->psl; - WORKBENCH_PrivateData *wpd = stl->g_data; - WORKBENCH_MaterialData *material; - WORKBENCH_ObjectData *engine_object_data = (WORKBENCH_ObjectData *)DRW_drawdata_ensure( - &ob->id, &draw_engine_workbench_solid, sizeof(WORKBENCH_ObjectData), &workbench_init_object_data, NULL); - WORKBENCH_MaterialData material_template; - DRWShadingGroup *grp; - - /* Solid */ - workbench_material_update_data(wpd, ob, mat, &material_template); - material_template.object_id = OBJECT_ID_PASS_ENABLED(wpd) ? engine_object_data->object_id : 1; - material_template.color_type = color_type; - material_template.ima = ima; - material_template.iuser = iuser; - material_template.interp = interp; - uint hash = workbench_material_get_hash(&material_template, false); - - material = BLI_ghash_lookup(wpd->material_transp_hash, POINTER_FROM_UINT(hash)); - if (material == NULL) { - material = MEM_mallocN(sizeof(WORKBENCH_MaterialData), __func__); - - /* transparent accum */ - grp = DRW_shgroup_create( - color_type == V3D_SHADING_TEXTURE_COLOR ? wpd->transparent_accum_texture_sh: wpd->transparent_accum_sh, - psl->transparent_accum_pass); - DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo); - DRW_shgroup_uniform_float_copy(grp, "alpha", wpd->shading.xray_alpha); - DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)wpd->viewvecs, 3); - workbench_material_copy(material, &material_template); - if (STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) { - BKE_studiolight_ensure_flag(wpd->studio_light, STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE); - DRW_shgroup_uniform_texture(grp, "matcapImage", wpd->studio_light->equirect_radiance_gputexture ); - } - if (SPECULAR_HIGHLIGHT_ENABLED(wpd) || MATCAP_ENABLED(wpd)) { - DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); - } - if (SHADOW_ENABLED(wpd)) { - DRW_shgroup_uniform_float_copy(grp, "shadowMultiplier", wpd->shadow_multiplier); - DRW_shgroup_uniform_float_copy(grp, "shadowShift", wpd->shadow_shift); - DRW_shgroup_uniform_float_copy(grp, "shadowFocus", wpd->shadow_focus); - } - - workbench_material_shgroup_uniform(wpd, grp, material, ob, false, false, interp); - material->shgrp = grp; - - /* Depth */ - if (workbench_material_determine_color_type(wpd, material->ima, ob) == V3D_SHADING_TEXTURE_COLOR) { - material->shgrp_object_outline = DRW_shgroup_create( - sh_data->object_outline_texture_sh, psl->object_outline_pass); - GPUTexture *tex = GPU_texture_from_blender(material->ima, material->iuser, GL_TEXTURE_2D, false); - DRW_shgroup_uniform_texture(material->shgrp_object_outline, "image", tex); - } - else { - material->shgrp_object_outline = DRW_shgroup_create( - sh_data->object_outline_sh, psl->object_outline_pass); - } - material->object_id = engine_object_data->object_id; - DRW_shgroup_uniform_int(material->shgrp_object_outline, "object_id", &material->object_id, 1); - if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_shgroup_world_clip_planes_from_rv3d(material->shgrp_object_outline, draw_ctx->rv3d); - } - BLI_ghash_insert(wpd->material_transp_hash, POINTER_FROM_UINT(hash), material); - } - return material; + const DRWContextState *draw_ctx = DRW_context_state_get(); + WORKBENCH_FORWARD_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_PassList *psl = vedata->psl; + WORKBENCH_PrivateData *wpd = stl->g_data; + WORKBENCH_MaterialData *material; + WORKBENCH_ObjectData *engine_object_data = (WORKBENCH_ObjectData *)DRW_drawdata_ensure( + &ob->id, + &draw_engine_workbench_solid, + sizeof(WORKBENCH_ObjectData), + &workbench_init_object_data, + NULL); + WORKBENCH_MaterialData material_template; + DRWShadingGroup *grp; + + /* Solid */ + workbench_material_update_data(wpd, ob, mat, &material_template); + material_template.object_id = OBJECT_ID_PASS_ENABLED(wpd) ? engine_object_data->object_id : 1; + material_template.color_type = color_type; + material_template.ima = ima; + material_template.iuser = iuser; + material_template.interp = interp; + uint hash = workbench_material_get_hash(&material_template, false); + + material = BLI_ghash_lookup(wpd->material_transp_hash, POINTER_FROM_UINT(hash)); + if (material == NULL) { + material = MEM_mallocN(sizeof(WORKBENCH_MaterialData), __func__); + + /* transparent accum */ + grp = DRW_shgroup_create(color_type == V3D_SHADING_TEXTURE_COLOR ? + wpd->transparent_accum_texture_sh : + wpd->transparent_accum_sh, + psl->transparent_accum_pass); + DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo); + DRW_shgroup_uniform_float_copy(grp, "alpha", wpd->shading.xray_alpha); + DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)wpd->viewvecs, 3); + workbench_material_copy(material, &material_template); + if (STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) { + BKE_studiolight_ensure_flag(wpd->studio_light, STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE); + DRW_shgroup_uniform_texture( + grp, "matcapImage", wpd->studio_light->equirect_radiance_gputexture); + } + if (SPECULAR_HIGHLIGHT_ENABLED(wpd) || MATCAP_ENABLED(wpd)) { + DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); + } + if (SHADOW_ENABLED(wpd)) { + DRW_shgroup_uniform_float_copy(grp, "shadowMultiplier", wpd->shadow_multiplier); + DRW_shgroup_uniform_float_copy(grp, "shadowShift", wpd->shadow_shift); + DRW_shgroup_uniform_float_copy(grp, "shadowFocus", wpd->shadow_focus); + } + + workbench_material_shgroup_uniform(wpd, grp, material, ob, false, false, interp); + material->shgrp = grp; + + /* Depth */ + if (workbench_material_determine_color_type(wpd, material->ima, ob) == + V3D_SHADING_TEXTURE_COLOR) { + material->shgrp_object_outline = DRW_shgroup_create(sh_data->object_outline_texture_sh, + psl->object_outline_pass); + GPUTexture *tex = GPU_texture_from_blender( + material->ima, material->iuser, GL_TEXTURE_2D, false); + DRW_shgroup_uniform_texture(material->shgrp_object_outline, "image", tex); + } + else { + material->shgrp_object_outline = DRW_shgroup_create(sh_data->object_outline_sh, + psl->object_outline_pass); + } + material->object_id = engine_object_data->object_id; + DRW_shgroup_uniform_int(material->shgrp_object_outline, "object_id", &material->object_id, 1); + if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { + DRW_shgroup_world_clip_planes_from_rv3d(material->shgrp_object_outline, draw_ctx->rv3d); + } + BLI_ghash_insert(wpd->material_transp_hash, POINTER_FROM_UINT(hash), material); + } + return material; } -static GPUShader *ensure_forward_accum_shaders( - WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair, eGPUShaderConfig sh_cfg) +static GPUShader *ensure_forward_accum_shaders(WORKBENCH_PrivateData *wpd, + bool use_textures, + bool is_hair, + eGPUShaderConfig sh_cfg) { - WORKBENCH_FORWARD_Shaders *sh_data = &e_data.sh_data[sh_cfg]; - int index = workbench_material_get_accum_shader_index(wpd, use_textures, is_hair); - if (sh_data->transparent_accum_sh_cache[index] == NULL) { - const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg]; - char *defines = workbench_material_build_defines(wpd, use_textures, is_hair); - char *transparent_accum_vert = workbench_build_forward_vert(is_hair); - char *transparent_accum_frag = workbench_build_forward_transparent_accum_frag(); - sh_data->transparent_accum_sh_cache[index] = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, transparent_accum_vert, NULL}, - .frag = (const char *[]){transparent_accum_frag, NULL}, - .defs = (const char *[]){sh_cfg_data->def, defines, NULL}, - }); - MEM_freeN(transparent_accum_vert); - MEM_freeN(transparent_accum_frag); - MEM_freeN(defines); - } - return sh_data->transparent_accum_sh_cache[index]; + WORKBENCH_FORWARD_Shaders *sh_data = &e_data.sh_data[sh_cfg]; + int index = workbench_material_get_accum_shader_index(wpd, use_textures, is_hair); + if (sh_data->transparent_accum_sh_cache[index] == NULL) { + const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg]; + char *defines = workbench_material_build_defines(wpd, use_textures, is_hair); + char *transparent_accum_vert = workbench_build_forward_vert(is_hair); + char *transparent_accum_frag = workbench_build_forward_transparent_accum_frag(); + sh_data->transparent_accum_sh_cache[index] = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, transparent_accum_vert, NULL}, + .frag = (const char *[]){transparent_accum_frag, NULL}, + .defs = (const char *[]){sh_cfg_data->def, defines, NULL}, + }); + MEM_freeN(transparent_accum_vert); + MEM_freeN(transparent_accum_frag); + MEM_freeN(defines); + } + return sh_data->transparent_accum_sh_cache[index]; } static GPUShader *ensure_forward_composite_shaders(WORKBENCH_PrivateData *wpd) { - int index = OBJECT_OUTLINE_ENABLED(wpd) ? 1 : 0; - if (e_data.composite_sh_cache[index] == NULL) { - char *defines = workbench_material_build_defines(wpd, false, false); - char *composite_frag = workbench_build_forward_composite_frag(); - e_data.composite_sh_cache[index] = DRW_shader_create_fullscreen(composite_frag, defines); - MEM_freeN(composite_frag); - MEM_freeN(defines); - } - return e_data.composite_sh_cache[index]; + int index = OBJECT_OUTLINE_ENABLED(wpd) ? 1 : 0; + if (e_data.composite_sh_cache[index] == NULL) { + char *defines = workbench_material_build_defines(wpd, false, false); + char *composite_frag = workbench_build_forward_composite_frag(); + e_data.composite_sh_cache[index] = DRW_shader_create_fullscreen(composite_frag, defines); + MEM_freeN(composite_frag); + MEM_freeN(defines); + } + return e_data.composite_sh_cache[index]; } void workbench_forward_choose_shaders(WORKBENCH_PrivateData *wpd, eGPUShaderConfig sh_cfg) { - wpd->composite_sh = ensure_forward_composite_shaders(wpd); - wpd->transparent_accum_sh = ensure_forward_accum_shaders(wpd, false, false, sh_cfg); - wpd->transparent_accum_hair_sh = ensure_forward_accum_shaders(wpd, false, true, sh_cfg); - wpd->transparent_accum_texture_sh = ensure_forward_accum_shaders(wpd, true, false, sh_cfg); - wpd->transparent_accum_texture_hair_sh = ensure_forward_accum_shaders(wpd, true, true, sh_cfg); + wpd->composite_sh = ensure_forward_composite_shaders(wpd); + wpd->transparent_accum_sh = ensure_forward_accum_shaders(wpd, false, false, sh_cfg); + wpd->transparent_accum_hair_sh = ensure_forward_accum_shaders(wpd, false, true, sh_cfg); + wpd->transparent_accum_texture_sh = ensure_forward_accum_shaders(wpd, true, false, sh_cfg); + wpd->transparent_accum_texture_hair_sh = ensure_forward_accum_shaders(wpd, true, true, sh_cfg); } void workbench_forward_outline_shaders_ensure(WORKBENCH_PrivateData *wpd, eGPUShaderConfig sh_cfg) { - WORKBENCH_FORWARD_Shaders *sh_data = &e_data.sh_data[sh_cfg]; - - if (sh_data->object_outline_sh == NULL) { - const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg]; - char *defines = workbench_material_build_defines(wpd, false, false); - char *defines_texture = workbench_material_build_defines(wpd, true, false); - char *defines_hair = workbench_material_build_defines(wpd, false, true); - char *forward_vert = workbench_build_forward_vert(false); - char *forward_hair_vert = workbench_build_forward_vert(true); - - sh_data->object_outline_sh = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, forward_vert, NULL}, - .frag = (const char *[]){datatoc_workbench_forward_depth_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, defines, NULL}, - }); - sh_data->object_outline_texture_sh = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, forward_vert, NULL}, - .frag = (const char *[]){datatoc_workbench_forward_depth_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, defines_texture, NULL}, - }); - sh_data->object_outline_hair_sh = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, forward_hair_vert, NULL}, - .frag = (const char *[]){datatoc_workbench_forward_depth_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, defines_hair, NULL}, - }); - - MEM_freeN(forward_hair_vert); - MEM_freeN(forward_vert); - MEM_freeN(defines); - MEM_freeN(defines_texture); - MEM_freeN(defines_hair); - } + WORKBENCH_FORWARD_Shaders *sh_data = &e_data.sh_data[sh_cfg]; + + if (sh_data->object_outline_sh == NULL) { + const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg]; + char *defines = workbench_material_build_defines(wpd, false, false); + char *defines_texture = workbench_material_build_defines(wpd, true, false); + char *defines_hair = workbench_material_build_defines(wpd, false, true); + char *forward_vert = workbench_build_forward_vert(false); + char *forward_hair_vert = workbench_build_forward_vert(true); + + sh_data->object_outline_sh = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, forward_vert, NULL}, + .frag = (const char *[]){datatoc_workbench_forward_depth_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, defines, NULL}, + }); + sh_data->object_outline_texture_sh = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, forward_vert, NULL}, + .frag = (const char *[]){datatoc_workbench_forward_depth_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, defines_texture, NULL}, + }); + sh_data->object_outline_hair_sh = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, forward_hair_vert, NULL}, + .frag = (const char *[]){datatoc_workbench_forward_depth_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, defines_hair, NULL}, + }); + + MEM_freeN(forward_hair_vert); + MEM_freeN(forward_vert); + MEM_freeN(defines); + MEM_freeN(defines_texture); + MEM_freeN(defines_hair); + } } /* public functions */ void workbench_forward_engine_init(WORKBENCH_Data *vedata) { - WORKBENCH_FramebufferList *fbl = vedata->fbl; - WORKBENCH_PassList *psl = vedata->psl; - WORKBENCH_StorageList *stl = vedata->stl; - DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - const DRWContextState *draw_ctx = DRW_context_state_get(); - DRWShadingGroup *grp; - - if (!stl->g_data) { - /* Alloc transient pointers */ - stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__); - } - if (!stl->effects) { - stl->effects = MEM_callocN(sizeof(*stl->effects), __func__); - workbench_effect_info_init(stl->effects); - } - WORKBENCH_PrivateData *wpd = stl->g_data; - workbench_private_data_init(wpd); - float light_direction[3]; - workbench_private_data_get_light_direction(wpd, light_direction); - - if (!e_data.checker_depth_sh) { - e_data.checker_depth_sh = DRW_shader_create_fullscreen( - datatoc_workbench_checkerboard_depth_frag_glsl, NULL); - } - - workbench_forward_outline_shaders_ensure(wpd, draw_ctx->sh_cfg); - - workbench_volume_engine_init(); - workbench_fxaa_engine_init(); - workbench_taa_engine_init(vedata); - - workbench_forward_outline_shaders_ensure(wpd, draw_ctx->sh_cfg); - workbench_forward_choose_shaders(wpd, draw_ctx->sh_cfg); - - const float *viewport_size = DRW_viewport_size_get(); - const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; - const eGPUTextureFormat comp_tex_format = DRW_state_is_image_render() ? GPU_RGBA16F : GPU_R11F_G11F_B10F; - - e_data.object_id_tx = DRW_texture_pool_query_2d( - size[0], size[1], GPU_R32UI, &draw_engine_workbench_transparent); - e_data.transparent_accum_tx = DRW_texture_pool_query_2d( - size[0], size[1], GPU_RGBA16F, &draw_engine_workbench_transparent); - e_data.transparent_revealage_tx = DRW_texture_pool_query_2d( - size[0], size[1], GPU_R16F, &draw_engine_workbench_transparent); - e_data.composite_buffer_tx = DRW_texture_pool_query_2d( - size[0], size[1], comp_tex_format, &draw_engine_workbench_transparent); - - GPU_framebuffer_ensure_config(&fbl->object_outline_fb, { - GPU_ATTACHMENT_TEXTURE(dtxl->depth), - GPU_ATTACHMENT_TEXTURE(e_data.object_id_tx), - }); - GPU_framebuffer_ensure_config(&fbl->transparent_accum_fb, { - GPU_ATTACHMENT_NONE, - GPU_ATTACHMENT_TEXTURE(e_data.transparent_accum_tx), - GPU_ATTACHMENT_TEXTURE(e_data.transparent_revealage_tx), - }); - GPU_framebuffer_ensure_config(&fbl->composite_fb, { - GPU_ATTACHMENT_NONE, - GPU_ATTACHMENT_TEXTURE(e_data.composite_buffer_tx), - }); - GPU_framebuffer_ensure_config(&fbl->effect_fb, { - GPU_ATTACHMENT_NONE, - GPU_ATTACHMENT_TEXTURE(e_data.transparent_accum_tx), - }); - - workbench_volume_cache_init(vedata); - const bool do_cull = CULL_BACKFACE_ENABLED(wpd); - const int cull_state = (do_cull) ? DRW_STATE_CULL_BACK : 0; - - /* Transparency Accum */ - { - int state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_OIT | cull_state; - psl->transparent_accum_pass = DRW_pass_create("Transparent Accum", state); - } - /* Depth */ - { - int state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | cull_state; - psl->object_outline_pass = DRW_pass_create("Object Outline Pass", state); - } - /* Composite */ - { - int state = DRW_STATE_WRITE_COLOR; - psl->composite_pass = DRW_pass_create("Composite", state); - - grp = DRW_shgroup_create(wpd->composite_sh, psl->composite_pass); - if (OBJECT_ID_PASS_ENABLED(wpd)) { - DRW_shgroup_uniform_texture_ref(grp, "objectId", &e_data.object_id_tx); - } - DRW_shgroup_uniform_texture_ref(grp, "transparentAccum", &e_data.transparent_accum_tx); - DRW_shgroup_uniform_texture_ref(grp, "transparentRevealage", &e_data.transparent_revealage_tx); - DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo); - DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); - DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); - } - - /* TODO(campbell): displays but masks geometry, - * only use with wire or solid-without-xray for now. */ - if ((wpd->shading.type != OB_WIRE && !XRAY_FLAG_ENABLED(wpd)) && - (draw_ctx->rv3d && (draw_ctx->rv3d->rflag & RV3D_CLIPPING) && draw_ctx->rv3d->clipbb)) - { - psl->background_pass = DRW_pass_create( - "Background", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL); - GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR_BACKGROUND); - grp = DRW_shgroup_create(shader, psl->background_pass); - wpd->world_clip_planes_batch = DRW_draw_background_clipping_batch_from_rv3d(draw_ctx->rv3d); - DRW_shgroup_call_add(grp, wpd->world_clip_planes_batch, NULL); - DRW_shgroup_uniform_vec4(grp, "color", &wpd->world_clip_planes_color[0], 1); - } - - { - workbench_aa_create_pass(vedata, &e_data.transparent_accum_tx); - } - - /* Checker Depth */ - { - static float noise_offset = 0.0f; - float blend_threshold = 0.0f; - - if (DRW_state_is_image_render()) { - /* TODO: Should be based on the number of samples used for render. */ - noise_offset = fmodf(noise_offset + 1.0f / 8.0f, 1.0f); - } - - if (XRAY_FLAG_ENABLED(wpd)) { - blend_threshold = 1.0f - XRAY_ALPHA(wpd) * 0.9f; - } - - if (wpd->shading.type == OB_WIRE) { - wpd->shading.xray_alpha = 0.0f; - wpd->shading.xray_alpha_wire = 0.0f; - } - - int state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS; - psl->checker_depth_pass = DRW_pass_create("Checker Depth", state); - grp = DRW_shgroup_create(e_data.checker_depth_sh, psl->checker_depth_pass); - DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); - DRW_shgroup_uniform_float_copy(grp, "threshold", blend_threshold); - DRW_shgroup_uniform_float_copy(grp, "offset", noise_offset); - } + WORKBENCH_FramebufferList *fbl = vedata->fbl; + WORKBENCH_PassList *psl = vedata->psl; + WORKBENCH_StorageList *stl = vedata->stl; + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + const DRWContextState *draw_ctx = DRW_context_state_get(); + DRWShadingGroup *grp; + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__); + } + if (!stl->effects) { + stl->effects = MEM_callocN(sizeof(*stl->effects), __func__); + workbench_effect_info_init(stl->effects); + } + WORKBENCH_PrivateData *wpd = stl->g_data; + workbench_private_data_init(wpd); + float light_direction[3]; + workbench_private_data_get_light_direction(wpd, light_direction); + + if (!e_data.checker_depth_sh) { + e_data.checker_depth_sh = DRW_shader_create_fullscreen( + datatoc_workbench_checkerboard_depth_frag_glsl, NULL); + } + + workbench_forward_outline_shaders_ensure(wpd, draw_ctx->sh_cfg); + + workbench_volume_engine_init(); + workbench_fxaa_engine_init(); + workbench_taa_engine_init(vedata); + + workbench_forward_outline_shaders_ensure(wpd, draw_ctx->sh_cfg); + workbench_forward_choose_shaders(wpd, draw_ctx->sh_cfg); + + const float *viewport_size = DRW_viewport_size_get(); + const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; + const eGPUTextureFormat comp_tex_format = DRW_state_is_image_render() ? GPU_RGBA16F : + GPU_R11F_G11F_B10F; + + e_data.object_id_tx = DRW_texture_pool_query_2d( + size[0], size[1], GPU_R32UI, &draw_engine_workbench_transparent); + e_data.transparent_accum_tx = DRW_texture_pool_query_2d( + size[0], size[1], GPU_RGBA16F, &draw_engine_workbench_transparent); + e_data.transparent_revealage_tx = DRW_texture_pool_query_2d( + size[0], size[1], GPU_R16F, &draw_engine_workbench_transparent); + e_data.composite_buffer_tx = DRW_texture_pool_query_2d( + size[0], size[1], comp_tex_format, &draw_engine_workbench_transparent); + + GPU_framebuffer_ensure_config(&fbl->object_outline_fb, + { + GPU_ATTACHMENT_TEXTURE(dtxl->depth), + GPU_ATTACHMENT_TEXTURE(e_data.object_id_tx), + }); + GPU_framebuffer_ensure_config(&fbl->transparent_accum_fb, + { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(e_data.transparent_accum_tx), + GPU_ATTACHMENT_TEXTURE(e_data.transparent_revealage_tx), + }); + GPU_framebuffer_ensure_config(&fbl->composite_fb, + { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(e_data.composite_buffer_tx), + }); + GPU_framebuffer_ensure_config(&fbl->effect_fb, + { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(e_data.transparent_accum_tx), + }); + + workbench_volume_cache_init(vedata); + const bool do_cull = CULL_BACKFACE_ENABLED(wpd); + const int cull_state = (do_cull) ? DRW_STATE_CULL_BACK : 0; + + /* Transparency Accum */ + { + int state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_OIT | cull_state; + psl->transparent_accum_pass = DRW_pass_create("Transparent Accum", state); + } + /* Depth */ + { + int state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | cull_state; + psl->object_outline_pass = DRW_pass_create("Object Outline Pass", state); + } + /* Composite */ + { + int state = DRW_STATE_WRITE_COLOR; + psl->composite_pass = DRW_pass_create("Composite", state); + + grp = DRW_shgroup_create(wpd->composite_sh, psl->composite_pass); + if (OBJECT_ID_PASS_ENABLED(wpd)) { + DRW_shgroup_uniform_texture_ref(grp, "objectId", &e_data.object_id_tx); + } + DRW_shgroup_uniform_texture_ref(grp, "transparentAccum", &e_data.transparent_accum_tx); + DRW_shgroup_uniform_texture_ref(grp, "transparentRevealage", &e_data.transparent_revealage_tx); + DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo); + DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + } + + /* TODO(campbell): displays but masks geometry, + * only use with wire or solid-without-xray for now. */ + if ((wpd->shading.type != OB_WIRE && !XRAY_FLAG_ENABLED(wpd)) && + (draw_ctx->rv3d && (draw_ctx->rv3d->rflag & RV3D_CLIPPING) && draw_ctx->rv3d->clipbb)) { + psl->background_pass = DRW_pass_create("Background", + DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL); + GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR_BACKGROUND); + grp = DRW_shgroup_create(shader, psl->background_pass); + wpd->world_clip_planes_batch = DRW_draw_background_clipping_batch_from_rv3d(draw_ctx->rv3d); + DRW_shgroup_call_add(grp, wpd->world_clip_planes_batch, NULL); + DRW_shgroup_uniform_vec4(grp, "color", &wpd->world_clip_planes_color[0], 1); + } + + { + workbench_aa_create_pass(vedata, &e_data.transparent_accum_tx); + } + + /* Checker Depth */ + { + static float noise_offset = 0.0f; + float blend_threshold = 0.0f; + + if (DRW_state_is_image_render()) { + /* TODO: Should be based on the number of samples used for render. */ + noise_offset = fmodf(noise_offset + 1.0f / 8.0f, 1.0f); + } + + if (XRAY_FLAG_ENABLED(wpd)) { + blend_threshold = 1.0f - XRAY_ALPHA(wpd) * 0.9f; + } + + if (wpd->shading.type == OB_WIRE) { + wpd->shading.xray_alpha = 0.0f; + wpd->shading.xray_alpha_wire = 0.0f; + } + + int state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS; + psl->checker_depth_pass = DRW_pass_create("Checker Depth", state); + grp = DRW_shgroup_create(e_data.checker_depth_sh, psl->checker_depth_pass); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + DRW_shgroup_uniform_float_copy(grp, "threshold", blend_threshold); + DRW_shgroup_uniform_float_copy(grp, "offset", noise_offset); + } } void workbench_forward_engine_free() { - for (int sh_data_index = 0; sh_data_index < ARRAY_SIZE(e_data.sh_data); sh_data_index++) { - WORKBENCH_FORWARD_Shaders *sh_data = &e_data.sh_data[sh_data_index]; - for (int index = 0; index < MAX_ACCUM_SHADERS; index++) { - DRW_SHADER_FREE_SAFE(sh_data->transparent_accum_sh_cache[index]); - } - DRW_SHADER_FREE_SAFE(sh_data->object_outline_sh); - DRW_SHADER_FREE_SAFE(sh_data->object_outline_texture_sh); - DRW_SHADER_FREE_SAFE(sh_data->object_outline_hair_sh); - } - - for (int index = 0; index < 2; index++) { - DRW_SHADER_FREE_SAFE(e_data.composite_sh_cache[index]); - } - DRW_SHADER_FREE_SAFE(e_data.checker_depth_sh); - - workbench_volume_engine_free(); - workbench_fxaa_engine_free(); - workbench_taa_engine_free(); - workbench_dof_engine_free(); + for (int sh_data_index = 0; sh_data_index < ARRAY_SIZE(e_data.sh_data); sh_data_index++) { + WORKBENCH_FORWARD_Shaders *sh_data = &e_data.sh_data[sh_data_index]; + for (int index = 0; index < MAX_ACCUM_SHADERS; index++) { + DRW_SHADER_FREE_SAFE(sh_data->transparent_accum_sh_cache[index]); + } + DRW_SHADER_FREE_SAFE(sh_data->object_outline_sh); + DRW_SHADER_FREE_SAFE(sh_data->object_outline_texture_sh); + DRW_SHADER_FREE_SAFE(sh_data->object_outline_hair_sh); + } + + for (int index = 0; index < 2; index++) { + DRW_SHADER_FREE_SAFE(e_data.composite_sh_cache[index]); + } + DRW_SHADER_FREE_SAFE(e_data.checker_depth_sh); + + workbench_volume_engine_free(); + workbench_fxaa_engine_free(); + workbench_taa_engine_free(); + workbench_dof_engine_free(); } void workbench_forward_cache_init(WORKBENCH_Data *UNUSED(vedata)) @@ -457,179 +475,180 @@ void workbench_forward_cache_init(WORKBENCH_Data *UNUSED(vedata)) static void workbench_forward_cache_populate_particles(WORKBENCH_Data *vedata, Object *ob) { - WORKBENCH_StorageList *stl = vedata->stl; - WORKBENCH_PassList *psl = vedata->psl; - WORKBENCH_PrivateData *wpd = stl->g_data; - - for (ModifierData *md = ob->modifiers.first; md; md = md->next) { - if (md->type != eModifierType_ParticleSystem) { - continue; - } - ParticleSystem *psys = ((ParticleSystemModifierData *)md)->psys; - if (!DRW_object_is_visible_psys_in_active_context(ob, psys)) { - continue; - } - ParticleSettings *part = psys->part; - const int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as; - - if (draw_as == PART_DRAW_PATH) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - Material *mat; - Image *image; - ImageUser *iuser; - int interp; - workbench_material_get_image_and_mat(ob, part->omat, &image, &iuser, &interp, &mat); - int color_type = workbench_material_determine_color_type(wpd, image, ob); - WORKBENCH_MaterialData *material = workbench_forward_get_or_create_material_data(vedata, ob, mat, image, iuser, color_type, interp); - - struct GPUShader *shader = (color_type != V3D_SHADING_TEXTURE_COLOR) - ? wpd->transparent_accum_hair_sh - : wpd->transparent_accum_texture_hair_sh; - DRWShadingGroup *shgrp = DRW_shgroup_hair_create( - ob, psys, md, - psl->transparent_accum_pass, - shader); - DRW_shgroup_uniform_block(shgrp, "world_block", wpd->world_ubo); - workbench_material_shgroup_uniform(wpd, shgrp, material, ob, false, false, interp); - DRW_shgroup_uniform_vec4(shgrp, "viewvecs[0]", (float *)wpd->viewvecs, 3); - /* Hairs have lots of layer and can rapidly become the most prominent surface. - * So lower their alpha artificially. */ - float hair_alpha = XRAY_ALPHA(wpd) * 0.33f; - DRW_shgroup_uniform_float_copy(shgrp, "alpha", hair_alpha); - if (STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) { - BKE_studiolight_ensure_flag(wpd->studio_light, STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE); - DRW_shgroup_uniform_texture(shgrp, "matcapImage", wpd->studio_light->equirect_radiance_gputexture ); - } - if (SPECULAR_HIGHLIGHT_ENABLED(wpd) || MATCAP_ENABLED(wpd)) { - DRW_shgroup_uniform_vec2(shgrp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); - } - - WORKBENCH_FORWARD_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; - shgrp = DRW_shgroup_hair_create( - ob, psys, md, - vedata->psl->object_outline_pass, - sh_data->object_outline_hair_sh); - DRW_shgroup_uniform_int(shgrp, "object_id", &material->object_id, 1); - } - } + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_PassList *psl = vedata->psl; + WORKBENCH_PrivateData *wpd = stl->g_data; + + for (ModifierData *md = ob->modifiers.first; md; md = md->next) { + if (md->type != eModifierType_ParticleSystem) { + continue; + } + ParticleSystem *psys = ((ParticleSystemModifierData *)md)->psys; + if (!DRW_object_is_visible_psys_in_active_context(ob, psys)) { + continue; + } + ParticleSettings *part = psys->part; + const int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as; + + if (draw_as == PART_DRAW_PATH) { + const DRWContextState *draw_ctx = DRW_context_state_get(); + Material *mat; + Image *image; + ImageUser *iuser; + int interp; + workbench_material_get_image_and_mat(ob, part->omat, &image, &iuser, &interp, &mat); + int color_type = workbench_material_determine_color_type(wpd, image, ob); + WORKBENCH_MaterialData *material = workbench_forward_get_or_create_material_data( + vedata, ob, mat, image, iuser, color_type, interp); + + struct GPUShader *shader = (color_type != V3D_SHADING_TEXTURE_COLOR) ? + wpd->transparent_accum_hair_sh : + wpd->transparent_accum_texture_hair_sh; + DRWShadingGroup *shgrp = DRW_shgroup_hair_create( + ob, psys, md, psl->transparent_accum_pass, shader); + DRW_shgroup_uniform_block(shgrp, "world_block", wpd->world_ubo); + workbench_material_shgroup_uniform(wpd, shgrp, material, ob, false, false, interp); + DRW_shgroup_uniform_vec4(shgrp, "viewvecs[0]", (float *)wpd->viewvecs, 3); + /* Hairs have lots of layer and can rapidly become the most prominent surface. + * So lower their alpha artificially. */ + float hair_alpha = XRAY_ALPHA(wpd) * 0.33f; + DRW_shgroup_uniform_float_copy(shgrp, "alpha", hair_alpha); + if (STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) { + BKE_studiolight_ensure_flag(wpd->studio_light, STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE); + DRW_shgroup_uniform_texture( + shgrp, "matcapImage", wpd->studio_light->equirect_radiance_gputexture); + } + if (SPECULAR_HIGHLIGHT_ENABLED(wpd) || MATCAP_ENABLED(wpd)) { + DRW_shgroup_uniform_vec2(shgrp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); + } + + WORKBENCH_FORWARD_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; + shgrp = DRW_shgroup_hair_create( + ob, psys, md, vedata->psl->object_outline_pass, sh_data->object_outline_hair_sh); + DRW_shgroup_uniform_int(shgrp, "object_id", &material->object_id, 1); + } + } } void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob) { - WORKBENCH_StorageList *stl = vedata->stl; - WORKBENCH_PrivateData *wpd = stl->g_data; - const DRWContextState *draw_ctx = DRW_context_state_get(); - Scene *scene = draw_ctx->scene; - const bool is_wire = (ob->dt == OB_WIRE); - - if (!DRW_object_is_renderable(ob)) { - return; - } - - if (ob->type == OB_MESH) { - workbench_forward_cache_populate_particles(vedata, ob); - } - - ModifierData *md; - if (((ob->base_flag & BASE_FROM_DUPLI) == 0) && - (md = modifiers_findByType(ob, eModifierType_Smoke)) && - (modifier_isEnabled(scene, md, eModifierMode_Realtime)) && - (((SmokeModifierData *)md)->domain != NULL)) - { - workbench_volume_cache_populate(vedata, scene, ob, md); - return; /* Do not draw solid in this case. */ - } - - if (!(DRW_object_visibility_in_active_context(ob) & OB_VISIBLE_SELF)) { - return; - } - if (ob->dt < OB_WIRE) { - return; - } - - WORKBENCH_MaterialData *material; - if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) { - const bool is_active = (ob == draw_ctx->obact); - const bool is_sculpt_mode = is_active && (draw_ctx->object_mode & OB_MODE_SCULPT) != 0; - bool is_drawn = false; - - if (!is_sculpt_mode && TEXTURE_DRAWING_ENABLED(wpd) && ELEM(ob->type, OB_MESH)) { - const Mesh *me = ob->data; - if (me->mloopuv) { - const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol)); - struct GPUBatch **geom_array = DRW_cache_mesh_surface_texpaint_get(ob); - for (int i = 0; i < materials_len; i++) { - Material *mat; - Image *image; - ImageUser *iuser; - int interp; - workbench_material_get_image_and_mat(ob, i + 1, &image, &iuser, &interp, &mat); - int color_type = workbench_material_determine_color_type(wpd, image, ob); - material = workbench_forward_get_or_create_material_data(vedata, ob, mat, image, iuser, color_type, interp); - DRW_shgroup_call_object_add(material->shgrp_object_outline, geom_array[i], ob); - DRW_shgroup_call_object_add(material->shgrp, geom_array[i], ob); - } - is_drawn = true; - } - } - - /* Fallback from not drawn OB_TEXTURE mode or just OB_SOLID mode */ - if (!is_drawn) { - if (ELEM(wpd->shading.color_type, - V3D_SHADING_SINGLE_COLOR, V3D_SHADING_OBJECT_COLOR, V3D_SHADING_RANDOM_COLOR)) - { - /* No material split needed */ - struct GPUBatch *geom = DRW_cache_object_surface_get(ob); - if (geom) { - material = workbench_forward_get_or_create_material_data(vedata, ob, NULL, NULL, NULL, wpd->shading.color_type, 0); - if (is_sculpt_mode) { - DRW_shgroup_call_sculpt_add(material->shgrp_object_outline, ob, ob->obmat); - if (!is_wire) { - DRW_shgroup_call_sculpt_add(material->shgrp, ob, ob->obmat); - } - } - else { - DRW_shgroup_call_object_add(material->shgrp_object_outline, geom, ob); - if (!is_wire) { - DRW_shgroup_call_object_add(material->shgrp, geom, ob); - } - } - } - } - else { - const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol)); - struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len); - for (int i = 0; i < materials_len; i++) { - gpumat_array[i] = NULL; - } - - struct GPUBatch **mat_geom = DRW_cache_object_surface_material_get( - ob, gpumat_array, materials_len, NULL, NULL, NULL); - if (mat_geom) { - for (int i = 0; i < materials_len; ++i) { - if (mat_geom[i] == NULL) { - continue; - } - - Material *mat = give_current_material(ob, i + 1); - material = workbench_forward_get_or_create_material_data(vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0); - if (is_sculpt_mode) { - DRW_shgroup_call_sculpt_add(material->shgrp_object_outline, ob, ob->obmat); - if (!is_wire) { - DRW_shgroup_call_sculpt_add(material->shgrp, ob, ob->obmat); - } - } - else { - DRW_shgroup_call_object_add(material->shgrp_object_outline, mat_geom[i], ob); - if (!is_wire) { - DRW_shgroup_call_object_add(material->shgrp, mat_geom[i], ob); - } - } - } - } - } - } - } + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_PrivateData *wpd = stl->g_data; + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + const bool is_wire = (ob->dt == OB_WIRE); + + if (!DRW_object_is_renderable(ob)) { + return; + } + + if (ob->type == OB_MESH) { + workbench_forward_cache_populate_particles(vedata, ob); + } + + ModifierData *md; + if (((ob->base_flag & BASE_FROM_DUPLI) == 0) && + (md = modifiers_findByType(ob, eModifierType_Smoke)) && + (modifier_isEnabled(scene, md, eModifierMode_Realtime)) && + (((SmokeModifierData *)md)->domain != NULL)) { + workbench_volume_cache_populate(vedata, scene, ob, md); + return; /* Do not draw solid in this case. */ + } + + if (!(DRW_object_visibility_in_active_context(ob) & OB_VISIBLE_SELF)) { + return; + } + if (ob->dt < OB_WIRE) { + return; + } + + WORKBENCH_MaterialData *material; + if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) { + const bool is_active = (ob == draw_ctx->obact); + const bool is_sculpt_mode = is_active && (draw_ctx->object_mode & OB_MODE_SCULPT) != 0; + bool is_drawn = false; + + if (!is_sculpt_mode && TEXTURE_DRAWING_ENABLED(wpd) && ELEM(ob->type, OB_MESH)) { + const Mesh *me = ob->data; + if (me->mloopuv) { + const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol)); + struct GPUBatch **geom_array = DRW_cache_mesh_surface_texpaint_get(ob); + for (int i = 0; i < materials_len; i++) { + Material *mat; + Image *image; + ImageUser *iuser; + int interp; + workbench_material_get_image_and_mat(ob, i + 1, &image, &iuser, &interp, &mat); + int color_type = workbench_material_determine_color_type(wpd, image, ob); + material = workbench_forward_get_or_create_material_data( + vedata, ob, mat, image, iuser, color_type, interp); + DRW_shgroup_call_object_add(material->shgrp_object_outline, geom_array[i], ob); + DRW_shgroup_call_object_add(material->shgrp, geom_array[i], ob); + } + is_drawn = true; + } + } + + /* Fallback from not drawn OB_TEXTURE mode or just OB_SOLID mode */ + if (!is_drawn) { + if (ELEM(wpd->shading.color_type, + V3D_SHADING_SINGLE_COLOR, + V3D_SHADING_OBJECT_COLOR, + V3D_SHADING_RANDOM_COLOR)) { + /* No material split needed */ + struct GPUBatch *geom = DRW_cache_object_surface_get(ob); + if (geom) { + material = workbench_forward_get_or_create_material_data( + vedata, ob, NULL, NULL, NULL, wpd->shading.color_type, 0); + if (is_sculpt_mode) { + DRW_shgroup_call_sculpt_add(material->shgrp_object_outline, ob, ob->obmat); + if (!is_wire) { + DRW_shgroup_call_sculpt_add(material->shgrp, ob, ob->obmat); + } + } + else { + DRW_shgroup_call_object_add(material->shgrp_object_outline, geom, ob); + if (!is_wire) { + DRW_shgroup_call_object_add(material->shgrp, geom, ob); + } + } + } + } + else { + const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol)); + struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len); + for (int i = 0; i < materials_len; i++) { + gpumat_array[i] = NULL; + } + + struct GPUBatch **mat_geom = DRW_cache_object_surface_material_get( + ob, gpumat_array, materials_len, NULL, NULL, NULL); + if (mat_geom) { + for (int i = 0; i < materials_len; ++i) { + if (mat_geom[i] == NULL) { + continue; + } + + Material *mat = give_current_material(ob, i + 1); + material = workbench_forward_get_or_create_material_data( + vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0); + if (is_sculpt_mode) { + DRW_shgroup_call_sculpt_add(material->shgrp_object_outline, ob, ob->obmat); + if (!is_wire) { + DRW_shgroup_call_sculpt_add(material->shgrp, ob, ob->obmat); + } + } + else { + DRW_shgroup_call_object_add(material->shgrp_object_outline, mat_geom[i], ob); + if (!is_wire) { + DRW_shgroup_call_object_add(material->shgrp, mat_geom[i], ob); + } + } + } + } + } + } + } } void workbench_forward_cache_finish(WORKBENCH_Data *UNUSED(vedata)) @@ -638,69 +657,69 @@ void workbench_forward_cache_finish(WORKBENCH_Data *UNUSED(vedata)) void workbench_forward_draw_background(WORKBENCH_Data *UNUSED(vedata)) { - const float clear_depth = 1.0f; - DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); - DRW_stats_group_start("Clear depth"); - GPU_framebuffer_bind(dfbl->default_fb); - GPU_framebuffer_clear_depth(dfbl->default_fb, clear_depth); - DRW_stats_group_end(); + const float clear_depth = 1.0f; + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + DRW_stats_group_start("Clear depth"); + GPU_framebuffer_bind(dfbl->default_fb); + GPU_framebuffer_clear_depth(dfbl->default_fb, clear_depth); + DRW_stats_group_end(); } void workbench_forward_draw_scene(WORKBENCH_Data *vedata) { - WORKBENCH_PassList *psl = vedata->psl; - WORKBENCH_StorageList *stl = vedata->stl; - WORKBENCH_FramebufferList *fbl = vedata->fbl; - WORKBENCH_PrivateData *wpd = stl->g_data; - DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); - - if (TAA_ENABLED(wpd)) { - workbench_taa_draw_scene_start(vedata); - } - - /* Write Depth + Object ID */ - const float clear_outline[4] = {0.0f}; - GPU_framebuffer_bind(fbl->object_outline_fb); - GPU_framebuffer_clear_color(fbl->object_outline_fb, clear_outline); - DRW_draw_pass(psl->object_outline_pass); - - if (XRAY_ALPHA(wpd) > 0.0) { - const float clear_color[4] = {0.0f, 0.0f, 0.0f, 1.0f}; - GPU_framebuffer_bind(fbl->transparent_accum_fb); - GPU_framebuffer_clear_color(fbl->transparent_accum_fb, clear_color); - DRW_draw_pass(psl->transparent_accum_pass); - } - else { - /* TODO(fclem): this is unnecessary and takes up perf. - * Better change the composite frag shader to not use the tx. */ - const float clear_color[4] = {0.0f, 0.0f, 0.0f, 1.0f}; - GPU_framebuffer_bind(fbl->transparent_accum_fb); - GPU_framebuffer_clear_color(fbl->transparent_accum_fb, clear_color); - } - - /* Composite */ - GPU_framebuffer_bind(fbl->composite_fb); - DRW_draw_pass(psl->composite_pass); - DRW_draw_pass(psl->volume_pass); - - /* Only when clipping is enabled. */ - if (psl->background_pass) { - DRW_draw_pass(psl->background_pass); - } - - /* Color correct and Anti aliasing */ - workbench_aa_draw_pass(vedata, e_data.composite_buffer_tx); - - /* Apply checker pattern */ - GPU_framebuffer_bind(dfbl->depth_only_fb); - DRW_draw_pass(psl->checker_depth_pass); + WORKBENCH_PassList *psl = vedata->psl; + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_FramebufferList *fbl = vedata->fbl; + WORKBENCH_PrivateData *wpd = stl->g_data; + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + + if (TAA_ENABLED(wpd)) { + workbench_taa_draw_scene_start(vedata); + } + + /* Write Depth + Object ID */ + const float clear_outline[4] = {0.0f}; + GPU_framebuffer_bind(fbl->object_outline_fb); + GPU_framebuffer_clear_color(fbl->object_outline_fb, clear_outline); + DRW_draw_pass(psl->object_outline_pass); + + if (XRAY_ALPHA(wpd) > 0.0) { + const float clear_color[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + GPU_framebuffer_bind(fbl->transparent_accum_fb); + GPU_framebuffer_clear_color(fbl->transparent_accum_fb, clear_color); + DRW_draw_pass(psl->transparent_accum_pass); + } + else { + /* TODO(fclem): this is unnecessary and takes up perf. + * Better change the composite frag shader to not use the tx. */ + const float clear_color[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + GPU_framebuffer_bind(fbl->transparent_accum_fb); + GPU_framebuffer_clear_color(fbl->transparent_accum_fb, clear_color); + } + + /* Composite */ + GPU_framebuffer_bind(fbl->composite_fb); + DRW_draw_pass(psl->composite_pass); + DRW_draw_pass(psl->volume_pass); + + /* Only when clipping is enabled. */ + if (psl->background_pass) { + DRW_draw_pass(psl->background_pass); + } + + /* Color correct and Anti aliasing */ + workbench_aa_draw_pass(vedata, e_data.composite_buffer_tx); + + /* Apply checker pattern */ + GPU_framebuffer_bind(dfbl->depth_only_fb); + DRW_draw_pass(psl->checker_depth_pass); } void workbench_forward_draw_finish(WORKBENCH_Data *vedata) { - WORKBENCH_StorageList *stl = vedata->stl; - WORKBENCH_PrivateData *wpd = stl->g_data; + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_PrivateData *wpd = stl->g_data; - workbench_private_data_free(wpd); - workbench_volume_smoke_textures_free(wpd); + workbench_private_data_free(wpd); + workbench_volume_smoke_textures_free(wpd); } diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c index 2cec691a62f..d73eee37a98 100644 --- a/source/blender/draw/engines/workbench/workbench_materials.c +++ b/source/blender/draw/engines/workbench/workbench_materials.c @@ -37,260 +37,278 @@ #define HSV_SATURATION 0.5 #define HSV_VALUE 0.8 -void workbench_material_update_data(WORKBENCH_PrivateData *wpd, Object *ob, Material *mat, WORKBENCH_MaterialData *data) +void workbench_material_update_data(WORKBENCH_PrivateData *wpd, + Object *ob, + Material *mat, + WORKBENCH_MaterialData *data) { - /* When V3D_SHADING_TEXTURE_COLOR is active, use V3D_SHADING_MATERIAL_COLOR as fallback when no texture could be determined */ - int color_type = wpd->shading.color_type == V3D_SHADING_TEXTURE_COLOR ? V3D_SHADING_MATERIAL_COLOR : wpd->shading.color_type; - copy_v3_fl3(data->diffuse_color, 0.8f, 0.8f, 0.8f); - copy_v3_v3(data->base_color, data->diffuse_color); - copy_v3_fl3(data->specular_color, 0.05f, 0.05f, 0.05f); /* Dielectric: 5% reflective. */ - data->metallic = 0.0f; - data->roughness = 0.5f; /* sqrtf(0.25f); */ + /* When V3D_SHADING_TEXTURE_COLOR is active, use V3D_SHADING_MATERIAL_COLOR as fallback when no texture could be determined */ + int color_type = wpd->shading.color_type == V3D_SHADING_TEXTURE_COLOR ? + V3D_SHADING_MATERIAL_COLOR : + wpd->shading.color_type; + copy_v3_fl3(data->diffuse_color, 0.8f, 0.8f, 0.8f); + copy_v3_v3(data->base_color, data->diffuse_color); + copy_v3_fl3(data->specular_color, 0.05f, 0.05f, 0.05f); /* Dielectric: 5% reflective. */ + data->metallic = 0.0f; + data->roughness = 0.5f; /* sqrtf(0.25f); */ - if (color_type == V3D_SHADING_SINGLE_COLOR) { - copy_v3_v3(data->diffuse_color, wpd->shading.single_color); - copy_v3_v3(data->base_color, data->diffuse_color); - } - else if (color_type == V3D_SHADING_RANDOM_COLOR) { - uint hash = BLI_ghashutil_strhash_p_murmur(ob->id.name); - if (ob->id.lib) { - hash = (hash * 13) ^ BLI_ghashutil_strhash_p_murmur(ob->id.lib->name); - } + if (color_type == V3D_SHADING_SINGLE_COLOR) { + copy_v3_v3(data->diffuse_color, wpd->shading.single_color); + copy_v3_v3(data->base_color, data->diffuse_color); + } + else if (color_type == V3D_SHADING_RANDOM_COLOR) { + uint hash = BLI_ghashutil_strhash_p_murmur(ob->id.name); + if (ob->id.lib) { + hash = (hash * 13) ^ BLI_ghashutil_strhash_p_murmur(ob->id.lib->name); + } - float hue = BLI_hash_int_01(hash); - float hsv[3] = {hue, HSV_SATURATION, HSV_VALUE}; - hsv_to_rgb_v(hsv, data->diffuse_color); - copy_v3_v3(data->base_color, data->diffuse_color); - } - else if (color_type == V3D_SHADING_OBJECT_COLOR) { - copy_v3_v3(data->diffuse_color, ob->color); - copy_v3_v3(data->base_color, data->diffuse_color); - } - else { - /* V3D_SHADING_MATERIAL_COLOR */ - if (mat) { - if (SPECULAR_HIGHLIGHT_ENABLED(wpd)) { - copy_v3_v3(data->base_color, &mat->r); - mul_v3_v3fl(data->diffuse_color, &mat->r, 1.0f - mat->metallic); - mul_v3_v3fl(data->specular_color, &mat->r, mat->metallic); - add_v3_fl(data->specular_color, 0.05f * (1.0f - mat->metallic)); - data->metallic = mat->metallic; - data->roughness = sqrtf(mat->roughness); /* Remap to disney roughness. */ - } - else { - copy_v3_v3(data->base_color, &mat->r); - copy_v3_v3(data->diffuse_color, &mat->r); - } - } - } + float hue = BLI_hash_int_01(hash); + float hsv[3] = {hue, HSV_SATURATION, HSV_VALUE}; + hsv_to_rgb_v(hsv, data->diffuse_color); + copy_v3_v3(data->base_color, data->diffuse_color); + } + else if (color_type == V3D_SHADING_OBJECT_COLOR) { + copy_v3_v3(data->diffuse_color, ob->color); + copy_v3_v3(data->base_color, data->diffuse_color); + } + else { + /* V3D_SHADING_MATERIAL_COLOR */ + if (mat) { + if (SPECULAR_HIGHLIGHT_ENABLED(wpd)) { + copy_v3_v3(data->base_color, &mat->r); + mul_v3_v3fl(data->diffuse_color, &mat->r, 1.0f - mat->metallic); + mul_v3_v3fl(data->specular_color, &mat->r, mat->metallic); + add_v3_fl(data->specular_color, 0.05f * (1.0f - mat->metallic)); + data->metallic = mat->metallic; + data->roughness = sqrtf(mat->roughness); /* Remap to disney roughness. */ + } + else { + copy_v3_v3(data->base_color, &mat->r); + copy_v3_v3(data->diffuse_color, &mat->r); + } + } + } } char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair) { - char *str = NULL; + char *str = NULL; - DynStr *ds = BLI_dynstr_new(); + DynStr *ds = BLI_dynstr_new(); - if (wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE) { - BLI_dynstr_append(ds, "#define V3D_SHADING_OBJECT_OUTLINE\n"); - } - if (wpd->shading.flag & V3D_SHADING_SHADOW) { - BLI_dynstr_append(ds, "#define V3D_SHADING_SHADOW\n"); - } - if (SSAO_ENABLED(wpd) || CURVATURE_ENABLED(wpd)) { - BLI_dynstr_append(ds, "#define WB_CAVITY\n"); - } - if (SPECULAR_HIGHLIGHT_ENABLED(wpd)) { - BLI_dynstr_append(ds, "#define V3D_SHADING_SPECULAR_HIGHLIGHT\n"); - } - if (STUDIOLIGHT_ENABLED(wpd)) { - BLI_dynstr_append(ds, "#define V3D_LIGHTING_STUDIO\n"); - } - if (FLAT_ENABLED(wpd)) { - BLI_dynstr_append(ds, "#define V3D_LIGHTING_FLAT\n"); - } - if (MATCAP_ENABLED(wpd)) { - BLI_dynstr_append(ds, "#define V3D_LIGHTING_MATCAP\n"); - } - if (OBJECT_ID_PASS_ENABLED(wpd)) { - BLI_dynstr_append(ds, "#define OBJECT_ID_PASS_ENABLED\n"); - } - if (MATDATA_PASS_ENABLED(wpd)) { - BLI_dynstr_append(ds, "#define MATDATA_PASS_ENABLED\n"); - } - if (NORMAL_VIEWPORT_PASS_ENABLED(wpd)) { - BLI_dynstr_append(ds, "#define NORMAL_VIEWPORT_PASS_ENABLED\n"); - } - if (use_textures) { - BLI_dynstr_append(ds, "#define V3D_SHADING_TEXTURE_COLOR\n"); - } - if (NORMAL_ENCODING_ENABLED()) { - BLI_dynstr_append(ds, "#define WORKBENCH_ENCODE_NORMALS\n"); - } - if (is_hair) { - BLI_dynstr_append(ds, "#define HAIR_SHADER\n"); - } + if (wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE) { + BLI_dynstr_append(ds, "#define V3D_SHADING_OBJECT_OUTLINE\n"); + } + if (wpd->shading.flag & V3D_SHADING_SHADOW) { + BLI_dynstr_append(ds, "#define V3D_SHADING_SHADOW\n"); + } + if (SSAO_ENABLED(wpd) || CURVATURE_ENABLED(wpd)) { + BLI_dynstr_append(ds, "#define WB_CAVITY\n"); + } + if (SPECULAR_HIGHLIGHT_ENABLED(wpd)) { + BLI_dynstr_append(ds, "#define V3D_SHADING_SPECULAR_HIGHLIGHT\n"); + } + if (STUDIOLIGHT_ENABLED(wpd)) { + BLI_dynstr_append(ds, "#define V3D_LIGHTING_STUDIO\n"); + } + if (FLAT_ENABLED(wpd)) { + BLI_dynstr_append(ds, "#define V3D_LIGHTING_FLAT\n"); + } + if (MATCAP_ENABLED(wpd)) { + BLI_dynstr_append(ds, "#define V3D_LIGHTING_MATCAP\n"); + } + if (OBJECT_ID_PASS_ENABLED(wpd)) { + BLI_dynstr_append(ds, "#define OBJECT_ID_PASS_ENABLED\n"); + } + if (MATDATA_PASS_ENABLED(wpd)) { + BLI_dynstr_append(ds, "#define MATDATA_PASS_ENABLED\n"); + } + if (NORMAL_VIEWPORT_PASS_ENABLED(wpd)) { + BLI_dynstr_append(ds, "#define NORMAL_VIEWPORT_PASS_ENABLED\n"); + } + if (use_textures) { + BLI_dynstr_append(ds, "#define V3D_SHADING_TEXTURE_COLOR\n"); + } + if (NORMAL_ENCODING_ENABLED()) { + BLI_dynstr_append(ds, "#define WORKBENCH_ENCODE_NORMALS\n"); + } + if (is_hair) { + BLI_dynstr_append(ds, "#define HAIR_SHADER\n"); + } - str = BLI_dynstr_get_cstring(ds); - BLI_dynstr_free(ds); - return str; + str = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); + return str; } uint workbench_material_get_hash(WORKBENCH_MaterialData *material_template, bool is_ghost) { - uint input[4]; - uint result; - float *color = material_template->diffuse_color; - input[0] = (uint)(color[0] * 512); - input[1] = (uint)(color[1] * 512); - input[2] = (uint)(color[2] * 512); - input[3] = material_template->object_id; - result = BLI_ghashutil_uinthash_v4_murmur(input); + uint input[4]; + uint result; + float *color = material_template->diffuse_color; + input[0] = (uint)(color[0] * 512); + input[1] = (uint)(color[1] * 512); + input[2] = (uint)(color[2] * 512); + input[3] = material_template->object_id; + result = BLI_ghashutil_uinthash_v4_murmur(input); - color = material_template->specular_color; - input[0] = (uint)(color[0] * 512); - input[1] = (uint)(color[1] * 512); - input[2] = (uint)(color[2] * 512); - input[3] = (uint)(material_template->roughness * 512); - result += BLI_ghashutil_uinthash_v4_murmur(input); + color = material_template->specular_color; + input[0] = (uint)(color[0] * 512); + input[1] = (uint)(color[1] * 512); + input[2] = (uint)(color[2] * 512); + input[3] = (uint)(material_template->roughness * 512); + result += BLI_ghashutil_uinthash_v4_murmur(input); - result += BLI_ghashutil_uinthash((uint)is_ghost); + result += BLI_ghashutil_uinthash((uint)is_ghost); - /* add texture reference */ - if (material_template->ima) { - result += BLI_ghashutil_inthash_p_murmur(material_template->ima); - } + /* add texture reference */ + if (material_template->ima) { + result += BLI_ghashutil_inthash_p_murmur(material_template->ima); + } - return result; + return result; } int workbench_material_get_composite_shader_index(WORKBENCH_PrivateData *wpd) { - /* NOTE: change MAX_COMPOSITE_SHADERS accordingly when modifying this function. */ - int index = 0; - /* 2 bits FLAT/STUDIO/MATCAP + Specular highlight */ - index = SPECULAR_HIGHLIGHT_ENABLED(wpd) ? 3 : wpd->shading.light; - SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_SHADOW, 1 << 2); - SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_CAVITY, 1 << 3); - SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE, 1 << 4); - SET_FLAG_FROM_TEST(index, MATDATA_PASS_ENABLED(wpd), 1 << 5); - BLI_assert(index < MAX_COMPOSITE_SHADERS); - return index; + /* NOTE: change MAX_COMPOSITE_SHADERS accordingly when modifying this function. */ + int index = 0; + /* 2 bits FLAT/STUDIO/MATCAP + Specular highlight */ + index = SPECULAR_HIGHLIGHT_ENABLED(wpd) ? 3 : wpd->shading.light; + SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_SHADOW, 1 << 2); + SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_CAVITY, 1 << 3); + SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE, 1 << 4); + SET_FLAG_FROM_TEST(index, MATDATA_PASS_ENABLED(wpd), 1 << 5); + BLI_assert(index < MAX_COMPOSITE_SHADERS); + return index; } -int workbench_material_get_prepass_shader_index( - WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair) +int workbench_material_get_prepass_shader_index(WORKBENCH_PrivateData *wpd, + bool use_textures, + bool is_hair) { - /* NOTE: change MAX_PREPASS_SHADERS accordingly when modifying this function. */ - int index = 0; - SET_FLAG_FROM_TEST(index, is_hair, 1 << 0); - SET_FLAG_FROM_TEST(index, MATDATA_PASS_ENABLED(wpd), 1 << 1); - SET_FLAG_FROM_TEST(index, OBJECT_ID_PASS_ENABLED(wpd), 1 << 2); - SET_FLAG_FROM_TEST(index, NORMAL_VIEWPORT_PASS_ENABLED(wpd), 1 << 3); - SET_FLAG_FROM_TEST(index, MATCAP_ENABLED(wpd), 1 << 4); - SET_FLAG_FROM_TEST(index, use_textures, 1 << 5); - BLI_assert(index < MAX_PREPASS_SHADERS); - return index; + /* NOTE: change MAX_PREPASS_SHADERS accordingly when modifying this function. */ + int index = 0; + SET_FLAG_FROM_TEST(index, is_hair, 1 << 0); + SET_FLAG_FROM_TEST(index, MATDATA_PASS_ENABLED(wpd), 1 << 1); + SET_FLAG_FROM_TEST(index, OBJECT_ID_PASS_ENABLED(wpd), 1 << 2); + SET_FLAG_FROM_TEST(index, NORMAL_VIEWPORT_PASS_ENABLED(wpd), 1 << 3); + SET_FLAG_FROM_TEST(index, MATCAP_ENABLED(wpd), 1 << 4); + SET_FLAG_FROM_TEST(index, use_textures, 1 << 5); + BLI_assert(index < MAX_PREPASS_SHADERS); + return index; } -int workbench_material_get_accum_shader_index(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair) +int workbench_material_get_accum_shader_index(WORKBENCH_PrivateData *wpd, + bool use_textures, + bool is_hair) { - /* NOTE: change MAX_ACCUM_SHADERS accordingly when modifying this function. */ - int index = 0; - /* 2 bits FLAT/STUDIO/MATCAP + Specular highlight */ - index = SPECULAR_HIGHLIGHT_ENABLED(wpd) ? 3 : wpd->shading.light; - SET_FLAG_FROM_TEST(index, use_textures, 1 << 2); - SET_FLAG_FROM_TEST(index, is_hair, 1 << 3); - /* 1 bits SHADOWS (only facing factor) */ - SET_FLAG_FROM_TEST(index, SHADOW_ENABLED(wpd), 1 << 4); - BLI_assert(index < MAX_ACCUM_SHADERS); - return index; + /* NOTE: change MAX_ACCUM_SHADERS accordingly when modifying this function. */ + int index = 0; + /* 2 bits FLAT/STUDIO/MATCAP + Specular highlight */ + index = SPECULAR_HIGHLIGHT_ENABLED(wpd) ? 3 : wpd->shading.light; + SET_FLAG_FROM_TEST(index, use_textures, 1 << 2); + SET_FLAG_FROM_TEST(index, is_hair, 1 << 3); + /* 1 bits SHADOWS (only facing factor) */ + SET_FLAG_FROM_TEST(index, SHADOW_ENABLED(wpd), 1 << 4); + BLI_assert(index < MAX_ACCUM_SHADERS); + return index; } int workbench_material_determine_color_type(WORKBENCH_PrivateData *wpd, Image *ima, Object *ob) { - int color_type = wpd->shading.color_type; - if ((color_type == V3D_SHADING_TEXTURE_COLOR && ima == NULL) || (ob->dt < OB_TEXTURE)) { - color_type = V3D_SHADING_MATERIAL_COLOR; - } - return color_type; + int color_type = wpd->shading.color_type; + if ((color_type == V3D_SHADING_TEXTURE_COLOR && ima == NULL) || (ob->dt < OB_TEXTURE)) { + color_type = V3D_SHADING_MATERIAL_COLOR; + } + return color_type; } -void workbench_material_get_image_and_mat(Object *ob, int mat_nr, Image **r_image, ImageUser **r_iuser, int *r_interp, Material **r_mat) +void workbench_material_get_image_and_mat( + Object *ob, int mat_nr, Image **r_image, ImageUser **r_iuser, int *r_interp, Material **r_mat) { - bNode *node; - *r_mat = give_current_material(ob, mat_nr); - ED_object_get_active_image(ob, mat_nr, r_image, r_iuser, &node, NULL); - if (node && *r_image) { - switch (node->type) { - case SH_NODE_TEX_IMAGE: - { - NodeTexImage *storage = node->storage; - *r_interp = storage->interpolation; - break; - } - case SH_NODE_TEX_ENVIRONMENT: - { - NodeTexEnvironment *storage = node->storage; - *r_interp = storage->interpolation; - break; - } - default: - BLI_assert(!"Node type not supported by workbench"); - *r_interp = 0; - } - } - else { - *r_interp = 0; - } + bNode *node; + *r_mat = give_current_material(ob, mat_nr); + ED_object_get_active_image(ob, mat_nr, r_image, r_iuser, &node, NULL); + if (node && *r_image) { + switch (node->type) { + case SH_NODE_TEX_IMAGE: { + NodeTexImage *storage = node->storage; + *r_interp = storage->interpolation; + break; + } + case SH_NODE_TEX_ENVIRONMENT: { + NodeTexEnvironment *storage = node->storage; + *r_interp = storage->interpolation; + break; + } + default: + BLI_assert(!"Node type not supported by workbench"); + *r_interp = 0; + } + } + else { + *r_interp = 0; + } } -void workbench_material_shgroup_uniform( - WORKBENCH_PrivateData *wpd, DRWShadingGroup *grp, WORKBENCH_MaterialData *material, Object *ob, - const bool use_metallic, const bool deferred, const int interp) +void workbench_material_shgroup_uniform(WORKBENCH_PrivateData *wpd, + DRWShadingGroup *grp, + WORKBENCH_MaterialData *material, + Object *ob, + const bool use_metallic, + const bool deferred, + const int interp) { - if (deferred && !MATDATA_PASS_ENABLED(wpd)) { - return; - } + if (deferred && !MATDATA_PASS_ENABLED(wpd)) { + return; + } - if (workbench_material_determine_color_type(wpd, material->ima, ob) == V3D_SHADING_TEXTURE_COLOR) { - ImBuf *ibuf = BKE_image_acquire_ibuf(material->ima, material->iuser, NULL); - const bool do_color_correction = wpd->use_color_management && - (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0); - BKE_image_release_ibuf(material->ima, ibuf, NULL); - GPUTexture *tex = GPU_texture_from_blender(material->ima, material->iuser, GL_TEXTURE_2D, false); - DRW_shgroup_uniform_texture(grp, "image", tex); - DRW_shgroup_uniform_bool_copy(grp, "imageSrgb", do_color_correction); - DRW_shgroup_uniform_bool_copy(grp, "imageNearest", (interp == SHD_INTERP_CLOSEST)); - } - else { - DRW_shgroup_uniform_vec3(grp, "materialDiffuseColor", (use_metallic) ? material->base_color : material->diffuse_color, 1); - } + if (workbench_material_determine_color_type(wpd, material->ima, ob) == + V3D_SHADING_TEXTURE_COLOR) { + ImBuf *ibuf = BKE_image_acquire_ibuf(material->ima, material->iuser, NULL); + const bool do_color_correction = wpd->use_color_management && + (ibuf && + (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0); + BKE_image_release_ibuf(material->ima, ibuf, NULL); + GPUTexture *tex = GPU_texture_from_blender( + material->ima, material->iuser, GL_TEXTURE_2D, false); + DRW_shgroup_uniform_texture(grp, "image", tex); + DRW_shgroup_uniform_bool_copy(grp, "imageSrgb", do_color_correction); + DRW_shgroup_uniform_bool_copy(grp, "imageNearest", (interp == SHD_INTERP_CLOSEST)); + } + else { + DRW_shgroup_uniform_vec3(grp, + "materialDiffuseColor", + (use_metallic) ? material->base_color : material->diffuse_color, + 1); + } - if (SPECULAR_HIGHLIGHT_ENABLED(wpd)) { - if (use_metallic) { - DRW_shgroup_uniform_float(grp, "materialMetallic", &material->metallic, 1); - } - else { - DRW_shgroup_uniform_vec3(grp, "materialSpecularColor", material->specular_color, 1); - } - DRW_shgroup_uniform_float(grp, "materialRoughness", &material->roughness, 1); - } + if (SPECULAR_HIGHLIGHT_ENABLED(wpd)) { + if (use_metallic) { + DRW_shgroup_uniform_float(grp, "materialMetallic", &material->metallic, 1); + } + else { + DRW_shgroup_uniform_vec3(grp, "materialSpecularColor", material->specular_color, 1); + } + DRW_shgroup_uniform_float(grp, "materialRoughness", &material->roughness, 1); + } - if (WORLD_CLIPPING_ENABLED(wpd)) { - DRW_shgroup_uniform_vec4(grp, "WorldClipPlanes", wpd->world_clip_planes[0], 6); - DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); - } + if (WORLD_CLIPPING_ENABLED(wpd)) { + DRW_shgroup_uniform_vec4(grp, "WorldClipPlanes", wpd->world_clip_planes[0], 6); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); + } } -void workbench_material_copy(WORKBENCH_MaterialData *dest_material, const WORKBENCH_MaterialData *source_material) +void workbench_material_copy(WORKBENCH_MaterialData *dest_material, + const WORKBENCH_MaterialData *source_material) { - dest_material->object_id = source_material->object_id; - copy_v3_v3(dest_material->base_color, source_material->base_color); - copy_v3_v3(dest_material->diffuse_color, source_material->diffuse_color); - copy_v3_v3(dest_material->specular_color, source_material->specular_color); - dest_material->metallic = source_material->metallic; - dest_material->roughness = source_material->roughness; - dest_material->ima = source_material->ima; - dest_material->iuser = source_material->iuser; + dest_material->object_id = source_material->object_id; + copy_v3_v3(dest_material->base_color, source_material->base_color); + copy_v3_v3(dest_material->diffuse_color, source_material->diffuse_color); + copy_v3_v3(dest_material->specular_color, source_material->specular_color); + dest_material->metallic = source_material->metallic; + dest_material->roughness = source_material->roughness; + dest_material->ima = source_material->ima; + dest_material->iuser = source_material->iuser; } diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h index 75d72933c8e..0e2ef2f94d2 100644 --- a/source/blender/draw/engines/workbench/workbench_private.h +++ b/source/blender/draw/engines/workbench/workbench_private.h @@ -23,7 +23,6 @@ #ifndef __WORKBENCH_PRIVATE_H__ #define __WORKBENCH_PRIVATE_H__ - #include "BKE_studiolight.h" #include "DNA_image_types.h" @@ -47,258 +46,282 @@ #define STUDIOLIGHT_ENABLED(wpd) (wpd->shading.light == V3D_LIGHTING_STUDIO) #define MATCAP_ENABLED(wpd) (wpd->shading.light == V3D_LIGHTING_MATCAP) #define USE_WORLD_ORIENTATION(wpd) ((wpd->shading.flag & V3D_SHADING_WORLD_ORIENTATION) != 0) -#define STUDIOLIGHT_TYPE_WORLD_ENABLED(wpd) (STUDIOLIGHT_ENABLED(wpd) && (wpd->studio_light->flag & STUDIOLIGHT_TYPE_WORLD)) -#define STUDIOLIGHT_TYPE_STUDIO_ENABLED(wpd) (STUDIOLIGHT_ENABLED(wpd) && (wpd->studio_light->flag & STUDIOLIGHT_TYPE_STUDIO)) -#define STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd) (MATCAP_ENABLED(wpd) && (wpd->studio_light->flag & STUDIOLIGHT_TYPE_MATCAP)) -#define SSAO_ENABLED(wpd) ((wpd->shading.flag & V3D_SHADING_CAVITY) && ((wpd->shading.cavity_type == V3D_SHADING_CAVITY_SSAO) || (wpd->shading.cavity_type == V3D_SHADING_CAVITY_BOTH))) -#define CURVATURE_ENABLED(wpd) ((wpd->shading.flag & V3D_SHADING_CAVITY) && ((wpd->shading.cavity_type == V3D_SHADING_CAVITY_CURVATURE) || (wpd->shading.cavity_type == V3D_SHADING_CAVITY_BOTH))) +#define STUDIOLIGHT_TYPE_WORLD_ENABLED(wpd) \ + (STUDIOLIGHT_ENABLED(wpd) && (wpd->studio_light->flag & STUDIOLIGHT_TYPE_WORLD)) +#define STUDIOLIGHT_TYPE_STUDIO_ENABLED(wpd) \ + (STUDIOLIGHT_ENABLED(wpd) && (wpd->studio_light->flag & STUDIOLIGHT_TYPE_STUDIO)) +#define STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd) \ + (MATCAP_ENABLED(wpd) && (wpd->studio_light->flag & STUDIOLIGHT_TYPE_MATCAP)) +#define SSAO_ENABLED(wpd) \ + ((wpd->shading.flag & V3D_SHADING_CAVITY) && \ + ((wpd->shading.cavity_type == V3D_SHADING_CAVITY_SSAO) || \ + (wpd->shading.cavity_type == V3D_SHADING_CAVITY_BOTH))) +#define CURVATURE_ENABLED(wpd) \ + ((wpd->shading.flag & V3D_SHADING_CAVITY) && \ + ((wpd->shading.cavity_type == V3D_SHADING_CAVITY_CURVATURE) || \ + (wpd->shading.cavity_type == V3D_SHADING_CAVITY_BOTH))) #define CAVITY_ENABLED(wpd) (CURVATURE_ENABLED(wpd) || SSAO_ENABLED(wpd)) #define SHADOW_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_SHADOW) -#define GHOST_ENABLED(psl) (!DRW_pass_is_empty(psl->ghost_prepass_pass) || !DRW_pass_is_empty(psl->ghost_prepass_hair_pass)) +#define GHOST_ENABLED(psl) \ + (!DRW_pass_is_empty(psl->ghost_prepass_pass) || !DRW_pass_is_empty(psl->ghost_prepass_hair_pass)) #define CULL_BACKFACE_ENABLED(wpd) ((wpd->shading.flag & V3D_SHADING_BACKFACE_CULLING) != 0) -#define OIT_ENABLED(wpd) (ELEM(wpd->shading.color_type, V3D_SHADING_MATERIAL_COLOR, V3D_SHADING_OBJECT_COLOR, V3D_SHADING_TEXTURE_COLOR)) - -#define IS_NAVIGATING(wpd) ((DRW_context_state_get()->rv3d) && (DRW_context_state_get()->rv3d->rflag & RV3D_NAVIGATING)) -#define FXAA_ENABLED(wpd) ((!DRW_state_is_opengl_render()) && \ - (IN_RANGE(wpd->preferences->gpu_viewport_quality, GPU_VIEWPORT_QUALITY_FXAA, GPU_VIEWPORT_QUALITY_TAA8) || \ - ((IS_NAVIGATING(wpd) || wpd->is_playback) && (wpd->preferences->gpu_viewport_quality >= GPU_VIEWPORT_QUALITY_TAA8)))) -#define TAA_ENABLED(wpd) ((DRW_state_is_image_render() && DRW_context_state_get()->scene->r.mode & R_OSA) || \ - (!DRW_state_is_image_render() && wpd->preferences->gpu_viewport_quality >= GPU_VIEWPORT_QUALITY_TAA8 && !IS_NAVIGATING(wpd) && !wpd->is_playback)) -#define SPECULAR_HIGHLIGHT_ENABLED(wpd) (STUDIOLIGHT_ENABLED(wpd) && (wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT) && (!STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd))) +#define OIT_ENABLED(wpd) \ + (ELEM(wpd->shading.color_type, \ + V3D_SHADING_MATERIAL_COLOR, \ + V3D_SHADING_OBJECT_COLOR, \ + V3D_SHADING_TEXTURE_COLOR)) + +#define IS_NAVIGATING(wpd) \ + ((DRW_context_state_get()->rv3d) && (DRW_context_state_get()->rv3d->rflag & RV3D_NAVIGATING)) +#define FXAA_ENABLED(wpd) \ + ((!DRW_state_is_opengl_render()) && \ + (IN_RANGE(wpd->preferences->gpu_viewport_quality, \ + GPU_VIEWPORT_QUALITY_FXAA, \ + GPU_VIEWPORT_QUALITY_TAA8) || \ + ((IS_NAVIGATING(wpd) || wpd->is_playback) && \ + (wpd->preferences->gpu_viewport_quality >= GPU_VIEWPORT_QUALITY_TAA8)))) +#define TAA_ENABLED(wpd) \ + ((DRW_state_is_image_render() && DRW_context_state_get()->scene->r.mode & R_OSA) || \ + (!DRW_state_is_image_render() && \ + wpd->preferences->gpu_viewport_quality >= GPU_VIEWPORT_QUALITY_TAA8 && !IS_NAVIGATING(wpd) && \ + !wpd->is_playback)) +#define SPECULAR_HIGHLIGHT_ENABLED(wpd) \ + (STUDIOLIGHT_ENABLED(wpd) && (wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT) && \ + (!STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd))) #define OBJECT_OUTLINE_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE) #define OBJECT_ID_PASS_ENABLED(wpd) (OBJECT_OUTLINE_ENABLED(wpd) || CURVATURE_ENABLED(wpd)) -#define MATDATA_PASS_ENABLED(wpd) (wpd->shading.color_type != V3D_SHADING_SINGLE_COLOR || MATCAP_ENABLED(wpd)) -#define NORMAL_VIEWPORT_COMP_PASS_ENABLED(wpd) (MATCAP_ENABLED(wpd) || STUDIOLIGHT_ENABLED(wpd) || SHADOW_ENABLED(wpd)) -#define NORMAL_VIEWPORT_PASS_ENABLED(wpd) (NORMAL_VIEWPORT_COMP_PASS_ENABLED(wpd) || SSAO_ENABLED(wpd) || CURVATURE_ENABLED(wpd)) +#define MATDATA_PASS_ENABLED(wpd) \ + (wpd->shading.color_type != V3D_SHADING_SINGLE_COLOR || MATCAP_ENABLED(wpd)) +#define NORMAL_VIEWPORT_COMP_PASS_ENABLED(wpd) \ + (MATCAP_ENABLED(wpd) || STUDIOLIGHT_ENABLED(wpd) || SHADOW_ENABLED(wpd)) +#define NORMAL_VIEWPORT_PASS_ENABLED(wpd) \ + (NORMAL_VIEWPORT_COMP_PASS_ENABLED(wpd) || SSAO_ENABLED(wpd) || CURVATURE_ENABLED(wpd)) #define NORMAL_ENCODING_ENABLED() (true) #define WORLD_CLIPPING_ENABLED(wpd) (wpd->world_clip_planes != NULL) - struct RenderEngine; struct RenderLayer; struct rcti; - typedef struct WORKBENCH_FramebufferList { - /* Deferred render buffers */ - struct GPUFrameBuffer *prepass_fb; - struct GPUFrameBuffer *ghost_prepass_fb; - struct GPUFrameBuffer *cavity_fb; - struct GPUFrameBuffer *composite_fb; - struct GPUFrameBuffer *id_clear_fb; - - struct GPUFrameBuffer *effect_fb; - struct GPUFrameBuffer *effect_taa_fb; - struct GPUFrameBuffer *depth_buffer_fb; - struct GPUFrameBuffer *color_only_fb; - - struct GPUFrameBuffer *dof_downsample_fb; - struct GPUFrameBuffer *dof_coc_tile_h_fb; - struct GPUFrameBuffer *dof_coc_tile_v_fb; - struct GPUFrameBuffer *dof_coc_dilate_fb; - struct GPUFrameBuffer *dof_blur1_fb; - struct GPUFrameBuffer *dof_blur2_fb; - - /* Forward render buffers */ - struct GPUFrameBuffer *object_outline_fb; - struct GPUFrameBuffer *transparent_accum_fb; - struct GPUFrameBuffer *transparent_revealage_fb; + /* Deferred render buffers */ + struct GPUFrameBuffer *prepass_fb; + struct GPUFrameBuffer *ghost_prepass_fb; + struct GPUFrameBuffer *cavity_fb; + struct GPUFrameBuffer *composite_fb; + struct GPUFrameBuffer *id_clear_fb; + + struct GPUFrameBuffer *effect_fb; + struct GPUFrameBuffer *effect_taa_fb; + struct GPUFrameBuffer *depth_buffer_fb; + struct GPUFrameBuffer *color_only_fb; + + struct GPUFrameBuffer *dof_downsample_fb; + struct GPUFrameBuffer *dof_coc_tile_h_fb; + struct GPUFrameBuffer *dof_coc_tile_v_fb; + struct GPUFrameBuffer *dof_coc_dilate_fb; + struct GPUFrameBuffer *dof_blur1_fb; + struct GPUFrameBuffer *dof_blur2_fb; + + /* Forward render buffers */ + struct GPUFrameBuffer *object_outline_fb; + struct GPUFrameBuffer *transparent_accum_fb; + struct GPUFrameBuffer *transparent_revealage_fb; } WORKBENCH_FramebufferList; typedef struct WORKBENCH_TextureList { - struct GPUTexture *dof_source_tx; - struct GPUTexture *coc_halfres_tx; - struct GPUTexture *history_buffer_tx; - struct GPUTexture *depth_buffer_tx; + struct GPUTexture *dof_source_tx; + struct GPUTexture *coc_halfres_tx; + struct GPUTexture *history_buffer_tx; + struct GPUTexture *depth_buffer_tx; } WORKBENCH_TextureList; typedef struct WORKBENCH_StorageList { - struct WORKBENCH_PrivateData *g_data; - struct WORKBENCH_EffectInfo *effects; - float *dof_ubo_data; + struct WORKBENCH_PrivateData *g_data; + struct WORKBENCH_EffectInfo *effects; + float *dof_ubo_data; } WORKBENCH_StorageList; typedef struct WORKBENCH_PassList { - /* deferred rendering */ - struct DRWPass *prepass_pass; - struct DRWPass *prepass_hair_pass; - struct DRWPass *ghost_prepass_pass; - struct DRWPass *ghost_prepass_hair_pass; - struct DRWPass *cavity_pass; - struct DRWPass *shadow_depth_pass_pass; - struct DRWPass *shadow_depth_pass_mani_pass; - struct DRWPass *shadow_depth_fail_pass; - struct DRWPass *shadow_depth_fail_mani_pass; - struct DRWPass *shadow_depth_fail_caps_pass; - struct DRWPass *shadow_depth_fail_caps_mani_pass; - struct DRWPass *composite_pass; - struct DRWPass *composite_shadow_pass; - struct DRWPass *oit_composite_pass; - struct DRWPass *background_pass; - struct DRWPass *background_pass_clip; - struct DRWPass *ghost_resolve_pass; - struct DRWPass *effect_aa_pass; - struct DRWPass *dof_down_ps; - struct DRWPass *dof_down2_ps; - struct DRWPass *dof_flatten_v_ps; - struct DRWPass *dof_flatten_h_ps; - struct DRWPass *dof_dilate_h_ps; - struct DRWPass *dof_dilate_v_ps; - struct DRWPass *dof_blur1_ps; - struct DRWPass *dof_blur2_ps; - struct DRWPass *dof_resolve_ps; - struct DRWPass *volume_pass; - - /* forward rendering */ - struct DRWPass *transparent_accum_pass; - struct DRWPass *object_outline_pass; - struct DRWPass *depth_pass; - struct DRWPass *checker_depth_pass; + /* deferred rendering */ + struct DRWPass *prepass_pass; + struct DRWPass *prepass_hair_pass; + struct DRWPass *ghost_prepass_pass; + struct DRWPass *ghost_prepass_hair_pass; + struct DRWPass *cavity_pass; + struct DRWPass *shadow_depth_pass_pass; + struct DRWPass *shadow_depth_pass_mani_pass; + struct DRWPass *shadow_depth_fail_pass; + struct DRWPass *shadow_depth_fail_mani_pass; + struct DRWPass *shadow_depth_fail_caps_pass; + struct DRWPass *shadow_depth_fail_caps_mani_pass; + struct DRWPass *composite_pass; + struct DRWPass *composite_shadow_pass; + struct DRWPass *oit_composite_pass; + struct DRWPass *background_pass; + struct DRWPass *background_pass_clip; + struct DRWPass *ghost_resolve_pass; + struct DRWPass *effect_aa_pass; + struct DRWPass *dof_down_ps; + struct DRWPass *dof_down2_ps; + struct DRWPass *dof_flatten_v_ps; + struct DRWPass *dof_flatten_h_ps; + struct DRWPass *dof_dilate_h_ps; + struct DRWPass *dof_dilate_v_ps; + struct DRWPass *dof_blur1_ps; + struct DRWPass *dof_blur2_ps; + struct DRWPass *dof_resolve_ps; + struct DRWPass *volume_pass; + + /* forward rendering */ + struct DRWPass *transparent_accum_pass; + struct DRWPass *object_outline_pass; + struct DRWPass *depth_pass; + struct DRWPass *checker_depth_pass; } WORKBENCH_PassList; typedef struct WORKBENCH_Data { - void *engine_type; - WORKBENCH_FramebufferList *fbl; - WORKBENCH_TextureList *txl; - WORKBENCH_PassList *psl; - WORKBENCH_StorageList *stl; + void *engine_type; + WORKBENCH_FramebufferList *fbl; + WORKBENCH_TextureList *txl; + WORKBENCH_PassList *psl; + WORKBENCH_StorageList *stl; } WORKBENCH_Data; typedef struct WORKBENCH_UBO_Light { - float light_direction[4]; - float specular_color[3], pad; - float diffuse_color[3], wrapped; + float light_direction[4]; + float specular_color[3], pad; + float diffuse_color[3], wrapped; } WORKBENCH_UBO_Light; typedef struct WORKBENCH_UBO_World { - float background_color_low[4]; - float background_color_high[4]; - float object_outline_color[4]; - float shadow_direction_vs[4]; - WORKBENCH_UBO_Light lights[4]; - float ambient_color[4]; - int num_lights; - int matcap_orientation; - float background_alpha; - float curvature_ridge; - float curvature_valley; - int pad[3]; + float background_color_low[4]; + float background_color_high[4]; + float object_outline_color[4]; + float shadow_direction_vs[4]; + WORKBENCH_UBO_Light lights[4]; + float ambient_color[4]; + int num_lights; + int matcap_orientation; + float background_alpha; + float curvature_ridge; + float curvature_valley; + int pad[3]; } WORKBENCH_UBO_World; BLI_STATIC_ASSERT_ALIGN(WORKBENCH_UBO_World, 16) - typedef struct WORKBENCH_PrivateData { - struct GHash *material_hash; - struct GHash *material_transp_hash; - struct GPUShader *prepass_solid_sh; - struct GPUShader *prepass_solid_hair_sh; - struct GPUShader *prepass_texture_sh; - struct GPUShader *prepass_texture_hair_sh; - struct GPUShader *composite_sh; - struct GPUShader *background_sh; - struct GPUShader *transparent_accum_sh; - struct GPUShader *transparent_accum_hair_sh; - struct GPUShader *transparent_accum_texture_sh; - struct GPUShader *transparent_accum_texture_hair_sh; - View3DShading shading; - StudioLight *studio_light; - const UserDef *preferences; - struct GPUUniformBuffer *world_ubo; - struct DRWShadingGroup *shadow_shgrp; - struct DRWShadingGroup *depth_shgrp; - WORKBENCH_UBO_World world_data; - float shadow_multiplier; - float shadow_shift; - float shadow_focus; - float cached_shadow_direction[3]; - float shadow_mat[4][4]; - float shadow_inv[4][4]; - /* Far plane of the view frustum. */ - float shadow_far_plane[4]; - /* Near plane corners in shadow space. */ - float shadow_near_corners[4][3]; - /* min and max of shadow_near_corners. allow fast test */ - float shadow_near_min[3]; - float shadow_near_max[3]; - /* This is a parallelogram, so only 2 normal and distance to the edges. */ - float shadow_near_sides[2][4]; - bool shadow_changed; - bool is_playback; - - float (*world_clip_planes)[4]; - struct GPUBatch *world_clip_planes_batch; - float world_clip_planes_color[4]; - - /* Volumes */ - bool volumes_do; - ListBase smoke_domains; - - /* Ssao */ - float winmat[4][4]; - float viewvecs[3][4]; - float ssao_params[4]; - float ssao_settings[4]; - - /* Dof */ - struct GPUTexture *dof_blur_tx; - struct GPUTexture *coc_temp_tx; - struct GPUTexture *coc_tiles_tx[2]; - struct GPUUniformBuffer *dof_ubo; - float dof_aperturesize; - float dof_distance; - float dof_invsensorsize; - float dof_near_far[2]; - float dof_blades; - float dof_rotation; - float dof_ratio; - bool dof_enabled; - - /* Color Management */ - bool use_color_management; - bool use_color_render_settings; + struct GHash *material_hash; + struct GHash *material_transp_hash; + struct GPUShader *prepass_solid_sh; + struct GPUShader *prepass_solid_hair_sh; + struct GPUShader *prepass_texture_sh; + struct GPUShader *prepass_texture_hair_sh; + struct GPUShader *composite_sh; + struct GPUShader *background_sh; + struct GPUShader *transparent_accum_sh; + struct GPUShader *transparent_accum_hair_sh; + struct GPUShader *transparent_accum_texture_sh; + struct GPUShader *transparent_accum_texture_hair_sh; + View3DShading shading; + StudioLight *studio_light; + const UserDef *preferences; + struct GPUUniformBuffer *world_ubo; + struct DRWShadingGroup *shadow_shgrp; + struct DRWShadingGroup *depth_shgrp; + WORKBENCH_UBO_World world_data; + float shadow_multiplier; + float shadow_shift; + float shadow_focus; + float cached_shadow_direction[3]; + float shadow_mat[4][4]; + float shadow_inv[4][4]; + /* Far plane of the view frustum. */ + float shadow_far_plane[4]; + /* Near plane corners in shadow space. */ + float shadow_near_corners[4][3]; + /* min and max of shadow_near_corners. allow fast test */ + float shadow_near_min[3]; + float shadow_near_max[3]; + /* This is a parallelogram, so only 2 normal and distance to the edges. */ + float shadow_near_sides[2][4]; + bool shadow_changed; + bool is_playback; + + float (*world_clip_planes)[4]; + struct GPUBatch *world_clip_planes_batch; + float world_clip_planes_color[4]; + + /* Volumes */ + bool volumes_do; + ListBase smoke_domains; + + /* Ssao */ + float winmat[4][4]; + float viewvecs[3][4]; + float ssao_params[4]; + float ssao_settings[4]; + + /* Dof */ + struct GPUTexture *dof_blur_tx; + struct GPUTexture *coc_temp_tx; + struct GPUTexture *coc_tiles_tx[2]; + struct GPUUniformBuffer *dof_ubo; + float dof_aperturesize; + float dof_distance; + float dof_invsensorsize; + float dof_near_far[2]; + float dof_blades; + float dof_rotation; + float dof_ratio; + bool dof_enabled; + + /* Color Management */ + bool use_color_management; + bool use_color_render_settings; } WORKBENCH_PrivateData; /* Transient data */ typedef struct WORKBENCH_EffectInfo { - float override_persmat[4][4]; - float override_persinv[4][4]; - float override_winmat[4][4]; - float override_wininv[4][4]; - float last_mat[4][4]; - float curr_mat[4][4]; - int jitter_index; - float taa_mix_factor; - bool view_updated; + float override_persmat[4][4]; + float override_persinv[4][4]; + float override_winmat[4][4]; + float override_wininv[4][4]; + float last_mat[4][4]; + float curr_mat[4][4]; + int jitter_index; + float taa_mix_factor; + bool view_updated; } WORKBENCH_EffectInfo; typedef struct WORKBENCH_MaterialData { - float base_color[3]; - float diffuse_color[3]; - float specular_color[3]; - float metallic; - float roughness; - int object_id; - int color_type; - int interp; - Image *ima; - ImageUser *iuser; - - /* Linked shgroup for drawing */ - DRWShadingGroup *shgrp; - /* forward rendering */ - DRWShadingGroup *shgrp_object_outline; + float base_color[3]; + float diffuse_color[3]; + float specular_color[3]; + float metallic; + float roughness; + int object_id; + int color_type; + int interp; + Image *ima; + ImageUser *iuser; + + /* Linked shgroup for drawing */ + DRWShadingGroup *shgrp; + /* forward rendering */ + DRWShadingGroup *shgrp_object_outline; } WORKBENCH_MaterialData; typedef struct WORKBENCH_ObjectData { - DrawData dd; + DrawData dd; - /* Shadow direction in local object space. */ - float shadow_dir[3], shadow_depth; - /* Min, max in shadow space */ - float shadow_min[3], shadow_max[3]; - BoundBox shadow_bbox; - bool shadow_bbox_dirty; + /* Shadow direction in local object space. */ + float shadow_dir[3], shadow_depth; + /* Min, max in shadow space */ + float shadow_min[3], shadow_max[3]; + BoundBox shadow_bbox; + bool shadow_bbox_dirty; - int object_id; + int object_id; } WORKBENCH_ObjectData; /* workbench_deferred.c */ @@ -324,8 +347,13 @@ void workbench_forward_cache_finish(WORKBENCH_Data *vedata); /* For OIT in deferred */ void workbench_forward_outline_shaders_ensure(WORKBENCH_PrivateData *wpd, eGPUShaderConfig sh_cfg); void workbench_forward_choose_shaders(WORKBENCH_PrivateData *wpd, eGPUShaderConfig sh_cfg); -WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data( - WORKBENCH_Data *vedata, Object *ob, Material *mat, Image *ima, ImageUser *iuser, int color_type, int interp); +WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_Data *vedata, + Object *ob, + Material *mat, + Image *ima, + ImageUser *iuser, + int color_type, + int interp); /* workbench_effect_aa.c */ void workbench_aa_create_pass(WORKBENCH_Data *vedata, GPUTexture **tx); @@ -348,45 +376,79 @@ int workbench_taa_calculate_num_iterations(WORKBENCH_Data *vedata); /* workbench_effect_dof.c */ void workbench_dof_engine_init(WORKBENCH_Data *vedata, Object *camera); void workbench_dof_engine_free(void); -void workbench_dof_create_pass(WORKBENCH_Data *vedata, GPUTexture **dof_input, GPUTexture *noise_tex); +void workbench_dof_create_pass(WORKBENCH_Data *vedata, + GPUTexture **dof_input, + GPUTexture *noise_tex); void workbench_dof_draw_pass(WORKBENCH_Data *vedata); /* workbench_materials.c */ int workbench_material_determine_color_type(WORKBENCH_PrivateData *wpd, Image *ima, Object *ob); -void workbench_material_get_image_and_mat(Object *ob, int mat_nr, Image **r_image, ImageUser **r_iuser, int *r_interp, Material **r_mat); -char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair); -void workbench_material_update_data(WORKBENCH_PrivateData *wpd, Object *ob, Material *mat, WORKBENCH_MaterialData *data); +void workbench_material_get_image_and_mat( + Object *ob, int mat_nr, Image **r_image, ImageUser **r_iuser, int *r_interp, Material **r_mat); +char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, + bool use_textures, + bool is_hair); +void workbench_material_update_data(WORKBENCH_PrivateData *wpd, + Object *ob, + Material *mat, + WORKBENCH_MaterialData *data); uint workbench_material_get_hash(WORKBENCH_MaterialData *material_template, bool is_ghost); int workbench_material_get_composite_shader_index(WORKBENCH_PrivateData *wpd); -int workbench_material_get_prepass_shader_index(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair); -int workbench_material_get_accum_shader_index(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair); -void workbench_material_shgroup_uniform( - WORKBENCH_PrivateData *wpd, DRWShadingGroup *grp, WORKBENCH_MaterialData *material, Object *ob, - const bool use_metallic, const bool deferred, const int interp); -void workbench_material_copy(WORKBENCH_MaterialData *dest_material, const WORKBENCH_MaterialData *source_material); +int workbench_material_get_prepass_shader_index(WORKBENCH_PrivateData *wpd, + bool use_textures, + bool is_hair); +int workbench_material_get_accum_shader_index(WORKBENCH_PrivateData *wpd, + bool use_textures, + bool is_hair); +void workbench_material_shgroup_uniform(WORKBENCH_PrivateData *wpd, + DRWShadingGroup *grp, + WORKBENCH_MaterialData *material, + Object *ob, + const bool use_metallic, + const bool deferred, + const int interp); +void workbench_material_copy(WORKBENCH_MaterialData *dest_material, + const WORKBENCH_MaterialData *source_material); /* workbench_studiolight.c */ -void studiolight_update_world(WORKBENCH_PrivateData *wpd, StudioLight *sl, WORKBENCH_UBO_World *wd); +void studiolight_update_world(WORKBENCH_PrivateData *wpd, + StudioLight *sl, + WORKBENCH_UBO_World *wd); void studiolight_update_light(WORKBENCH_PrivateData *wpd, const float light_direction[3]); -bool studiolight_object_cast_visible_shadow(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed); -float studiolight_object_shadow_distance(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed); -bool studiolight_camera_in_object_shadow(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed); +bool studiolight_object_cast_visible_shadow(WORKBENCH_PrivateData *wpd, + Object *ob, + WORKBENCH_ObjectData *oed); +float studiolight_object_shadow_distance(WORKBENCH_PrivateData *wpd, + Object *ob, + WORKBENCH_ObjectData *oed); +bool studiolight_camera_in_object_shadow(WORKBENCH_PrivateData *wpd, + Object *ob, + WORKBENCH_ObjectData *oed); /* workbench_data.c */ void workbench_effect_info_init(WORKBENCH_EffectInfo *effect_info); void workbench_private_data_init(WORKBENCH_PrivateData *wpd); void workbench_private_data_free(WORKBENCH_PrivateData *wpd); -void workbench_private_data_get_light_direction(WORKBENCH_PrivateData *wpd, float r_light_direction[3]); +void workbench_private_data_get_light_direction(WORKBENCH_PrivateData *wpd, + float r_light_direction[3]); /* workbench_volume.c */ void workbench_volume_engine_init(void); void workbench_volume_engine_free(void); void workbench_volume_cache_init(WORKBENCH_Data *vedata); -void workbench_volume_cache_populate(WORKBENCH_Data *vedata, Scene *scene, Object *ob, struct ModifierData *md); +void workbench_volume_cache_populate(WORKBENCH_Data *vedata, + Scene *scene, + Object *ob, + struct ModifierData *md); void workbench_volume_smoke_textures_free(WORKBENCH_PrivateData *wpd); /* workbench_render.c */ -void workbench_render(WORKBENCH_Data *vedata, struct RenderEngine *engine, struct RenderLayer *render_layer, const struct rcti *rect); -void workbench_render_update_passes(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer); +void workbench_render(WORKBENCH_Data *vedata, + struct RenderEngine *engine, + struct RenderLayer *render_layer, + const struct rcti *rect); +void workbench_render_update_passes(struct RenderEngine *engine, + struct Scene *scene, + struct ViewLayer *view_layer); #endif diff --git a/source/blender/draw/engines/workbench/workbench_render.c b/source/blender/draw/engines/workbench/workbench_render.c index 663727285a1..1497ef493cf 100644 --- a/source/blender/draw/engines/workbench/workbench_render.c +++ b/source/blender/draw/engines/workbench/workbench_render.c @@ -39,177 +39,181 @@ #include "workbench_private.h" -static void workbench_render_deferred_cache( - void *vedata, struct Object *ob, - struct RenderEngine *UNUSED(engine), struct Depsgraph *UNUSED(depsgraph)) +static void workbench_render_deferred_cache(void *vedata, + struct Object *ob, + struct RenderEngine *UNUSED(engine), + struct Depsgraph *UNUSED(depsgraph)) { - workbench_deferred_solid_cache_populate(vedata, ob); + workbench_deferred_solid_cache_populate(vedata, ob); } -static void workbench_render_forward_cache( - void *vedata, struct Object *ob, - struct RenderEngine *UNUSED(engine), struct Depsgraph *UNUSED(depsgraph)) +static void workbench_render_forward_cache(void *vedata, + struct Object *ob, + struct RenderEngine *UNUSED(engine), + struct Depsgraph *UNUSED(depsgraph)) { - workbench_forward_cache_populate(vedata, ob); + workbench_forward_cache_populate(vedata, ob); } static void workbench_render_matrices_init(RenderEngine *engine, Depsgraph *depsgraph) { - /* TODO(sergey): Shall render hold pointer to an evaluated camera instead? */ - Scene *scene = DEG_get_evaluated_scene(depsgraph); - struct Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re)); - float frame = BKE_scene_frame_get(scene); - - /* Set the persective, view and window matrix. */ - float winmat[4][4], wininv[4][4]; - float viewmat[4][4], viewinv[4][4]; - float persmat[4][4], persinv[4][4]; - - RE_GetCameraWindow(engine->re, ob_camera_eval, frame, winmat); - RE_GetCameraModelMatrix(engine->re, ob_camera_eval, viewinv); - - invert_m4_m4(viewmat, viewinv); - mul_m4_m4m4(persmat, winmat, viewmat); - invert_m4_m4(persinv, persmat); - invert_m4_m4(wininv, winmat); - - DRW_viewport_matrix_override_set(persmat, DRW_MAT_PERS); - DRW_viewport_matrix_override_set(persinv, DRW_MAT_PERSINV); - DRW_viewport_matrix_override_set(winmat, DRW_MAT_WIN); - DRW_viewport_matrix_override_set(wininv, DRW_MAT_WININV); - DRW_viewport_matrix_override_set(viewmat, DRW_MAT_VIEW); - DRW_viewport_matrix_override_set(viewinv, DRW_MAT_VIEWINV); + /* TODO(sergey): Shall render hold pointer to an evaluated camera instead? */ + Scene *scene = DEG_get_evaluated_scene(depsgraph); + struct Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re)); + float frame = BKE_scene_frame_get(scene); + + /* Set the persective, view and window matrix. */ + float winmat[4][4], wininv[4][4]; + float viewmat[4][4], viewinv[4][4]; + float persmat[4][4], persinv[4][4]; + + RE_GetCameraWindow(engine->re, ob_camera_eval, frame, winmat); + RE_GetCameraModelMatrix(engine->re, ob_camera_eval, viewinv); + + invert_m4_m4(viewmat, viewinv); + mul_m4_m4m4(persmat, winmat, viewmat); + invert_m4_m4(persinv, persmat); + invert_m4_m4(wininv, winmat); + + DRW_viewport_matrix_override_set(persmat, DRW_MAT_PERS); + DRW_viewport_matrix_override_set(persinv, DRW_MAT_PERSINV); + DRW_viewport_matrix_override_set(winmat, DRW_MAT_WIN); + DRW_viewport_matrix_override_set(wininv, DRW_MAT_WININV); + DRW_viewport_matrix_override_set(viewmat, DRW_MAT_VIEW); + DRW_viewport_matrix_override_set(viewinv, DRW_MAT_VIEWINV); } static bool workbench_render_framebuffers_init(void) { - /* For image render, allocate own buffers because we don't have a viewport. */ - const float *viewport_size = DRW_viewport_size_get(); - const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; + /* For image render, allocate own buffers because we don't have a viewport. */ + const float *viewport_size = DRW_viewport_size_get(); + const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; - DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - dtxl->color = GPU_texture_create_2d(size[0], size[1], GPU_RGBA16F, NULL, NULL); - dtxl->depth = GPU_texture_create_2d(size[0], size[1], GPU_DEPTH24_STENCIL8, NULL, NULL); + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + dtxl->color = GPU_texture_create_2d(size[0], size[1], GPU_RGBA16F, NULL, NULL); + dtxl->depth = GPU_texture_create_2d(size[0], size[1], GPU_DEPTH24_STENCIL8, NULL, NULL); - if (!(dtxl->depth && dtxl->color)) { - return false; - } + if (!(dtxl->depth && dtxl->color)) { + return false; + } - DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); - GPU_framebuffer_ensure_config(&dfbl->default_fb, { - GPU_ATTACHMENT_TEXTURE(dtxl->depth), - GPU_ATTACHMENT_TEXTURE(dtxl->color) - }); + GPU_framebuffer_ensure_config( + &dfbl->default_fb, + {GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_TEXTURE(dtxl->color)}); - GPU_framebuffer_ensure_config(&dfbl->depth_only_fb, { - GPU_ATTACHMENT_TEXTURE(dtxl->depth), - GPU_ATTACHMENT_NONE - }); + GPU_framebuffer_ensure_config(&dfbl->depth_only_fb, + {GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_NONE}); - GPU_framebuffer_ensure_config(&dfbl->color_only_fb, { - GPU_ATTACHMENT_NONE, - GPU_ATTACHMENT_TEXTURE(dtxl->color) - }); + GPU_framebuffer_ensure_config(&dfbl->color_only_fb, + {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(dtxl->color)}); - bool ok = true; - ok = ok && GPU_framebuffer_check_valid(dfbl->default_fb, NULL); - ok = ok && GPU_framebuffer_check_valid(dfbl->color_only_fb, NULL); - ok = ok && GPU_framebuffer_check_valid(dfbl->depth_only_fb, NULL); + bool ok = true; + ok = ok && GPU_framebuffer_check_valid(dfbl->default_fb, NULL); + ok = ok && GPU_framebuffer_check_valid(dfbl->color_only_fb, NULL); + ok = ok && GPU_framebuffer_check_valid(dfbl->depth_only_fb, NULL); - return ok; + return ok; } static void workbench_render_framebuffers_finish(void) { } -void workbench_render(WORKBENCH_Data *data, RenderEngine *engine, RenderLayer *render_layer, const rcti *rect) +void workbench_render(WORKBENCH_Data *data, + RenderEngine *engine, + RenderLayer *render_layer, + const rcti *rect) { - DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); - const DRWContextState *draw_ctx = DRW_context_state_get(); - const Scene *scene = draw_ctx->scene; - Depsgraph *depsgraph = draw_ctx->depsgraph; - workbench_render_matrices_init(engine, depsgraph); - - if (!workbench_render_framebuffers_init()) { - RE_engine_report(engine, RPT_ERROR, "Failed to allocate OpenGL buffers"); - return; - } - - const bool deferred = !XRAY_FLAG_ENABLED(&scene->display); - - if (deferred) { - /* Init engine. */ - workbench_deferred_engine_init(data); - - /* Init objects. */ - workbench_deferred_cache_init(data); - DRW_render_object_iter(data, engine, depsgraph, workbench_render_deferred_cache); - workbench_deferred_cache_finish(data); - DRW_render_instance_buffer_finish(); - - /* Also we weed to have a correct fbo bound for DRW_hair_update */ - GPU_framebuffer_bind(dfbl->color_only_fb); - DRW_hair_update(); - - /* Draw. */ - int num_samples = workbench_taa_calculate_num_iterations(data); - for (int sample = 0; sample < num_samples; sample++) { - if (RE_engine_test_break(engine)) { - break; - } - /* TODO: Save matrices instead of recomputing them for each samples. */ - workbench_render_matrices_init(engine, depsgraph); - - workbench_deferred_draw_background(data); - workbench_deferred_draw_scene(data); - } - - workbench_deferred_draw_finish(data); - } - else { - /* Init engine. */ - workbench_forward_engine_init(data); - - /* Init objects. */ - workbench_forward_cache_init(data); - DRW_render_object_iter(data, engine, depsgraph, workbench_render_forward_cache); - workbench_forward_cache_finish(data); - DRW_render_instance_buffer_finish(); - - /* Also we weed to have a correct fbo bound for DRW_hair_update */ - GPU_framebuffer_bind(dfbl->color_only_fb); - DRW_hair_update(); - - /* Draw. */ - int num_samples = workbench_taa_calculate_num_iterations(data); - for (int sample = 0; sample < num_samples; sample++) { - if (RE_engine_test_break(engine)) { - break; - } - - workbench_forward_draw_background(data); - workbench_forward_draw_scene(data); - } - - workbench_forward_draw_finish(data); - } - - /* Write render output. */ - const char *viewname = RE_GetActiveRenderView(engine->re); - RenderPass *rp = RE_pass_find_by_name(render_layer, RE_PASSNAME_COMBINED, viewname); - - GPU_framebuffer_bind(dfbl->color_only_fb); - GPU_framebuffer_read_color(dfbl->color_only_fb, - rect->xmin, rect->ymin, - BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), - 4, 0, rp->rect); - - workbench_render_framebuffers_finish(); + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + const DRWContextState *draw_ctx = DRW_context_state_get(); + const Scene *scene = draw_ctx->scene; + Depsgraph *depsgraph = draw_ctx->depsgraph; + workbench_render_matrices_init(engine, depsgraph); + + if (!workbench_render_framebuffers_init()) { + RE_engine_report(engine, RPT_ERROR, "Failed to allocate OpenGL buffers"); + return; + } + + const bool deferred = !XRAY_FLAG_ENABLED(&scene->display); + + if (deferred) { + /* Init engine. */ + workbench_deferred_engine_init(data); + + /* Init objects. */ + workbench_deferred_cache_init(data); + DRW_render_object_iter(data, engine, depsgraph, workbench_render_deferred_cache); + workbench_deferred_cache_finish(data); + DRW_render_instance_buffer_finish(); + + /* Also we weed to have a correct fbo bound for DRW_hair_update */ + GPU_framebuffer_bind(dfbl->color_only_fb); + DRW_hair_update(); + + /* Draw. */ + int num_samples = workbench_taa_calculate_num_iterations(data); + for (int sample = 0; sample < num_samples; sample++) { + if (RE_engine_test_break(engine)) { + break; + } + /* TODO: Save matrices instead of recomputing them for each samples. */ + workbench_render_matrices_init(engine, depsgraph); + + workbench_deferred_draw_background(data); + workbench_deferred_draw_scene(data); + } + + workbench_deferred_draw_finish(data); + } + else { + /* Init engine. */ + workbench_forward_engine_init(data); + + /* Init objects. */ + workbench_forward_cache_init(data); + DRW_render_object_iter(data, engine, depsgraph, workbench_render_forward_cache); + workbench_forward_cache_finish(data); + DRW_render_instance_buffer_finish(); + + /* Also we weed to have a correct fbo bound for DRW_hair_update */ + GPU_framebuffer_bind(dfbl->color_only_fb); + DRW_hair_update(); + + /* Draw. */ + int num_samples = workbench_taa_calculate_num_iterations(data); + for (int sample = 0; sample < num_samples; sample++) { + if (RE_engine_test_break(engine)) { + break; + } + + workbench_forward_draw_background(data); + workbench_forward_draw_scene(data); + } + + workbench_forward_draw_finish(data); + } + + /* Write render output. */ + const char *viewname = RE_GetActiveRenderView(engine->re); + RenderPass *rp = RE_pass_find_by_name(render_layer, RE_PASSNAME_COMBINED, viewname); + + GPU_framebuffer_bind(dfbl->color_only_fb); + GPU_framebuffer_read_color(dfbl->color_only_fb, + rect->xmin, + rect->ymin, + BLI_rcti_size_x(rect), + BLI_rcti_size_y(rect), + 4, + 0, + rp->rect); + + workbench_render_framebuffers_finish(); } void workbench_render_update_passes(RenderEngine *engine, Scene *scene, ViewLayer *view_layer) { - RE_engine_register_pass(engine, scene, view_layer, RE_PASSNAME_COMBINED, 4, "RGBA", SOCK_RGBA); + RE_engine_register_pass(engine, scene, view_layer, RE_PASSNAME_COMBINED, 4, "RGBA", SOCK_RGBA); } diff --git a/source/blender/draw/engines/workbench/workbench_studiolight.c b/source/blender/draw/engines/workbench/workbench_studiolight.c index f382ad31752..5c95a835adc 100644 --- a/source/blender/draw/engines/workbench/workbench_studiolight.c +++ b/source/blender/draw/engines/workbench/workbench_studiolight.c @@ -27,266 +27,286 @@ #include "BLI_math.h" -void studiolight_update_world(WORKBENCH_PrivateData *wpd, StudioLight *studiolight, WORKBENCH_UBO_World *wd) +void studiolight_update_world(WORKBENCH_PrivateData *wpd, + StudioLight *studiolight, + WORKBENCH_UBO_World *wd) { - float view_matrix[4][4], rot_matrix[4][4]; - DRW_viewport_matrix_get(view_matrix, DRW_MAT_VIEW); - - if (USE_WORLD_ORIENTATION(wpd)) { - axis_angle_to_mat4_single(rot_matrix, 'Z', -wpd->shading.studiolight_rot_z); - mul_m4_m4m4(rot_matrix, view_matrix, rot_matrix); - swap_v3_v3(rot_matrix[2], rot_matrix[1]); - negate_v3(rot_matrix[2]); - } - else { - unit_m4(rot_matrix); - } - - if (U.edit_studio_light) { - studiolight = BKE_studiolight_studio_edit_get(); - } - - /* Studio Lights. */ - for (int i = 0; i < 4; i++) { - WORKBENCH_UBO_Light *light = &wd->lights[i]; - - SolidLight *sl = &studiolight->light[i]; - if (sl->flag) { - copy_v3_v3(light->light_direction, sl->vec); - mul_mat3_m4_v3(rot_matrix, light->light_direction); - /* We should predivide the power by PI but that makes the lights really dim. */ - copy_v3_v3(light->specular_color, sl->spec); - copy_v3_v3(light->diffuse_color, sl->col); - light->wrapped = sl->smooth; - } - else { - copy_v3_fl3(light->light_direction, 1.0f, 0.0f, 0.0f); - copy_v3_fl(light->specular_color, 0.0f); - copy_v3_fl(light->diffuse_color, 0.0f); - } - } - - copy_v3_v3(wd->ambient_color, studiolight->light_ambient); + float view_matrix[4][4], rot_matrix[4][4]; + DRW_viewport_matrix_get(view_matrix, DRW_MAT_VIEW); + + if (USE_WORLD_ORIENTATION(wpd)) { + axis_angle_to_mat4_single(rot_matrix, 'Z', -wpd->shading.studiolight_rot_z); + mul_m4_m4m4(rot_matrix, view_matrix, rot_matrix); + swap_v3_v3(rot_matrix[2], rot_matrix[1]); + negate_v3(rot_matrix[2]); + } + else { + unit_m4(rot_matrix); + } + + if (U.edit_studio_light) { + studiolight = BKE_studiolight_studio_edit_get(); + } + + /* Studio Lights. */ + for (int i = 0; i < 4; i++) { + WORKBENCH_UBO_Light *light = &wd->lights[i]; + + SolidLight *sl = &studiolight->light[i]; + if (sl->flag) { + copy_v3_v3(light->light_direction, sl->vec); + mul_mat3_m4_v3(rot_matrix, light->light_direction); + /* We should predivide the power by PI but that makes the lights really dim. */ + copy_v3_v3(light->specular_color, sl->spec); + copy_v3_v3(light->diffuse_color, sl->col); + light->wrapped = sl->smooth; + } + else { + copy_v3_fl3(light->light_direction, 1.0f, 0.0f, 0.0f); + copy_v3_fl(light->specular_color, 0.0f); + copy_v3_fl(light->diffuse_color, 0.0f); + } + } + + copy_v3_v3(wd->ambient_color, studiolight->light_ambient); #if 0 - BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_SPHERICAL_HARMONICS_COEFFICIENTS_CALCULATED); - -#if STUDIOLIGHT_SH_BANDS == 2 - /* Use Geomerics non-linear SH. */ - mul_v3_v3fl(wd->spherical_harmonics_coefs[0], sl->spherical_harmonics_coefs[0], M_1_PI); - /* Swizzle to make shader code simpler. */ - for (int i = 0; i < 3; ++i) { - copy_v3_fl3( - wd->spherical_harmonics_coefs[i + 1], - -sl->spherical_harmonics_coefs[3][i], - sl->spherical_harmonics_coefs[2][i], - -sl->spherical_harmonics_coefs[1][i]); - mul_v3_fl(wd->spherical_harmonics_coefs[i + 1], M_1_PI * 1.5f); /* 1.5f is to improve the contrast a bit. */ - } - - /* Precompute as much as we can. See shader code for derivation. */ - float len_r1[3], lr1_r0[3], p[3], a[3]; - for (int i = 0; i < 3; ++i) { - mul_v3_fl(wd->spherical_harmonics_coefs[i + 1], 0.5f); - len_r1[i] = len_v3(wd->spherical_harmonics_coefs[i + 1]); - mul_v3_fl(wd->spherical_harmonics_coefs[i + 1], 1.0f / len_r1[i]); - } - /* lr1_r0 = lenR1 / R0; */ - copy_v3_v3(lr1_r0, wd->spherical_harmonics_coefs[0]); - invert_v3(lr1_r0); - mul_v3_v3(lr1_r0, len_r1); - /* p = 1.0 + 2.0 * lr1_r0; */ - copy_v3_v3(p, lr1_r0); - mul_v3_fl(p, 2.0f); - add_v3_fl(p, 1.0f); - /* a = (1.0 - lr1_r0) / (1.0 + lr1_r0); */ - copy_v3_v3(a, lr1_r0); - add_v3_fl(a, 1.0f); - invert_v3(a); - negate_v3(lr1_r0); - add_v3_fl(lr1_r0, 1.0f); - mul_v3_v3(a, lr1_r0); - /* sh_coefs[4] = p; */ - copy_v3_v3(wd->spherical_harmonics_coefs[4], p); - /* sh_coefs[5] = R0 * a; */ - mul_v3_v3v3(wd->spherical_harmonics_coefs[5], wd->spherical_harmonics_coefs[0], a); - /* sh_coefs[0] = R0 * (1.0 - a) * (p + 1.0); */ - negate_v3(a); - add_v3_fl(a, 1.0f); - add_v3_fl(p, 1.0f); - mul_v3_v3(a, p); - mul_v3_v3(wd->spherical_harmonics_coefs[0], a); -#else - for (int i = 0; i < STUDIOLIGHT_SH_EFFECTIVE_COEFS_LEN; i++) { - /* Can't memcpy because of alignment */ - copy_v3_v3(wd->spherical_harmonics_coefs[i], sl->spherical_harmonics_coefs[i]); - } -#endif + BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_SPHERICAL_HARMONICS_COEFFICIENTS_CALCULATED); + +# if STUDIOLIGHT_SH_BANDS == 2 + /* Use Geomerics non-linear SH. */ + mul_v3_v3fl(wd->spherical_harmonics_coefs[0], sl->spherical_harmonics_coefs[0], M_1_PI); + /* Swizzle to make shader code simpler. */ + for (int i = 0; i < 3; ++i) { + copy_v3_fl3( + wd->spherical_harmonics_coefs[i + 1], + -sl->spherical_harmonics_coefs[3][i], + sl->spherical_harmonics_coefs[2][i], + -sl->spherical_harmonics_coefs[1][i]); + mul_v3_fl(wd->spherical_harmonics_coefs[i + 1], M_1_PI * 1.5f); /* 1.5f is to improve the contrast a bit. */ + } + + /* Precompute as much as we can. See shader code for derivation. */ + float len_r1[3], lr1_r0[3], p[3], a[3]; + for (int i = 0; i < 3; ++i) { + mul_v3_fl(wd->spherical_harmonics_coefs[i + 1], 0.5f); + len_r1[i] = len_v3(wd->spherical_harmonics_coefs[i + 1]); + mul_v3_fl(wd->spherical_harmonics_coefs[i + 1], 1.0f / len_r1[i]); + } + /* lr1_r0 = lenR1 / R0; */ + copy_v3_v3(lr1_r0, wd->spherical_harmonics_coefs[0]); + invert_v3(lr1_r0); + mul_v3_v3(lr1_r0, len_r1); + /* p = 1.0 + 2.0 * lr1_r0; */ + copy_v3_v3(p, lr1_r0); + mul_v3_fl(p, 2.0f); + add_v3_fl(p, 1.0f); + /* a = (1.0 - lr1_r0) / (1.0 + lr1_r0); */ + copy_v3_v3(a, lr1_r0); + add_v3_fl(a, 1.0f); + invert_v3(a); + negate_v3(lr1_r0); + add_v3_fl(lr1_r0, 1.0f); + mul_v3_v3(a, lr1_r0); + /* sh_coefs[4] = p; */ + copy_v3_v3(wd->spherical_harmonics_coefs[4], p); + /* sh_coefs[5] = R0 * a; */ + mul_v3_v3v3(wd->spherical_harmonics_coefs[5], wd->spherical_harmonics_coefs[0], a); + /* sh_coefs[0] = R0 * (1.0 - a) * (p + 1.0); */ + negate_v3(a); + add_v3_fl(a, 1.0f); + add_v3_fl(p, 1.0f); + mul_v3_v3(a, p); + mul_v3_v3(wd->spherical_harmonics_coefs[0], a); +# else + for (int i = 0; i < STUDIOLIGHT_SH_EFFECTIVE_COEFS_LEN; i++) { + /* Can't memcpy because of alignment */ + copy_v3_v3(wd->spherical_harmonics_coefs[i], sl->spherical_harmonics_coefs[i]); + } +# endif #endif } -static void compute_parallel_lines_nor_and_dist(const float v1[2], const float v2[2], const float v3[2], float r_line[2]) +static void compute_parallel_lines_nor_and_dist(const float v1[2], + const float v2[2], + const float v3[2], + float r_line[2]) { - sub_v2_v2v2(r_line, v2, v1); - /* Find orthogonal vector. */ - SWAP(float, r_line[0], r_line[1]); - r_line[0] = -r_line[0]; - /* Edge distances. */ - r_line[2] = dot_v2v2(r_line, v1); - r_line[3] = dot_v2v2(r_line, v3); - /* Make sure r_line[2] is the minimum. */ - if (r_line[2] > r_line[3]) { - SWAP(float, r_line[2], r_line[3]); - } + sub_v2_v2v2(r_line, v2, v1); + /* Find orthogonal vector. */ + SWAP(float, r_line[0], r_line[1]); + r_line[0] = -r_line[0]; + /* Edge distances. */ + r_line[2] = dot_v2v2(r_line, v1); + r_line[3] = dot_v2v2(r_line, v3); + /* Make sure r_line[2] is the minimum. */ + if (r_line[2] > r_line[3]) { + SWAP(float, r_line[2], r_line[3]); + } } void studiolight_update_light(WORKBENCH_PrivateData *wpd, const float light_direction[3]) { - wpd->shadow_changed = !compare_v3v3(wpd->cached_shadow_direction, light_direction, 1e-5f); - - if (wpd->shadow_changed) { - float up[3] = {0.0f, 0.0f, 1.0f}; - unit_m4(wpd->shadow_mat); - - /* TODO fix singularity. */ - copy_v3_v3(wpd->shadow_mat[2], light_direction); - cross_v3_v3v3(wpd->shadow_mat[0], wpd->shadow_mat[2], up); - normalize_v3(wpd->shadow_mat[0]); - cross_v3_v3v3(wpd->shadow_mat[1], wpd->shadow_mat[2], wpd->shadow_mat[0]); - - invert_m4_m4(wpd->shadow_inv, wpd->shadow_mat); - - copy_v3_v3(wpd->cached_shadow_direction, light_direction); - } - - float planes[6][4]; - DRW_culling_frustum_planes_get(planes); - /* we only need the far plane. */ - copy_v4_v4(wpd->shadow_far_plane, planes[2]); - - BoundBox frustum_corners; - DRW_culling_frustum_corners_get(&frustum_corners); - - mul_v3_mat3_m4v3(wpd->shadow_near_corners[0], wpd->shadow_inv, frustum_corners.vec[0]); - mul_v3_mat3_m4v3(wpd->shadow_near_corners[1], wpd->shadow_inv, frustum_corners.vec[3]); - mul_v3_mat3_m4v3(wpd->shadow_near_corners[2], wpd->shadow_inv, frustum_corners.vec[7]); - mul_v3_mat3_m4v3(wpd->shadow_near_corners[3], wpd->shadow_inv, frustum_corners.vec[4]); - - INIT_MINMAX(wpd->shadow_near_min, wpd->shadow_near_max); - for (int i = 0; i < 4; ++i) { - minmax_v3v3_v3(wpd->shadow_near_min, wpd->shadow_near_max, wpd->shadow_near_corners[i]); - } - - compute_parallel_lines_nor_and_dist(wpd->shadow_near_corners[0], wpd->shadow_near_corners[1], wpd->shadow_near_corners[2], wpd->shadow_near_sides[0]); - compute_parallel_lines_nor_and_dist(wpd->shadow_near_corners[1], wpd->shadow_near_corners[2], wpd->shadow_near_corners[0], wpd->shadow_near_sides[1]); + wpd->shadow_changed = !compare_v3v3(wpd->cached_shadow_direction, light_direction, 1e-5f); + + if (wpd->shadow_changed) { + float up[3] = {0.0f, 0.0f, 1.0f}; + unit_m4(wpd->shadow_mat); + + /* TODO fix singularity. */ + copy_v3_v3(wpd->shadow_mat[2], light_direction); + cross_v3_v3v3(wpd->shadow_mat[0], wpd->shadow_mat[2], up); + normalize_v3(wpd->shadow_mat[0]); + cross_v3_v3v3(wpd->shadow_mat[1], wpd->shadow_mat[2], wpd->shadow_mat[0]); + + invert_m4_m4(wpd->shadow_inv, wpd->shadow_mat); + + copy_v3_v3(wpd->cached_shadow_direction, light_direction); + } + + float planes[6][4]; + DRW_culling_frustum_planes_get(planes); + /* we only need the far plane. */ + copy_v4_v4(wpd->shadow_far_plane, planes[2]); + + BoundBox frustum_corners; + DRW_culling_frustum_corners_get(&frustum_corners); + + mul_v3_mat3_m4v3(wpd->shadow_near_corners[0], wpd->shadow_inv, frustum_corners.vec[0]); + mul_v3_mat3_m4v3(wpd->shadow_near_corners[1], wpd->shadow_inv, frustum_corners.vec[3]); + mul_v3_mat3_m4v3(wpd->shadow_near_corners[2], wpd->shadow_inv, frustum_corners.vec[7]); + mul_v3_mat3_m4v3(wpd->shadow_near_corners[3], wpd->shadow_inv, frustum_corners.vec[4]); + + INIT_MINMAX(wpd->shadow_near_min, wpd->shadow_near_max); + for (int i = 0; i < 4; ++i) { + minmax_v3v3_v3(wpd->shadow_near_min, wpd->shadow_near_max, wpd->shadow_near_corners[i]); + } + + compute_parallel_lines_nor_and_dist(wpd->shadow_near_corners[0], + wpd->shadow_near_corners[1], + wpd->shadow_near_corners[2], + wpd->shadow_near_sides[0]); + compute_parallel_lines_nor_and_dist(wpd->shadow_near_corners[1], + wpd->shadow_near_corners[2], + wpd->shadow_near_corners[0], + wpd->shadow_near_sides[1]); } -static BoundBox *studiolight_object_shadow_bbox_get(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed) +static BoundBox *studiolight_object_shadow_bbox_get(WORKBENCH_PrivateData *wpd, + Object *ob, + WORKBENCH_ObjectData *oed) { - if ((oed->shadow_bbox_dirty) || (wpd->shadow_changed)) { - float tmp_mat[4][4]; - mul_m4_m4m4(tmp_mat, wpd->shadow_inv, ob->obmat); - - /* Get AABB in shadow space. */ - INIT_MINMAX(oed->shadow_min, oed->shadow_max); - - /* From object space to shadow space */ - BoundBox *bbox = BKE_object_boundbox_get(ob); - for (int i = 0; i < 8; ++i) { - float corner[3]; - mul_v3_m4v3(corner, tmp_mat, bbox->vec[i]); - minmax_v3v3_v3(oed->shadow_min, oed->shadow_max, corner); - } - oed->shadow_depth = oed->shadow_max[2] - oed->shadow_min[2]; - /* Extend towards infinity. */ - oed->shadow_max[2] += 1e4f; - - /* Get extended AABB in world space. */ - BKE_boundbox_init_from_minmax(&oed->shadow_bbox, oed->shadow_min, oed->shadow_max); - for (int i = 0; i < 8; ++i) { - mul_m4_v3(wpd->shadow_mat, oed->shadow_bbox.vec[i]); - } - oed->shadow_bbox_dirty = false; - } - - return &oed->shadow_bbox; + if ((oed->shadow_bbox_dirty) || (wpd->shadow_changed)) { + float tmp_mat[4][4]; + mul_m4_m4m4(tmp_mat, wpd->shadow_inv, ob->obmat); + + /* Get AABB in shadow space. */ + INIT_MINMAX(oed->shadow_min, oed->shadow_max); + + /* From object space to shadow space */ + BoundBox *bbox = BKE_object_boundbox_get(ob); + for (int i = 0; i < 8; ++i) { + float corner[3]; + mul_v3_m4v3(corner, tmp_mat, bbox->vec[i]); + minmax_v3v3_v3(oed->shadow_min, oed->shadow_max, corner); + } + oed->shadow_depth = oed->shadow_max[2] - oed->shadow_min[2]; + /* Extend towards infinity. */ + oed->shadow_max[2] += 1e4f; + + /* Get extended AABB in world space. */ + BKE_boundbox_init_from_minmax(&oed->shadow_bbox, oed->shadow_min, oed->shadow_max); + for (int i = 0; i < 8; ++i) { + mul_m4_v3(wpd->shadow_mat, oed->shadow_bbox.vec[i]); + } + oed->shadow_bbox_dirty = false; + } + + return &oed->shadow_bbox; } -bool studiolight_object_cast_visible_shadow(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed) +bool studiolight_object_cast_visible_shadow(WORKBENCH_PrivateData *wpd, + Object *ob, + WORKBENCH_ObjectData *oed) { - BoundBox *shadow_bbox = studiolight_object_shadow_bbox_get(wpd, ob, oed); - return DRW_culling_box_test(shadow_bbox); + BoundBox *shadow_bbox = studiolight_object_shadow_bbox_get(wpd, ob, oed); + return DRW_culling_box_test(shadow_bbox); } -float studiolight_object_shadow_distance(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed) +float studiolight_object_shadow_distance(WORKBENCH_PrivateData *wpd, + Object *ob, + WORKBENCH_ObjectData *oed) { - BoundBox *shadow_bbox = studiolight_object_shadow_bbox_get(wpd, ob, oed); - - int corners[4] = {0, 3, 4, 7}; - float dist = 1e4f, dist_isect; - for (int i = 0; i < 4; ++i) { - if (isect_ray_plane_v3(shadow_bbox->vec[corners[i]], - wpd->cached_shadow_direction, - wpd->shadow_far_plane, - &dist_isect, true)) - { - if (dist_isect < dist) { - dist = dist_isect; - } - } - else { - /* All rays are parallels. If one fails, the other will too. */ - break; - } - } - return max_ii(dist - oed->shadow_depth, 0); + BoundBox *shadow_bbox = studiolight_object_shadow_bbox_get(wpd, ob, oed); + + int corners[4] = {0, 3, 4, 7}; + float dist = 1e4f, dist_isect; + for (int i = 0; i < 4; ++i) { + if (isect_ray_plane_v3(shadow_bbox->vec[corners[i]], + wpd->cached_shadow_direction, + wpd->shadow_far_plane, + &dist_isect, + true)) { + if (dist_isect < dist) { + dist = dist_isect; + } + } + else { + /* All rays are parallels. If one fails, the other will too. */ + break; + } + } + return max_ii(dist - oed->shadow_depth, 0); } -bool studiolight_camera_in_object_shadow(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed) +bool studiolight_camera_in_object_shadow(WORKBENCH_PrivateData *wpd, + Object *ob, + WORKBENCH_ObjectData *oed) { - /* Just to be sure the min, max are updated. */ - studiolight_object_shadow_bbox_get(wpd, ob, oed); - - /* Test if near plane is in front of the shadow. */ - if (oed->shadow_min[2] > wpd->shadow_near_max[2]) { - return false; - } - - /* Separation Axis Theorem test */ - - /* Test bbox sides first (faster) */ - if ((oed->shadow_min[0] > wpd->shadow_near_max[0]) || - (oed->shadow_max[0] < wpd->shadow_near_min[0]) || - (oed->shadow_min[1] > wpd->shadow_near_max[1]) || - (oed->shadow_max[1] < wpd->shadow_near_min[1])) - { - return false; - } - - /* Test projected near rectangle sides */ - float pts[4][2] = { - {oed->shadow_min[0], oed->shadow_min[1]}, - {oed->shadow_min[0], oed->shadow_max[1]}, - {oed->shadow_max[0], oed->shadow_min[1]}, - {oed->shadow_max[0], oed->shadow_max[1]}, - }; - - for (int i = 0; i < 2; ++i) { - float min_dst = FLT_MAX, max_dst = -FLT_MAX; - for (int j = 0; j < 4; ++j) { - float dst = dot_v2v2(wpd->shadow_near_sides[i], pts[j]); - /* Do min max */ - if (min_dst > dst) { min_dst = dst; } - if (max_dst < dst) { max_dst = dst; } - } - - if ((wpd->shadow_near_sides[i][2] > max_dst) || - (wpd->shadow_near_sides[i][3] < min_dst)) - { - return false; - } - } - - /* No separation axis found. Both shape intersect. */ - return true; + /* Just to be sure the min, max are updated. */ + studiolight_object_shadow_bbox_get(wpd, ob, oed); + + /* Test if near plane is in front of the shadow. */ + if (oed->shadow_min[2] > wpd->shadow_near_max[2]) { + return false; + } + + /* Separation Axis Theorem test */ + + /* Test bbox sides first (faster) */ + if ((oed->shadow_min[0] > wpd->shadow_near_max[0]) || + (oed->shadow_max[0] < wpd->shadow_near_min[0]) || + (oed->shadow_min[1] > wpd->shadow_near_max[1]) || + (oed->shadow_max[1] < wpd->shadow_near_min[1])) { + return false; + } + + /* Test projected near rectangle sides */ + float pts[4][2] = { + {oed->shadow_min[0], oed->shadow_min[1]}, + {oed->shadow_min[0], oed->shadow_max[1]}, + {oed->shadow_max[0], oed->shadow_min[1]}, + {oed->shadow_max[0], oed->shadow_max[1]}, + }; + + for (int i = 0; i < 2; ++i) { + float min_dst = FLT_MAX, max_dst = -FLT_MAX; + for (int j = 0; j < 4; ++j) { + float dst = dot_v2v2(wpd->shadow_near_sides[i], pts[j]); + /* Do min max */ + if (min_dst > dst) { + min_dst = dst; + } + if (max_dst < dst) { + max_dst = dst; + } + } + + if ((wpd->shadow_near_sides[i][2] > max_dst) || (wpd->shadow_near_sides[i][3] < min_dst)) { + return false; + } + } + + /* No separation axis found. Both shape intersect. */ + return true; } diff --git a/source/blender/draw/engines/workbench/workbench_volume.c b/source/blender/draw/engines/workbench/workbench_volume.c index 0f5debc46d8..accc7e91576 100644 --- a/source/blender/draw/engines/workbench/workbench_volume.c +++ b/source/blender/draw/engines/workbench/workbench_volume.c @@ -35,20 +35,20 @@ #include "GPU_draw.h" enum { - VOLUME_SH_SLICE = 0, - VOLUME_SH_COBA, - VOLUME_SH_CUBIC, + VOLUME_SH_SLICE = 0, + VOLUME_SH_COBA, + VOLUME_SH_CUBIC, }; #define VOLUME_SH_MAX (1 << (VOLUME_SH_CUBIC + 1)) static struct { - struct GPUShader *volume_sh[VOLUME_SH_MAX]; - struct GPUShader *volume_coba_sh; - struct GPUShader *volume_slice_sh; - struct GPUShader *volume_slice_coba_sh; - struct GPUTexture *dummy_tex; - struct GPUTexture *dummy_coba_tex; + struct GPUShader *volume_sh[VOLUME_SH_MAX]; + struct GPUShader *volume_coba_sh; + struct GPUShader *volume_slice_sh; + struct GPUShader *volume_slice_coba_sh; + struct GPUTexture *dummy_tex; + struct GPUTexture *dummy_coba_tex; } e_data = {{NULL}}; extern char datatoc_workbench_volume_vert_glsl[]; @@ -56,174 +56,177 @@ extern char datatoc_workbench_volume_frag_glsl[]; static GPUShader *volume_shader_get(bool slice, bool coba, bool cubic) { - int id = 0; - id += (slice) ? (1 << VOLUME_SH_SLICE) : 0; - id += (coba) ? (1 << VOLUME_SH_COBA) : 0; - id += (cubic) ? (1 << VOLUME_SH_CUBIC) : 0; - - if (!e_data.volume_sh[id]) { - DynStr *ds = BLI_dynstr_new(); - - if (slice) { - BLI_dynstr_append(ds, "#define VOLUME_SLICE\n"); - } - if (coba) { - BLI_dynstr_append(ds, "#define USE_COBA\n"); - } - if (cubic) { - BLI_dynstr_append(ds, "#define USE_TRICUBIC\n"); - } - - char *defines = BLI_dynstr_get_cstring(ds); - BLI_dynstr_free(ds); - - e_data.volume_sh[id] = DRW_shader_create( - datatoc_workbench_volume_vert_glsl, NULL, - datatoc_workbench_volume_frag_glsl, - defines); - - MEM_freeN(defines); - } - - return e_data.volume_sh[id]; + int id = 0; + id += (slice) ? (1 << VOLUME_SH_SLICE) : 0; + id += (coba) ? (1 << VOLUME_SH_COBA) : 0; + id += (cubic) ? (1 << VOLUME_SH_CUBIC) : 0; + + if (!e_data.volume_sh[id]) { + DynStr *ds = BLI_dynstr_new(); + + if (slice) { + BLI_dynstr_append(ds, "#define VOLUME_SLICE\n"); + } + if (coba) { + BLI_dynstr_append(ds, "#define USE_COBA\n"); + } + if (cubic) { + BLI_dynstr_append(ds, "#define USE_TRICUBIC\n"); + } + + char *defines = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); + + e_data.volume_sh[id] = DRW_shader_create( + datatoc_workbench_volume_vert_glsl, NULL, datatoc_workbench_volume_frag_glsl, defines); + + MEM_freeN(defines); + } + + return e_data.volume_sh[id]; } void workbench_volume_engine_init(void) { - if (!e_data.dummy_tex) { - float pixel[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - e_data.dummy_tex = GPU_texture_create_3d(1, 1, 1, GPU_RGBA8, pixel, NULL); - e_data.dummy_coba_tex = GPU_texture_create_1d(1, GPU_RGBA8, pixel, NULL); - } + if (!e_data.dummy_tex) { + float pixel[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + e_data.dummy_tex = GPU_texture_create_3d(1, 1, 1, GPU_RGBA8, pixel, NULL); + e_data.dummy_coba_tex = GPU_texture_create_1d(1, GPU_RGBA8, pixel, NULL); + } } void workbench_volume_engine_free(void) { - for (int i = 0; i < VOLUME_SH_MAX; ++i) { - DRW_SHADER_FREE_SAFE(e_data.volume_sh[i]); - } - DRW_TEXTURE_FREE_SAFE(e_data.dummy_tex); - DRW_TEXTURE_FREE_SAFE(e_data.dummy_coba_tex); + for (int i = 0; i < VOLUME_SH_MAX; ++i) { + DRW_SHADER_FREE_SAFE(e_data.volume_sh[i]); + } + DRW_TEXTURE_FREE_SAFE(e_data.dummy_tex); + DRW_TEXTURE_FREE_SAFE(e_data.dummy_coba_tex); } void workbench_volume_cache_init(WORKBENCH_Data *vedata) { - vedata->psl->volume_pass = DRW_pass_create("Volumes", DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_PREMUL | DRW_STATE_CULL_FRONT); + vedata->psl->volume_pass = DRW_pass_create( + "Volumes", DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_PREMUL | DRW_STATE_CULL_FRONT); } -void workbench_volume_cache_populate(WORKBENCH_Data *vedata, Scene *scene, Object *ob, ModifierData *md) +void workbench_volume_cache_populate(WORKBENCH_Data *vedata, + Scene *scene, + Object *ob, + ModifierData *md) { - SmokeModifierData *smd = (SmokeModifierData *)md; - SmokeDomainSettings *sds = smd->domain; - WORKBENCH_PrivateData *wpd = vedata->stl->g_data; - WORKBENCH_EffectInfo *effect_info = vedata->stl->effects; - DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - DRWShadingGroup *grp = NULL; - - /* Don't show smoke before simulation starts, this could be made an option in the future. */ - if (!sds->fluid || CFRA < sds->point_cache[0]->startframe) { - return; - } - - wpd->volumes_do = true; - const bool show_highres = BKE_smoke_show_highres(scene, sds); - if (sds->use_coba) { - GPU_create_smoke_coba_field(smd); - } - else if (!sds->wt || !show_highres) { - GPU_create_smoke(smd, 0); - } - else if (sds->wt && show_highres) { - GPU_create_smoke(smd, 1); - } - - if ((!sds->use_coba && sds->tex == NULL) || - (sds->use_coba && sds->tex_field == NULL)) - { - return; - } - - const bool use_slice = (sds->slice_method == MOD_SMOKE_SLICE_AXIS_ALIGNED && - sds->axis_slice_method == AXIS_SLICE_SINGLE); - const bool cubic_interp = (sds->interp_method == VOLUME_INTERP_CUBIC); - GPUShader *sh = volume_shader_get(use_slice, sds->use_coba, cubic_interp); - - if (use_slice) { - float invviewmat[4][4]; - DRW_viewport_matrix_get(invviewmat, DRW_MAT_VIEWINV); - - const int axis = (sds->slice_axis == SLICE_AXIS_AUTO) - ? axis_dominant_v3_single(invviewmat[2]) - : sds->slice_axis - 1; - float dim[3]; - BKE_object_dimensions_get(ob, dim); - /* 0.05f to acheive somewhat the same opacity as the full view. */ - float step_length = max_ff(1e-16f, dim[axis] * 0.05f); - - grp = DRW_shgroup_create(sh, vedata->psl->volume_pass); - DRW_shgroup_uniform_float_copy(grp, "slicePosition", sds->slice_depth); - DRW_shgroup_uniform_int_copy(grp, "sliceAxis", axis); - DRW_shgroup_uniform_float_copy(grp, "stepLength", step_length); - DRW_shgroup_state_disable(grp, DRW_STATE_CULL_FRONT); - } - else { - double noise_ofs; - BLI_halton_1d(3, 0.0, effect_info->jitter_index, &noise_ofs); - float dim[3], step_length, max_slice; - float slice_ct[3] = {sds->res[0], sds->res[1], sds->res[2]}; - mul_v3_fl(slice_ct, max_ff(0.001f, sds->slice_per_voxel)); - max_slice = max_fff(slice_ct[0], slice_ct[1], slice_ct[2]); - BKE_object_dimensions_get(ob, dim); - invert_v3(slice_ct); - mul_v3_v3(dim, slice_ct); - step_length = len_v3(dim); - - grp = DRW_shgroup_create(sh, vedata->psl->volume_pass); - DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)wpd->viewvecs, 3); - DRW_shgroup_uniform_int_copy(grp, "samplesLen", max_slice); - DRW_shgroup_uniform_float_copy(grp, "stepLength", step_length); - DRW_shgroup_uniform_float_copy(grp, "noiseOfs", noise_ofs); - DRW_shgroup_state_enable(grp, DRW_STATE_CULL_FRONT); - } - - if (sds->use_coba) { - DRW_shgroup_uniform_texture(grp, "densityTexture", sds->tex_field); - DRW_shgroup_uniform_texture(grp, "transferTexture", sds->tex_coba); - } - else { - static float white[3] = {1.0f, 1.0f, 1.0f}; - bool use_constant_color = ((sds->active_fields & SM_ACTIVE_COLORS) == 0 && - (sds->active_fields & SM_ACTIVE_COLOR_SET) != 0); - DRW_shgroup_uniform_texture(grp, "densityTexture", sds->tex); - DRW_shgroup_uniform_texture(grp, "shadowTexture", sds->tex_shadow); - DRW_shgroup_uniform_texture(grp, "flameTexture", (sds->tex_flame) ? sds->tex_flame : e_data.dummy_tex); - DRW_shgroup_uniform_texture(grp, "flameColorTexture", (sds->tex_flame) ? sds->tex_flame_coba : e_data.dummy_coba_tex); - DRW_shgroup_uniform_vec3(grp, "activeColor", (use_constant_color) ? sds->active_color : white, 1); - } - DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); - DRW_shgroup_uniform_float_copy(grp, "densityScale", 10.0f * sds->display_thickness); - - if (use_slice) { - DRW_shgroup_call_object_add(grp, DRW_cache_quad_get(), ob); - } - else { - DRW_shgroup_call_object_add(grp, DRW_cache_cube_get(), ob); - } - - BLI_addtail(&wpd->smoke_domains, BLI_genericNodeN(smd)); + SmokeModifierData *smd = (SmokeModifierData *)md; + SmokeDomainSettings *sds = smd->domain; + WORKBENCH_PrivateData *wpd = vedata->stl->g_data; + WORKBENCH_EffectInfo *effect_info = vedata->stl->effects; + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + DRWShadingGroup *grp = NULL; + + /* Don't show smoke before simulation starts, this could be made an option in the future. */ + if (!sds->fluid || CFRA < sds->point_cache[0]->startframe) { + return; + } + + wpd->volumes_do = true; + const bool show_highres = BKE_smoke_show_highres(scene, sds); + if (sds->use_coba) { + GPU_create_smoke_coba_field(smd); + } + else if (!sds->wt || !show_highres) { + GPU_create_smoke(smd, 0); + } + else if (sds->wt && show_highres) { + GPU_create_smoke(smd, 1); + } + + if ((!sds->use_coba && sds->tex == NULL) || (sds->use_coba && sds->tex_field == NULL)) { + return; + } + + const bool use_slice = (sds->slice_method == MOD_SMOKE_SLICE_AXIS_ALIGNED && + sds->axis_slice_method == AXIS_SLICE_SINGLE); + const bool cubic_interp = (sds->interp_method == VOLUME_INTERP_CUBIC); + GPUShader *sh = volume_shader_get(use_slice, sds->use_coba, cubic_interp); + + if (use_slice) { + float invviewmat[4][4]; + DRW_viewport_matrix_get(invviewmat, DRW_MAT_VIEWINV); + + const int axis = (sds->slice_axis == SLICE_AXIS_AUTO) ? + axis_dominant_v3_single(invviewmat[2]) : + sds->slice_axis - 1; + float dim[3]; + BKE_object_dimensions_get(ob, dim); + /* 0.05f to acheive somewhat the same opacity as the full view. */ + float step_length = max_ff(1e-16f, dim[axis] * 0.05f); + + grp = DRW_shgroup_create(sh, vedata->psl->volume_pass); + DRW_shgroup_uniform_float_copy(grp, "slicePosition", sds->slice_depth); + DRW_shgroup_uniform_int_copy(grp, "sliceAxis", axis); + DRW_shgroup_uniform_float_copy(grp, "stepLength", step_length); + DRW_shgroup_state_disable(grp, DRW_STATE_CULL_FRONT); + } + else { + double noise_ofs; + BLI_halton_1d(3, 0.0, effect_info->jitter_index, &noise_ofs); + float dim[3], step_length, max_slice; + float slice_ct[3] = {sds->res[0], sds->res[1], sds->res[2]}; + mul_v3_fl(slice_ct, max_ff(0.001f, sds->slice_per_voxel)); + max_slice = max_fff(slice_ct[0], slice_ct[1], slice_ct[2]); + BKE_object_dimensions_get(ob, dim); + invert_v3(slice_ct); + mul_v3_v3(dim, slice_ct); + step_length = len_v3(dim); + + grp = DRW_shgroup_create(sh, vedata->psl->volume_pass); + DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)wpd->viewvecs, 3); + DRW_shgroup_uniform_int_copy(grp, "samplesLen", max_slice); + DRW_shgroup_uniform_float_copy(grp, "stepLength", step_length); + DRW_shgroup_uniform_float_copy(grp, "noiseOfs", noise_ofs); + DRW_shgroup_state_enable(grp, DRW_STATE_CULL_FRONT); + } + + if (sds->use_coba) { + DRW_shgroup_uniform_texture(grp, "densityTexture", sds->tex_field); + DRW_shgroup_uniform_texture(grp, "transferTexture", sds->tex_coba); + } + else { + static float white[3] = {1.0f, 1.0f, 1.0f}; + bool use_constant_color = ((sds->active_fields & SM_ACTIVE_COLORS) == 0 && + (sds->active_fields & SM_ACTIVE_COLOR_SET) != 0); + DRW_shgroup_uniform_texture(grp, "densityTexture", sds->tex); + DRW_shgroup_uniform_texture(grp, "shadowTexture", sds->tex_shadow); + DRW_shgroup_uniform_texture( + grp, "flameTexture", (sds->tex_flame) ? sds->tex_flame : e_data.dummy_tex); + DRW_shgroup_uniform_texture( + grp, "flameColorTexture", (sds->tex_flame) ? sds->tex_flame_coba : e_data.dummy_coba_tex); + DRW_shgroup_uniform_vec3( + grp, "activeColor", (use_constant_color) ? sds->active_color : white, 1); + } + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); + DRW_shgroup_uniform_float_copy(grp, "densityScale", 10.0f * sds->display_thickness); + + if (use_slice) { + DRW_shgroup_call_object_add(grp, DRW_cache_quad_get(), ob); + } + else { + DRW_shgroup_call_object_add(grp, DRW_cache_cube_get(), ob); + } + + BLI_addtail(&wpd->smoke_domains, BLI_genericNodeN(smd)); } void workbench_volume_smoke_textures_free(WORKBENCH_PrivateData *wpd) { - /* Free Smoke Textures after rendering */ - /* XXX This is a waste of processing and GPU bandwidth if nothing - * is updated. But the problem is since Textures are stored in the - * modifier we don't want them to take precious VRAM if the - * modifier is not used for display. We should share them for - * all viewport in a redraw at least. */ - for (LinkData *link = wpd->smoke_domains.first; link; link = link->next) { - SmokeModifierData *smd = (SmokeModifierData *)link->data; - GPU_free_smoke(smd); - } - BLI_freelistN(&wpd->smoke_domains); + /* Free Smoke Textures after rendering */ + /* XXX This is a waste of processing and GPU bandwidth if nothing + * is updated. But the problem is since Textures are stored in the + * modifier we don't want them to take precious VRAM if the + * modifier is not used for display. We should share them for + * all viewport in a redraw at least. */ + for (LinkData *link = wpd->smoke_domains.first; link; link = link->next) { + SmokeModifierData *smd = (SmokeModifierData *)link->data; + GPU_free_smoke(smd); + } + BLI_freelistN(&wpd->smoke_domains); } |