Workbench: Shadows
authorJeroen Bakker <j.bakker@atmind.nl>
Fri, 4 May 2018 12:07:00 +0000 (14:07 +0200)
committerJeroen Bakker <j.bakker@atmind.nl>
Fri, 4 May 2018 12:08:40 +0000 (14:08 +0200)
Initial review of the shard shadows in the workbench engine.

Speed optimizations like transform feedback are not implemented yet. I first want this part to be reviewed and merged.

@fclem please check the note in drw_stencil_set it was holding back nequal == 0 as by default DST.stencil_mask was set to 0. questioin is should we remove the whole check or not.

Also I am still looking for a better name (or split the enum) for DRW_STATE_STENCIL_DEPTH_FAIL_INCR_DECR_WRAP

Reviewers: fclem

Reviewed By: fclem

Tags: #code_quest

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

18 files changed:
release/scripts/startup/bl_ui/properties_render.py
release/scripts/startup/bl_ui/space_view3d.py
source/blender/blenloader/intern/versioning_280.c
source/blender/draw/CMakeLists.txt
source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl
source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl [new file with mode: 0644]
source/blender/draw/engines/workbench/shaders/workbench_shadow_vert.glsl [new file with mode: 0644]
source/blender/draw/engines/workbench/solid_mode.c
source/blender/draw/engines/workbench/workbench_engine.c
source/blender/draw/engines/workbench/workbench_materials.c
source/blender/draw/engines/workbench/workbench_private.h
source/blender/draw/intern/DRW_render.h
source/blender/draw/intern/draw_manager.h
source/blender/draw/intern/draw_manager_exec.c
source/blender/editors/space_view3d/space_view3d.c
source/blender/makesdna/DNA_view3d_types.h
source/blender/makesrna/intern/rna_layer.c
source/blender/makesrna/intern/rna_space.c

index 9a9b973650c19e0bb5d9162a3ed52ba06436c510..08f19a02ecc12d5fb7c66514407061b0759973c1 100644 (file)
@@ -755,17 +755,7 @@ class RENDER_PT_workbench_environment_light(RenderButtonsPanel, Panel):
         layout = self.layout
         scene = context.scene
         props = scene.layer_properties['BLENDER_WORKBENCH']
-
-        row = layout.row(align=True)
-        col = row.column(align=True)
-        col.prop(props, "diffuse_light_x_neg", text="Left/Right")
-        col.prop(props, "diffuse_light_x_pos", text="")
-        col = row.column(align=True)
-        col.prop(props, "diffuse_light_y_pos", text="Up/Down")
-        col.prop(props, "diffuse_light_y_neg", text="")
-        col = row.column(align=True)
-        col.prop(props, "diffuse_light_z_pos", text="Front/Back")
-        col.prop(props, "diffuse_light_z_neg", text="")
+        layout.prop(props, "light_direction", text="")
 
 
 classes = (
index 16448c2ad0ea4a1a7e0b67004cda4ae15d5988e7..bba398670790de27397c469fe49bc585a2eaa95b 100644 (file)
@@ -3552,8 +3552,13 @@ class VIEW3D_PT_shading(Panel):
             col.row().prop(shading, "light", expand=True)
             if shading.light == 'STUDIO':
                 col.row().template_icon_view(shading, "studiolight")
+                col.separator()
+
+            col.prop(shading, "show_shadows")
+            if shading.show_shadows:
+                col.prop(shading, "ambient_light_intensity")
+                col.separator()
 
-            col.separator()
             col.prop(shading, "show_object_overlap")
 
 
index 07f51dfbc2f1971b4222f7510dffe92e53c9cd90..b0cfadacb2c6c1aed1d77a57e3adc03aad5f7f5c 100644 (file)
@@ -1068,6 +1068,11 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main)
                                                        }
                                                }
                                        }
+                                       if (sl->spacetype == SPACE_VIEW3D) {
+                                               View3D *v3d = (View3D *)sl;
+                                               v3d->drawtype_ambient_intensity = 0.5;
+                                               v3d->overlays |= V3D_OVERLAY_HIDE_CURSOR;
+                                       }
                                }
                        }
                }
index e3b6e6fb1f9777122192f67632c5d72f7224df31..3c4d7da29fb5f20318879cf6ea1fc86a5808ecb2 100644 (file)
@@ -212,6 +212,8 @@ data_to_c_simple(engines/eevee/shaders/volumetric_integration_frag.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_composite_frag.glsl SRC)
+data_to_c_simple(engines/workbench/shaders/workbench_shadow_vert.glsl SRC)
+data_to_c_simple(engines/workbench/shaders/workbench_shadow_geom.glsl SRC)
 data_to_c_simple(engines/workbench/shaders/workbench_background_lib.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)
index 38211239d01837a3f0298a55066099cd593ffb2f..b032bb6a7b557029fb925ede596d2aeb5227d753 100644 (file)
@@ -6,8 +6,8 @@ uniform sampler2D colorBuffer;
 uniform sampler2D normalBuffer;
 /* normalBuffer contains viewport normals */
 uniform vec2 invertedViewportSize;
