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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2020-03-02 21:11:08 +0300
committerClément Foucault <foucault.clem@gmail.com>2020-03-03 03:42:31 +0300
commitaae2e1326fe60e8356735dcc079b55727a86bf75 (patch)
tree8ba85c07010f5d1927f12beafe7bfe37aacb4ee3
parent606f1d80b39a978f32aaae5a0cd22e18775dd36a (diff)
Workbench: Refactor: Add cavity support
-rw-r--r--source/blender/draw/CMakeLists.txt1
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_cavity_frag.glsl4
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl96
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl18
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_curvature_lib.glsl47
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl15
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_effect_cavity_frag.glsl31
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl6
-rw-r--r--source/blender/draw/engines/workbench/workbench_data.c21
-rw-r--r--source/blender/draw/engines/workbench/workbench_deferred.c6
-rw-r--r--source/blender/draw/engines/workbench/workbench_effect_aa.c9
-rw-r--r--source/blender/draw/engines/workbench/workbench_effect_cavity.c157
-rw-r--r--source/blender/draw/engines/workbench/workbench_effect_dof.c2
-rw-r--r--source/blender/draw/engines/workbench/workbench_effect_taa.c7
-rw-r--r--source/blender/draw/engines/workbench/workbench_engine.c8
-rw-r--r--source/blender/draw/engines/workbench/workbench_private.h35
-rw-r--r--source/blender/draw/engines/workbench/workbench_render.c4
-rw-r--r--source/blender/draw/engines/workbench/workbench_shader.c51
18 files changed, 367 insertions, 151 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index c6935dfdd95..692dc300d89 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -255,6 +255,7 @@ data_to_c_simple(engines/workbench/shaders/workbench_composite_frag.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_data_lib.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_deferred_composite_frag.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_deferred_background_frag.glsl SRC)
+data_to_c_simple(engines/workbench/shaders/workbench_effect_cavity_frag.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_effect_dof_frag.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_effect_fxaa_frag.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_effect_taa_frag.glsl SRC)
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 a0e04f252e2..7031328eb2e 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_cavity_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_cavity_frag.glsl
@@ -28,7 +28,7 @@ layout(std140) uniform samples_block
#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)
+vec3 view_space_from_depth(in vec2 uvcoords, in float depth)
{
if (WinMatrix[3][3] == 0.0) {
/* Perspective */
@@ -63,7 +63,7 @@ void main()
#ifdef USE_CAVITY
float depth = texelFetch(depthBuffer, texel, 0).x;
- vec3 position = get_view_space_from_depth(screenco, depth);
+ vec3 position = 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);
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl
index 376b19cdd1b..c1207c0d32f 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl
@@ -1,77 +1,86 @@
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_data_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_common_lib.glsl)
-/* from The Alchemy screen-space ambient obscurance algorithm
+layout(std140) uniform samples_block
+{
+ vec4 samples_coords[512];
+};
+
+uniform sampler2D cavityJitter;
+
+/* From The Alchemy screen-space ambient obscurance algorithm
* http://graphics.cs.williams.edu/papers/AlchemyHPG11/VV11AlchemyAO.pdf */
-void ssao_factors(in float depth,
- in vec3 normal,
- in vec3 position,
- in vec2 screenco,
- out float cavities,
- out float edges)
+void cavity_compute(vec2 screenco,
+ sampler2D depthBuffer,
+ sampler2D normalBuffer,
+ out float cavities,
+ out float edges)
{
cavities = edges = 0.0;
- /* early out if there is no need for SSAO */
- if (ssao_factor_cavity == 0.0 && ssao_factor_edge == 0.0) {
+
+ float depth = texture(depthBuffer, screenco).x;
+
+ /* Early out if background */
+ if (depth == 1.0) {
return;
}
- /* take the normalized ray direction here */
- vec3 noise = texture(ssao_jitter, screenco.xy * jitter_tilling).rgb;
+ vec3 position = view_space_from_depth(screenco, depth, world_data.viewvecs, ProjectionMatrix);
+ vec3 normal = workbench_normal_decode(texture(normalBuffer, screenco));
+
+ vec2 jitter_co = (screenco * world_data.viewport_size.xy) * world_data.cavity_jitter_scale;
+ vec3 noise = texture(cavityJitter, jitter_co).rgb;
/* find the offset in screen space by multiplying a point
* in camera space at the depth of the point by the projection matrix. */
vec2 offset;
- float homcoord = WinMatrix[2][3] * position.z + WinMatrix[3][3];
- offset.x = WinMatrix[0][0] * ssao_distance / homcoord;
- offset.y = WinMatrix[1][1] * ssao_distance / homcoord;
+ float homcoord = ProjectionMatrix[2][3] * position.z + ProjectionMatrix[3][3];
+ offset.x = ProjectionMatrix[0][0] * world_data.cavity_distance / homcoord;
+ offset.y = ProjectionMatrix[1][1] * world_data.cavity_distance / homcoord;
/* convert from -1.0...1.0 range to 0.0..1.0 for easy use with texture coordinates */
offset *= 0.5;
- int num_samples = int(ssao_samples_num);
-
/* Note. Putting noise usage here to put some ALU after texture fetch. */
vec2 rotX = noise.rg;
vec2 rotY = vec2(-rotX.y, rotX.x);
- for (int x = 0; x < num_samples; x++) {
- int sample_index = x + (int(ssao_iteration) * num_samples);
- if (sample_index > 500) {
- continue;
- }
- /* ssao_samples[x].xy is sample direction (normalized).
- * ssao_samples[x].z is sample distance from disk center. */
-
+ int sample_start = world_data.cavity_sample_start;
+ int sample_end = world_data.cavity_sample_end;
+ for (int i = sample_start; i < sample_end && i < 512; i++) {
+ /* sample_coord.xy is sample direction (normalized).
+ * sample_coord.z is sample distance from disk center. */
+ vec3 sample_coord = samples_coords[i].xyz;
/* Rotate with random direction to get jittered result. */
- vec2 dir_jittered = vec2(dot(ssao_samples[sample_index].xy, rotX),
- dot(ssao_samples[sample_index].xy, rotY));
- dir_jittered.xy *= ssao_samples[sample_index].z + noise.b;
+ vec2 dir_jittered = vec2(dot(sample_coord.xy, rotX), dot(sample_coord.xy, rotY));
+ dir_jittered.xy *= sample_coord.z + noise.b;
- vec2 uvcoords = screenco.xy + dir_jittered * offset;
-
- if (uvcoords.x > 1.0 || uvcoords.x < 0.0 || uvcoords.y > 1.0 || uvcoords.y < 0.0) {
+ vec2 uvcoords = screenco + dir_jittered * offset;
+ /* Out of screen case. */
+ if (any(greaterThan(abs(uvcoords - 0.5), vec2(0.5)))) {
continue;
}
-
- float depth_new = texture(depthBuffer, uvcoords).r;
-
+ /* Sample depth. */
+ float s_depth = texture(depthBuffer, uvcoords).r;
/* Handle Background case */
- bool is_background = (depth_new == 1.0);
-
+ bool is_background = (s_depth == 1.0);
/* This trick provide good edge effect even if no neighbor is found. */
- vec3 pos_new = get_view_space_from_depth(uvcoords, (is_background) ? depth : depth_new);
+ s_depth = (is_background) ? depth : s_depth;
+ vec3 s_pos = view_space_from_depth(uvcoords, s_depth, world_data.viewvecs, ProjectionMatrix);
if (is_background) {
- pos_new.z -= ssao_distance;
+ s_pos.z -= world_data.cavity_distance;
}
- vec3 dir = pos_new - position;
+ vec3 dir = s_pos - position;
float len = length(dir);
float f_cavities = dot(dir, normal);
float f_edge = -f_cavities;
float f_bias = 0.05 * len + 0.0001;
- float attenuation = 1.0 / (len * (1.0 + len * len * ssao_attenuation));
+ float attenuation = 1.0 / (len * (1.0 + len * len * world_data.cavity_attenuation));
/* use minor bias here to avoid self shadowing */
if (f_cavities > -f_bias) {
@@ -82,11 +91,10 @@ void ssao_factors(in float depth,
edges += f_edge * attenuation;
}
}
-
- cavities /= ssao_samples_num;
- edges /= ssao_samples_num;
+ cavities *= world_data.cavity_sample_count_inv;
+ edges *= world_data.cavity_sample_count_inv;
/* don't let cavity wash out the surface appearance */
- cavities = clamp(cavities * ssao_factor_cavity, 0.0, 1.0);
- edges = edges * ssao_factor_edge;
+ cavities = clamp(cavities * world_data.cavity_valley_factor, 0.0, 1.0);
+ edges = edges * world_data.cavity_ridge_factor;
}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl
index 74a745ce74d..0e2eee99a1b 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl
@@ -77,3 +77,21 @@ vec3 view_vector_from_screen_uv(vec2 uv, vec4 viewvecs[3], mat4 proj_mat)
return vec3(0.0, 0.0, 1.0);
}
}
+
+vec3 view_space_from_depth(vec2 uvcoords, float depth, vec4 viewvecs[3], mat4 proj_mat)
+{
+ if (proj_mat[3][3] == 0.0) {
+ /* Perspective */
+ float d = 2.0 * depth - 1.0;
+
+ float zview = -proj_mat[3][2] / (d + proj_mat[2][2]);
+
+ return zview * (viewvecs[0].xyz + vec3(uvcoords, 0.0) * viewvecs[1].xyz);
+ }
+ else {
+ /* Orthographic */
+ vec3 offset = vec3(uvcoords, depth);
+
+ return viewvecs[0].xyz + offset * viewvecs[1].xyz;
+ }
+}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_curvature_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_curvature_lib.glsl
index 22dc906be83..8754b7147d9 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_curvature_lib.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_curvature_lib.glsl
@@ -1,6 +1,5 @@
-#ifndef CURVATURE_OFFSET
-# define CURVATURE_OFFSET 1
-#endif
+
+#pragma BLENDER_REQUIRE(workbench_data_lib.glsl)
float curvature_soft_clamp(float curvature, float control)
{
@@ -10,33 +9,35 @@ float curvature_soft_clamp(float curvature, float control)
return 0.25 / control;
}
-float calculate_curvature(
- usampler2D objectId, sampler2D normalBuffer, ivec2 texel, float ridge, float valley)
+void curvature_compute(vec2 uv,
+ usampler2D objectIdBuffer,
+ sampler2D normalBuffer,
+ out float curvature)
{
- uint object_up = texelFetchOffset(objectId, texel, 0, ivec2(0, CURVATURE_OFFSET)).r;
- uint object_down = texelFetchOffset(objectId, texel, 0, ivec2(0, -CURVATURE_OFFSET)).r;
- uint object_left = texelFetchOffset(objectId, texel, 0, ivec2(-CURVATURE_OFFSET, 0)).r;
- uint object_right = texelFetchOffset(objectId, texel, 0, ivec2(CURVATURE_OFFSET, 0)).r;
+ curvature = 0.0;
+
+ vec3 offset = vec3(world_data.viewport_size_inv, 0.0) * world_data.curvature_offset;
+ uint object_up = texture(objectIdBuffer, uv + offset.zy).r;
+ uint object_down = texture(objectIdBuffer, uv - offset.zy).r;
+ uint object_right = texture(objectIdBuffer, uv + offset.xz).r;
+ uint object_left = texture(objectIdBuffer, uv - offset.xz).r;
+ /* Remove object outlines. */
if ((object_up != object_down) || (object_right != object_left)) {
- return 0.0;
+ return;
}
- vec2 normal_up = texelFetchOffset(normalBuffer, texel, 0, ivec2(0, CURVATURE_OFFSET)).rg;
- vec2 normal_down = texelFetchOffset(normalBuffer, texel, 0, ivec2(0, -CURVATURE_OFFSET)).rg;
- vec2 normal_left = texelFetchOffset(normalBuffer, texel, 0, ivec2(-CURVATURE_OFFSET, 0)).rg;
- vec2 normal_right = texelFetchOffset(normalBuffer, texel, 0, ivec2(CURVATURE_OFFSET, 0)).rg;
-
- normal_up = workbench_normal_decode(normal_up).rg;
- normal_down = workbench_normal_decode(normal_down).rg;
- normal_left = workbench_normal_decode(normal_left).rg;
- normal_right = workbench_normal_decode(normal_right).rg;
+ float normal_up = workbench_normal_decode(texture(normalBuffer, uv + offset.zy)).g;
+ float normal_down = workbench_normal_decode(texture(normalBuffer, uv - offset.zy)).g;
+ float normal_right = workbench_normal_decode(texture(normalBuffer, uv + offset.xz)).r;
+ float normal_left = workbench_normal_decode(texture(normalBuffer, uv - offset.xz)).r;
- float normal_diff = ((normal_up.g - normal_down.g) + (normal_right.r - normal_left.r));
+ float normal_diff = (normal_up - normal_down) + (normal_right - normal_left);
if (normal_diff < 0) {
- return -2.0 * curvature_soft_clamp(-normal_diff, valley);
+ curvature = -2.0 * curvature_soft_clamp(-normal_diff, world_data.curvature_valley);
+ }
+ else {
+ curvature = 2.0 * curvature_soft_clamp(normal_diff, world_data.curvature_ridge);
}
-
- return 2.0 * curvature_soft_clamp(normal_diff, ridge);
}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl
index 75fde40bc94..69aadabe860 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl
@@ -16,10 +16,21 @@ struct WorldData {
/* - 16 bytes alignment- */
LightData lights[4];
vec4 ambient_color;
- int matcap_orientation;
+
+ int cavity_sample_start;
+ int cavity_sample_end;
+ float cavity_sample_count_inv;
+ float cavity_jitter_scale;
+
+ float cavity_valley_factor;
+ float cavity_ridge_factor;
+ float cavity_attenuation;
+ float cavity_distance;
+
float curvature_ridge;
float curvature_valley;
- int _pad0;
+ float curvature_offset;
+ int matcap_orientation;
};
#define viewport_size_inv viewport_size.zw
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_effect_cavity_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_effect_cavity_frag.glsl
new file mode 100644
index 00000000000..328d50e69e0
--- /dev/null
+++ b/source/blender/draw/engines/workbench/shaders/workbench_effect_cavity_frag.glsl
@@ -0,0 +1,31 @@
+
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_common_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_cavity_lib.glsl)
+#pragma BLENDER_REQUIRE(workbench_curvature_lib.glsl)
+
+uniform sampler2D depthBuffer;
+uniform sampler2D normalBuffer;
+uniform usampler2D objectIdBuffer;
+
+in vec4 uvcoordsvar;
+
+out vec4 fragColor;
+
+void main()
+{
+ float cavity = 0.0, edges = 0.0, curvature = 0.0;
+
+#ifdef USE_CAVITY
+ cavity_compute(uvcoordsvar.st, depthBuffer, normalBuffer, cavity, edges);
+#endif
+
+#ifdef USE_CURVATURE
+ curvature_compute(uvcoordsvar.st, objectIdBuffer, normalBuffer, curvature);
+#endif
+
+ float final_cavity_factor = clamp((1.0 - cavity) * (1.0 + edges) * (1.0 + curvature), 0.0, 4.0);
+
+ fragColor.rgb = vec3(final_cavity_factor);
+ fragColor.a = 1.0;
+}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl
index c38d8fe06bc..c8f0a04918d 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl
@@ -41,7 +41,7 @@ float get_view_z_from_depth(float depth)
}
}
-vec3 get_view_space_from_depth(vec2 uvcoords, float depth)
+vec3 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);
@@ -208,8 +208,8 @@ void main()
float depth = texelFetch(depthBuffer, ivec2(gl_FragCoord.xy), 0).r;
float depth_end = min(depth, gl_FragCoord.z);
- vec3 vs_ray_end = get_view_space_from_depth(screen_uv, depth_end);
- vec3 vs_ray_ori = get_view_space_from_depth(screen_uv, 0.0);
+ vec3 vs_ray_end = view_space_from_depth(screen_uv, depth_end);
+ vec3 vs_ray_ori = 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);
diff --git a/source/blender/draw/engines/workbench/workbench_data.c b/source/blender/draw/engines/workbench/workbench_data.c
index 937c6a33319..0f7a4f8f9c8 100644
--- a/source/blender/draw/engines/workbench/workbench_data.c
+++ b/source/blender/draw/engines/workbench/workbench_data.c
@@ -27,6 +27,7 @@
#include "DNA_userdef_types.h"
#include "ED_view3d.h"
+#include "ED_screen.h"
#include "UI_resources.h"
@@ -56,6 +57,8 @@ static void workbench_view_layer_data_free(void *storage)
WORKBENCH_ViewLayerData *vldata = (WORKBENCH_ViewLayerData *)storage;
DRW_UBO_FREE_SAFE(vldata->world_ubo);
+ DRW_UBO_FREE_SAFE(vldata->cavity_sample_ubo);
+ DRW_TEXTURE_FREE_SAFE(vldata->cavity_jitter_tx);
BLI_memblock_destroy(vldata->material_ubo_data, NULL);
BLI_memblock_destroy(vldata->material_ubo, workbench_ubo_free);
@@ -189,11 +192,22 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd)
WORKBENCH_ViewLayerData *vldata = workbench_view_layer_data_ensure_ex(draw_ctx->view_layer);
View3D *v3d = draw_ctx->v3d;
+ 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;
+ }
+
wpd->ctx_mode = CTX_data_mode_enum_ex(
draw_ctx->object_edit, draw_ctx->obact, draw_ctx->object_mode);
wpd->preferences = &U;
wpd->sh_cfg = draw_ctx->sh_cfg;
+ wpd->vldata = vldata;
+
+ wpd->taa_sample_len = workbench_taa_calculate_num_iterations(wpd);
wpd->world_ubo = vldata->world_ubo;
@@ -244,13 +258,12 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd)
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);
+ copy_v2_v2(wpd->world_data.viewport_size, DRW_viewport_size_get());
+ copy_v2_v2(wpd->world_data.viewport_size_inv, DRW_viewport_invert_size_get());
workbench_shadow_world_data_update(wpd);
+ workbench_cavity_data_update(wpd);
workbench_viewvecs_update(wpd->world_data.viewvecs);
- copy_v2_v2(wpd->world_data.viewport_size, DRW_viewport_size_get());
- copy_v2_v2(wpd->world_data.viewport_size_inv, DRW_viewport_invert_size_get());
DRW_uniformbuffer_update(wpd->world_ubo, &wpd->world_data);
diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c
index 4bd0e663650..886fc836ce8 100644
--- a/source/blender/draw/engines/workbench/workbench_deferred.c
+++ b/source/blender/draw/engines/workbench/workbench_deferred.c
@@ -192,7 +192,7 @@ static char *workbench_build_cavity_frag(bool cavity, bool curvature, bool high_
return str;
}
-static GPUShader *workbench_cavity_shader_get(bool cavity, bool curvature)
+static GPUShader *workbench__cavity_shader_get(bool cavity, bool curvature)
{
const bool high_dpi = (U.pixelsize > 1.5f);
int index = 0;
@@ -547,7 +547,7 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
{
/* AO Samples Tex */
- int num_iterations = workbench_taa_calculate_num_iterations(vedata);
+ int num_iterations = workbench_taa_calculate_num_iterations(vedata->stl->wpd);
const int ssao_samples_single_iteration = scene->display.matcap_ssao_samples;
const int ssao_samples = MIN2(num_iterations * ssao_samples_single_iteration, 500);
@@ -596,7 +596,7 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
if (CAVITY_ENABLED(wpd)) {
int state = DRW_STATE_WRITE_COLOR;
- GPUShader *shader = workbench_cavity_shader_get(SSAO_ENABLED(wpd), CURVATURE_ENABLED(wpd));
+ 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);
diff --git a/source/blender/draw/engines/workbench/workbench_effect_aa.c b/source/blender/draw/engines/workbench/workbench_effect_aa.c
index c03fe5cd5c8..482cb81917f 100644
--- a/source/blender/draw/engines/workbench/workbench_effect_aa.c
+++ b/source/blender/draw/engines/workbench/workbench_effect_aa.c
@@ -32,15 +32,6 @@ void workbench_aa_create_pass(WORKBENCH_Data *vedata, GPUTexture **tx)
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 (workbench_is_taa_enabled(wpd)) {
psl->effect_aa_pass = workbench_taa_create_pass(vedata, tx);
diff --git a/source/blender/draw/engines/workbench/workbench_effect_cavity.c b/source/blender/draw/engines/workbench/workbench_effect_cavity.c
index 42652cf4299..5f7f8feb42d 100644
--- a/source/blender/draw/engines/workbench/workbench_effect_cavity.c
+++ b/source/blender/draw/engines/workbench/workbench_effect_cavity.c
@@ -22,57 +22,142 @@
#include "DRW_render.h"
+#include "BLI_rand.h"
+
+#include "../eevee/eevee_lut.h" /* TODO find somewhere to share blue noise Table */
+
#include "workbench_engine.h"
#include "workbench_private.h"
-#if 0
+#define JITTER_TEX_SIZE 64
+
+/* Using Hammersley distribution */
+static float *create_disk_samples(int num_samples, int num_iterations)
{
+ const int total_samples = num_samples * num_iterations;
+ const float num_samples_inv = 1.0f / num_samples;
+ /* vec4 to ensure memory alignment. */
+ float(*texels)[4] = MEM_mallocN(sizeof(float[4]) * total_samples, __func__);
- {
- /* AO Samples Tex */
- int num_iterations = workbench_taa_calculate_num_iterations(vedata);
+ 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);
- const int ssao_samples_single_iteration = scene->display.matcap_ssao_samples;
- const int ssao_samples = MIN2(num_iterations * ssao_samples_single_iteration, 500);
+ 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;
+ }
- 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);
- }
+ return (float *)texels;
+}
- 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);
- }
+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_WRAP, &jitter[0][0]);
}
+static void workbench_cavity_samples_ubo_ensure(WORKBENCH_PrivateData *wpd)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+
+ int cavity_sample_count_single_iteration = scene->display.matcap_ssao_samples;
+ int cavity_sample_count = MIN2(wpd->taa_sample_len * cavity_sample_count_single_iteration, 512);
+
+ if (wpd->vldata->cavity_sample_count != cavity_sample_count) {
+ DRW_UBO_FREE_SAFE(wpd->vldata->cavity_sample_ubo);
+ DRW_TEXTURE_FREE_SAFE(wpd->vldata->cavity_jitter_tx);
+ }
+
+ if (wpd->vldata->cavity_sample_ubo == NULL) {
+ float *samples = create_disk_samples(cavity_sample_count_single_iteration,
+ wpd->taa_sample_len);
+ wpd->vldata->cavity_jitter_tx = create_jitter_texture(cavity_sample_count);
+ /* NOTE: Uniform buffer needs to always be filled to be valid. */
+ wpd->vldata->cavity_sample_ubo = DRW_uniformbuffer_create(sizeof(float[4]) * 512, samples);
+ wpd->vldata->cavity_sample_count = cavity_sample_count;
+ MEM_freeN(samples);
+ }
+}
+
+void workbench_cavity_data_update(WORKBENCH_PrivateData *wpd)
+{
+ WORKBENCH_UBO_World *wd = &wpd->world_data;
+ View3DShading *shading = &wpd->shading;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+
+ int cavity_sample_count_single_iteration = scene->display.matcap_ssao_samples;
+
+ wd->cavity_sample_start = cavity_sample_count_single_iteration * wpd->taa_sample;
+ wd->cavity_sample_end = min_ff(wd->cavity_sample_start + cavity_sample_count_single_iteration,
+ wpd->vldata->cavity_sample_count);
+ wd->cavity_sample_count_inv = 1.0f / (wd->cavity_sample_end - wd->cavity_sample_start);
+ wd->cavity_jitter_scale = 1.0f / 64.0f;
+
+ wd->cavity_valley_factor = shading->cavity_valley_factor;
+ wd->cavity_ridge_factor = shading->cavity_ridge_factor;
+ wd->cavity_attenuation = scene->display.matcap_ssao_attenuation;
+ wd->cavity_distance = scene->display.matcap_ssao_distance;
+
+ wd->curvature_ridge = 0.5f / max_ff(SQUARE(shading->curvature_ridge_factor), 1e-4f);
+ wd->curvature_valley = 0.7f / max_ff(SQUARE(shading->curvature_valley_factor), 1e-4f);
+ wd->curvature_offset = G_draw.block.sizePixel;
+}
+
+void workbench_cavity_cache_init(WORKBENCH_Data *data)
+{
+ WORKBENCH_PassList *psl = data->psl;
+ WORKBENCH_PrivateData *wpd = data->stl->wpd;
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+ struct GPUShader *sh;
+ DRWShadingGroup *grp;
+
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);
+ workbench_cavity_samples_ubo_ensure(wpd);
+
+ int state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_MUL;
+ DRW_PASS_CREATE(psl->cavity_pass, state);
+
+ sh = workbench_shader_cavity_get(SSAO_ENABLED(wpd), CURVATURE_ENABLED(wpd));
+
+ grp = DRW_shgroup_create(sh, psl->cavity_pass);
+ DRW_shgroup_uniform_texture(grp, "normalBuffer", wpd->normal_buffer_tx);
+ DRW_shgroup_uniform_block(grp, "samples_block", wpd->vldata->cavity_sample_ubo);
+ DRW_shgroup_uniform_block(grp, "world_block", wpd->world_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);
+ DRW_shgroup_uniform_texture(grp, "depthBuffer", dtxl->depth);
+ DRW_shgroup_uniform_texture(grp, "cavityJitter", wpd->vldata->cavity_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_uniform_texture(grp, "objectIdBuffer", wpd->object_id_tx);
}
-
- DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
}
-#endif \ No newline at end of file
+ else {
+ psl->cavity_pass = NULL;
+ }
+}
diff --git a/source/blender/draw/engines/workbench/workbench_effect_dof.c b/source/blender/draw/engines/workbench/workbench_effect_dof.c
index 3709c5600e6..219cf3ba625 100644
--- a/source/blender/draw/engines/workbench/workbench_effect_dof.c
+++ b/source/blender/draw/engines/workbench/workbench_effect_dof.c
@@ -343,7 +343,7 @@ void workbench_dof_create_pass(WORKBENCH_Data *vedata,
#endif
{
float offset = stl->effects->jitter_index /
- (float)workbench_taa_calculate_num_iterations(vedata);
+ (float)workbench_taa_calculate_num_iterations(vedata->stl->wpd);
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);
diff --git a/source/blender/draw/engines/workbench/workbench_effect_taa.c b/source/blender/draw/engines/workbench/workbench_effect_taa.c
index 772d859392b..3512836376e 100644
--- a/source/blender/draw/engines/workbench/workbench_effect_taa.c
+++ b/source/blender/draw/engines/workbench/workbench_effect_taa.c
@@ -21,6 +21,7 @@
*/
#include "workbench_private.h"
+
#include "BLI_jitter_2d.h"
static struct {
@@ -86,10 +87,8 @@ static void workbench_taa_jitter_init(void)
workbench_taa_jitter_init_order(e_data.jitter_32, 32);
}
-int workbench_taa_calculate_num_iterations(WORKBENCH_Data *vedata)
+int workbench_taa_calculate_num_iterations(WORKBENCH_PrivateData *wpd)
{
- WORKBENCH_StorageList *stl = vedata->stl;
- WORKBENCH_PrivateData *wpd = stl->g_data;
const Scene *scene = DRW_context_state_get()->scene;
int result;
if (workbench_is_taa_enabled(wpd)) {
@@ -211,7 +210,7 @@ void workbench_taa_draw_scene_start(WORKBENCH_Data *vedata)
int num_samples = 8;
float(*samples)[2];
- num_samples = workbench_taa_calculate_num_iterations(vedata);
+ num_samples = workbench_taa_calculate_num_iterations(vedata->stl->wpd);
switch (num_samples) {
default:
case 5:
diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c
index ac0a4e6221a..b9017f9bfff 100644
--- a/source/blender/draw/engines/workbench/workbench_engine.c
+++ b/source/blender/draw/engines/workbench/workbench_engine.c
@@ -83,6 +83,7 @@ static void workbench_cache_init(void *ved)
workbench_opaque_cache_init(vedata);
workbench_transparent_cache_init(vedata);
workbench_shadow_cache_init(vedata);
+ workbench_cavity_cache_init(vedata);
// workbench_aa_create_pass(vedata);
// workbench_dof_create_pass(vedata);
@@ -415,9 +416,10 @@ static void workbench_draw_scene(void *ved)
GPU_framebuffer_bind(dfbl->default_fb);
DRW_draw_pass(psl->composite_pass);
- /* TODO(fclem) ambient occlusion */
- // GPU_framebuffer_bind(dfbl->color_only_fb);
- // DRW_draw_pass(psl->ambient_occlusion_pass);
+ if (psl->cavity_pass) {
+ GPU_framebuffer_bind(dfbl->color_only_fb);
+ DRW_draw_pass(psl->cavity_pass);
+ }
}
{
diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h
index 155deba8380..901509837cb 100644
--- a/source/blender/draw/engines/workbench/workbench_private.h
+++ b/source/blender/draw/engines/workbench/workbench_private.h
@@ -215,10 +215,21 @@ typedef struct WORKBENCH_UBO_World {
float shadow_focus, shadow_shift, shadow_mul, shadow_add;
WORKBENCH_UBO_Light lights[4];
float ambient_color[4];
- int matcap_orientation;
+
+ int cavity_sample_start;
+ int cavity_sample_end;
+ float cavity_sample_count_inv;
+ float cavity_jitter_scale;
+
+ float cavity_valley_factor;
+ float cavity_ridge_factor;
+ float cavity_attenuation;
+ float cavity_distance;
+
float curvature_ridge;
float curvature_valley;
- int _pad0;
+ float curvature_offset;
+ int matcap_orientation;
} WORKBENCH_UBO_World;
BLI_STATIC_ASSERT_ALIGN(WORKBENCH_UBO_World, 16)
@@ -252,6 +263,9 @@ typedef struct WORKBENCH_PrivateData {
struct GPUShader *transparent_accum_textured_sh;
struct GPUShader *transparent_accum_textured_array_sh;
struct GPUShader *transparent_accum_vertex_sh;
+
+ struct WORKBENCH_ViewLayerData *vldata;
+
View3DShading shading;
eContextObjectMode ctx_mode;
StudioLight *studio_light;
@@ -283,6 +297,12 @@ typedef struct WORKBENCH_PrivateData {
bool shadow_changed;
bool is_playback;
+ /* Temporal Antialiasing */
+ /** Total number of samples to after which TAA stops accumulating samples. */
+ int taa_sample_len;
+ /** Current TAA sample index in [0..taa_sample_len[ range. */
+ int taa_sample;
+
/* Opaque pipeline */
struct GPUTexture *object_id_tx;
struct GPUTexture *material_buffer_tx;
@@ -375,8 +395,11 @@ typedef struct WORKBENCH_ObjectData {
typedef struct WORKBENCH_ViewLayerData {
struct GPUUniformBuffer *world_ubo;
+ struct GPUUniformBuffer *cavity_sample_ubo;
+ struct GPUTexture *cavity_jitter_tx;
struct BLI_memblock *material_ubo;
struct BLI_memblock *material_ubo_data;
+ int cavity_sample_count;
} WORKBENCH_ViewLayerData;
/* Enumeration containing override options for base color rendering.
@@ -524,6 +547,8 @@ GPUShader *workbench_shader_transparent_resolve_get(WORKBENCH_PrivateData *wpd);
GPUShader *workbench_shader_shadow_pass_get(bool manifold);
GPUShader *workbench_shader_shadow_fail_get(bool manifold, bool cap);
+GPUShader *workbench_shader_cavity_get(bool cavity, bool curvature);
+
void workbench_shader_library_ensure(void);
void workbench_shader_free(void);
@@ -572,9 +597,13 @@ DRWPass *workbench_taa_create_pass(WORKBENCH_Data *vedata, GPUTexture **color_bu
void workbench_taa_draw_scene_start(WORKBENCH_Data *vedata);
void workbench_taa_draw_scene_end(WORKBENCH_Data *vedata);
void workbench_taa_view_updated(WORKBENCH_Data *vedata);
-int workbench_taa_calculate_num_iterations(WORKBENCH_Data *vedata);
+int workbench_taa_calculate_num_iterations(WORKBENCH_PrivateData *wpd);
int workbench_num_viewport_rendering_iterations(WORKBENCH_Data *vedata);
+/* workbench_cavity.c */
+void workbench_cavity_data_update(WORKBENCH_PrivateData *wpd);
+void workbench_cavity_cache_init(WORKBENCH_Data *data);
+
/* workbench_effect_dof.c */
void workbench_dof_engine_init(WORKBENCH_Data *vedata, Object *camera);
void workbench_dof_engine_free(void);
diff --git a/source/blender/draw/engines/workbench/workbench_render.c b/source/blender/draw/engines/workbench/workbench_render.c
index c8f74120113..803bf17662f 100644
--- a/source/blender/draw/engines/workbench/workbench_render.c
+++ b/source/blender/draw/engines/workbench/workbench_render.c
@@ -154,7 +154,7 @@ void workbench_render(WORKBENCH_Data *data,
DRW_hair_update();
/* Draw. */
- int num_samples = workbench_taa_calculate_num_iterations(data);
+ int num_samples = workbench_taa_calculate_num_iterations(data->stl->wpd);
for (int sample = 0; sample < num_samples; sample++) {
if (RE_engine_test_break(engine)) {
break;
@@ -179,7 +179,7 @@ void workbench_render(WORKBENCH_Data *data,
DRW_hair_update();
/* Draw. */
- int num_samples = workbench_taa_calculate_num_iterations(data);
+ int num_samples = workbench_taa_calculate_num_iterations(data->stl->wpd);
for (int sample = 0; sample < num_samples; sample++) {
if (RE_engine_test_break(engine)) {
break;
diff --git a/source/blender/draw/engines/workbench/workbench_shader.c b/source/blender/draw/engines/workbench/workbench_shader.c
index 3470d42608e..cbbc8787fbf 100644
--- a/source/blender/draw/engines/workbench/workbench_shader.c
+++ b/source/blender/draw/engines/workbench/workbench_shader.c
@@ -34,11 +34,7 @@ extern char datatoc_workbench_prepass_vert_glsl[];
extern char datatoc_workbench_prepass_hair_vert_glsl[];
extern char datatoc_workbench_prepass_frag_glsl[];
-// extern char datatoc_workbench_cavity_frag_glsl[];
-// extern char datatoc_workbench_forward_composite_frag_glsl[];
-// extern char datatoc_workbench_deferred_composite_frag_glsl[];
-// extern char datatoc_workbench_deferred_background_frag_glsl[];
-// extern char datatoc_workbench_ghost_resolve_frag_glsl[];
+extern char datatoc_workbench_effect_cavity_frag_glsl[];
extern char datatoc_workbench_composite_frag_glsl[];
@@ -81,6 +77,8 @@ static struct {
struct GPUShader *shadow_depth_pass_sh[2];
struct GPUShader *shadow_depth_fail_sh[2][2];
+ struct GPUShader *cavity_sh[2][2];
+
struct DRWShaderLibrary *lib;
} e_data = {{{{NULL}}}};
@@ -92,28 +90,29 @@ void workbench_shader_library_ensure(void)
DRW_SHADER_LIB_ADD(e_data.lib, common_hair_lib);
DRW_SHADER_LIB_ADD(e_data.lib, common_view_lib);
DRW_SHADER_LIB_ADD(e_data.lib, workbench_shader_interface_lib);
- DRW_SHADER_LIB_ADD(e_data.lib, workbench_cavity_lib);
DRW_SHADER_LIB_ADD(e_data.lib, workbench_common_lib);
DRW_SHADER_LIB_ADD(e_data.lib, workbench_image_lib);
DRW_SHADER_LIB_ADD(e_data.lib, workbench_material_lib);
DRW_SHADER_LIB_ADD(e_data.lib, workbench_data_lib);
DRW_SHADER_LIB_ADD(e_data.lib, workbench_matcap_lib);
DRW_SHADER_LIB_ADD(e_data.lib, workbench_object_outline_lib);
+ DRW_SHADER_LIB_ADD(e_data.lib, workbench_cavity_lib);
DRW_SHADER_LIB_ADD(e_data.lib, workbench_curvature_lib);
DRW_SHADER_LIB_ADD(e_data.lib, workbench_world_light_lib);
}
}
-static char *workbench_build_defines(WORKBENCH_PrivateData *wpd, bool textured, bool tiled)
+static char *workbench_build_defines(
+ WORKBENCH_PrivateData *wpd, bool textured, bool tiled, bool cavity, bool curvature)
{
char *str = NULL;
DynStr *ds = BLI_dynstr_new();
- if (wpd->shading.light == V3D_LIGHTING_STUDIO) {
+ if (wpd && wpd->shading.light == V3D_LIGHTING_STUDIO) {
BLI_dynstr_append(ds, "#define V3D_LIGHTING_STUDIO\n");
}
- else if (wpd->shading.light == V3D_LIGHTING_MATCAP) {
+ else if (wpd && wpd->shading.light == V3D_LIGHTING_MATCAP) {
BLI_dynstr_append(ds, "#define V3D_LIGHTING_MATCAP\n");
}
else {
@@ -130,6 +129,12 @@ static char *workbench_build_defines(WORKBENCH_PrivateData *wpd, bool textured,
if (tiled) {
BLI_dynstr_append(ds, "#define TEXTURE_IMAGE_ARRAY\n");
}
+ if (cavity) {
+ BLI_dynstr_append(ds, "#define USE_CAVITY\n");
+ }
+ if (curvature) {
+ BLI_dynstr_append(ds, "#define USE_CURVATURE\n");
+ }
str = BLI_dynstr_get_cstring(ds);
BLI_dynstr_free(ds);
@@ -153,7 +158,7 @@ static GPUShader *workbench_shader_get_ex(
&e_data.opaque_prepass_sh_cache[wpd->sh_cfg][hair][color];
if (*shader == NULL) {
- char *defines = workbench_build_defines(wpd, textured, tiled);
+ char *defines = workbench_build_defines(wpd, textured, tiled, false, false);
char *frag_file = transp ? datatoc_workbench_transparent_accum_frag_glsl :
datatoc_workbench_prepass_frag_glsl;
@@ -207,7 +212,7 @@ GPUShader *workbench_shader_composite_get(WORKBENCH_PrivateData *wpd)
BLI_assert(light < MAX_LIGHTING);
if (*shader == NULL) {
- char *defines = workbench_build_defines(wpd, false, false);
+ char *defines = workbench_build_defines(wpd, false, false, false, false);
char *frag = DRW_shader_library_create_shader_string(e_data.lib,
datatoc_workbench_composite_frag_glsl);
@@ -235,7 +240,7 @@ GPUShader *workbench_shader_merge_infront_get(WORKBENCH_PrivateData *UNUSED(wpd)
GPUShader *workbench_shader_transparent_resolve_get(WORKBENCH_PrivateData *wpd)
{
if (e_data.oit_resolve_sh == NULL) {
- char *defines = workbench_build_defines(wpd, false, false);
+ char *defines = workbench_build_defines(wpd, false, false, false, false);
e_data.oit_resolve_sh = DRW_shader_create_fullscreen(
datatoc_workbench_transparent_resolve_frag_glsl, defines);
@@ -283,6 +288,24 @@ GPUShader *workbench_shader_shadow_fail_get(bool manifold, bool cap)
return workbench_shader_shadow_pass_get_ex(false, manifold, cap);
}
+GPUShader *workbench_shader_cavity_get(bool cavity, bool curvature)
+{
+ BLI_assert(cavity || curvature);
+ struct GPUShader **shader = &e_data.cavity_sh[cavity][curvature];
+
+ if (*shader == NULL) {
+ char *defines = workbench_build_defines(NULL, false, false, cavity, curvature);
+ char *frag = DRW_shader_library_create_shader_string(
+ e_data.lib, datatoc_workbench_effect_cavity_frag_glsl);
+
+ *shader = DRW_shader_create_fullscreen(frag, defines);
+
+ MEM_freeN(defines);
+ MEM_freeN(frag);
+ }
+ return *shader;
+}
+
void workbench_shader_free(void)
{
for (int j = 0; j < sizeof(e_data.opaque_prepass_sh_cache) / sizeof(void *); j++) {
@@ -305,6 +328,10 @@ void workbench_shader_free(void)
struct GPUShader **sh_array = &e_data.shadow_depth_fail_sh[0][0];
DRW_SHADER_FREE_SAFE(sh_array[j]);
}
+ for (int j = 0; j < sizeof(e_data.cavity_sh) / sizeof(void *); j++) {
+ struct GPUShader **sh_array = &e_data.cavity_sh[0][0];
+ DRW_SHADER_FREE_SAFE(sh_array[j]);
+ }
DRW_SHADER_FREE_SAFE(e_data.oit_resolve_sh);
DRW_SHADER_FREE_SAFE(e_data.merge_infront_sh);