Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2018-11-28 17:57:40 +0300
committerClément Foucault <foucault.clem@gmail.com>2018-11-28 17:59:56 +0300
commit2d720f51cd786f3e0924602efb6ec89ef8ed077f (patch)
tree3b1ac1223a1c35e17e5085f99ef231273c801526 /source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl
parent52458ab49d40081466e369709d68c13a6a47663e (diff)
Workbench: Change Studio lighting
This is in order to have more flexible ligthing presets in the future. The diffuse lighting from hdris was nice but lacked the corresponding specular information. This is an attempt to make it possible to customize the lighting and have a cheap/easy/nice-looking pseudo-PBR workflow. * Add cheap PBR to Workbench with fresnel and better roughness support. This improves the look of the metallic surfaces and is easier to control. * Add ambient light to studio lights settings: just a constant color added to the shading. * Add Smooth option to studio lights settings: This option fakes the effect of making the light bigger making the lighting smoother for this light. Smoother lights gets reflected like a background hdri. * Change default light settings to include the smooth params. * Remove specular highlights from flat shading. (could be added back but how do we make it good looking?) * If specular lighting is disabled, use base color without using metallic. * Include a lot of code simplification/cleanup/confusion fix.
Diffstat (limited to 'source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl')
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl146
1 files changed, 104 insertions, 42 deletions
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)
{
-#ifdef V3D_SHADING_SPECULAR_HIGHLIGHT
- vec3 specular_light = specular_data.rgb * light_data.specular_color.rgb * light_data.specular_color.a;
-
- float shininess = exp2(10.0 * (1.0 - specular_data.a) + 1);
-
-# 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;
-
-# 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
+ 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);
+}
- vec3 specular_color = specular_light * specular_influence;
+/* 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;
-#else /* V3D_SHADING_SPECULAR_HIGHLIGHT */
- vec3 specular_color = vec3(0.0);
-#endif /* V3D_SHADING_SPECULAR_HIGHLIGHT */
- return specular_color;
+ return spec_light;
}
-vec3 get_world_specular_lights(WorldData world_data, vec4 specular_data, vec3 N, vec3 I)
+/* NL need to be unclamped. w in [0..1] range. */
+vec4 wrapped_lighting(vec4 NL, vec4 w)
{
- 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;
+ 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
+ /* 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);
+
+ 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);
+
+ vec4 spec_light = blinn_specular(shininess, spec_angle, spec_NL);
+
+ /* Simulate Env. light. */
+ vec4 w = mix(wrap, vec4(1.0), roughness);
+ vec4 spec_env = wrapped_lighting(wrap_NL, w);
+
+ spec_light = mix(spec_light, spec_env, wrap * wrap);
+
+ /* 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;
}