1 /**
2 * Lighting pass shader for Point Lights
3 */
4 module dash.graphics.shaders.glsl.pointlight;
5 import dash.graphics.shaders.glsl;
6 
7 package:
8 
9 /// Takes a mesh representing the possible area of the light and creates a ray to each vertex
10 immutable string pointlightVS = glslVersion ~ q{
11     layout(location = 0) in vec3 vPosition_m;
12     layout(location = 1) in vec2 vUV;
13     layout(location = 2) in vec3 vNormal_m;
14     layout(location = 3) in vec3 vTangent_m;
15     
16     out vec4 fPosition_s;
17     out vec3 fViewRay;
18     
19     //uniform mat4 world;
20     uniform mat4 worldView;
21     uniform mat4 worldViewProj;
22     
23     void main( void )
24     {
25         // gl_Position is like SV_Position
26         fPosition_s = worldViewProj * vec4( vPosition_m, 1.0f );
27         gl_Position = fPosition_s;
28 
29         fViewRay = ( worldView * vec4( vPosition_m, 1.0 ) ).xyz;
30 
31     }
32 };
33 
34 /// Outputs diffuse and specular color from the light, using the view ray to reconstruct position and a falloff rate to attenuate
35 immutable string pointlightFS = glslVersion ~ q{
36     struct PointLight{
37         vec3 pos_v;
38         vec3 color;
39         float radius;
40         float falloffRate;
41     };
42     
43     in vec4 fPosition_s;
44     in vec3 fViewRay;
45     
46     out vec4 color;
47     
48     uniform sampler2D diffuseTexture;
49     uniform sampler2D normalTexture;
50     uniform sampler2D depthTexture;
51     uniform PointLight light;
52     // A pair of constants for reconstructing the linear Z
53     // [ (-Far * Near ) / ( Far - Near ),  Far / ( Far - Near )  ]
54     uniform vec2 projectionConstants;
55 
56     // Function for decoding normals
57     vec3 decode( vec2 enc )
58     {
59         float t = ( ( enc.x * enc.x ) + ( enc.y * enc.y ) ) / 4;
60         float ti = sqrt( 1 - t );
61         return vec3( ti * enc.x, ti * enc.y, -1 + t * 2 );
62     }
63 
64     void main( void )
65     {
66         // The viewray should have interpolated across the pixels covered by the light, so we should just be able to clamp it's depth to 1
67         vec3 viewRay = vec3( fViewRay.xy / fViewRay.z, 1.0f );
68         vec2 UV = ( ( fPosition_s.xy / fPosition_s.w ) + 1 ) / 2;
69         vec3 textureColor = texture( diffuseTexture, UV ).xyz;
70         float specularIntensity = texture( diffuseTexture, UV ).w;
71         vec3 normal_v = texture( normalTexture, UV ).xyz;
72 
73         // Reconstruct position from depth
74         float depth = texture( depthTexture, UV ).x;
75         float linearDepth = projectionConstants.x / ( projectionConstants.y - depth );
76         vec3 position_v = viewRay * linearDepth;
77 
78         // calculate normalized light direction, and distance
79         vec3 lightDir_v = light.pos_v - position_v;
80         float distance = sqrt( dot(lightDir_v,lightDir_v) );
81         lightDir_v = normalize( lightDir_v );
82 
83         // calculate exponential attenuation
84         float attenuation = pow( max( 1-distance/light.radius, 0), light.falloffRate + 1.0f );
85 
86         // Diffuse lighting calculations
87         float diffuseScale = clamp( dot( normal_v, lightDir_v ), 0, 1 );
88         
89         // Specular lighting calculations
90         // Usually in these you see an "eyeDirection" variable, but in view space that is our position
91         float specularScale = clamp( dot( normalize( position_v ), reflect( lightDir_v, normal_v ) ), 0, 1 );
92         
93         vec3 diffuse = ( diffuseScale * light.color ) * textureColor ;
94         // "8" is the reflectiveness
95         // textureColor.w is the shininess
96         // specularIntensity is the light's contribution
97         vec3 specular = ( pow( specularScale, 8 ) * light.color * specularIntensity);
98         
99         color = vec4((diffuse + specular ) * attenuation, 1.0f ) ;
100         //color = vec4( vec3(1,0,0), 1.0f );
101         
102     }
103 };