Skip to content

Commit 8f5f77f

Browse files
authored
Merge pull request scp-fs2open#1622 from asarium/opengl/directionalDeferredLights
Use deferred shader for applying directional lights
2 parents 9953c6a + 0d188fe commit 8f5f77f

20 files changed

Lines changed: 366 additions & 160 deletions

code/def_files/data/effects/deferred-clear-f.sdr

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ out vec4 fragOut0;
22
out vec4 fragOut1;
33
out vec4 fragOut2;
44
out vec4 fragOut3;
5+
out vec4 fragOut4;
56
void main()
67
{
78
fragOut0 = vec4(0.0, 0.0, 0.0, 1.0); // color
89
fragOut1 = vec4(0.0, 0.0, -1000000.0, 1.0); // position
910
fragOut2 = vec4(0.0, 0.0, 0.0, 1.0); // normal
1011
fragOut3 = vec4(0.0, 0.0, 0.0, 0.0); // specular
11-
}
12+
fragOut4 = vec4(0.0, 0.0, 0.0, 1.0); // emissive
13+
}

code/def_files/data/effects/deferred-f.sdr

Lines changed: 83 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11

22
#include "lighting.sdr"
33

4+
#include "shadows.sdr"
5+
46
in vec3 beamVec;
57
in vec3 lightPosition;
68
out vec4 fragOut0;
@@ -9,10 +11,23 @@ uniform sampler2D ColorBuffer;
911
uniform sampler2D NormalBuffer;
1012
uniform sampler2D PositionBuffer;
1113
uniform sampler2D SpecBuffer;
14+
uniform sampler2DArray shadow_map;
15+
16+
layout (std140) uniform globalDeferredData {
17+
mat4 shadow_mv_matrix;
18+
mat4 shadow_proj_matrix[4];
1219

13-
uniform float specFactor;
14-
uniform float invScreenWidth;
15-
uniform float invScreenHeight;
20+
mat4 inv_view_matrix;
21+
22+
float veryneardist;
23+
float neardist;
24+
float middist;
25+
float fardist;
26+
27+
float specFactor;
28+
float invScreenWidth;
29+
float invScreenHeight;
30+
};
1631

