diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py index 9a9b973650c..08f19a02ecc 100644 --- a/release/scripts/startup/bl_ui/properties_render.py +++ b/release/scripts/startup/bl_ui/properties_render.py @@ -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 = ( diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 16448c2ad0e..bba39867079 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -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") diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 07f51dfbc2f..b0cfadacb2c 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -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; + } } } } diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index e3b6e6fb1f9..3c4d7da29fb 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -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) diff --git a/source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl index 38211239d01..b032bb6a7b5 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl @@ -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 index 00000000000..a1abfb3fe1c --- /dev/null +++ b/source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl @@ -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 index 00000000000..7322266a956 --- /dev/null +++ b/source/blender/draw/engines/workbench/shaders/workbench_shadow_vert.glsl @@ -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); +} diff --git a/source/blender/draw/engines/workbench/solid_mode.c b/source/blender/draw/engines/workbench/solid_mode.c index 2a1b5eecc27..c001cd13bb8 100644 --- a/source/blender/draw/engines/workbench/solid_mode.c +++ b/source/blender/draw/engines/workbench/solid_mode.c @@ -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) diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c index f758918d577..40d5c2b12f9 100644 --- a/source/blender/draw/engines/workbench/workbench_engine.c +++ b/source/blender/draw/engines/workbench/workbench_engine.c @@ -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. */ diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c index 69d983b96c7..04a12d992b3 100644 --- a/source/blender/draw/engines/workbench/workbench_materials.c +++ b/source/blender/draw/engines/workbench/workbench_materials.c @@ -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" @@ -37,23 +38,31 @@ #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); diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h index 1f66fb31095..6b8acaebc82 100644 --- a/source/blender/draw/engines/workbench/workbench_private.h +++ b/source/blender/draw/engines/workbench/workbench_private.h @@ -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); diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index 51fba1500f7..0912e5dde29 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -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 { diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h index 00d7c7233a5..7a45b808651 100644 --- a/source/blender/draw/intern/draw_manager.h +++ b/source/blender/draw/intern/draw_manager.h @@ -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 */ diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c index 232ae36438e..434c021775a 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -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); } } } diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index ceff9fb2851..6071b8d8e94 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -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; diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 8b5c6f84f78..8021ed12e45 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -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; diff --git a/source/blender/makesrna/intern/rna_layer.c b/source/blender/makesrna/intern/rna_layer.c index 93df67306e3..e394680cddd 100644 --- a/source/blender/makesrna/intern/rna_layer.c +++ b/source/blender/makesrna/intern/rna_layer.c @@ -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); + 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_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); - 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"); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 60c4fc20f77..bb9c711838a 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -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)