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 };