-
 uniform vec3 objectOverlapColor = vec3(0.0);
+uniform float lightMultiplier;
 
 layout(std140) uniform world_block {
        WorldData world_data;
@@ -52,11 +52,11 @@ void main()
        vec3 normal_viewport = texelFetch(normalBuffer, texel, 0).rgb;
 #endif /* WORKBENCH_ENCODE_NORMALS */
        vec3 diffuse_light = get_world_diffuse_light(world_data, normal_viewport);
-       vec3 shaded_color = diffuse_light * diffuse_color.rgb;
+       vec3 shaded_color = diffuse_light * diffuse_color.rgb * lightMultiplier;
 
 #else /* V3D_LIGHTING_STUDIO */
        vec3 diffuse_color = texelFetch(colorBuffer, texel, 0).rgb;
-       vec3 shaded_color = diffuse_color;
+       vec3 shaded_color = diffuse_color * lightMultiplier;
 #endif /* V3D_LIGHTING_STUDIO */
 
 
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl b/source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl
new file mode 100644 (file)
index 0000000..a1abfb3
--- /dev/null
@@ -0,0 +1,51 @@
+layout(triangles) in;
+layout(triangle_strip, max_vertices=9) out;
+
+uniform mat4 ModelMatrix;
+uniform mat4 ModelViewProjectionMatrix;
+
+uniform vec3 lightDirection = vec3(0.57, 0.57, -0.57);
+
+in VertexData {
+       flat vec4 lightDirectionMS;
+       vec4 frontPosition;
+       vec4 backPosition;
+} vertexData[];
+
+vec3 face_normal(vec3 v1, vec3 v2, vec3 v3) {
+       return normalize(cross(v2 - v1, v3 - v1));
+}
+void main()
+{
+       vec4 light_direction = vertexData[0].lightDirectionMS;
+       vec4 v1 = gl_in[0].gl_Position;
+       vec4 v2 = gl_in[1].gl_Position;
+       vec4 v3 = gl_in[2].gl_Position;
+       bool backface = dot(face_normal(v1.xyz, v2.xyz, v3.xyz), light_direction.xyz) > 0.0;
+       
+       int index0 = backface?0:2;
+       int index2 = backface?2:0;
+       
+       /* back cap */
+       gl_Position = vertexData[index0].backPosition;
+       EmitVertex();
+       gl_Position = vertexData[1].backPosition;
+       EmitVertex();
+       gl_Position = vertexData[index2].backPosition;
+       EmitVertex();
+
+       /* sides */
+       gl_Position = vertexData[index2].frontPosition;
+       EmitVertex();
+       gl_Position = vertexData[index0].backPosition;
+       EmitVertex();
+       gl_Position = vertexData[index0].frontPosition;
+       EmitVertex();
+       gl_Position = vertexData[1].backPosition;
+       EmitVertex();
+       gl_Position = vertexData[1].frontPosition;
+       EmitVertex();
+       gl_Position = vertexData[index2].frontPosition;
+       EmitVertex();
+       EndPrimitive();
+}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_shadow_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_shadow_vert.glsl
new file mode 100644 (file)
index 0000000..7322266
--- /dev/null
@@ -0,0 +1,23 @@
+#define EPSILON 0.000001
+#define INFINITE 100.0
+
+uniform mat4 ModelMatrixInverse;
+uniform mat4 ModelViewProjectionMatrix;
+uniform vec3 lightDirection = vec3(0.57, 0.57, -0.57);
+
+in vec4 pos;
+
+out VertexData {
+       flat vec4 lightDirectionMS;
+       vec4 frontPosition;
+       vec4 backPosition;
+} vertexData;
+
+void main()
+{
+       gl_Position = pos;
+       vertexData.lightDirectionMS = normalize(ModelMatrixInverse * vec4(lightDirection, 0.0));
+       vertexData.lightDirectionMS.w = 0.0;
+       vertexData.frontPosition = ModelViewProjectionMatrix * (pos + vertexData.lightDirectionMS * EPSILON);
+       vertexData.backPosition = ModelViewProjectionMatrix * (pos + vertexData.lightDirectionMS * INFINITE);
+}
index 2a1b5eecc27aa0e80de8ea60aef3fb3052d8d659..c001cd13bb81e230b93485d644258f38a7b62bfd 100644 (file)
@@ -59,8 +59,10 @@ static void workbench_solid_cache_finish(void *vedata)
        workbench_materials_cache_finish(data);
 }
 
-static void workbench_solid_draw_background(void *UNUSED(vedata))
+static void workbench_solid_draw_background(void *vedata)
 {
+       WORKBENCH_Data * data = (WORKBENCH_Data *)vedata;
+       workbench_materials_draw_background(data);
 }
 
 static void workbench_solid_draw_scene(void *vedata)
