Workbench: Add Curvature overlay for better visibility of surface detail for e.g...
authorLukas Stockner <lukas.stockner@freenet.de>
Mon, 26 Nov 2018 15:49:56 +0000 (16:49 +0100)
committerLukas Stockner <lukas.stockner@freenet.de>
Mon, 26 Nov 2018 16:31:18 +0000 (17:31 +0100)
The approach is fairly simple, just apply an edge detection filter to the view normal and scale the brightness based on that.

The overlay is disabled at object boundaries to avoid dark lines around objects.

Generally, this implementation follows the proposal of @monio at https://blender.community/c/rightclickselect/J9bbbc.
The changes are:
- Dynamic filter radius (on high-DPI displays, a radius of two is used)
- Options to reduce the strength of both ridges and valleys
- Tweaked function for the strength reduction (the original method actually had a local maximum, resulting in a brighter line inside valleys)
- Multiplication for blending instead of overlay, which doesn't work reliably with scene-referred intensities
- Renamed to point out the distinction between it and the SSAO-based cavity overlay

Reviewers: jbakker

Reviewed By: jbakker

Subscribers: billreynish, manitwo, linko, monio

Differential Revision: https://developer.blender.org/D3617

14 files changed:
release/scripts/startup/bl_ui/space_view3d.py
source/blender/blenkernel/intern/screen.c
source/blender/blenloader/intern/versioning_280.c
source/blender/draw/CMakeLists.txt
source/blender/draw/engines/workbench/shaders/workbench_curvature_lib.glsl [new file with mode: 0644]
source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl
source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl
source/blender/draw/engines/workbench/workbench_data.c
source/blender/draw/engines/workbench/workbench_deferred.c
source/blender/draw/engines/workbench/workbench_forward.c
source/blender/draw/engines/workbench/workbench_materials.c
source/blender/draw/engines/workbench/workbench_private.h
source/blender/makesdna/DNA_view3d_types.h
source/blender/makesrna/intern/rna_space.c

index d8dcd94902b4f5555c55134f044fa4d7fc17a0a9..07b71136d8b461cc5fea2ad968fc9636ce87df34 100644 (file)
@@ -4325,16 +4325,25 @@ class VIEW3D_PT_shading_options(Panel):
             row.active = not shading.show_xray
             row.prop(shading, "show_cavity")
 
-            if shading.show_cavity:
-                sub = col.row(align=True)
-                sub.active = not shading.show_xray and shading.show_cavity
-                sub.prop(shading, "cavity_ridge_factor")
-                sub.prop(shading, "cavity_valley_factor")
-                sub.popover(
-                    panel="VIEW3D_PT_shading_options_ssao",
-                    icon='PREFERENCES',
-                    text=""
-                )
+            if shading.show_cavity and not shading.show_xray:
+                row.prop(shading, "cavity_type", text="Type")
+
+                if shading.cavity_type in {'WORLD', 'BOTH'}:
+                    col.label(text="World Space")
+                    sub = col.row(align=True)
+                    sub.prop(shading, "cavity_ridge_factor", text="Ridge")
+                    sub.prop(shading, "cavity_valley_factor", text="Valley")
+                    sub.popover(
+                        panel="VIEW3D_PT_shading_options_ssao",
+                        icon='PREFERENCES',
+                        text=""
+                    )
+
+                if shading.cavity_type in {'SCREEN', 'BOTH'}:
+                    col.label(text="Screen Space")
+                    sub = col.row(align=True)
+                    sub.prop(shading, "curvature_ridge_factor", text="Ridge")
+                    sub.prop(shading, "curvature_valley_factor", text="Valley")
 
         row = layout.split()
         row.prop(shading, "show_object_outline")
index e23291d42d4b09a3a9e21acd01e6e22adc901f88..225f74616cffbc14c3d2f32a6db723d7e2ece352 100644 (file)
@@ -822,6 +822,8 @@ void BKE_screen_view3d_shading_init(View3DShading *shading)
        shading->xray_alpha_wire = 0.5f;
        shading->cavity_valley_factor = 1.0f;
        shading->cavity_ridge_factor = 1.0f;