1732
layout (std140) uniform lightData {
1833
vec3 diffuseLightColor;
@@ -27,60 +42,92 @@ layout (std140) uniform lightData {
2742
vec3 scale;
2843
float lightRadius;
2944

45+
vec3 lightDir;
3046
int lightType;
47+
48+
bool enable_shadows;
3149
};
3250

51+
void GetLightInfo(vec3 position, out vec3 lightDir, out float attenuation)
52+
{
53+
if (lightType == LT_DIRECTIONAL) {
54+
lightDir = normalize(lightPosition);
55+
attenuation = 1.0;
56+
} else {
57+
// Positional light source
58+
lightDir = lightPosition - position.xyz;
59+
float dist = length(lightDir);
60+
attenuation = 1.0 - clamp(dist / lightRadius, 0.0, 1.0);
61+
62+
if(dist > lightRadius && lightType != LT_TUBE) {
63+
discard;
64+
}
65+
66+
if (lightType == LT_TUBE) { // Tube light
67+
float beamLength = length(beamVec);
68+
vec3 beamDir = beamVec / beamLength;
69+
// Get nearest point on line
70+
float neardist = clamp(dot(lightDir, beamDir), 0.0, beamLength);
71+
// Move back from the endpoint of the beam along the beam by the distance we calculated
72+
vec3 nearest = lightPosition - beamDir * neardist;
73+
lightDir = nearest - position.xyz;
74+
dist = length(lightDir);
75+
if(dist > lightRadius) {
76+
discard;
77+
}
78+
} else if (lightType == LT_CONE) {
79+
float coneDot = dot(normalize(-lightDir), coneDir);
80+
if(dualCone) {
81+
if(abs(coneDot) < coneAngle) {
82+
discard;
83+
} else {
84+
attenuation *= smoothstep(coneAngle, coneInnerAngle, abs(coneDot));
85+
}
86+
} else {
87+
if (coneDot < coneAngle) {
88+
discard;
89+
} else {
90+
attenuation *= smoothstep(coneAngle, coneInnerAngle, coneDot);
91+
}
92+
}
93+
}
94+
95+
lightDir = normalize(lightDir);
96+
}
97+
}
98+
3399
void main()
34100
{
35101
vec2 screenPos = gl_FragCoord.xy * vec2(invScreenWidth, invScreenHeight);
36102
vec3 position = texture(PositionBuffer, screenPos).xyz;
37103

38104
if(abs(dot(position, position)) < 0.1)
39105
discard;
40-
vec3 lightDir = lightPosition - position.xyz;
41-
float dist = length(lightDir);
42-
if(dist > lightRadius && lightType != 1)
43-
discard;
106+
44107
vec3 color = texture(ColorBuffer, screenPos).rgb;
45108
vec4 normal = texture(NormalBuffer, screenPos);
46109
vec4 specColor = texture(SpecBuffer, screenPos);
47110
float gloss = normal.a;
48111
float fresnel = specColor.a;
49112
vec3 eyeDir = normalize(-position);
50113

51-
if(lightType == 1)
52-
{
53-
float beamLength = length(beamVec);
54-
vec3 beamDir = beamVec / beamLength;
55-
// Get nearest point on line
56-
float neardist = clamp(dot(lightDir, beamDir), 0.0, beamLength);
57-
// Move back from the endpoint of the beam along the beam by the distance we calculated
58-
vec3 nearest = lightPosition - beamDir * neardist;
59-
lightDir = nearest - position.xyz;
60-
dist = length(lightDir);
61-
if(dist > lightRadius)
62-
discard;
63-
}
114+
vec3 lightDir;
115+
float attenuation;
64116

65-
float attenuation = 1.0 - clamp(dist / lightRadius, 0.0, 1.0);
117+
GetLightInfo(position, lightDir, attenuation);
66118

67-
if(lightType == 2)
68-
{
69-
float coneDot = dot(normalize(-lightDir), coneDir);
70-
if(dualCone) {
71-
if(abs(coneDot) < coneAngle)
72-
discard;
73-
else
74-
attenuation *= smoothstep(coneAngle, coneInnerAngle, abs(coneDot));
75-
} else {
76-
if(coneDot < coneAngle)
77-
discard;
78-
else
79-
attenuation *= smoothstep(coneAngle, coneInnerAngle, coneDot);
80-
}
119+
if (enable_shadows) {
120+
vec4 fragShadowPos = shadow_mv_matrix * inv_view_matrix * vec4(position, 1.0);
121+
vec4 fragShadowUV[4];
122+
fragShadowUV[0] = transformToShadowMap(shadow_proj_matrix[0], 0, fragShadowPos);
123+
fragShadowUV[1] = transformToShadowMap(shadow_proj_matrix[1], 1, fragShadowPos);
124+
fragShadowUV[2] = transformToShadowMap(shadow_proj_matrix[2], 2, fragShadowPos);
125+
fragShadowUV[3] = transformToShadowMap(shadow_proj_matrix[3], 3, fragShadowPos);
126+
127+
attenuation *= getShadowValue(shadow_map, -position.z, fragShadowPos.z, fragShadowUV, fardist, middist,
128+
neardist, veryneardist);
81129
}
82130

83-
lightDir /= dist;
84131
vec3 halfVec = normalize(lightDir + eyeDir);
85132
float NdotL = clamp(dot(normal.xyz, lightDir), 0.0, 1.0);
86133
vec4 fragmentColor = vec4(color * (diffuseLightColor * NdotL * attenuation), 1.0);

code/def_files/data/effects/deferred-v.sdr

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
2+
#include "lighting.sdr"
3+
14
in vec4 vertPosition;
25
uniform mat4 modelViewMatrix;
36
uniform mat4 projMatrix;
@@ -15,15 +18,23 @@ layout (std140) uniform lightData {
1518
vec3 scale;
1619
float lightRadius;
1720

21+
vec3 lightDir;
1822
int lightType;
23+
24+
bool enable_shadows;
1925
};
2026

2127
out vec3 lightPosition;
2228
out vec3 beamVec;
2329
void main()
2430
{
25-
gl_Position = projMatrix * modelViewMatrix * vec4(vertPosition.xyz * scale, 1.0);
26-
lightPosition = modelViewMatrix[3].xyz;
27-
if(lightType == 1)
28-
beamVec = vec3(modelViewMatrix * vec4(0.0, 0.0, -scale.z, 0.0));
31+
if (lightType == LT_DIRECTIONAL) {
32+
gl_Position = vec4(vertPosition.xyz, 1.0);
33+
lightPosition = lightDir;
34+
} else {
35+
gl_Position = projMatrix * modelViewMatrix * vec4(vertPosition.xyz * scale, 1.0);
36+
lightPosition = modelViewMatrix[3].xyz;
37+
if(lightType == LT_TUBE)
38+
beamVec = vec3(modelViewMatrix * vec4(0.0, 0.0, -scale.z, 0.0));
39+
}
2940
}

code/def_files/data/effects/lighting.sdr

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11

2+
const int LT_DIRECTIONAL = 0; // A light like a sun
3+
const int LT_POINT = 1; // A point light, like an explosion
4+
const int LT_TUBE = 2; // A tube light, like a fluorescent light
5+
const int LT_CONE = 3; // A cone light, like a flood light
6+
27
const float SPEC_INTENSITY_POINT = 5.3 ;// Point light
38
const float SPEC_INTENSITY_DIRECTIONAL = 3.0 ;// Directional light
49
const float SPECULAR_FACTOR = 1.75;

code/def_files/data/effects/main-f.sdr

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ out vec4 fragOut0;
146146
out vec4 fragOut1;
147147
out vec4 fragOut2;
148148
out vec4 fragOut3;
149+
out vec4 fragOut4;
149150

150151
vec3 FresnelLazarovEnv(vec3 specColor, vec3 view, vec3 normal, float gloss)
151152
{
@@ -213,12 +214,15 @@ void main()
213214
#ifdef FLAG_SHADOW_MAP
214215
// need depth and depth squared for variance shadow maps
215216
fragOut0 = vec4(fragPosition.z, fragPosition.z * fragPosition.z * VARIANCE_SHADOW_SCALE_INV, 0.0, 1.0);
216-
return;
217+
if (true) {
218+
return;
219+
}
217220
#endif
218221
vec3 eyeDir = vec3(normalize(-fragPosition).xyz);
219222
vec2 texCoord = fragTexCoord.xy;
220223
vec4 baseColor = color;
221224
vec4 specColor = vec4(0.0, 0.0, 0.0, 1.0);
225+
vec4 emissiveColor = vec4(0.0, 0.0, 0.0, 1.0);
222226
float fresnelFactor = 0.0;
223227
float glossData = 0.6;
224228
#ifdef FLAG_LIGHT
@@ -295,30 +299,45 @@ void main()
295299
baseColor.rgb = max(baseColor.rgb, vec3(0.0));
296300
#endif
297301
#endif
302+
// Lights aren't applied when we are rendering to the G-buffers since that gets handled later
303+
#ifdef FLAG_DEFERRED
304+
#ifdef FLAG_LIGHT
305+
// Ambient lighting still needs to be done since that counts as an "emissive" color
306+
vec3 lightAmbient = (emissionFactor + ambientFactor * ambientFactor) * aoFactors.x; // ambientFactor^2 due to legacy OpenGL compatibility behavior
307+
emissiveColor.rgb += baseColor.rgb * lightAmbient;
308+
#else
309+
#ifdef FLAG_SPEC_MAP
310+
baseColor.rgb += pow(1.0 - clamp(dot(eyeDir, normal), 0.0, 1.0), 5.0 * clamp(glossData, 0.01, 1.0)) * specColor.rgb;
311+
#endif
312+
// If there is no lighting then we copy the color data so far into the
313+
emissiveColor.rgb += baseColor.rgb;
314+
#endif
315+
#else
316+
#ifdef FLAG_LIGHT
298317
float shadow = 1.0;
299-
#ifdef FLAG_SHADOWS
318+
#ifdef FLAG_SHADOWS
300319
shadow = getShadowValue(shadow_map, -fragPosition.z, fragShadowPos.z, fragShadowUV, fardist, middist, neardist, veryneardist);
301-
#endif
302-
#ifdef FLAG_LIGHT
320+
#endif
303321
baseColor.rgb = CalculateLighting(normal, baseColor.rgb, specColor.rgb, glossData, fresnelFactor, shadow, aoFactors.x);
304-
#else
305-
#ifdef FLAG_SPEC_MAP
322+
#else
323+
#ifdef FLAG_SPEC_MAP
306324
baseColor.rgb += pow(1.0 - clamp(dot(eyeDir, normal), 0.0, 1.0), 5.0 * clamp(glossData, 0.01, 1.0)) * specColor.rgb;
325+
#endif
307326
#endif
308327
#endif
309328
#ifdef FLAG_ENV_MAP
310-
vec3 envReflectNM = fragEnvReflect;
329+
vec3 envReflectNM = fragEnvReflect;
311330
#ifdef FLAG_NORMAL_MAP
312-
envReflectNM += vec3(normalSample, 0.0);
331+
envReflectNM += vec3(normalSample, 0.0);
313332
envReflectNM = normalize(envReflectNM);
314333
#endif
315334
float mip = (envGloss) ? (1.0 - glossData) * 7.0 : 0.0;
316-
vec4 envColour = textureLod(sEnvmap, envReflectNM, mip);
335+
vec4 envColour = textureLod(sEnvmap, envReflectNM, mip);
317336
#ifdef FLAG_HDR
318337
envColour.rgb = pow(envColour.rgb, vec3(SRGB_GAMMA));
319338
#endif
320339
envColour.rgb *= (envGloss) ? 1.0 : specColor.a;
321-
baseColor.rgb += envColour.rgb * FresnelLazarovEnv(specColor.rgb, eyeDir, normal, glossData);
340+
emissiveColor.rgb += envColour.rgb * FresnelLazarovEnv(specColor.rgb, eyeDir, normal, glossData);
322341
#endif
323342
#ifdef FLAG_GLOW_MAP
324343
vec3 glowColor = texture(sGlowmap, vec3(texCoord, float(sGlowmapIndex))).rgb;
@@ -332,7 +351,7 @@ void main()
332351
glowColor = team_glow_enabled ? mix((base * teamMask.b) + (stripe * teamMask.a), glowColor, clamp(glowColorLuminance - teamMask.b - teamMask.a, 0.0, 1.0)) : glowColor;
333352
#endif
334353
#endif
335-
baseColor.rgb += glowColor * GLOW_MAP_INTENSITY;
354+
emissiveColor.rgb += glowColor * GLOW_MAP_INTENSITY;
336355
#endif
337356

338357
#ifdef FLAG_FOG
@@ -355,15 +374,13 @@ void main()
355374
#ifdef FLAG_ANIMATED
356375
if (effect_num == 0) {
357376
float shinefactor = 1.0/(1.0 + pow(abs((fract(abs(texCoord.x))-anim_timer) * 1000.0), 2.0)) * 1000.0;
358-
baseColor.rgb = baseColor.rgb + vec3(shinefactor);
377+
emissiveColor.rgb += vec3(shinefactor);
359378
baseColor.a = baseColor.a * clamp(shinefactor * (fract(abs(texCoord.x))-anim_timer) * -10000.0,0.0,1.0);
360379
}
361380
if (effect_num == 1) {
362381
float shinefactor = 1.0/(1.0 + pow(abs(fragPosition.y-anim_timer), 2.0));
363-
baseColor.rgb = baseColor.rgb + vec3(shinefactor);
364-
#ifdef FLAG_LIGHT
365-
baseColor.a = baseColor.a;
366-
#else
382+
emissiveColor.rgb += vec3(shinefactor);
383+
#ifndef FLAG_LIGHT
367384
// ATI Wireframe fix *grumble*
368385
baseColor.a = clamp((fragPosition.y-anim_timer) * 10000.0,0.0,1.0);
369386
#endif
@@ -382,11 +399,16 @@ void main()
382399
#ifdef FLAG_NORMAL_ALPHA
383400
float normViewOffset = dot(vec3(0.0, 0.0, 1.0), normal);
384401
baseColor.a = smoothstep(min(normalAlphaMinMax.x, normalAlphaMinMax.y), max(normalAlphaMinMax.x, normalAlphaMinMax.y), clamp(normalAlphaMinMax.x > normalAlphaMinMax.y ? normViewOffset : 1.0 - normViewOffset, 0.0, 1.0));
402+
#endif
403+
#ifndef FLAG_DEFERRED
404+
// emissive colors won't be added later when we are using forward rendering so we need to do that here
405+
baseColor.rgb += emissiveColor.rgb;
385406
#endif
386407
fragOut0 = baseColor;
387408
#ifdef FLAG_DEFERRED
388409
fragOut1 = vec4(fragPosition.xyz, 1.0);
389410
fragOut2 = vec4(normal, glossData);
390411
fragOut3 = vec4(specColor.rgb, fresnelFactor);
412+
fragOut4 = emissiveColor;
391413
#endif
392414
}

code/def_files/data/effects/main-v.sdr

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#extension GL_ARB_gpu_shader5: enable
22

3+
#include "shadows.sdr"
4+
35
#define MAX_LIGHTS 8
46

57
struct model_light {
@@ -144,18 +146,6 @@ void getModelTransform(inout mat4 transform, out bool invisible, int id, int mat
144146
transform[3].w = 1.0;
145147
}
146148
#endif
147-
#ifdef FLAG_SHADOWS
148-
vec4 transformToShadowMap(int i, vec4 pos)
149-
{
150-
vec4 shadow_proj;
151-
shadow_proj = shadow_proj_matrix[i] * pos;
152-
shadow_proj += 1.0;
153-
shadow_proj *= 0.5;
154-
shadow_proj.w = shadow_proj.z;
155-
shadow_proj.z = float(i);
156-
return shadow_proj;
157-
}
158-
#endif
159149
void main()
160150
{
161151
vec4 position;
@@ -210,10 +200,10 @@ void main()
210200
#endif
211201
#ifdef FLAG_SHADOWS
212202
fragShadowPos = shadow_mv_matrix * modelMatrix * orient * vertPosition;
213-
fragShadowUV[0] = transformToShadowMap(0, fragShadowPos);
214-
fragShadowUV[1] = transformToShadowMap(1, fragShadowPos);
215-
fragShadowUV[2] = transformToShadowMap(2, fragShadowPos);
216-
fragShadowUV[3] = transformToShadowMap(3, fragShadowPos);
203+
fragShadowUV[0] = transformToShadowMap(shadow_proj_matrix[0], 0, fragShadowPos);
204+
fragShadowUV[1] = transformToShadowMap(shadow_proj_matrix[1], 1, fragShadowPos);
205+
fragShadowUV[2] = transformToShadowMap(shadow_proj_matrix[2], 2, fragShadowPos);
206+
fragShadowUV[3] = transformToShadowMap(shadow_proj_matrix[3], 3, fragShadowPos);
217207
#endif
218208
#ifdef FLAG_NORMAL_MAP
219209
// Setup stuff for normal maps

0 commit comments

Comments
 (0)