index f758918d577081345d7f61ba70a11e8756f06dac..40d5c2b12f9fe39c0d8ce93e9cc18871a644bac4 100644 (file)
@@ -58,7 +58,9 @@ static void workbench_view_layer_settings_create(RenderEngine *UNUSED(engine), I
        BLI_assert(props &&
                   props->type == IDP_GROUP &&
                   props->subtype == IDP_GROUP_SUB_ENGINE_RENDER);
-       UNUSED_VARS_NDEBUG(props);
+
+       const float light_direction[3] = {-0.577350269, -0.577350269, 0.577350269};
+       BKE_collection_engine_property_add_float_array(props, "light_direction", light_direction, 3);   UNUSED_VARS_NDEBUG(props);
 }
 
 /* Note: currently unused, we may want to register so we can see this when debugging the view. */
index 69d983b96c7f8c80a630647e349e35e083d1d8c9..04a12d992b3f99dd733285af755aaa599d044e46 100644 (file)
@@ -25,8 +25,9 @@
 
 #include "workbench_private.h"
 
-#include "BLI_dynstr.h"
 #include "BLI_alloca.h"
+#include "BLI_dynstr.h"
+#include "BLI_utildefines.h"
 
 #include "BKE_particle.h"
 
 #include "UI_resources.h"
 
 /* *********** STATIC *********** */
+
+// #define DEBUG_SHADOW_VOLUME
 #define MAX_SHADERS 255
+
 static struct {
        struct GPUShader *prepass_sh_cache[MAX_SHADERS];
        struct GPUShader *composite_sh_cache[MAX_SHADERS];
+       struct GPUShader *shadow_sh;
 
        struct GPUTexture *object_id_tx; /* ref only, not alloced */
        struct GPUTexture *color_buffer_tx; /* ref only, not alloced */
        struct GPUTexture *normal_buffer_tx; /* ref only, not alloced */
 
+       float light_direction[3]; /* world light direction for shadows */
        int next_object_id;
-} e_data = {{NULL}};
+} e_data = {NULL};
 
 /* Shaders */
 extern char datatoc_workbench_prepass_vert_glsl[];
 extern char datatoc_workbench_prepass_frag_glsl[];
 extern char datatoc_workbench_composite_frag_glsl[];
 
+extern char datatoc_workbench_shadow_vert_glsl[];
+extern char datatoc_workbench_shadow_geom_glsl[];
+
 extern char datatoc_workbench_background_lib_glsl[];
 extern char datatoc_workbench_common_lib_glsl[];
 extern char datatoc_workbench_data_lib_glsl[];
@@ -64,7 +73,7 @@ extern DrawEngineType draw_engine_workbench_solid;
 
 #define OBJECT_ID_PASS_ENABLED(wpd) (wpd->drawtype_options & V3D_DRAWOPTION_OBJECT_OVERLAP)
 #define NORMAL_VIEWPORT_PASS_ENABLED(wpd) (wpd->drawtype_lighting & V3D_LIGHTING_STUDIO)
-
+#define SHADOW_ENABLED(wpd) (wpd->drawtype_options & V3D_DRAWOPTION_SHADOW)
 static char *workbench_build_defines(WORKBENCH_PrivateData *wpd)
 {
        char *str = NULL;
@@ -127,7 +136,8 @@ static char *workbench_build_prepass_frag(void)
 
 static int get_shader_index(WORKBENCH_PrivateData *wpd)
 {
-       return (wpd->drawtype_options << 2) + wpd->drawtype_lighting;
+       const int DRAWOPTIONS_MASK = V3D_DRAWOPTION_OBJECT_OVERLAP;
+       return ((wpd->drawtype_options & DRAWOPTIONS_MASK) << 2) + wpd->drawtype_lighting;
 }
 
 static void select_deferred_shaders(WORKBENCH_PrivateData *wpd)
@@ -209,6 +219,7 @@ void workbench_materials_engine_init(WORKBENCH_Data *vedata)
                memset(e_data.prepass_sh_cache,   0x00, sizeof(struct GPUShader *) * MAX_SHADERS);
                memset(e_data.composite_sh_cache, 0x00, sizeof(struct GPUShader *) * MAX_SHADERS);
                e_data.next_object_id = 1;
+               e_data.shadow_sh = DRW_shader_create(datatoc_workbench_shadow_vert_glsl, datatoc_workbench_shadow_geom_glsl, NULL, NULL);
        }
 
        if (!stl->g_data) {
@@ -248,6 +259,22 @@ void workbench_materials_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.shadow_sh);
+}
+
+static void workbench_composite_uniforms(WORKBENCH_PrivateData *wpd, DRWShadingGroup *grp)
+{
+       DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+       DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
+       DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &e_data.color_buffer_tx);
+       if (OBJECT_ID_PASS_ENABLED(wpd)) {
+               DRW_shgroup_uniform_texture_ref(grp, "objectId", &e_data.object_id_tx);
+       }
+       if (NORMAL_VIEWPORT_PASS_ENABLED(wpd)) {
+               DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &e_data.normal_buffer_tx);
+       }
+       DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo);
+       DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1);
 }
 
 void workbench_materials_cache_init(WORKBENCH_Data *vedata)
