1$input v_texcoord0
2
3/*
4 * Copyright 2016 Joseph Cherlin. All rights reserved.
5 * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
6 */
7
8#include "../common/common.sh"
9
10SAMPLER2D(s_normal, 0);
11SAMPLER2D(s_color,  1);
12SAMPLER2D(s_light,  2);
13SAMPLER2D(s_depth,  3);
14SAMPLER2DSHADOW(s_shadowMap, 4);
15
16// Single directional light for entire scene
17uniform vec4 u_lightDir;
18uniform mat4 u_invMvp;
19uniform mat4 u_lightMtx;
20uniform vec4 u_shadowDimsInv;
21uniform vec4 u_rsmAmount;
22
23float hardShadow(sampler2DShadow _sampler, vec4 _shadowCoord, float _bias)
24{
25	vec2 texCoord = _shadowCoord.xy;
26	return shadow2D(_sampler, vec3(texCoord.xy, _shadowCoord.z-_bias) );
27}
28
29float PCF(sampler2DShadow _sampler, vec4 _shadowCoord, float _bias, vec2 _texelSize)
30{
31	vec2 texCoord = _shadowCoord.xy;
32
33	bool outside = any(greaterThan(texCoord, vec2_splat(1.0)))
34		|| any(lessThan   (texCoord, vec2_splat(0.0)))
35		;
36
37	if (outside)
38	{
39		return 1.0;
40	}
41
42	float result = 0.0;
43	vec2 offset = _texelSize * _shadowCoord.w;
44
45	result += hardShadow(_sampler, _shadowCoord + vec4(vec2(-1.5, -1.5) * offset, 0.0, 0.0), _bias);
46	result += hardShadow(_sampler, _shadowCoord + vec4(vec2(-1.5, -0.5) * offset, 0.0, 0.0), _bias);
47	result += hardShadow(_sampler, _shadowCoord + vec4(vec2(-1.5,  0.5) * offset, 0.0, 0.0), _bias);
48	result += hardShadow(_sampler, _shadowCoord + vec4(vec2(-1.5,  1.5) * offset, 0.0, 0.0), _bias);
49
50	result += hardShadow(_sampler, _shadowCoord + vec4(vec2(-0.5, -1.5) * offset, 0.0, 0.0), _bias);
51	result += hardShadow(_sampler, _shadowCoord + vec4(vec2(-0.5, -0.5) * offset, 0.0, 0.0), _bias);
52	result += hardShadow(_sampler, _shadowCoord + vec4(vec2(-0.5,  0.5) * offset, 0.0, 0.0), _bias);
53	result += hardShadow(_sampler, _shadowCoord + vec4(vec2(-0.5,  1.5) * offset, 0.0, 0.0), _bias);
54
55	result += hardShadow(_sampler, _shadowCoord + vec4(vec2(0.5, -1.5) * offset, 0.0, 0.0), _bias);
56	result += hardShadow(_sampler, _shadowCoord + vec4(vec2(0.5, -0.5) * offset, 0.0, 0.0), _bias);
57	result += hardShadow(_sampler, _shadowCoord + vec4(vec2(0.5,  0.5) * offset, 0.0, 0.0), _bias);
58	result += hardShadow(_sampler, _shadowCoord + vec4(vec2(0.5,  1.5) * offset, 0.0, 0.0), _bias);
59
60	result += hardShadow(_sampler, _shadowCoord + vec4(vec2(1.5, -1.5) * offset, 0.0, 0.0), _bias);
61	result += hardShadow(_sampler, _shadowCoord + vec4(vec2(1.5, -0.5) * offset, 0.0, 0.0), _bias);
62	result += hardShadow(_sampler, _shadowCoord + vec4(vec2(1.5,  0.5) * offset, 0.0, 0.0), _bias);
63	result += hardShadow(_sampler, _shadowCoord + vec4(vec2(1.5,  1.5) * offset, 0.0, 0.0), _bias);
64
65	return result / 16.0;
66}
67
68
69float toClipSpaceDepth(float _depthTextureZ)
70{
71#if BGFX_SHADER_LANGUAGE_HLSL || BGFX_SHADER_LANGUAGE_PSSL || BGFX_SHADER_LANGUAGE_METAL
72	return _depthTextureZ;
73#else
74	return _depthTextureZ * 2.0 - 1.0;
75#endif // BGFX_SHADER_LANGUAGE_HLSL || BGFX_SHADER_LANGUAGE_PSSL || BGFX_SHADER_LANGUAGE_METAL
76}
77
78vec3 clipToWorld(mat4 _invViewProj, vec3 _clipPos)
79{
80	vec4 wpos = mul(_invViewProj, vec4(_clipPos, 1.0) );
81	return wpos.xyz / wpos.w;
82}
83
84void main()
85{
86	vec3 n  = texture2D(s_normal, v_texcoord0).xyz;
87	// Expand out normal
88	n = n*2.0+-1.0;
89	vec3 l = u_lightDir.xyz;//normalize(vec3(-0.8,0.75,-1.0));
90	float dirLightIntensity = 1.0;
91	float dirLight = max(0.0,dot(n,l)) * dirLightIntensity;
92
93	// Apply shadow map
94
95	// Get world position so we can transform it into light space, to look into shadow map
96	vec2 texCoord = v_texcoord0.xy;
97	float deviceDepth = texture2D(s_depth, texCoord).x;
98	float depth       = toClipSpaceDepth(deviceDepth);
99	vec3 clip = vec3(texCoord * 2.0 - 1.0, depth);
100#if BGFX_SHADER_LANGUAGE_HLSL || BGFX_SHADER_LANGUAGE_PSSL || BGFX_SHADER_LANGUAGE_METAL
101	clip.y = -clip.y;
102#endif // BGFX_SHADER_LANGUAGE_HLSL || BGFX_SHADER_LANGUAGE_PSSL || BGFX_SHADER_LANGUAGE_METAL
103	vec3 wpos = clipToWorld(u_invMvp, clip);
104
105	const float shadowMapOffset = 0.003;
106	vec3 posOffset = wpos + n.xyz * shadowMapOffset;
107	vec4 shadowCoord = mul(u_lightMtx, vec4(posOffset, 1.0) );
108
109#if BGFX_SHADER_LANGUAGE_HLSL || BGFX_SHADER_LANGUAGE_METAL
110	shadowCoord.y *= -1.0;
111#endif // BGFX_SHADER_LANGUAGE_HLSL || BGFX_SHADER_LANGUAGE_METAL
112
113	float shadowMapBias = 0.001;
114	vec2 texelSize = vec2_splat(u_shadowDimsInv.x);
115
116	shadowCoord.xy /= shadowCoord.w;
117	shadowCoord.xy = shadowCoord.xy*0.5 + 0.5;
118
119#if BGFX_SHADER_LANGUAGE_GLSL
120	shadowCoord.z = shadowCoord.z*0.5 + 0.5;
121#endif // BGFX_SHADER_LANGUAGE_GLSL
122
123	float visibility = PCF(s_shadowMap, shadowCoord, shadowMapBias, texelSize);
124
125	dirLight *= visibility;
126
127	// Light from light buffer
128	vec3 albedo = texture2D(s_color, v_texcoord0).xyz;
129	vec3 lightBuffer = texture2D(s_light, v_texcoord0).xyz;
130
131	gl_FragColor.xyz = mix(dirLight * albedo, lightBuffer * albedo, u_rsmAmount.x);
132
133	gl_FragColor.w = 1.0;
134}
135