diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py index 5e57e267add..89c1f32ed2d 100644 --- a/release/scripts/startup/bl_ui/properties_material.py +++ b/release/scripts/startup/bl_ui/properties_material.py @@ -253,8 +253,8 @@ class MATERIAL_PT_viewport(MaterialButtonsPanel, Panel): layout.use_property_split = True col = layout.column() - col.prop(mat, "diffuse_color") - col.prop(mat, "specular_color") + col.prop(mat, "diffuse_color", text="Color") + col.prop(mat, "metallic") col.prop(mat, "roughness") diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 6add7bf32eb..8ace0b8164e 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -1531,8 +1531,8 @@ class USERPREF_PT_studiolight_camera(Panel, StudioLightPanelMixin): sl_orientation = 'CAMERA' -class USERPREF_PT_studiolight_specular(Panel, StudioLightPanelMixin): - bl_label = "Specular Lights" +class USERPREF_PT_studiolight_lights(Panel, StudioLightPanelMixin): + bl_label = "Studio Lights" sl_orientation = 'CAMERA' @classmethod @@ -1548,7 +1548,9 @@ class USERPREF_PT_studiolight_specular(Panel, StudioLightPanelMixin): sub = col.column() sub.active = light.use + sub.prop(light, "diffuse_color") sub.prop(light, "specular_color") + sub.prop(light, "smooth") col = split.column() col.active = light.use @@ -1561,6 +1563,8 @@ class USERPREF_PT_studiolight_specular(Panel, StudioLightPanelMixin): userpref = context.user_preferences system = userpref.system + layout.prop(system, "light_ambient") + light = system.solid_lights[0] colsplit = column.split(factor=0.85) self.opengl_light_buttons(colsplit, light) @@ -1572,7 +1576,6 @@ class USERPREF_PT_studiolight_specular(Panel, StudioLightPanelMixin): light = system.solid_lights[2] self.opengl_light_buttons(column, light) - classes = ( USERPREF_HT_header, USERPREF_PT_navigation, @@ -1590,7 +1593,7 @@ classes = ( USERPREF_PT_studiolight_matcaps, USERPREF_PT_studiolight_world, USERPREF_PT_studiolight_camera, - USERPREF_PT_studiolight_specular, + USERPREF_PT_studiolight_lights, ) if __name__ == "__main__": # only for live edit. diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 77f9c2332ac..8eac3cec976 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -4205,13 +4205,14 @@ class VIEW3D_PT_shading_lighting(Panel): sub.scale_y = 0.6 # smaller matcap/hdri preview if shading.light == 'STUDIO': - sub.template_icon_view(shading, "studio_light", scale=3) + # Not implemented right now + # sub.template_icon_view(shading, "studio_light", scale=3) - if shading.selected_studio_light.orientation == 'WORLD': - col.prop(shading, "studiolight_rotate_z", text="Rotation") + # if shading.selected_studio_light.orientation == 'WORLD': + # col.prop(shading, "studiolight_rotate_z", text="Rotation") col = split.column() - col.operator('wm.studiolight_userpref_show', emboss=False, text="", icon='PREFERENCES') + # col.operator('wm.studiolight_userpref_show', emboss=False, text="", icon='PREFERENCES') elif shading.light == 'MATCAP': sub.template_icon_view(shading, "studio_light", scale=3) @@ -4355,8 +4356,8 @@ class VIEW3D_PT_shading_options(Panel): sub.prop(shading, "object_outline_color", text="") col = layout.column() - if (shading.light is not 'MATCAP') and (shading.type is not 'WIREFRAME'): - col.prop(shading, "show_specular_highlight") + if (shading.light == 'STUDIO') and (shading.type is not 'WIREFRAME'): + col.prop(shading, "show_specular_highlight", text="Specular Lighting") class VIEW3D_PT_shading_options_shadow(Panel): diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c index f9f9905be3c..055e4b065a1 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -280,4 +280,15 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template) } } } + + for (bScreen *sc = bmain->screen.first; sc; sc = sc->id.next) { + for (ScrArea *sa = sc->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.flag |= V3D_SHADING_SPECULAR_HIGHLIGHT; + } + } + } + } } diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c index a65520c35fa..55c875e3412 100644 --- a/source/blender/blenloader/intern/versioning_userdef.c +++ b/source/blender/blenloader/intern/versioning_userdef.c @@ -421,6 +421,22 @@ void BLO_version_defaults_userpref_blend(Main *bmain, UserDef *userdef) */ { /* (keep this block even if it becomes empty). */ + copy_v4_fl4(userdef->light[0].vec, -0.580952, 0.228571, 0.781185, 0.0); + copy_v4_fl4(userdef->light[0].col, 0.900000, 0.900000, 0.900000, 1.000000); + copy_v4_fl4(userdef->light[0].spec, 0.318547, 0.318547, 0.318547, 1.000000); + userdef->light[0].smooth = 0.1; + + copy_v4_fl4(userdef->light[1].vec, 0.788218, 0.593482, -0.162765, 0.0); + copy_v4_fl4(userdef->light[1].col, 0.267115, 0.269928, 0.358840, 1.000000); + copy_v4_fl4(userdef->light[1].spec, 0.090838, 0.090838, 0.090838, 1.000000); + userdef->light[1].smooth = 0.25; + + copy_v4_fl4(userdef->light[2].vec, 0.696472, -0.696472, -0.172785, 0.0); + copy_v4_fl4(userdef->light[2].col, 0.293216, 0.304662, 0.401968, 1.000000); + copy_v4_fl4(userdef->light[2].spec, 0.069399, 0.020331, 0.020331, 1.000000); + userdef->light[2].smooth = 0.5; + + copy_v4_fl4(userdef->light_ambient, 0.025000, 0.025000, 0.025000, 1.000000); } if (userdef->pixelsize == 0.0f) diff --git a/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl index 3a538f4f2ac..fd058d45cf6 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl @@ -1,6 +1,7 @@ struct LightData { - vec4 light_direction_vs; + vec4 direction; vec4 specular_color; + vec4 diffuse_color_wrap; /* rgb: diffuse col a: wrapped lighting factor */ }; struct WorldData { @@ -9,7 +10,8 @@ struct WorldData { vec4 background_color_high; vec4 object_outline_color; vec4 shadow_direction_vs; - LightData lights[3]; + LightData lights[4]; + vec4 ambient_color; int num_lights; int matcap_orientation; float background_alpha; diff --git a/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl index f15e6b613a9..4aa471f70d8 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl @@ -1,6 +1,7 @@ out vec4 fragColor; uniform mat4 ProjectionMatrix; +uniform mat4 ViewMatrixInverse; uniform usampler2D objectId; uniform sampler2D colorBuffer; @@ -14,7 +15,6 @@ uniform vec4 viewvecs[3]; uniform float shadowMultiplier; uniform float lightMultiplier; uniform float shadowShift = 0.1; -uniform mat3 normalWorldMatrix; #ifdef STUDIOLIGHT_ORIENTATION_VIEWNORMAL uniform sampler2D matcapImage; @@ -70,39 +70,30 @@ void main() vec3 I_vs = view_vector_from_screen_uv(uv_viewport, viewvecs, ProjectionMatrix); -#ifdef STUDIOLIGHT_ORIENTATION_VIEWNORMAL + /* -------- SHADING --------- */ +#ifdef V3D_LIGHTING_FLAT + vec3 shaded_color = diffuse_color.rgb; + +#elif defined(V3D_LIGHTING_MATCAP) bool flipped = world_data.matcap_orientation != 0; vec2 matcap_uv = matcap_uv_compute(I_vs, normal_viewport, flipped); - diffuse_color = textureLod(matcapImage, matcap_uv, 0.0); -#endif + vec3 object_color = texelFetch(specularBuffer, texel, 0).rgb; + vec3 matcap = textureLod(matcapImage, matcap_uv, 0.0).rgb; + vec3 shaded_color = matcap * object_color; -#ifdef V3D_SHADING_SPECULAR_HIGHLIGHT +#elif defined(V3D_LIGHTING_STUDIO) + +# ifdef V3D_SHADING_SPECULAR_HIGHLIGHT vec4 specular_data = texelFetch(specularBuffer, texel, 0); - vec3 specular_color = get_world_specular_lights(world_data, specular_data, normal_viewport, I_vs); -#else - vec3 specular_color = vec3(0.0); -#endif - -#ifdef V3D_LIGHTING_FLAT - vec3 diffuse_light = vec3(1.0); -#endif - -#ifdef V3D_LIGHTING_MATCAP - vec3 diffuse_light = texelFetch(specularBuffer, texel, 0).rgb; -#endif - -#ifdef V3D_LIGHTING_STUDIO -# ifdef STUDIOLIGHT_ORIENTATION_CAMERA - vec3 diffuse_light = get_camera_diffuse_light(world_data, normal_viewport); -# endif - -# ifdef STUDIOLIGHT_ORIENTATION_WORLD - vec3 normal_world = normalWorldMatrix * normal_viewport; - vec3 diffuse_light = get_world_diffuse_light(world_data, normal_world); +# else + vec4 specular_data = vec4(0.0); # endif + vec3 shaded_color = get_world_lighting(world_data, + diffuse_color.rgb, specular_data.rgb, specular_data.a, + normal_viewport, I_vs); #endif - vec3 shaded_color = diffuse_light * diffuse_color.rgb + specular_color; + /* -------- POST EFFECTS --------- */ #ifdef V3D_SHADING_SSAO vec2 cavity = texelFetch(cavityBuffer, texel, 0).rg; shaded_color *= 1.0 - cavity.x; @@ -119,16 +110,12 @@ void main() /* The step function might be ok for meshes but it's * clearly not the case for hairs. Do smoothstep in this case. */ float shadow_mix = smoothstep(1.0, shadowShift, light_factor); - float light_multiplier = mix(lightMultiplier, shadowMultiplier, shadow_mix); - -#else /* V3D_SHADING_SHADOW */ - float light_multiplier = 1.0; -#endif /* V3D_SHADING_SHADOW */ - - shaded_color *= light_multiplier; + shaded_color *= mix(lightMultiplier, shadowMultiplier, shadow_mix); +#endif #ifdef V3D_SHADING_OBJECT_OUTLINE shaded_color = mix(world_data.object_outline_color.rgb, shaded_color, object_outline); -#endif /* V3D_SHADING_OBJECT_OUTLINE */ +#endif + fragColor = vec4(shaded_color, 1.0); } diff --git a/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl index 67a22073a4b..c00edb06100 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl @@ -4,7 +4,7 @@ uniform float ImageTransparencyCutoff = 0.1; #endif uniform mat4 ProjectionMatrix; -uniform mat3 normalWorldMatrix; +uniform mat4 ViewMatrixInverse; uniform float alpha = 0.5; uniform vec2 invertedViewportSize; uniform vec4 viewvecs[3]; @@ -33,7 +33,6 @@ layout(location=1) out float revealageAccum; /* revealage actually stored in tra void main() { vec4 diffuse_color; - vec3 diffuse_light = vec3(1.0); #ifdef V3D_SHADING_TEXTURE_COLOR diffuse_color = texture(image, uv_interp); @@ -51,30 +50,22 @@ void main() vec3 nor = normalize(normal_viewport); #endif -#ifdef V3D_LIGHTING_MATCAP + /* -------- SHADING --------- */ +#ifdef V3D_LIGHTING_FLAT + vec3 shaded_color = diffuse_color.rgb; + +#elif defined(V3D_LIGHTING_MATCAP) bool flipped = world_data.matcap_orientation != 0; vec2 matcap_uv = matcap_uv_compute(I_vs, nor, flipped); - diffuse_light = texture(matcapImage, matcap_uv).rgb; -#endif + vec3 matcap = textureLod(matcapImage, matcap_uv, 0.0).rgb; + vec3 shaded_color = matcap * diffuse_color.rgb; -#ifdef V3D_SHADING_SPECULAR_HIGHLIGHT - vec3 specular_color = get_world_specular_lights(world_data, vec4(materialSpecularColor.rgb, materialRoughness), nor, I_vs); -#else - vec3 specular_color = vec3(0.0); +#elif defined(V3D_LIGHTING_STUDIO) + vec3 shaded_color = get_world_lighting(world_data, + diffuse_color.rgb, materialSpecularColor.rgb, materialRoughness, + nor, I_vs); #endif -#ifdef V3D_LIGHTING_STUDIO -# ifdef STUDIOLIGHT_ORIENTATION_CAMERA - diffuse_light = get_camera_diffuse_light(world_data, nor); -# endif -# ifdef STUDIOLIGHT_ORIENTATION_WORLD - vec3 normal_world = normalWorldMatrix * nor; - diffuse_light = get_world_diffuse_light(world_data, normal_world); -# endif -#endif - - vec3 shaded_color = diffuse_light * diffuse_color.rgb + specular_color; - /* Based on : * McGuire and Bavoil, Weighted Blended Order-Independent Transparency, Journal of * Computer Graphics Techniques (JCGT), vol. 2, no. 2, 122–141, 2013 diff --git a/source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl index ab48aa5fa03..e25be733d44 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl @@ -72,58 +72,120 @@ vec3 spherical_harmonics(vec3 N, vec3 sh_coefs[STUDIOLIGHT_SH_MAX_COMPONENTS]) } #endif -vec3 get_world_diffuse_light(WorldData world_data, vec3 N) +/* [Drobot2014a] Low Level Optimizations for GCN */ +vec4 fast_rcp(vec4 v) { - return spherical_harmonics(N, world_data.spherical_harmonics_coefs); + return intBitsToFloat(0x7eef370b - floatBitsToInt(v)); } -vec3 get_camera_diffuse_light(WorldData world_data, vec3 N) +vec3 brdf_approx(vec3 spec_color, float roughness, float NV) { - return spherical_harmonics(vec3(N.x, -N.z, N.y), world_data.spherical_harmonics_coefs); + /* Treat anything below 2% as shadowing. + * (in other words, makes it possible to completely disable + * specular on a material by setting specular color to black). */ + float shadowing = clamp(50.0 * spec_color.g, 0.0, 1.0); + /* Very rough own approx. We don't need it to be correct, just fast. + * Just simulate fresnel effect with roughness attenuation. */ + float fresnel = exp2(-8.35 * NV) * (1.0 - roughness); + return mix(spec_color, vec3(1.0), fresnel) * shadowing; } -/* N And I are in View Space. */ -vec3 get_world_specular_light(vec4 specular_data, LightData light_data, vec3 N, vec3 I) +void prep_specular( + vec3 L, vec3 I, vec3 N, vec3 R, + out float NL, out float wrapped_NL, out float spec_angle) { + wrapped_NL = dot(L, R); + vec3 half_dir = normalize(L + I); + spec_angle = clamp(dot(half_dir, N), 0.0, 1.0); + NL = clamp(dot(L, N), 0.0, 1.0); +} + +/* Normalized Blinn shading */ +vec4 blinn_specular(vec4 shininess, vec4 spec_angle, vec4 NL) +{ + /* Pi is already divided in the lamp power. + * normalization_factor = (shininess + 8.0) / (8.0 * M_PI) */ + vec4 normalization_factor = shininess * 0.125 + 1.0; + vec4 spec_light = pow(spec_angle, shininess) * NL * normalization_factor; + + return spec_light; +} + +/* NL need to be unclamped. w in [0..1] range. */ +vec4 wrapped_lighting(vec4 NL, vec4 w) +{ + vec4 w_1 = w + 1.0; + vec4 denom = fast_rcp(w_1 * w_1); + return clamp((NL + w) * denom, 0.0, 1.0); +} + +vec3 get_world_lighting( + WorldData world_data, + vec3 diffuse_color, vec3 specular_color, float roughness, + vec3 N, vec3 I) +{ + vec3 specular_light = world_data.ambient_color.rgb; + vec3 diffuse_light = world_data.ambient_color.rgb; + vec4 wrap = vec4( + world_data.lights[0].diffuse_color_wrap.a, + world_data.lights[1].diffuse_color_wrap.a, + world_data.lights[2].diffuse_color_wrap.a, + world_data.lights[3].diffuse_color_wrap.a + ); + #ifdef V3D_SHADING_SPECULAR_HIGHLIGHT - vec3 specular_light = specular_data.rgb * light_data.specular_color.rgb * light_data.specular_color.a; + /* Prepare Specular computation. Eval 4 lights at once. */ + vec3 R = -reflect(I, N); + vec4 spec_angle, spec_NL, wrap_NL; + prep_specular(world_data.lights[0].direction.xyz, I, N, R, spec_NL.x, wrap_NL.x, spec_angle.x); + prep_specular(world_data.lights[1].direction.xyz, I, N, R, spec_NL.y, wrap_NL.y, spec_angle.y); + prep_specular(world_data.lights[2].direction.xyz, I, N, R, spec_NL.z, wrap_NL.z, spec_angle.z); + prep_specular(world_data.lights[3].direction.xyz, I, N, R, spec_NL.w, wrap_NL.w, spec_angle.w); - float shininess = exp2(10.0 * (1.0 - specular_data.a) + 1); + vec4 gloss = vec4(1.0 - roughness); + /* Reduce gloss for smooth light. (simulate bigger light) */ + gloss *= 1.0 - wrap; + vec4 shininess = exp2(10.0 * gloss + 1.0); -# ifdef BLINN - float normalization_factor = (shininess + 8.0) / (8.0 * M_PI); - vec3 L = -light_data.light_direction_vs.xyz; - vec3 halfDir = normalize(L + I); - float spec_angle = max(dot(halfDir, N), 0.0); - float NL = max(dot(L, N), 0.0); - float specular_influence = pow(spec_angle, shininess) * NL * normalization_factor; + vec4 spec_light = blinn_specular(shininess, spec_angle, spec_NL); -# else - vec3 reflection_vector = reflect(I, N); - float spec_angle = max(dot(light_data.light_direction_vs.xyz, reflection_vector), 0.0); - float specular_influence = pow(spec_angle, shininess); -# endif + /* Simulate Env. light. */ + vec4 w = mix(wrap, vec4(1.0), roughness); + vec4 spec_env = wrapped_lighting(wrap_NL, w); - vec3 specular_color = specular_light * specular_influence; + spec_light = mix(spec_light, spec_env, wrap * wrap); -#else /* V3D_SHADING_SPECULAR_HIGHLIGHT */ - vec3 specular_color = vec3(0.0); -#endif /* V3D_SHADING_SPECULAR_HIGHLIGHT */ - return specular_color; -} - -vec3 get_world_specular_lights(WorldData world_data, vec4 specular_data, vec3 N, vec3 I) -{ - vec3 specular_light = vec3(0.0); - /* Manual loop unrolling provide much better perf. */ - if (world_data.num_lights > 0) { - specular_light += get_world_specular_light(specular_data, world_data.lights[0], N, I); - } - if (world_data.num_lights > 1) { - specular_light += get_world_specular_light(specular_data, world_data.lights[1], N, I); - } - if (world_data.num_lights > 2) { - specular_light += get_world_specular_light(specular_data, world_data.lights[2], N, I); - } - return specular_light; + /* Multiply result by lights specular colors. */ + specular_light += spec_light.x * world_data.lights[0].specular_color.rgb; + specular_light += spec_light.y * world_data.lights[1].specular_color.rgb; + specular_light += spec_light.z * world_data.lights[2].specular_color.rgb; + specular_light += spec_light.w * world_data.lights[3].specular_color.rgb; + + float NV = clamp(dot(N, I), 0.0, 1.0); + specular_color = brdf_approx(specular_color, roughness, NV); +#endif + specular_light *= specular_color; + + /* Prepare diffuse computation. Eval 4 lights at once. */ + vec4 diff_NL; + diff_NL.x = dot(world_data.lights[0].direction.xyz, N); + diff_NL.y = dot(world_data.lights[1].direction.xyz, N); + diff_NL.z = dot(world_data.lights[2].direction.xyz, N); + diff_NL.w = dot(world_data.lights[3].direction.xyz, N); + + vec4 diff_light = wrapped_lighting(diff_NL, wrap); + + /* Multiply result by lights diffuse colors. */ + diffuse_light += diff_light.x * world_data.lights[0].diffuse_color_wrap.rgb; + diffuse_light += diff_light.y * world_data.lights[1].diffuse_color_wrap.rgb; + diffuse_light += diff_light.z * world_data.lights[2].diffuse_color_wrap.rgb; + diffuse_light += diff_light.w * world_data.lights[3].diffuse_color_wrap.rgb; + + /* Energy conservation with colored specular look strange. + * Limit this strangeness by using mono-chromatic specular intensity. */ + float spec_energy = dot(specular_color, vec3(0.33333)); + + diffuse_light *= diffuse_color * (1.0 - spec_energy); + + return diffuse_light + specular_light; } diff --git a/source/blender/draw/engines/workbench/workbench_data.c b/source/blender/draw/engines/workbench/workbench_data.c index 18f4ced6074..522b7d6e8c4 100644 --- a/source/blender/draw/engines/workbench/workbench_data.c +++ b/source/blender/draw/engines/workbench/workbench_data.c @@ -157,37 +157,56 @@ void workbench_private_data_get_light_direction(WORKBENCH_PrivateData *wpd, floa const DRWContextState *draw_ctx = DRW_context_state_get(); Scene *scene = draw_ctx->scene; WORKBENCH_UBO_World *wd = &wpd->world_data; - float view_matrix[4][4]; + float view_matrix[4][4], view_inv[4][4], rot_matrix[4][4]; DRW_viewport_matrix_get(view_matrix, DRW_MAT_VIEW); + DRW_viewport_matrix_get(view_inv, DRW_MAT_VIEWINV); copy_v3_v3(r_light_direction, scene->display.light_direction); negate_v3(r_light_direction); - { - WORKBENCH_UBO_Light *light = &wd->lights[0]; - mul_v3_mat3_m4v3(light->light_direction_vs, view_matrix, r_light_direction); - light->light_direction_vs[3] = 0.0f; - copy_v3_fl(light->specular_color, 1.0f); - light->energy = 1.0f; - copy_v4_v4(wd->shadow_direction_vs, light->light_direction_vs); - wd->num_lights = 1; + /* Shadow direction. */ + mul_v3_mat3_m4v3(wd->shadow_direction_vs, view_matrix, r_light_direction); + + /* TODO enable when we support studiolight presets. */ + if (STUDIOLIGHT_ORIENTATION_WORLD_ENABLED(wpd) && false) { + axis_angle_to_mat4_single(rot_matrix, 'Y', -wpd->shading.studiolight_rot_z); + mul_m4_m4m4(rot_matrix, rot_matrix, view_matrix); + swap_v3_v3(rot_matrix[2], rot_matrix[1]); + negate_v3(rot_matrix[2]); + } + else { + unit_m4(rot_matrix); } - if (!STUDIOLIGHT_ORIENTATION_WORLD_ENABLED(wpd)) { - int light_index = 0; - for (int index = 0 ; index < 3; index++) { - SolidLight *sl = &U.light[index]; - if (sl->flag) { - WORKBENCH_UBO_Light *light = &wd->lights[light_index++]; - copy_v4_v4(light->light_direction_vs, sl->vec); - negate_v3(light->light_direction_vs); - copy_v4_v4(light->specular_color, sl->spec); - light->energy = 1.0f; - } + /* Studio Lights. */ + for (int i = 0; i < 4; i++) { + WORKBENCH_UBO_Light *light = &wd->lights[i]; + /* TODO use 4 lights in studiolights prefs. */ + if (i > 2) { + copy_v3_fl3(light->light_direction, 1.0f, 0.0f, 0.0f); + copy_v3_fl(light->specular_color, 0.0f); + copy_v3_fl(light->diffuse_color, 0.0f); + continue; + } + + SolidLight *sl = &U.light[i]; + if (sl->flag) { + copy_v3_v3(light->light_direction, sl->vec); + mul_mat3_m4_v3(rot_matrix, light->light_direction); + /* We should predivide the power by PI but that makes the lights really dim. */ + copy_v3_v3(light->specular_color, sl->spec); + copy_v3_v3(light->diffuse_color, sl->col); + light->wrapped = sl->smooth; + } + else { + copy_v3_fl3(light->light_direction, 1.0f, 0.0f, 0.0f); + copy_v3_fl(light->specular_color, 0.0f); + copy_v3_fl(light->diffuse_color, 0.0f); } - wd->num_lights = light_index; } + copy_v4_v4(wd->ambient_color, U.light_ambient); + DRW_uniformbuffer_update(wpd->world_ubo, wd); } diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c index fa50a7a2232..5c65cf78820 100644 --- a/source/blender/draw/engines/workbench/workbench_deferred.c +++ b/source/blender/draw/engines/workbench/workbench_deferred.c @@ -78,7 +78,6 @@ static struct { SceneDisplay display; /* world light direction for shadows */ int next_object_id; - float normal_world_matrix[3][3]; struct GPUUniformBuffer *sampling_ubo; struct GPUTexture *jitter_tx; @@ -517,8 +516,6 @@ static void workbench_composite_uniforms(WORKBENCH_PrivateData *wpd, DRWShadingG BKE_studiolight_ensure_flag(wpd->studio_light, STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE); DRW_shgroup_uniform_texture(grp, "matcapImage", wpd->studio_light->equirect_radiance_gputexture ); } - - workbench_material_set_normal_world_matrix(grp, wpd, e_data.normal_world_matrix); } void workbench_deferred_cache_init(WORKBENCH_Data *vedata) diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c index 22b2a4020af..4365f4ec27c 100644 --- a/source/blender/draw/engines/workbench/workbench_forward.c +++ b/source/blender/draw/engines/workbench/workbench_forward.c @@ -62,7 +62,6 @@ static struct { struct GPUTexture *composite_buffer_tx; /* ref only, not alloced */ int next_object_id; - float normal_world_matrix[3][3]; } e_data = {{NULL}}; /* Shaders */ @@ -168,7 +167,6 @@ static WORKBENCH_MaterialData *get_or_create_material_data( DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo); DRW_shgroup_uniform_float(grp, "alpha", &wpd->shading.xray_alpha, 1); DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)wpd->viewvecs, 3); - workbench_material_set_normal_world_matrix(grp, wpd, e_data.normal_world_matrix); workbench_material_copy(material, &material_template); if (STUDIOLIGHT_ORIENTATION_VIEWNORMAL_ENABLED(wpd)) { BKE_studiolight_ensure_flag(wpd->studio_light, STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE); @@ -445,7 +443,6 @@ static void workbench_forward_cache_populate_particles(WORKBENCH_Data *vedata, O ob, psys, md, psl->transparent_accum_pass, shader); - workbench_material_set_normal_world_matrix(shgrp, wpd, e_data.normal_world_matrix); DRW_shgroup_uniform_block(shgrp, "world_block", wpd->world_ubo); workbench_material_shgroup_uniform(wpd, shgrp, material, ob); DRW_shgroup_uniform_vec4(shgrp, "viewvecs[0]", (float *)wpd->viewvecs, 3); diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c index 6f43e1f8707..cf0ed3147d0 100644 --- a/source/blender/draw/engines/workbench/workbench_materials.c +++ b/source/blender/draw/engines/workbench/workbench_materials.c @@ -8,17 +8,15 @@ #include "BLI_hash.h" #define HSV_SATURATION 0.5 -#define HSV_VALUE 0.9 +#define HSV_VALUE 0.8 void workbench_material_update_data(WORKBENCH_PrivateData *wpd, Object *ob, Material *mat, WORKBENCH_MaterialData *data) { /* When V3D_SHADING_TEXTURE_COLOR is active, use V3D_SHADING_MATERIAL_COLOR as fallback when no texture could be determined */ int color_type = wpd->shading.color_type == V3D_SHADING_TEXTURE_COLOR ? V3D_SHADING_MATERIAL_COLOR : wpd->shading.color_type; - static float default_diffuse_color[] = {0.8f, 0.8f, 0.8f, 1.0f}; - static float default_specular_color[] = {0.5f, 0.5f, 0.5f, 0.5f}; - copy_v4_v4(data->diffuse_color, default_diffuse_color); - copy_v4_v4(data->specular_color, default_specular_color); - data->roughness = 0.5f; + copy_v4_fl4(data->diffuse_color, 0.8f, 0.8f, 0.8f, 1.0f); + copy_v4_fl4(data->specular_color, 0.05f, 0.05f, 0.05f, 1.0f); /* Dielectric: 5% reflective. */ + data->roughness = 0.5; /* sqrtf(0.25f); */ if (color_type == V3D_SHADING_SINGLE_COLOR) { copy_v3_v3(data->diffuse_color, wpd->shading.single_color); @@ -36,9 +34,15 @@ void workbench_material_update_data(WORKBENCH_PrivateData *wpd, Object *ob, Mate else { /* V3D_SHADING_MATERIAL_COLOR */ if (mat) { - copy_v3_v3(data->diffuse_color, &mat->r); - copy_v3_v3(data->specular_color, &mat->specr); - data->roughness = mat->roughness; + if (SPECULAR_HIGHLIGHT_ENABLED(wpd)) { + mul_v3_v3fl(data->diffuse_color, &mat->r, 1.0f - mat->metallic); + mul_v3_v3fl(data->specular_color, &mat->r, mat->metallic); + add_v3_fl(data->specular_color, 0.05f * (1.0f - mat->metallic)); + data->roughness = sqrtf(mat->roughness); /* Remap to disney roughness. */ + } + else { + copy_v3_v3(data->diffuse_color, &mat->r); + } } } } @@ -161,21 +165,6 @@ int workbench_material_get_shader_index(WORKBENCH_PrivateData *wpd, bool use_tex return index; } -void workbench_material_set_normal_world_matrix( - DRWShadingGroup *grp, WORKBENCH_PrivateData *wpd, float persistent_matrix[3][3]) -{ - if (STUDIOLIGHT_ORIENTATION_WORLD_ENABLED(wpd)) { - float view_matrix_inverse[4][4]; - float rot_matrix[4][4]; - float matrix[4][4]; - axis_angle_to_mat4_single(rot_matrix, 'Z', -wpd->shading.studiolight_rot_z); - DRW_viewport_matrix_get(view_matrix_inverse, DRW_MAT_VIEWINV); - mul_m4_m4m4(matrix, rot_matrix, view_matrix_inverse); - copy_m3_m4(persistent_matrix, matrix); - DRW_shgroup_uniform_mat3(grp, "normalWorldMatrix", persistent_matrix); - } -} - int workbench_material_determine_color_type(WORKBENCH_PrivateData *wpd, Image *ima, Object *ob) { int color_type = wpd->shading.color_type; diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h index 97da3e5b58d..74764a1b159 100644 --- a/source/blender/draw/engines/workbench/workbench_private.h +++ b/source/blender/draw/engines/workbench/workbench_private.h @@ -59,7 +59,7 @@ (IN_RANGE(wpd->user_preferences->gpu_viewport_quality, GPU_VIEWPORT_QUALITY_FXAA, GPU_VIEWPORT_QUALITY_TAA8) || \ ((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 SPECULAR_HIGHLIGHT_ENABLED(wpd) (STUDIOLIGHT_ENABLED(wpd) && (wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT) && (!STUDIOLIGHT_ORIENTATION_VIEWNORMAL_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)) @@ -135,9 +135,9 @@ typedef struct WORKBENCH_Data { } WORKBENCH_Data; typedef struct WORKBENCH_UBO_Light { - float light_direction_vs[4]; - float specular_color[3]; - float energy; + float light_direction[4]; + float specular_color[3], pad; + float diffuse_color[3], wrapped; } WORKBENCH_UBO_Light; #define WORKBENCH_SH_DATA_LEN ((STUDIOLIGHT_SH_BANDS == 2) ? 6 : STUDIOLIGHT_SH_EFFECTIVE_COEFS_LEN) @@ -148,7 +148,8 @@ typedef struct WORKBENCH_UBO_World { float background_color_high[4]; float object_outline_color[4]; float shadow_direction_vs[4]; - WORKBENCH_UBO_Light lights[3]; + WORKBENCH_UBO_Light lights[4]; + float ambient_color[4]; int num_lights; int matcap_orientation; float background_alpha; @@ -293,8 +294,6 @@ char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, bool use_text void workbench_material_update_data(WORKBENCH_PrivateData *wpd, Object *ob, Material *mat, WORKBENCH_MaterialData *data); uint workbench_material_get_hash(WORKBENCH_MaterialData *material_template, bool is_ghost); int workbench_material_get_shader_index(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair); -void workbench_material_set_normal_world_matrix( - DRWShadingGroup *grp, WORKBENCH_PrivateData *wpd, float persistent_matrix[3][3]); void workbench_material_shgroup_uniform( WORKBENCH_PrivateData *wpd, DRWShadingGroup *grp, WORKBENCH_MaterialData *material, Object *ob); void workbench_material_copy(WORKBENCH_MaterialData *dest_material, const WORKBENCH_MaterialData *source_material); diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 952c4dcd831..5bb3523a458 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -492,7 +492,8 @@ enum { }; typedef struct SolidLight { - int flag, pad; + int flag; + float smooth; float col[4], spec[4], vec[4]; } SolidLight; @@ -586,6 +587,7 @@ typedef struct UserDef { short gp_settings; /* eGP_UserdefSettings */ short tb_leftmouse, tb_rightmouse; struct SolidLight light[3]; + float light_ambient[3], pad7; short gizmo_flag, gizmo_size; short pad6[3]; short textimeout, texcollectrate; diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 921d8a3b65d..3610a9b8514 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -3478,6 +3478,13 @@ static void rna_def_userdef_solidlight(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Enabled", "Enable this OpenGL light in solid draw mode"); RNA_def_property_update(prop, 0, "rna_UserDef_viewport_lights_update"); + prop = RNA_def_property(srna, "smooth", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "smooth"); + RNA_def_property_float_default(prop, 0.5f); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Smooth", "Smooth the lighting from this light"); + RNA_def_property_update(prop, 0, "rna_UserDef_viewport_lights_update"); + prop = RNA_def_property(srna, "direction", PROP_FLOAT, PROP_DIRECTION); RNA_def_property_float_sdna(prop, NULL, "vec"); RNA_def_property_array(prop, 3); @@ -3490,6 +3497,12 @@ static void rna_def_userdef_solidlight(BlenderRNA *brna) RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Specular Color", "Color of the light's specular highlight"); RNA_def_property_update(prop, 0, "rna_UserDef_viewport_lights_update"); + + prop = RNA_def_property(srna, "diffuse_color", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "col"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Diffuse Color", "Color of the light's diffuse highlight"); + RNA_def_property_update(prop, 0, "rna_UserDef_viewport_lights_update"); } static void rna_def_userdef_walk_navigation(BlenderRNA *brna) @@ -4278,6 +4291,12 @@ static void rna_def_userdef_system(BlenderRNA *brna) RNA_def_property_struct_type(prop, "UserSolidLight"); RNA_def_property_ui_text(prop, "Solid Lights", "Lights user to display objects in solid draw mode"); + prop = RNA_def_property(srna, "light_ambient", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "light_ambient"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Ambient Color", "Color of the ambient light that uniformly lit the scene"); + RNA_def_property_update(prop, 0, "rna_UserDef_viewport_lights_update"); + prop = RNA_def_property(srna, "use_weight_color_range", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_CUSTOM_RANGE); RNA_def_property_ui_text(prop, "Use Weight Color Range",