@@ -255,8 +282,12 @@ void workbench_materials_cache_init(WORKBENCH_Data *vedata)
        WORKBENCH_StorageList *stl = vedata->stl;
        WORKBENCH_PassList *psl = vedata->psl;
        WORKBENCH_PrivateData *wpd = stl->g_data;
-       DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
        DRWShadingGroup *grp;
+       const DRWContextState *draw_ctx = DRW_context_state_get();
+       ViewLayer *view_layer = draw_ctx->view_layer;
+       IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_WORKBENCH);
+       static float light_multiplier = 1.0f;
+
        const DRWContextState *DCS = DRW_context_state_get();
 
        wpd->material_hash = BLI_ghash_ptr_new(__func__);
@@ -266,11 +297,13 @@ void workbench_materials_cache_init(WORKBENCH_Data *vedata)
                wpd->drawtype_lighting = v3d->drawtype_lighting;
                wpd->drawtype_options = v3d->drawtype_options;
                wpd->drawtype_studiolight = v3d->drawtype_studiolight;
+               wpd->drawtype_ambient_intensity = v3d->drawtype_ambient_intensity;
        }
        else {
                wpd->drawtype_lighting = V3D_LIGHTING_STUDIO;
                wpd->drawtype_options = 0;
                wpd->drawtype_studiolight = 0;
+               wpd->drawtype_ambient_intensity = 0.5;
        }
 
        select_deferred_shaders(wpd);
@@ -281,25 +314,49 @@ void workbench_materials_cache_init(WORKBENCH_Data *vedata)
                UI_GetThemeColor3fv(TH_HIGH_GRAD, wd->background_color_high);
                studiolight_update_world(wpd->drawtype_studiolight, wd);
 
-               psl->composite_pass = DRW_pass_create("Composite", DRW_STATE_WRITE_COLOR);
-               grp = DRW_shgroup_create(wpd->composite_sh, psl->composite_pass);
-               DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
-               DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &e_data.color_buffer_tx);
-               if (OBJECT_ID_PASS_ENABLED(wpd)) {
-                       DRW_shgroup_uniform_texture_ref(grp, "objectId", &e_data.object_id_tx);
-               }
-               if (NORMAL_VIEWPORT_PASS_ENABLED(wpd)) {
-                       DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &e_data.normal_buffer_tx);
-               }
                wpd->world_ubo = DRW_uniformbuffer_create(sizeof(WORKBENCH_UBO_World), NULL);
-               DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo);
                DRW_uniformbuffer_update(wpd->world_ubo, &wpd->world_data);
-               DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1);
 
-               DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+               copy_v3_v3(e_data.light_direction, BKE_collection_engine_property_value_get_float_array(props, "light_direction"));
+               negate_v3(e_data.light_direction);
+
+               if (SHADOW_ENABLED(wpd)) {
+                       psl->composite_pass = DRW_pass_create("Composite", DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_EQUAL);
+                       grp = DRW_shgroup_create(wpd->composite_sh, psl->composite_pass);
+                       workbench_composite_uniforms(wpd, grp);
+                       DRW_shgroup_stencil_mask(grp, 0x00);
+                       DRW_shgroup_uniform_float(grp, "lightMultiplier", &light_multiplier, 1);
+                       DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+
+#ifdef DEBUG_SHADOW_VOLUME
+                       psl->shadow_pass = DRW_pass_create("Shadow", DRW_STATE_DEPTH_LESS | DRW_STATE_CULL_BACK | DRW_STATE_WRITE_COLOR);
+                       grp = DRW_shgroup_create(e_data.shadow_sh, psl->shadow_pass);
+                       DRW_shgroup_uniform_vec3(grp, "lightDirection", e_data.light_direction, 1);
+                       DRW_shgroup_stencil_mask(grp, 0xFF);
+                       wpd->shadow_shgrp = grp;
+#else
+                       psl->shadow_pass = DRW_pass_create("Shadow", DRW_STATE_DEPTH_GREATER | DRW_STATE_WRITE_STENCIL_SHADOW);
+                       grp = DRW_shgroup_create(e_data.shadow_sh, psl->shadow_pass);
+                       DRW_shgroup_uniform_vec3(grp, "lightDirection", e_data.light_direction, 1);
+                       DRW_shgroup_stencil_mask(grp, 0xFF);
+                       wpd->shadow_shgrp = grp;
+
+                       psl->composite_shadow_pass = DRW_pass_create("Composite Shadow", DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_NEQUAL);
+                       grp = DRW_shgroup_create(wpd->composite_sh, psl->composite_shadow_pass);
+                       DRW_shgroup_stencil_mask(grp, 0x00);
+                       workbench_composite_uniforms(wpd, grp);
+                       DRW_shgroup_uniform_float(grp, "lightMultiplier", &wpd->drawtype_ambient_intensity, 1);
+                       DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+#endif
+               }
+               else {
+                       psl->composite_pass = DRW_pass_create("Composite", DRW_STATE_WRITE_COLOR);
+                       grp = DRW_shgroup_create(wpd->composite_sh, psl->composite_pass);
+                       workbench_composite_uniforms(wpd, grp);
+                       DRW_shgroup_uniform_float(grp, "lightMultiplier", &light_multiplier, 1);
+                       DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+               }
        }