+       shading->curvature_ridge_factor = 1.0f;
+       shading->curvature_valley_factor = 1.0f;
        copy_v3_fl(shading->single_color, 0.8f);
        copy_v3_fl(shading->background_color, 0.05f);
 }
index 8870b346efca3516a74a580b2e6957b7c42f65bb..1bd99d00816fb8e509262626b280adc43882fc8d 100644 (file)
@@ -2414,7 +2414,6 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
 #undef PAINT_BLEND_HUE
 #undef PAINT_BLEND_ALPHA_SUB
 #undef PAINT_BLEND_ALPHA_ADD
-
                }
        }
 
@@ -2443,5 +2442,19 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
 
        {
                /* Versioning code until next subversion bump goes here. */
+
+               if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "float", "curvature_ridge_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.curvature_ridge_factor = 1.0f;
+                                                       v3d->shading.curvature_valley_factor = 1.0f;
+                                               }
+                                       }
+                               }
+                       }
+               }
        }
 }
index 2097fb66c8b4bf75914cd9107f280ac799bd8806..05865ba5636a662c6e051575c9c0a4d6e4c1ce76 100644 (file)
@@ -231,6 +231,7 @@ data_to_c_simple(engines/workbench/shaders/workbench_forward_depth_frag.glsl SRC
 data_to_c_simple(engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl SRC)
 data_to_c_simple(engines/workbench/shaders/workbench_ghost_resolve_frag.glsl SRC)
 data_to_c_simple(engines/workbench/shaders/workbench_object_outline_lib.glsl SRC)
+data_to_c_simple(engines/workbench/shaders/workbench_curvature_lib.glsl SRC)
 data_to_c_simple(engines/workbench/shaders/workbench_prepass_vert.glsl SRC)
 data_to_c_simple(engines/workbench/shaders/workbench_prepass_frag.glsl SRC)
 data_to_c_simple(engines/workbench/shaders/workbench_shadow_vert.glsl SRC)
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_curvature_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_curvature_lib.glsl
new file mode 100644 (file)
index 0000000..6b69367
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef CURVATURE_OFFSET
+#  define CURVATURE_OFFSET 1
+#endif
+
+float curvature_soft_clamp(float curvature, float 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)
+{
+    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;
+    }
+
+    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;
+
+#ifdef WORKBENCH_ENCODE_NORMALS
+    normal_up    = normal_decode(normal_up   ).rg;
+    normal_down  = normal_decode(normal_down ).rg;
+    normal_left  = normal_decode(normal_left ).rg;
+    normal_right = normal_decode(normal_right).rg;
+#endif
+
+    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);
+    return 2.0 * curvature_soft_clamp(normal_diff, ridge);
+}
index 7ba6b3a5193007b781911fa67a9ba8970394998f..3a538f4f2ac37937ee3010ab5aa5703174c365a7 100644 (file)
@@ -13,5 +13,7 @@ struct WorldData {
        int num_lights;
        int matcap_orientation;
        float background_alpha;
-       int pad[1];
+       float curvature_ridge;
+       float curvature_valley;
+       int pad[3];
 };
index 508aeb1f0c19995e62acbfe7014667c58e76a53c..f15e6b613a9dcc6afd56d7fd6efdd2efeaf05319 100644 (file)
@@ -103,12 +103,17 @@ void main()
 #endif
        vec3 shaded_color = diffuse_light * diffuse_color.rgb + specular_color;
 
-#ifdef V3D_SHADING_CAVITY
+#ifdef V3D_SHADING_SSAO
        vec2 cavity = texelFetch(cavityBuffer, texel, 0).rg;
        shaded_color *= 1.0 - cavity.x;
        shaded_color *= 1.0 + cavity.y;
 #endif
 
