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:
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenloader/intern/versioning_280.c13
-rw-r--r--source/blender/draw/CMakeLists.txt2
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_cavity_frag.glsl71
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl79
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl9
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl2
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl2
-rw-r--r--source/blender/draw/engines/workbench/workbench_data.c58
-rw-r--r--source/blender/draw/engines/workbench/workbench_deferred.c134
-rw-r--r--source/blender/draw/engines/workbench/workbench_materials.c12
-rw-r--r--source/blender/draw/engines/workbench/workbench_private.h16
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c2
-rw-r--r--source/blender/makesdna/DNA_view3d_types.h4
-rw-r--r--source/blender/makesrna/intern/rna_scene.c2
-rw-r--r--source/blender/makesrna/intern/rna_space.c24
15 files changed, 418 insertions, 12 deletions
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index f4c61e424ae..83a0f21002a 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -1568,5 +1568,18 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
}
+ if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "float", "cavity_valley_factor")) {
+ for (bScreen *screen = bmain->screen.first; screen; screen = screen->id.next) {
+ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+ for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
+ v3d->shading.cavity_valley_factor = 1.0f;
+ v3d->shading.cavity_ridge_factor = 1.0f;
+ }
+ }
+ }
+ }
+ }
}
}
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 40fd8762821..9c3aa34b5d8 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -219,6 +219,8 @@ data_to_c_simple(engines/eevee/shaders/volumetric_scatter_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/volumetric_integration_frag.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_background_lib.glsl SRC)
+data_to_c_simple(engines/workbench/shaders/workbench_cavity_lib.glsl SRC)
+data_to_c_simple(engines/workbench/shaders/workbench_cavity_frag.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_checkerboard_depth_frag.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_common_lib.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_data_lib.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
new file mode 100644
index 00000000000..f6ddd54b7f7
--- /dev/null
+++ b/source/blender/draw/engines/workbench/shaders/workbench_cavity_frag.glsl
@@ -0,0 +1,71 @@
+out vec4 fragColor;
+
+uniform sampler2D depthBuffer;
+uniform sampler2D colorBuffer;
+uniform sampler2D normalBuffer;
+uniform sampler2D positionBuffer;
+
+uniform vec2 invertedViewportSize;
+uniform mat4 WinMatrix; /* inverse WinMatrix */
+
+uniform vec4 viewvecs[3];
+uniform vec4 ssao_params;
+uniform vec4 ssao_settings;
+uniform sampler2D ssao_jitter;
+
+layout(std140) uniform samples_block {
+ vec4 ssao_samples[500];
+};
+
+#define ssao_samples_num ssao_params.x
+#define jitter_tilling ssao_params.yz
+#define dfdy_sign 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.a
+
+vec3 get_view_space_from_depth(in vec2 uvcoords, in float depth)
+{
+ if (WinMatrix[3][3] == 0.0) {
+ /* Perspective */
+ float d = 2.0 * depth - 1.0;
+
+ float zview = -WinMatrix[3][2] / (d + WinMatrix[2][2]);
+
+ return zview * (viewvecs[0].xyz + vec3(uvcoords, 0.0) * viewvecs[1].xyz);
+ }
+ else {
+ /* Orthographic */
+ vec3 offset = vec3(uvcoords, depth);
+
+ return viewvecs[0].xyz + offset * viewvecs[1].xyz;
+ }
+}
+
+/* forward declartion */
+void ssao_factors(
+ in float depth, in vec3 normal, in vec3 position, in vec2 screenco,
+ out float cavities, out float edges);
+
+
+void main()
+{
+ vec2 screenco = vec2(gl_FragCoord.xy) * invertedViewportSize;
+ ivec2 texel = ivec2(gl_FragCoord.xy);
+
+ float depth = texelFetch(depthBuffer, texel, 0).x;
+ vec3 position = get_view_space_from_depth(screenco, depth);
+
+ vec4 diffuse_color = texelFetch(colorBuffer, texel, 0);
+ vec3 normal_viewport = normal_decode(texelFetch(normalBuffer, texel, 0).rg);
+ if (diffuse_color.a == 0.0) {
+ normal_viewport = -normal_viewport;
+ }
+
+ float cavity = 0.0, edges = 0.0;
+ ssao_factors(depth, normal_viewport, position, screenco, cavity, edges);
+
+ fragColor = vec4(cavity, edges, 0.0, 1.0);
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl
new file mode 100644
index 00000000000..da0198ab2e7
--- /dev/null
+++ b/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl
@@ -0,0 +1,79 @@
+
+
+/* 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)
+{
+ 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 < 500; x++) {
+ /* 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[x].xy, rotX), dot(ssao_samples[x].xy, rotY));
+ dir_jittered.xy *= ssao_samples[x].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_deferred_composite_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl
index 326837bc69f..9116e2e7ef5 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
@@ -5,6 +5,8 @@ uniform sampler2D colorBuffer;
uniform sampler2D specularBuffer;
uniform sampler2D normalBuffer;
/* normalBuffer contains viewport normals */
+uniform sampler2D cavityBuffer;
+
uniform vec2 invertedViewportSize;
uniform float shadowMultiplier;
uniform float lightMultiplier;
@@ -77,7 +79,6 @@ void main()
#endif
#ifdef V3D_LIGHTING_MATCAP
- /* TODO: if pixel data is matcap. then */
vec3 diffuse_light = texelFetch(specularBuffer, texel, 0).rgb;
#endif
@@ -93,6 +94,12 @@ void main()
#endif
vec3 shaded_color = diffuse_light * diffuse_color.rgb + specular_color;
+#ifdef V3D_SHADING_CAVITY
+ vec2 cavity = texelFetch(cavityBuffer, texel, 0).rg;
+ shaded_color *= 1.0 - cavity.x;
+ shaded_color *= 1.0 + cavity.y;
+#endif
+
#ifdef V3D_SHADING_SHADOW
float light_factor = -dot(normal_viewport, world_data.light_direction_vs.xyz);
/* The step function might be ok for meshes but it's
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 5931a11f184..d33ef9a0abb 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl
@@ -9,9 +9,9 @@ uniform sampler2D image;
#endif
#ifdef NORMAL_VIEWPORT_PASS_ENABLED
-in vec3 position_viewport;
in vec3 normal_viewport;
#endif /* NORMAL_VIEWPORT_PASS_ENABLED */
+
#ifdef OB_TEXTURE
in vec2 uv_interp;
#endif /* OB_TEXTURE */
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 7da9c2644fe..82443e7336b 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl
@@ -18,6 +18,7 @@ flat out float hair_rand;
#ifdef NORMAL_VIEWPORT_PASS_ENABLED
out vec3 normal_viewport;
#endif
+
#ifdef OB_TEXTURE
out vec2 uv_interp;
#endif
@@ -57,6 +58,7 @@ void main()
#ifdef OB_TEXTURE
uv_interp = uv;
#endif
+
#ifdef NORMAL_VIEWPORT_PASS_ENABLED
normal_viewport = NormalMatrix * nor;
# ifndef HAIR_SHADER
diff --git a/source/blender/draw/engines/workbench/workbench_data.c b/source/blender/draw/engines/workbench/workbench_data.c
index 7468d748986..3a4bb1db749 100644
--- a/source/blender/draw/engines/workbench/workbench_data.c
+++ b/source/blender/draw/engines/workbench/workbench_data.c
@@ -58,6 +58,64 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd)
wd->object_outline_color[3] = 1.0f;
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];
+ float dfdyfacs[2];
+ 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();
+
+ DRW_state_dfdy_factors_get(dfdyfacs);
+
+ 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] = dfdyfacs[1]; /* dfdy sign for offscreen */
+
+ /* 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];
+ }
+ }
+
}
void workbench_private_data_get_light_direction(WORKBENCH_PrivateData *wpd, float light_direction[3])
diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c
index a91e9ab10df..caee998e427 100644
--- a/source/blender/draw/engines/workbench/workbench_deferred.c
+++ b/source/blender/draw/engines/workbench/workbench_deferred.c
@@ -30,6 +30,7 @@
#include "BLI_alloca.h"
#include "BLI_dynstr.h"
#include "BLI_utildefines.h"
+#include "BLI_rand.h"
#include "BKE_node.h"
#include "BKE_particle.h"
@@ -44,6 +45,7 @@
#include "GPU_shader.h"
#include "GPU_texture.h"
+#include "../eevee/eevee_lut.h" /* TODO find somewhere to share blue noise Table */
/* *********** STATIC *********** */
@@ -56,6 +58,7 @@
static struct {
struct GPUShader *prepass_sh_cache[MAX_SHADERS];
struct GPUShader *composite_sh_cache[MAX_SHADERS];
+ struct GPUShader *cavity_sh;
struct GPUShader *shadow_fail_sh;
struct GPUShader *shadow_fail_manifold_sh;
struct GPUShader *shadow_pass_sh;
@@ -65,6 +68,7 @@ static struct {
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 *specular_buffer_tx; /* ref only, not alloced */
struct GPUTexture *normal_buffer_tx; /* ref only, not alloced */
struct GPUTexture *composite_buffer_tx; /* ref only, not alloced */
@@ -73,6 +77,10 @@ static struct {
float light_direction_vs[3];
int next_object_id;
float normal_world_matrix[3][3];
+
+ struct GPUUniformBuffer *sampling_ubo;
+ struct GPUTexture *jitter_tx;
+ int cached_sample_num;
} e_data = {{NULL}};
/* Shaders */
@@ -80,6 +88,7 @@ extern char datatoc_common_hair_lib_glsl[];
extern char datatoc_workbench_prepass_vert_glsl[];
extern char datatoc_workbench_prepass_frag_glsl[];
+extern char datatoc_workbench_cavity_frag_glsl[];
extern char datatoc_workbench_deferred_composite_frag_glsl[];
extern char datatoc_workbench_shadow_vert_glsl[];
@@ -88,6 +97,7 @@ extern char datatoc_workbench_shadow_caps_geom_glsl[];
extern char datatoc_workbench_shadow_debug_frag_glsl[];
extern char datatoc_workbench_background_lib_glsl[];
+extern char datatoc_workbench_cavity_lib_glsl[];
extern char datatoc_workbench_common_lib_glsl[];
extern char datatoc_workbench_data_lib_glsl[];
extern char datatoc_workbench_object_outline_lib_glsl[];
@@ -146,6 +156,21 @@ static char *workbench_build_prepass_vert(void)
return str;
}
+static char *workbench_build_cavity_frag(void)
+{
+ char *str = NULL;
+
+ DynStr *ds = BLI_dynstr_new();
+
+ BLI_dynstr_append(ds, datatoc_workbench_common_lib_glsl);
+ BLI_dynstr_append(ds, datatoc_workbench_cavity_frag_glsl);
+ BLI_dynstr_append(ds, datatoc_workbench_cavity_lib_glsl);
+
+ str = BLI_dynstr_get_cstring(ds);
+ BLI_dynstr_free(ds);
+ return str;
+}
+
static void ensure_deferred_shaders(WORKBENCH_PrivateData *wpd, int index, int drawtype, bool is_hair)
{
if (e_data.prepass_sh_cache[index] == NULL) {
@@ -185,6 +210,50 @@ static void select_deferred_shaders(WORKBENCH_PrivateData *wpd)
wpd->composite_sh = e_data.composite_sh_cache[index_solid];
}
+
+/* Using Hammersley distribution */
+static float *create_disk_samples(int num_samples)
+{
+ /* vec4 to ensure memory alignment. */
+ float (*texels)[4] = MEM_mallocN(sizeof(float[4]) * num_samples, "concentric_tex");
+ const float num_samples_inv = 1.0f / num_samples;
+
+ for (int i = 0; i < num_samples; i++) {
+ float r = (i + 0.5f) * num_samples_inv;
+ double dphi;
+ BLI_hammersley_1D(i, &dphi);
+
+ float phi = (float)dphi * 2.0f * M_PI;
+ texels[i][0] = cosf(phi);
+ texels[i][1] = sinf(phi);
+ /* This deliberatly 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][3];
+ 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;
+ }
+
+ 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_RGB16F, DRW_TEX_FILTER | DRW_TEX_WRAP, &jitter[0][0]);
+}
/* Functions */
@@ -244,6 +313,10 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
datatoc_workbench_shadow_caps_geom_glsl,
shadow_frag,
"#define SHADOW_FAIL\n");
+
+ char *cavity_frag = workbench_build_cavity_frag();
+ e_data.cavity_sh = DRW_shader_create_fullscreen(cavity_frag, NULL);
+ MEM_freeN(cavity_frag);
}
if (!stl->g_data) {
@@ -251,13 +324,15 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
}
- workbench_private_data_init(stl->g_data);
+ WORKBENCH_PrivateData *wpd = stl->g_data;
+ workbench_private_data_init(wpd);
{
const float *viewport_size = DRW_viewport_size_get();
const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]};
e_data.object_id_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_R32UI, &draw_engine_workbench_solid);
e_data.color_buffer_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RGBA8, &draw_engine_workbench_solid);
+ e_data.cavity_buffer_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RG16, &draw_engine_workbench_solid);
e_data.specular_buffer_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RGBA8, &draw_engine_workbench_solid);
e_data.composite_buffer_tx = DRW_texture_pool_query_2D(
size[0], size[1], GPU_RGBA16F, &draw_engine_workbench_solid);
@@ -278,18 +353,59 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
GPU_ATTACHMENT_TEXTURE(e_data.specular_buffer_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),
});
}
+ {
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+ /* AO Samples Tex */
+ const int ssao_samples = scene->display.matcap_ssao_samples;
+ 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);
+ 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 */
{
int state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
psl->prepass_pass = DRW_pass_create("Prepass", state);
psl->prepass_hair_pass = DRW_pass_create("Prepass", state);
}
+
+ {
+ int state = DRW_STATE_WRITE_COLOR;
+ psl->cavity_pass = DRW_pass_create("Cavity", state);
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.cavity_sh, psl->cavity_pass);
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
+ DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &e_data.color_buffer_tx);
+ DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &e_data.normal_buffer_tx);
+
+ 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_block(grp, "samples_block", e_data.sampling_ubo);
+ DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+ }
}
void workbench_deferred_engine_free()
@@ -298,21 +414,29 @@ void workbench_deferred_engine_free()
DRW_SHADER_FREE_SAFE(e_data.prepass_sh_cache[index]);
DRW_SHADER_FREE_SAFE(e_data.composite_sh_cache[index]);
}
+ DRW_SHADER_FREE_SAFE(e_data.cavity_sh);
+ DRW_UBO_FREE_SAFE(e_data.sampling_ubo);
+ DRW_TEXTURE_FREE_SAFE(e_data.jitter_tx);
+
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);
+
}
static void workbench_composite_uniforms(WORKBENCH_PrivateData *wpd, DRWShadingGroup *grp)
{
DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &e_data.color_buffer_tx);
DRW_shgroup_uniform_texture_ref(grp, "objectId", &e_data.object_id_tx);
- if (NORMAL_VIEWPORT_PASS_ENABLED(wpd)) {
+ 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) || MATCAP_ENABLED(wpd)) {
DRW_shgroup_uniform_texture_ref(grp, "specularBuffer", &e_data.specular_buffer_tx);
@@ -715,6 +839,12 @@ void workbench_deferred_draw_scene(WORKBENCH_Data *vedata)
GPU_framebuffer_bind(fbl->prepass_fb);
DRW_draw_pass(psl->prepass_pass);
DRW_draw_pass(psl->prepass_hair_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);
diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c
index 2e2e6f8127a..d74c0606b5d 100644
--- a/source/blender/draw/engines/workbench/workbench_materials.c
+++ b/source/blender/draw/engines/workbench/workbench_materials.c
@@ -52,6 +52,9 @@ char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, int drawtype,
if (wpd->shading.flag & V3D_SHADING_SHADOW) {
BLI_dynstr_appendf(ds, "#define V3D_SHADING_SHADOW\n");
}
+ if (CAVITY_ENABLED(wpd)) {
+ BLI_dynstr_appendf(ds, "#define V3D_SHADING_CAVITY\n");
+ }
if (SPECULAR_HIGHLIGHT_ENABLED(wpd)) {
BLI_dynstr_appendf(ds, "#define V3D_SHADING_SPECULAR_HIGHLIGHT\n");
}
@@ -137,12 +140,13 @@ int workbench_material_get_shader_index(WORKBENCH_PrivateData *wpd, int drawtype
/* 1 bit V3D_SHADING_SPECULAR_HIGHLIGHT */
SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT, 1 << 3);
SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_SHADOW, 1 << 4);
- SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE, 1 << 5);
+ SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_CAVITY, 1 << 5);
+ SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE, 1 << 6);
/* 2 bits STUDIOLIGHT_ORIENTATION */
- SET_FLAG_FROM_TEST(index, wpd->studio_light->flag & STUDIOLIGHT_ORIENTATION_WORLD, 1 << 6);
- SET_FLAG_FROM_TEST(index, wpd->studio_light->flag & STUDIOLIGHT_ORIENTATION_VIEWNORMAL, 1 << 7);
+ SET_FLAG_FROM_TEST(index, wpd->studio_light->flag & STUDIOLIGHT_ORIENTATION_WORLD, 1 << 7);
+ SET_FLAG_FROM_TEST(index, wpd->studio_light->flag & STUDIOLIGHT_ORIENTATION_VIEWNORMAL, 1 << 8);
/* 1 bit for hair */
- SET_FLAG_FROM_TEST(index, is_hair, 1 << 8);
+ SET_FLAG_FROM_TEST(index, is_hair, 1 << 9);
return index;
}
diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h
index ac85f4c5296..758cc2be826 100644
--- a/source/blender/draw/engines/workbench/workbench_private.h
+++ b/source/blender/draw/engines/workbench/workbench_private.h
@@ -38,7 +38,7 @@
#define WORKBENCH_ENGINE "BLENDER_WORKBENCH"
#define M_GOLDEN_RATION_CONJUGATE 0.618033988749895
-#define MAX_SHADERS (1 << 9)
+#define MAX_SHADERS (1 << 10)
#define OB_SOLID_ENABLED(wpd) (wpd->drawtype & OB_SOLID)
#define OB_TEXTURE_ENABLED(wpd) (wpd->drawtype & OB_TEXTURE)
@@ -48,10 +48,12 @@
#define STUDIOLIGHT_ORIENTATION_WORLD_ENABLED(wpd) (STUDIOLIGHT_ENABLED(wpd) && (wpd->studio_light->flag & STUDIOLIGHT_ORIENTATION_WORLD))
#define STUDIOLIGHT_ORIENTATION_CAMERA_ENABLED(wpd) (STUDIOLIGHT_ENABLED(wpd) && (wpd->studio_light->flag & STUDIOLIGHT_ORIENTATION_CAMERA))
#define STUDIOLIGHT_ORIENTATION_VIEWNORMAL_ENABLED(wpd) (MATCAP_ENABLED(wpd) && (wpd->studio_light->flag & STUDIOLIGHT_ORIENTATION_VIEWNORMAL))
-#define OBJECT_ID_PASS_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE)
+#define CAVITY_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_CAVITY)
#define SHADOW_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_SHADOW)
#define SPECULAR_HIGHLIGHT_ENABLED(wpd) ((wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT) && (!STUDIOLIGHT_ORIENTATION_VIEWNORMAL_ENABLED(wpd)))
-#define NORMAL_VIEWPORT_PASS_ENABLED(wpd) (MATCAP_ENABLED(wpd) || STUDIOLIGHT_ENABLED(wpd) || SHADOW_ENABLED(wpd) || SPECULAR_HIGHLIGHT_ENABLED(wpd))
+#define OBJECT_ID_PASS_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE)
+#define NORMAL_VIEWPORT_COMP_PASS_ENABLED(wpd) (MATCAP_ENABLED(wpd) || STUDIOLIGHT_ENABLED(wpd) || SHADOW_ENABLED(wpd) || SPECULAR_HIGHLIGHT_ENABLED(wpd))
+#define NORMAL_VIEWPORT_PASS_ENABLED(wpd) (NORMAL_VIEWPORT_COMP_PASS_ENABLED(wpd) || CAVITY_ENABLED(wpd))
#define NORMAL_ENCODING_ENABLED() (true)
#define WORKBENCH_REVEALAGE_ENABLED
@@ -59,6 +61,7 @@
typedef struct WORKBENCH_FramebufferList {
/* Deferred render buffers */
struct GPUFrameBuffer *prepass_fb;
+ struct GPUFrameBuffer *cavity_fb;
struct GPUFrameBuffer *composite_fb;
/* Forward render buffers */
@@ -78,6 +81,7 @@ typedef struct WORKBENCH_PassList {
/* deferred rendering */
struct DRWPass *prepass_pass;
struct DRWPass *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;
@@ -168,6 +172,12 @@ typedef struct WORKBENCH_PrivateData {
float shadow_near_max[3];
float shadow_near_sides[2][4]; /* This is a parallelogram, so only 2 normal and distance to the edges. */
bool shadow_changed;
+
+ /* Ssao */
+ float winmat[4][4];
+ float viewvecs[3][4];
+ float ssao_params[4];
+ float ssao_settings[4];
} WORKBENCH_PrivateData; /* Transient data */
typedef struct WORKBENCH_MaterialData {
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 7d8df34264e..3bd416d7251 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -326,6 +326,8 @@ static SpaceLink *view3d_new(const ScrArea *UNUSED(sa), const Scene *scene)
v3d->shading.light = V3D_LIGHTING_STUDIO;
v3d->shading.shadow_intensity = 0.5f;
v3d->shading.xray_alpha = 0.5f;
+ v3d->shading.cavity_valley_factor = 1.0f;
+ v3d->shading.cavity_ridge_factor = 1.0f;
copy_v3_fl(v3d->shading.single_color, 0.8f);
v3d->overlay.flag = V3D_OVERLAY_LOOK_DEV;
diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h
index c0f13308df6..ea90ac261da 100644
--- a/source/blender/makesdna/DNA_view3d_types.h
+++ b/source/blender/makesdna/DNA_view3d_types.h
@@ -150,6 +150,9 @@ typedef struct View3DShading {
float object_outline_color[3];
float xray_alpha;
+
+ float cavity_valley_factor;
+ float cavity_ridge_factor;
} View3DShading;
/* 3D Viewport Overlay setings */
@@ -347,6 +350,7 @@ enum {
V3D_SHADING_SHADOW = (1 << 2),
V3D_SHADING_SCENE_LIGHT = (1 << 3),
V3D_SHADING_SPECULAR_HIGHLIGHT = (1 << 4),
+ V3D_SHADING_CAVITY = (1 << 5),
};
/* View3DShading->single_color_type */
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 80a7d0c6915..8055c8fe4d6 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -5759,7 +5759,7 @@ static void rna_def_scene_display(BlenderRNA *brna)
RNA_def_property_range(prop, 0.0f, 250.0f);
prop = RNA_def_property(srna, "matcap_ssao_factor_edge", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_default(prop, 1.0f);
+ RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_ui_text(prop, "Edge Strength", "Strength of the Edge effect");
RNA_def_property_range(prop, 0.0f, 250.0f);
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 284e0ea20bc..3c9484cc390 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -2350,6 +2350,30 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Matcap", "Matcap material and lighting");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ prop = RNA_def_property(srna, "show_cavity", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "shading.flag", V3D_SHADING_CAVITY);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_ui_text(prop, "Cavity", "Show Cavity");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "cavity_ridge_factor", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "shading.cavity_ridge_factor");
+ RNA_def_property_float_default(prop, 1.0f);
+ RNA_def_property_ui_text(prop, "Ridge", "Factor for the ridges");
+ RNA_def_property_range(prop, 0.0f, 250.0f);
+ RNA_def_property_ui_range(prop, 0.00f, 2.5f, 1, 3);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "cavity_valley_factor", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "shading.cavity_valley_factor");
+ RNA_def_property_float_default(prop, 1.0);
+ RNA_def_property_ui_text(prop, "Valley", "Factor for the valleys");
+ RNA_def_property_range(prop, 0.0f, 250.0f);
+ RNA_def_property_ui_range(prop, 0.00f, 2.5f, 1, 3);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
prop = RNA_def_property(srna, "studio_light_orientation", PROP_ENUM, PROP_NONE);
RNA_define_verify_sdna(0);
RNA_def_property_enum_sdna(prop, NULL, "shading.flag");