diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2018-06-03 13:13:19 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2018-06-03 13:36:03 +0300 |
commit | 32c5972653041a3423122b5a5ae791ef536b87ed (patch) | |
tree | 281dd3678d964369d9f87ebee300630a3c585d32 /source/blender/draw/engines/workbench/shaders | |
parent | 38bf3b8d23041c547186fee5633782384c8ab384 (diff) |
Workbench: Rework hair support.
Now hairs are shaded properly in workbench and support texturing.
I also added a 10% random normal direction per hair to have a bit more
variation in the shading. This is hardcoded for now.
Diffstat (limited to 'source/blender/draw/engines/workbench/shaders')
4 files changed, 83 insertions, 35 deletions
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 269911189fa..5f37490603d 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 @@ -47,7 +47,7 @@ void main() #ifdef NORMAL_VIEWPORT_PASS_ENABLED #ifdef WORKBENCH_ENCODE_NORMALS vec3 normal_viewport = normal_decode(texelFetch(normalBuffer, texel, 0).rg); - if (diffuse_color.a == 1.0) { + if (diffuse_color.a == 0.0) { normal_viewport = -normal_viewport; } #else /* WORKBENCH_ENCODE_NORMALS */ @@ -81,9 +81,13 @@ void main() #endif /* V3D_LIGHTING_STUDIO */ #ifdef V3D_SHADING_SHADOW - float shadow_mix = step(-shadowShift, dot(normal_viewport, world_data.light_direction_vs.xyz)); - float light_multiplier; - light_multiplier = mix(lightMultiplier, shadowMultiplier, shadow_mix); + float light_factor = -dot(normal_viewport, world_data.light_direction_vs.xyz); + /* 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 = (diffuse_color.a == 1.0 || diffuse_color.a == 0.0) + ? step(-shadowShift, -light_factor) + : smoothstep(1.0, shadowShift, light_factor); + float light_multiplier = mix(lightMultiplier, shadowMultiplier, shadow_mix); #else /* V3D_SHADING_SHADOW */ float light_multiplier = 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 3f271ec439b..a9c84e11aa6 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 @@ -39,20 +39,17 @@ void main() #endif #ifdef V3D_LIGHTING_STUDIO -#ifdef STUDIOLIGHT_ORIENTATION_CAMERA +# ifdef STUDIOLIGHT_ORIENTATION_CAMERA vec3 diffuse_light = get_camera_diffuse_light(world_data, normal_viewport); -#endif -#ifdef STUDIOLIGHT_ORIENTATION_WORLD +# endif +# ifdef STUDIOLIGHT_ORIENTATION_WORLD vec3 normal_world = normalWorldMatrix * normal_viewport; vec3 diffuse_light = get_world_diffuse_light(world_data, normal_world); -#endif - +# endif vec3 shaded_color = diffuse_light * diffuse_color.rgb + specular_color; - -#else /* V3D_LIGHTING_STUDIO */ +#else vec3 shaded_color = diffuse_color.rgb + specular_color; - -#endif /* V3D_LIGHTING_STUDIO */ +#endif vec4 premultiplied = vec4(shaded_color.rgb * alpha, alpha); transparentAccum = calculate_transparent_accum(premultiplied); diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl index c0f58271a8c..bc7741f853c 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl @@ -9,12 +9,17 @@ uniform sampler2D image; #endif #ifdef NORMAL_VIEWPORT_PASS_ENABLED +in vec3 position_viewport; in vec3 normal_viewport; #endif /* NORMAL_VIEWPORT_PASS_ENABLED */ #ifdef OB_TEXTURE in vec2 uv_interp; #endif /* OB_TEXTURE */ +#ifdef HAIR_SHADER +flat in float hair_rand; +#endif + layout(location=0) out uint objectId; layout(location=1) out vec4 diffuseColor; layout(location=2) out vec4 specularColor; @@ -35,23 +40,29 @@ void main() #ifdef OB_TEXTURE diffuseColor = texture(image, uv_interp); #endif /* OB_TEXTURE */ +#ifdef HAIR_SHADER + float hair_color_variation = hair_rand * 0.1; + diffuseColor.rgb = clamp(diffuseColor.rgb - hair_color_variation, 0.0, 1.0); +#endif #ifdef V3D_SHADING_SPECULAR_HIGHLIGHT specularColor = vec4(material_data.specular_color.rgb, material_data.roughness); +#ifdef HAIR_SHADER + specularColor.rgb = clamp(specularColor.rgb - hair_color_variation, 0.0, 1.0); +#endif #endif #ifdef NORMAL_VIEWPORT_PASS_ENABLED - #ifdef WORKBENCH_ENCODE_NORMALS - if (!gl_FrontFacing) { - normalViewport = normal_encode(normalize(-normal_viewport)); - diffuseColor.a = 1.0; - } - else { - normalViewport = normal_encode(normalize(normal_viewport)); - diffuseColor.a = 0.0; - } - #else /* WORKBENCH_ENCODE_NORMALS */ - normalViewport = normal_viewport; - #endif /* WORKBENCH_ENCODE_NORMALS */ + vec3 n = (gl_FrontFacing) ? normal_viewport : -normal_viewport; + n = normalize(n); +# ifdef WORKBENCH_ENCODE_NORMALS + diffuseColor.a = float(gl_FrontFacing); + normalViewport = normal_encode(n); +# else /* WORKBENCH_ENCODE_NORMALS */ + normalViewport = n; +# endif /* WORKBENCH_ENCODE_NORMALS */ +# ifdef HAIR_SHADER + diffuseColor.a = 0.5; +# endif #endif /* NORMAL_VIEWPORT_PASS_ENABLED */ } diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl index f2df117d897..7da9c2644fe 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl @@ -1,30 +1,66 @@ uniform mat4 ModelViewProjectionMatrix; -#ifdef NORMAL_VIEWPORT_PASS_ENABLED +uniform mat4 ProjectionMatrix; +uniform mat4 ViewProjectionMatrix; +uniform mat4 ViewMatrixInverse; uniform mat3 NormalMatrix; -#endif /* NORMAL_VIEWPORT_PASS_ENABLED */ +#ifndef HAIR_SHADER in vec3 pos; -#ifdef NORMAL_VIEWPORT_PASS_ENABLED in vec3 nor; -#endif /* NORMAL_VIEWPORT_PASS_ENABLED */ -#ifdef OB_TEXTURE in vec2 uv; -#endif +#else /* HAIR_SHADER */ +# ifdef OB_TEXTURE +uniform samplerBuffer u; /* active texture layer */ +# endif +flat out float hair_rand; +#endif /* HAIR_SHADER */ #ifdef NORMAL_VIEWPORT_PASS_ENABLED out vec3 normal_viewport; -#endif /* NORMAL_VIEWPORT_PASS_ENABLED */ +#endif #ifdef OB_TEXTURE out vec2 uv_interp; #endif +/* From http://libnoise.sourceforge.net/noisegen/index.html */ +float integer_noise(int n) +{ + n = (n >> 13) ^ n; + int nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff; + return (float(nn) / 1073741824.0); +} + void main() { +#ifdef HAIR_SHADER +# ifdef OB_TEXTURE + vec2 uv = hair_get_customdata_vec2(u); +# endif + float time, thick_time, thickness; + vec3 pos, tan, binor; + hair_get_pos_tan_binor_time( + (ProjectionMatrix[3][3] == 0.0), + ViewMatrixInverse[3].xyz, ViewMatrixInverse[2].xyz, + pos, tan, binor, time, thickness, thick_time); + /* To "simulate" anisotropic shading, randomize hair normal per strand. */ + hair_rand = integer_noise(hair_get_strand_id()); + tan = normalize(tan); + vec3 nor = normalize(cross(binor, tan)); + nor = normalize(mix(nor, -tan, hair_rand * 0.10)); + float cos_theta = (hair_rand*2.0 - 1.0) * 0.20; + float sin_theta = sqrt(max(0.0, 1.0f - cos_theta*cos_theta)); + nor = nor * sin_theta + binor * cos_theta; + gl_Position = ViewProjectionMatrix * vec4(pos, 1.0); +#else + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); +#endif #ifdef OB_TEXTURE uv_interp = uv; #endif #ifdef NORMAL_VIEWPORT_PASS_ENABLED - normal_viewport = normalize(NormalMatrix * nor); -#endif /* NORMAL_VIEWPORT_PASS_ENABLED */ - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + normal_viewport = NormalMatrix * nor; +# ifndef HAIR_SHADER + normal_viewport = normalize(normal_viewport); +# endif +#endif } |