+#ifdef V3D_SHADING_CURVATURE
+       float curvature = calculate_curvature(objectId, normalBuffer, texel, world_data.curvature_ridge, world_data.curvature_valley);
+       shaded_color *= curvature + 1.0;
+#endif
+
 #ifdef V3D_SHADING_SHADOW
        float light_factor = -dot(normal_viewport, world_data.shadow_direction_vs.xyz);
        /* The step function might be ok for meshes but it's
index aa99883bb6b463ef9dfef8f705c53a227c759686..94b721dd935105233c7212cd8fc42ff57952cd90 100644 (file)
@@ -84,6 +84,9 @@ 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(wpd->shading.curvature_ridge_factor*wpd->shading.curvature_ridge_factor, 1e-4f);
+       wd->curvature_valley = 0.7f / max_ff(wpd->shading.curvature_valley_factor*wpd->shading.curvature_valley_factor, 1e-4f);
+
        wpd->world_ubo = DRW_uniformbuffer_create(sizeof(WORKBENCH_UBO_World), &wpd->world_data);
 
        /* Cavity settings */
index 66dcfdd66d013e871c8a424ec33fe300ef638fa7..ce14ee66ab22c92291cb50acafc698941c98dfe3 100644 (file)
@@ -104,6 +104,7 @@ extern char datatoc_workbench_cavity_lib_glsl[];
 extern char datatoc_workbench_common_lib_glsl[];
 extern char datatoc_workbench_data_lib_glsl[];
 extern char datatoc_workbench_object_outline_lib_glsl[];
+extern char datatoc_workbench_curvature_lib_glsl[];
 extern char datatoc_workbench_world_light_lib_glsl[];
 
 extern char datatoc_gpu_shader_depth_only_frag_glsl[];
@@ -124,6 +125,9 @@ static char *workbench_build_composite_frag(WORKBENCH_PrivateData *wpd)
        if (wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE) {
                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);
 
@@ -499,7 +503,7 @@ static void workbench_composite_uniforms(WORKBENCH_PrivateData *wpd, DRWShadingG
        if (NORMAL_VIEWPORT_COMP_PASS_ENABLED(wpd)) {
                DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &e_data.normal_buffer_tx);
        }