-
-
 }
 static WORKBENCH_MaterialData *get_or_create_material_data(WORKBENCH_Data *vedata, IDProperty *props, Object *ob, Material *mat)
 {
@@ -324,6 +381,7 @@ static WORKBENCH_MaterialData *get_or_create_material_data(WORKBENCH_Data *vedat
        if (material == NULL) {
                material = MEM_mallocN(sizeof(WORKBENCH_MaterialData), __func__);
                material->shgrp = DRW_shgroup_create(wpd->prepass_sh, psl->prepass_pass);
+               DRW_shgroup_stencil_mask(material->shgrp, 0xFF);
                material->object_id = engine_object_data->object_id;
                copy_v3_v3(material->color, material_template.color);
                DRW_shgroup_uniform_vec3(material->shgrp, "object_color", material->color, 1);
@@ -366,6 +424,9 @@ static void workbench_cache_populate_particles(WORKBENCH_Data *vedata, IDPropert
 
 void workbench_materials_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
 {
+       WORKBENCH_StorageList *stl = vedata->stl;
+       WORKBENCH_PrivateData *wpd = stl->g_data;
+
        if (!DRW_object_is_renderable(ob))
                return;
 
@@ -409,6 +470,13 @@ void workbench_materials_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob
                                }
                        }
                }
+
+               if (SHADOW_ENABLED(wpd)) {
+                       struct Gwn_Batch *geom_shadow = DRW_cache_object_surface_get(ob);
+                       if (geom_shadow) {
+                               DRW_shgroup_call_object_add(wpd->shadow_shgrp, geom_shadow, ob);
+                       }
+               }
        }
 }
 
@@ -416,6 +484,22 @@ void workbench_materials_cache_finish(WORKBENCH_Data *UNUSED(vedata))
 {
 }
 
