1 2#include "lighting.sdr" 3 4#include "shadows.sdr" 5 6in vec3 beamVec; 7in vec3 lightPosition; 8out vec4 fragOut0; 9 10uniform sampler2D ColorBuffer; 11uniform sampler2D NormalBuffer; 12uniform sampler2D PositionBuffer; 13uniform sampler2D SpecBuffer; 14uniform sampler2DArray shadow_map; 15 16layout (std140) uniform globalDeferredData { 17 mat4 shadow_mv_matrix; 18 mat4 shadow_proj_matrix[4]; 19 20 mat4 inv_view_matrix; 21 22 float veryneardist; 23 float neardist; 24 float middist; 25 float fardist; 26 27 float invScreenWidth; 28 float invScreenHeight; 29}; 30 31layout (std140) uniform lightData { 32 vec3 diffuseLightColor; 33 float coneAngle; 34 35 vec3 specLightColor; 36 float coneInnerAngle; 37 38 vec3 coneDir; 39 bool dualCone; 40 41 vec3 scale; 42 float lightRadius; 43 44 vec3 lightDir; 45 int lightType; 46 47 bool enable_shadows; 48}; 49 50void GetLightInfo(vec3 position, out vec3 lightDir, out float attenuation) 51{ 52 if (lightType == LT_DIRECTIONAL) { 53 lightDir = normalize(lightPosition); 54 attenuation = 1.0; 55 } else { 56 // Positional light source 57 lightDir = lightPosition - position.xyz; 58 float dist = length(lightDir); 59 attenuation = 1.0 - clamp(dist / lightRadius, 0.0, 1.0); 60 61 if(dist > lightRadius && lightType != LT_TUBE) { 62 discard; 63 } 64 65 if (lightType == LT_TUBE) { // Tube light 66 float beamLength = length(beamVec); 67 vec3 beamDir = beamVec / beamLength; 68 //The actual 'lighting element' is shorter than the light volume cylinder 69 //To compensate the light is moved forward along the beam one radius and the length shortened 70 //this allows room for clean falloff of the light past the ends of beams. 71 vec3 adjustedLightPos = lightPosition - (beamDir * lightRadius); 72 beamLength = beamLength - (lightRadius * 2.0); 73 //adjustments having been made, lightdir needs recalculating 74 lightDir = adjustedLightPos - position.xyz; 75 // Get nearest point on line 76 float neardist = clamp(dot(lightDir, beamDir), 0.0, beamLength); 77 // Move back from the endpoint of the beam along the beam by the distance we calculated 78 vec3 nearest = adjustedLightPos - beamDir * neardist; 79 lightDir = nearest - position.xyz; 80 dist = length(lightDir); 81 if(dist > lightRadius) { 82 discard; 83 } 84 attenuation = 1.0 - clamp(dist / lightRadius, 0.0, 1.0); 85 } else if (lightType == LT_CONE) { 86 float coneDot = dot(normalize(-lightDir), coneDir); 87 if(dualCone) { 88 if(abs(coneDot) < coneAngle) { 89 discard; 90 } else { 91 attenuation *= smoothstep(coneAngle, coneInnerAngle, abs(coneDot)); 92 } 93 } else { 94 if (coneDot < coneAngle) { 95 discard; 96 } else { 97 attenuation *= smoothstep(coneAngle, coneInnerAngle, coneDot); 98 } 99 } 100 } 101 102 lightDir = normalize(lightDir); 103 } 104} 105 106void main() 107{ 108 vec2 screenPos = gl_FragCoord.xy * vec2(invScreenWidth, invScreenHeight); 109 vec3 position = texture(PositionBuffer, screenPos).xyz; 110 111 if(abs(dot(position, position)) < 0.1) 112 discard; 113 114 vec3 color = texture(ColorBuffer, screenPos).rgb; 115 vec4 normalData = texture(NormalBuffer, screenPos); 116 vec4 specColor = texture(SpecBuffer, screenPos); 117 // The vector in the normal buffer could be longer than the unit vector since decal rendering only adds to the normal buffer 118 vec3 normal = normalize(normalData.xyz); 119 float gloss = normalData.a; 120 float fresnel = specColor.a; 121 vec3 eyeDir = normalize(-position); 122 123 vec3 lightDir; 124 float attenuation; 125 126 GetLightInfo(position, lightDir, attenuation); 127 128 if (enable_shadows) { 129 vec4 fragShadowPos = shadow_mv_matrix * inv_view_matrix * vec4(position, 1.0); 130 vec4 fragShadowUV[4]; 131 fragShadowUV[0] = transformToShadowMap(shadow_proj_matrix[0], 0, fragShadowPos); 132 fragShadowUV[1] = transformToShadowMap(shadow_proj_matrix[1], 1, fragShadowPos); 133 fragShadowUV[2] = transformToShadowMap(shadow_proj_matrix[2], 2, fragShadowPos); 134 fragShadowUV[3] = transformToShadowMap(shadow_proj_matrix[3], 3, fragShadowPos); 135 136 attenuation *= getShadowValue(shadow_map, -position.z, fragShadowPos.z, fragShadowUV, fardist, middist, 137 neardist, veryneardist); 138 } 139 140 vec3 halfVec = normalize(lightDir + eyeDir); 141 float NdotL = clamp(dot(normal, lightDir), 0.0, 1.0); 142 vec4 fragmentColor = vec4(color * (diffuseLightColor * NdotL * attenuation), 1.0); 143 fragmentColor.rgb += computeLighting(specColor.rgb, lightDir, normal.xyz, halfVec, eyeDir, gloss, fresnel, NdotL).rgb * specLightColor * attenuation; 144 fragOut0 = max(fragmentColor, vec4(0.0)); 145} 146