-       if (CAVITY_ENABLED(wpd)) {
+       if (SSAO_ENABLED(wpd)) {
                DRW_shgroup_uniform_texture_ref(grp, "cavityBuffer", &e_data.cavity_buffer_tx);
        }
        if (SPECULAR_HIGHLIGHT_ENABLED(wpd) || MATCAP_ENABLED(wpd)) {
@@ -903,7 +907,7 @@ void workbench_deferred_draw_scene(WORKBENCH_Data *vedata)
                DRW_draw_pass(psl->ghost_resolve_pass);
        }
 
-       if (CAVITY_ENABLED(wpd)) {
+       if (SSAO_ENABLED(wpd)) {
                GPU_framebuffer_bind(fbl->cavity_fb);
                DRW_draw_pass(psl->cavity_pass);
        }
index aa75e1746c7bc880224961d215964fc4cfb92aa0..7a03984b196a6c991b76f2f13f043e3809a410f6 100644 (file)
@@ -75,6 +75,7 @@ extern char datatoc_workbench_data_lib_glsl[];
 extern char datatoc_workbench_background_lib_glsl[];
 extern char datatoc_workbench_checkerboard_depth_frag_glsl[];
 extern char datatoc_workbench_object_outline_lib_glsl[];
+extern char datatoc_workbench_curvature_lib_glsl[];
 extern char datatoc_workbench_prepass_vert_glsl[];
 extern char datatoc_workbench_common_lib_glsl[];
 extern char datatoc_workbench_world_light_lib_glsl[];
@@ -123,6 +124,7 @@ static char *workbench_build_forward_composite_frag(void)
        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);
 
        str = BLI_dynstr_get_cstring(ds);
index 2faa9e288f891c75ae52bb96bccd39e368a5a9a8..6f43e1f8707210481a1a02528aa691c331eb38d1 100644 (file)
@@ -55,8 +55,17 @@ char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, bool use_text
        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 (SSAO_ENABLED(wpd)) {
+               BLI_dynstr_appendf(ds, "#define V3D_SHADING_SSAO\n");
+       }
+       if (CURVATURE_ENABLED(wpd)) {
+               BLI_dynstr_appendf(ds, "#define V3D_SHADING_CURVATURE\n");
+               if (U.pixelsize > 1.5f) {
+                       BLI_dynstr_appendf(ds, "#define CURVATURE_OFFSET 2\n");
+               }
+               else {
+                       BLI_dynstr_appendf(ds, "#define CURVATURE_OFFSET 1\n");
+               }
        }
        if (SPECULAR_HIGHLIGHT_ENABLED(wpd)) {
                BLI_dynstr_appendf(ds, "#define V3D_SHADING_SPECULAR_HIGHLIGHT\n");
@@ -139,13 +148,16 @@ int workbench_material_get_shader_index(WORKBENCH_PrivateData *wpd, bool use_tex
        /* 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_CAVITY, 1 << 5);
+       SET_FLAG_FROM_TEST(index, SSAO_ENABLED(wpd), 1 << 5);
        SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE, 1 << 6);
+       bool uses_curvature = CURVATURE_ENABLED(wpd);
+       SET_FLAG_FROM_TEST(index, uses_curvature, 1 << 7);
+       SET_FLAG_FROM_TEST(index, uses_curvature && (U.pixelsize > 1.5f), 1 << 8);
        /* 2 bits STUDIOLIGHT_ORIENTATION */
-       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);
+       SET_FLAG_FROM_TEST(index, wpd->studio_light->flag & STUDIOLIGHT_ORIENTATION_WORLD, 1 << 9);
+       SET_FLAG_FROM_TEST(index, wpd->studio_light->flag & STUDIOLIGHT_ORIENTATION_VIEWNORMAL, 1 << 10);
        /* 1 bit for hair */
-       SET_FLAG_FROM_TEST(index, is_hair, 1 << 9);
+       SET_FLAG_FROM_TEST(index, is_hair, 1 << 11);
        return index;
 }
 
index 93b3bddfb72bf1d83f0bdf0e7d1f97948bfe0e05..08b6e4a218f346457ce39e9cf7329c398f933bbb 100644 (file)
@@ -49,7 +49,8 @@
 #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 CAVITY_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_CAVITY)
+#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 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))
 
                              ((IS_NAVIGATING(wpd) || wpd->is_playback) && (wpd->user_preferences->gpu_viewport_quality >= GPU_VIEWPORT_QUALITY_TAA8))))
 #define TAA_ENABLED(wpd) (DRW_state_is_image_render() || (wpd->user_preferences->gpu_viewport_quality >= GPU_VIEWPORT_QUALITY_TAA8 && !IS_NAVIGATING(wpd) && !wpd->is_playback))
 #define SPECULAR_HIGHLIGHT_ENABLED(wpd) ((wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT) && (!STUDIOLIGHT_ORIENTATION_VIEWNORMAL_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 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 NORMAL_VIEWPORT_COMP_PASS_ENABLED(wpd) (MATCAP_ENABLED(wpd) || STUDIOLIGHT_ENABLED(wpd) || SHADOW_ENABLED(wpd) || SPECULAR_HIGHLIGHT_ENABLED(wpd) || CURVATURE_ENABLED(wpd))
+#define NORMAL_VIEWPORT_PASS_ENABLED(wpd) (NORMAL_VIEWPORT_COMP_PASS_ENABLED(wpd) || SSAO_ENABLED(wpd))
 #define NORMAL_ENCODING_ENABLED() (true)
 
 
@@ -150,7 +152,9 @@ typedef struct WORKBENCH_UBO_World {
        int num_lights;
        int matcap_orientation;
        float background_alpha;
-       int pad[1];
+       float curvature_ridge;
+       float curvature_valley;
+       int pad[3];
 } WORKBENCH_UBO_World;
 BLI_STATIC_ASSERT_ALIGN(WORKBENCH_UBO_World, 16)
 