+void workbench_materials_draw_background(WORKBENCH_Data *vedata)
+{
+       WORKBENCH_StorageList *stl = vedata->stl;
+       WORKBENCH_FramebufferList *fbl = vedata->fbl;
+       WORKBENCH_PrivateData *wpd = stl->g_data;
+       const float clear_depth = 1.0f;
+       const float clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+       unsigned int clear_stencil = 0xFF;
+
+       GPU_framebuffer_bind(fbl->prepass_fb);
+       int clear_bits = GPU_DEPTH_BIT;
+       SET_FLAG_FROM_TEST(clear_bits, OBJECT_ID_PASS_ENABLED(wpd), GPU_COLOR_BIT);
+       SET_FLAG_FROM_TEST(clear_bits, SHADOW_ENABLED(wpd), GPU_STENCIL_BIT);
+       GPU_framebuffer_clear(fbl->prepass_fb, clear_bits, clear_color, clear_depth, clear_stencil);
+}
+
 void workbench_materials_draw_scene(WORKBENCH_Data *vedata)
 {
        WORKBENCH_PassList *psl = vedata->psl;
@@ -423,20 +507,27 @@ void workbench_materials_draw_scene(WORKBENCH_Data *vedata)
        WORKBENCH_FramebufferList *fbl = vedata->fbl;
        WORKBENCH_PrivateData *wpd = stl->g_data;
        DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
-       const float clear_depth = 1.0f;
 
+       /* clear in background */
        GPU_framebuffer_bind(fbl->prepass_fb);
-       if (OBJECT_ID_PASS_ENABLED(wpd)) {
-               const float clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
-               GPU_framebuffer_clear_color_depth(fbl->prepass_fb, clear_color, clear_depth);
+       DRW_draw_pass(psl->prepass_pass);
+       if (SHADOW_ENABLED(wpd)) {
+#ifdef DEBUG_SHADOW_VOLUME
+               GPU_framebuffer_bind(dfbl->default_fb);
+               DRW_draw_pass(psl->composite_pass);
+               DRW_draw_pass(psl->shadow_pass);
+#else
+               GPU_framebuffer_bind(dfbl->depth_only_fb);
+               DRW_draw_pass(psl->shadow_pass);
+               GPU_framebuffer_bind(dfbl->default_fb);
+               DRW_draw_pass(psl->composite_pass);
+               DRW_draw_pass(psl->composite_shadow_pass);
+#endif
        }
        else {
-               GPU_framebuffer_clear_depth(fbl->prepass_fb, clear_depth);
+               GPU_framebuffer_bind(dfbl->default_fb);
+               DRW_draw_pass(psl->composite_pass);
        }
-       DRW_draw_pass(psl->prepass_pass);
-
-       GPU_framebuffer_bind(dfbl->color_only_fb);
-       DRW_draw_pass(psl->composite_pass);
 
        BLI_ghash_free(wpd->material_hash, NULL, MEM_freeN);
        DRW_UBO_FREE_SAFE(wpd->world_ubo);
index 1f66fb31095547e7417cb62656c51ad3d6257501..6b8acaebc828f1001af1843bb234f27a398a6628 100644 (file)
@@ -44,7 +44,10 @@ typedef struct WORKBENCH_StorageList {
 
 typedef struct WORKBENCH_PassList {
        struct DRWPass *prepass_pass;
+       struct DRWPass *shadow_pass;
        struct DRWPass *composite_pass;
+       struct DRWPass *composite_shadow_pass;
+       struct DRWPass *composite_light_pass;
 } WORKBENCH_PassList;
 
 typedef struct WORKBENCH_Data {
@@ -74,7 +77,10 @@ typedef struct WORKBENCH_PrivateData {
        short drawtype_lighting;
        short drawtype_options;
        short drawtype_studiolight;
+       short pad;
+       float drawtype_ambient_intensity;
        struct GPUUniformBuffer *world_ubo;
+       struct DRWShadingGroup *shadow_shgrp;
        WORKBENCH_UBO_World world_data;
 } WORKBENCH_PrivateData; /* Transient data */
 
@@ -109,6 +115,7 @@ void workbench_solid_materials_free(void);
 /* workbench_materials.c */
 void workbench_materials_engine_init(WORKBENCH_Data *vedata);
 void workbench_materials_engine_free(void);
+void workbench_materials_draw_background(WORKBENCH_Data *vedata);
 void workbench_materials_draw_scene(WORKBENCH_Data *vedata);
 void workbench_materials_cache_init(WORKBENCH_Data *vedata);
 void workbench_materials_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob);
index 51fba1500f71bc7d8f5ca1d48c45c35757d266c6..0912e5dde29ac6a5686d666be44184096b38e031 100644 (file)
@@ -273,10 +273,11 @@ typedef enum {
        DRW_STATE_ADDITIVE_FULL = (1 << 19), /* Same as DRW_STATE_ADDITIVE but let alpha accumulate without premult. */
        DRW_STATE_BLEND_PREMUL  = (1 << 20), /* Use that if color is already premult by alpha. */
 
-       DRW_STATE_WRITE_STENCIL    = (1 << 27),
-       DRW_STATE_STENCIL_EQUAL    = (1 << 28),
+       DRW_STATE_WRITE_STENCIL          = (1 << 27),
+       DRW_STATE_WRITE_STENCIL_SHADOW   = (1 << 28),
+       DRW_STATE_STENCIL_EQUAL          = (1 << 29),
+       DRW_STATE_STENCIL_NEQUAL         = (1 << 30),
 } DRWState;
-
 #define DRW_STATE_DEFAULT (DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS)
 
 typedef enum {
index 00d7c7233a5ed97b5e7cc77c894d9b3ef01567ec..7a45b808651750a9b9eea910e6c18aa95ffa7207 100644 (file)
@@ -262,7 +262,7 @@ typedef struct ViewUboStorage {
 /* ------------- DRAW MANAGER ------------ */
 
 #define MAX_CLIP_PLANES 6 /* GL_MAX_CLIP_PLANES is at least 6 */
-
+#define STENCIL_UNDEFINED 256
 typedef struct DRWManager {
        /* TODO clean up this struct a bit */
        /* Cache generation */
index 232ae36438ef78496b6884ed2ebe9a38571c8775..434c021775a27e133a2282bf9ddddfbea7fd6ef4 100644 (file)
@@ -278,21 +278,27 @@ void drw_state_set(DRWState state)
                DRWState test;
                if (CHANGED_ANY_STORE_VAR(
                        DRW_STATE_WRITE_STENCIL |
-                       DRW_STATE_STENCIL_EQUAL,
+                       DRW_STATE_WRITE_STENCIL_SHADOW |
+                       DRW_STATE_STENCIL_EQUAL |
+                       DRW_STATE_STENCIL_NEQUAL,
                        test))
                {
                        if (test) {
                                glEnable(GL_STENCIL_TEST);
-
                                /* Stencil Write */
                                if ((state & DRW_STATE_WRITE_STENCIL) != 0) {
                                        glStencilMask(0xFF);
                                        glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
                                }
+                               else if ((state & DRW_STATE_WRITE_STENCIL_SHADOW) != 0) {
+                                       glStencilMask(0xFF);
+                                       glStencilOpSeparate(GL_BACK,  GL_KEEP, GL_INCR_WRAP, GL_KEEP);
+                                       glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_DECR_WRAP, GL_KEEP);
+                               }
                                /* Stencil Test */
-                               else if ((state & DRW_STATE_STENCIL_EQUAL) != 0) {
+                               else if ((state & (DRW_STATE_STENCIL_EQUAL | DRW_STATE_STENCIL_NEQUAL)) != 0) {
                                        glStencilMask(0x00); /* disable write */
-                                       DST.stencil_mask = 0;
+                                       DST.stencil_mask = STENCIL_UNDEFINED;
                                }
                                else {
                                        BLI_assert(0);
@@ -318,15 +324,17 @@ void drw_state_set(DRWState state)
 static void drw_stencil_set(unsigned int mask)
 {
        if (DST.stencil_mask != mask) {
+               DST.stencil_mask = mask;
                /* Stencil Write */
                if ((DST.state & DRW_STATE_WRITE_STENCIL) != 0) {
                        glStencilFunc(GL_ALWAYS, mask, 0xFF);
-                       DST.stencil_mask = mask;
                }
                /* Stencil Test */
                else if ((DST.state & DRW_STATE_STENCIL_EQUAL) != 0) {
                        glStencilFunc(GL_EQUAL, mask, 0xFF);
-                       DST.stencil_mask = mask;
+               }
+               else if ((DST.state & DRW_STATE_STENCIL_NEQUAL) != 0) {
+                       glStencilFunc(GL_NOTEQUAL, mask, 0xFF);
                }
        }
 }
index ceff9fb2851f3734ef6ef71f05849764e90a0984..6071b8d8e94347c91bda6f33db8a13b513d54145 100644 (file)
@@ -323,7 +323,7 @@ static SpaceLink *view3d_new(const ScrArea *UNUSED(sa), const Scene *scene)
        v3d->gridsubdiv = 10;
        v3d->drawtype = OB_SOLID;
        v3d->drawtype_lighting = V3D_LIGHTING_STUDIO;
-       v3d->overlays = 0;
+       v3d->drawtype_ambient_intensity = 0.5;
 
        v3d->gridflag = V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_FLOOR;
        
index 8b5c6f84f78753f0641b3c947b5f381c603401a7..8021ed12e452f6752e88d70867efd4d0c40e8db7 100644 (file)
@@ -90,6 +90,7 @@ enum {
        V3D_DRAWOPTION_OBJECT_OVERLAP = (1 << 1),
        V3D_DRAWOPTION_SINGLE_COLOR   = (1 << 2),
        V3D_DRAWOPTION_OBJECT_COLOR   = (1 << 4),
+       V3D_DRAWOPTION_SHADOW         = (1 << 5),
 };
 #define V3D_DRAWOPTION_SOLID_COLOR_MASK (V3D_DRAWOPTION_SINGLE_COLOR | V3D_DRAWOPTION_RANDOMIZE | V3D_DRAWOPTION_OBJECT_COLOR | V3D_DRAWOPTION_MATERIAL_COLOR)
 
@@ -259,9 +260,9 @@ typedef struct View3D {
        short drawtype_lighting;
        short drawtype_options;
        short drawtype_studiolight;
+       float drawtype_ambient_intensity;
 
        int overlays;
-       int pad6;
 
        View3DDebug debug;
 } View3D;
index 93df67306e3aed4903c37d3944e92bf5f8c64110..e394680cdddf4d6c19d5695bbeae4fd3270a02d2 100644 (file)
@@ -319,6 +319,9 @@ static void rna_LayerEngineSettings_##_ENGINE_##_##_NAME_##_set(PointerRNA *ptr,
 #define RNA_LAYER_ENGINE_WORKBENCH_GET_SET_INT(_NAME_) \
        RNA_LAYER_ENGINE_GET_SET(int, Workbench, COLLECTION_MODE_NONE, _NAME_)
 
+#define RNA_LAYER_ENGINE_WORKBENCH_GET_SET_BOOL(_NAME_) \
+       RNA_LAYER_ENGINE_GET_SET(bool, Workbench, COLLECTION_MODE_NONE, _NAME_)
+
 /* mode engines */
 
 #define RNA_LAYER_MODE_OBJECT_GET_SET_FLOAT(_NAME_) \
@@ -368,12 +371,7 @@ RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT(hair_brightness_randomness)
 RNA_LAYER_ENGINE_WORKBENCH_GET_SET_FLOAT(random_object_color_saturation)
 RNA_LAYER_ENGINE_WORKBENCH_GET_SET_FLOAT(random_object_color_value)
 /* View Layer settings */
-RNA_LAYER_ENGINE_WORKBENCH_GET_SET_FLOAT_ARRAY(diffuse_light_x_pos, 3)
-RNA_LAYER_ENGINE_WORKBENCH_GET_SET_FLOAT_ARRAY(diffuse_light_x_neg, 3)
-RNA_LAYER_ENGINE_WORKBENCH_GET_SET_FLOAT_ARRAY(diffuse_light_y_pos, 3)
-RNA_LAYER_ENGINE_WORKBENCH_GET_SET_FLOAT_ARRAY(diffuse_light_y_neg, 3)
-RNA_LAYER_ENGINE_WORKBENCH_GET_SET_FLOAT_ARRAY(diffuse_light_z_pos, 3)
-RNA_LAYER_ENGINE_WORKBENCH_GET_SET_FLOAT_ARRAY(diffuse_light_z_neg, 3)
+RNA_LAYER_ENGINE_WORKBENCH_GET_SET_FLOAT_ARRAY(light_direction, 3)
 
 /* eevee engine */
 /* ViewLayer settings. */
@@ -1709,51 +1707,10 @@ static void rna_def_view_layer_engine_settings_workbench(BlenderRNA *brna)
        RNA_def_struct_ui_text(srna, "Workbench Scene Layer Settings", "Workbench Engine settings");
 
        RNA_define_verify_sdna(0); /* not in sdna */
-
-       prop = RNA_def_property(srna, "diffuse_light_x_pos", PROP_FLOAT, PROP_COLOR);
-       RNA_def_property_array(prop, 3);
-       RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Workbench_diffuse_light_x_pos_get", "rna_LayerEngineSettings_Workbench_diffuse_light_x_pos_set", NULL);
-       RNA_def_property_ui_text(prop, "Diffuse +X Light", "Diffuse light color in positive X direction");
-       RNA_def_property_range(prop, 0.0f, 1.0f);
-       RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
-       RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
-
-       prop = RNA_def_property(srna, "diffuse_light_x_neg", PROP_FLOAT, PROP_COLOR);
-       RNA_def_property_array(prop, 3);
-       RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Workbench_diffuse_light_x_neg_get", "rna_LayerEngineSettings_Workbench_diffuse_light_x_neg_set", NULL);
-       RNA_def_property_ui_text(prop, "Diffuse -X Light", "Diffuse light color in negative X direction");
-       RNA_def_property_range(prop, 0.0f, 1.0f);
-       RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
-       RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
-
-       prop = RNA_def_property(srna, "diffuse_light_y_pos", PROP_FLOAT, PROP_COLOR);
-       RNA_def_property_array(prop, 3);
-       RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Workbench_diffuse_light_y_pos_get", "rna_LayerEngineSettings_Workbench_diffuse_light_y_pos_set", NULL);
-       RNA_def_property_ui_text(prop, "Diffuse +Y Light", "Diffuse light color in positive Y direction");
-       RNA_def_property_range(prop, 0.0f, 1.0f);
-       RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
-       RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
-
-       prop = RNA_def_property(srna, "diffuse_light_y_neg", PROP_FLOAT, PROP_COLOR);
-       RNA_def_property_array(prop, 3);
-       RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Workbench_diffuse_light_y_neg_get", "rna_LayerEngineSettings_Workbench_diffuse_light_y_neg_set", NULL);
-       RNA_def_property_ui_text(prop, "Diffuse -Y Light", "Diffuse light color in negative Y direction");
-       RNA_def_property_range(prop, 0.0f, 1.0f);
-       RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
-       RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
-
-       prop = RNA_def_property(srna, "diffuse_light_z_pos", PROP_FLOAT, PROP_COLOR);
-       RNA_def_property_array(prop, 3);
-       RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Workbench_diffuse_light_z_pos_get", "rna_LayerEngineSettings_Workbench_diffuse_light_z_pos_set", NULL);
-       RNA_def_property_ui_text(prop, "Diffuse +Z Light", "Diffuse light color in positive Z direction");
-       RNA_def_property_range(prop, 0.0f, 1.0f);
-       RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
-       RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
-
-       prop = RNA_def_property(srna, "diffuse_light_z_neg", PROP_FLOAT, PROP_COLOR);
+       prop = RNA_def_property(srna, "light_direction", PROP_FLOAT, PROP_DIRECTION);
        RNA_def_property_array(prop, 3);
-       RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Workbench_diffuse_light_z_neg_get", "rna_LayerEngineSettings_Workbench_diffuse_light_z_neg_set", NULL);
-       RNA_def_property_ui_text(prop, "Diffuse -Z Light", "Diffuse light color in negative Z direction");
+       RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Workbench_light_direction_get", "rna_LayerEngineSettings_Workbench_light_direction_set", NULL);
+       RNA_def_property_ui_text(prop, "Light Direction", "Direction of the light for shadow calculation");
        RNA_def_property_range(prop, 0.0f, 1.0f);
        RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
        RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
index 60c4fc20f7725319985ed5e0be9038df108c3021..bb9c711838a7a9ae56d75c01009e72cd872c92be 100644 (file)
@@ -2249,6 +2249,21 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
                                          NULL);
        RNA_def_property_ui_text(prop, "Color", "Single Color Mode");
        RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_3DViewShading_type_update");
+
+       prop = RNA_def_property(srna, "show_shadows", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "drawtype_options", V3D_DRAWOPTION_SHADOW);
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+       RNA_def_property_ui_text(prop, "Shadow", "Show Shadow");
+       RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_3DViewShading_type_update");
+
+       prop = RNA_def_property(srna, "ambient_light_intensity", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "drawtype_ambient_intensity");
+       RNA_def_property_float_default(prop, 0.5);
+       RNA_def_property_ui_text(prop, "Ambient Light", "Intensity of ambient light for shadows");
+       RNA_def_property_range(prop, 0.0f, 1.0f);
+       RNA_def_property_ui_range(prop, 0.00f, 1.0f, 1, 3);
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+       RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_3DViewShading_type_update");
 }
 
 static void rna_def_space_view3d_overlay(BlenderRNA *brna)