index b1a19cb3edcb95386db27084ede375fdcff55338..b06f94db0647ab2051079aba8bca8240102f4f28 100644 (file)
@@ -144,6 +144,8 @@ typedef struct View3DShading {
 
        char light;
        char background_type;
+       char cavity_type;
+       char pad[7];
 
        char studio_light[256]; /* FILE_MAXFILE */
        char matcap[256]; /* FILE_MAXFILE */
@@ -163,6 +165,9 @@ typedef struct View3DShading {
 
        float background_color[3];
 
+       float curvature_ridge_factor;
+       float curvature_valley_factor;
+
 } View3DShading;
 
 /* 3D Viewport Overlay settings */
@@ -406,6 +411,13 @@ enum {
        V3D_SHADING_BACKGROUND_VIEWPORT = 2,
 };
 
+/* View3DShading->cavity_type */
+enum {
+       V3D_SHADING_CAVITY_SSAO = 0,
+       V3D_SHADING_CAVITY_CURVATURE = 1,
+       V3D_SHADING_CAVITY_BOTH = 2,
+};
+
 /* View3DOverlay->flag */
 enum {
        V3D_OVERLAY_FACE_ORIENTATION  = (1 << 0),
index b28e095187782f75aefce89aed09041b1a36c3f3..de9cd0ef23501349674edab92c0921599811c8b0 100644 (file)
@@ -2396,6 +2396,13 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
        };
        static const float default_background_color[] = {0.05f, 0.05f, 0.05f};
 
+       static const EnumPropertyItem cavity_type_items[] = {
+               {V3D_SHADING_CAVITY_SSAO,      "WORLD",  0, "World",  "Cavity shading computed in world space, useful for larger-scale occlusion"},
+               {V3D_SHADING_CAVITY_CURVATURE, "SCREEN", 0, "Screen", "Curvature-based shading, useful for making fine details more visible"},
+               {V3D_SHADING_CAVITY_BOTH,      "BOTH",   0, "Both",   "Use both effects simultaneously"},
+               {0, NULL, 0, NULL, NULL}
+       };
+
 
        /* Note these settings are used for both 3D viewport and the OpenGL render
         * engine in the scene, so can't assume to always be part of a screen. */
@@ -2436,10 +2443,31 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
        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_type", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_items(prop, cavity_type_items);
+       RNA_def_property_ui_text(prop, "Cavity Type", "Way to draw the cavity shading");
+       RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+       prop = RNA_def_property(srna, "curvature_ridge_factor", PROP_FLOAT, PROP_FACTOR);
+       RNA_def_property_float_sdna(prop, NULL, "curvature_ridge_factor");
+       RNA_def_property_float_default(prop, 1.0f);
+       RNA_def_property_ui_text(prop, "Curvature Ridge", "Factor for the curvature ridges");
+       RNA_def_property_range(prop, 0.0f, 2.0f);
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+       RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+       prop = RNA_def_property(srna, "curvature_valley_factor", PROP_FLOAT, PROP_FACTOR);
+       RNA_def_property_float_sdna(prop, NULL, "curvature_valley_factor");
+       RNA_def_property_float_default(prop, 1.0f);
+       RNA_def_property_ui_text(prop, "Curvature Valley", "Factor for the curvature valleys");
+       RNA_def_property_range(prop, 0.0f, 2.0f);
+       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_ridge_factor", PROP_FLOAT, PROP_FACTOR);
        RNA_def_property_float_sdna(prop, NULL, "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_ui_text(prop, "Cavity Ridge", "Factor for the cavity 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);
@@ -2448,7 +2476,7 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
        prop = RNA_def_property(srna, "cavity_valley_factor", PROP_FLOAT, PROP_FACTOR);
        RNA_def_property_float_sdna(prop, NULL, "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_ui_text(prop, "Cavity Valley", "Factor for the cavity 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);