-
Notifications
You must be signed in to change notification settings - Fork 72
Expand file tree
/
Copy pathlightMapping_fp.glsl
More file actions
278 lines (226 loc) · 9.94 KB
/
lightMapping_fp.glsl
File metadata and controls
278 lines (226 loc) · 9.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
/*
===========================================================================
Copyright (C) 2006-2011 Robert Beckebans <trebor_7@users.sourceforge.net>
This file is part of XreaL source code.
XreaL source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
XreaL source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with XreaL source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/* lightMapping_fp.glsl */
#insert common
#insert computeLight_fp
#insert reliefMapping_fp
#define LIGHTMAPPING_GLSL
#define LIGHTGRID_GLSL
uniform sampler2D u_DiffuseMap;
uniform sampler2D u_MaterialMap;
uniform sampler2D u_GlowMap;
uniform float u_AlphaThreshold;
uniform vec3 u_ViewOrigin;
uniform colorModulatePack u_ColorModulateColorGen;
IN(smooth) vec3 var_Position;
IN(smooth) vec2 var_TexCoords;
IN(smooth) vec4 var_Color;
IN(smooth) vec3 var_Tangent;
IN(smooth) vec3 var_Binormal;
IN(smooth) vec3 var_Normal;
uniform sampler2D u_LightMap;
uniform sampler3D u_LightGrid1;
uniform sampler2D u_DeluxeMap;
uniform sampler3D u_LightGrid2;
#if defined(USE_LIGHT_MAPPING) || defined(USE_DELUXE_MAPPING)
IN(smooth) vec2 var_TexLight;
#endif
#if defined(USE_GRID_LIGHTING) || defined(USE_GRID_DELUXE_MAPPING)
uniform vec3 u_LightGridOrigin;
uniform vec3 u_LightGridScale;
#endif
#if defined(USE_MATERIAL_SYSTEM)
uniform bool u_ShowTris;
uniform vec3 u_MaterialColour;
#endif
#insert shaderProfiler_fp
DECLARE_OUTPUT(vec4)
void main()
{
#insert material_fp
#if defined(USE_MATERIAL_SYSTEM)
if( u_ShowTris ) {
outputColor = vec4( 0.0, 0.0, 1.0, 1.0 );
return;
}
#endif
// Compute view direction in world space.
vec3 viewDir = normalize(u_ViewOrigin - var_Position);
vec2 texCoords = var_TexCoords;
mat3 tangentToWorldMatrix = mat3(var_Tangent.xyz, var_Binormal.xyz, var_Normal.xyz);
#if defined(USE_RELIEF_MAPPING)
// Compute texcoords offset from heightmap.
#if defined(USE_HEIGHTMAP_IN_NORMALMAP)
vec2 texOffset = ReliefTexOffset(texCoords, viewDir, tangentToWorldMatrix, u_NormalMap);
#else
vec2 texOffset = ReliefTexOffset(texCoords, viewDir, tangentToWorldMatrix, u_HeightMap);
#endif
texCoords += texOffset;
#endif
// Compute the diffuse term.
vec4 diffuse = texture2D(u_DiffuseMap, texCoords);
// Apply vertex blend operation like: alphaGen vertex.
diffuse *= var_Color;
if(abs(diffuse.a + u_AlphaThreshold) <= 1.0)
{
discard;
return;
}
// Compute normal in world space from normalmap.
#if defined(r_normalMapping)
vec3 normal = NormalInWorldSpace(texCoords, tangentToWorldMatrix, u_NormalMap);
#else // !r_normalMapping
vec3 normal = NormalInWorldSpace(texCoords, tangentToWorldMatrix);
#endif // !r_normalMapping
#if defined(r_specularMapping) || defined(r_physicalMapping)
// Compute the material term.
vec4 material = texture2D(u_MaterialMap, texCoords);
#elif defined(r_realtimeLighting) \
|| defined( USE_DELUXE_MAPPING ) || defined(USE_GRID_DELUXE_MAPPING )
// The computeDynamicLights function requires this variable to exist.
vec4 material = vec4( 0.0, 0.0, 0.0, 1.0 );
#endif
// Compute final color.
vec4 color;
color.a = diffuse.a;
#if defined(USE_GRID_LIGHTING) || defined(USE_GRID_DELUXE_MAPPING)
// Compute light grid position.
vec3 lightGridPos = (var_Position - u_LightGridOrigin) * u_LightGridScale;
#endif
#if defined(USE_DELUXE_MAPPING)
// Compute light direction in world space from deluxe map.
vec4 deluxe = texture2D(u_DeluxeMap, var_TexLight);
vec3 lightDir = normalize(2.0 * deluxe.xyz - 1.0);
#elif defined(USE_GRID_DELUXE_MAPPING)
// Compute light direction in world space from light grid.
vec4 texel = texture3D(u_LightGrid2, lightGridPos);
vec3 lightDir = normalize(texel.xyz - (128.0 / 255.0));
#endif
float lightFactor = ColorModulateToLightFactor( u_ColorModulateColorGen );
#if defined(USE_LIGHT_MAPPING)
// Compute light color from world space lightmap.
// When doing vertex lighting with full-range overbright, this reads out
// 1<<overbrightBits and serves for the overbright shift for vertex colors.
vec3 lightColor = texture2D(u_LightMap, var_TexLight).rgb;
lightColor *= lightFactor;
color.rgb = vec3(0.0);
#else
// Compute light color from lightgrid.
vec3 ambientColor, lightColor;
ReadLightGrid(texture3D(u_LightGrid1, lightGridPos), lightFactor, ambientColor, lightColor);
color.rgb = ambientColor * r_AmbientScale * diffuse.rgb;
#endif
#if defined(USE_LIGHT_MAPPING) && defined(USE_DELUXE_MAPPING)
vec3 lightmapValue = lightColor;
/* Lightmaps generated by q3map2 don't store the raw light value, but
they store light premultiplied with the dot product of the light
direction and surface normal. The line is just an attempt to reverse
that and get the original light values.
The lightmap stores the light in this way because for the diffuse
lighting formula the outgoing light is equal to the incoming light
multiplied by the above dot product multiplied by the surface albedo.
So this premultiplication means that the diffuse lighting value can
be calculated with a single multiply operation.
But specular lighting and/or normal mapping formulas are more complex,
and so you need the true light value to get correct lighting.
Obviously the data is not good enough to recover the original color
in all cases. The lower bound was an arbitrary chose factor to
prevent too small divisors resulting in too bright lights.
Increasing the value should reduce these artifacts. -- gimhael
https://github.com/DaemonEngine/Daemon/issues/299#issuecomment-606186347
*/
vec3 flatNormal = normalize(var_Normal);
float flatNdotL = clamp(dot(flatNormal, lightDir), 0.3, 1.0);
lightColor /= flatNdotL;
// The light direction from the deluxe map may be nonsense, be it because q3map2
// goofed, or because the light actually comes from more than one direction(!!!!). The total, summed
// over light sources, of (light color) * dot(flat triangle's normal, light direction), as given by the lightmap, is more
// trustworthy. If the normalmapped normal is almost the same as the the original flat geometry's normal,
// we can bound how much the above sum can change, thus preventing the bogus light direction from
// wrecking the Lambert's law term of our lighting equation.
// So we want to compute the maximum of
// abs(dot(var_Normal, L) - dot(normal, L))
// = abs(dot(normal - var_Normal, L))
// over all possible L. This maximum occurs when L is parallel to normal - var_Normal.
float dotDelta = length(normal - flatNormal);
// So each dot product term can only increase or decrease by dotDelta. But we don't know
// what the original dot products were. We'll have to assume a maximum angle to be able to
// bound the percent change of the total.
float minimumAverageCosine = 0.1; // 84.3 degrees
float cosinesRatio = dot(normal, lightDir) / flatNdotL;
cosinesRatio = clamp( cosinesRatio, 1.0 - dotDelta / minimumAverageCosine, 1.0 + dotDelta / minimumAverageCosine );
vec3 lambertTerm = lightmapValue * cosinesRatio;
#else
vec3 lambertTerm; // not used
#endif
// Blend static light.
#if defined(USE_DELUXE_MAPPING) || defined(USE_GRID_DELUXE_MAPPING)
#if defined(USE_REFLECTIVE_SPECULAR)
vec4 modifiedSpecular = material * EnvironmentalSpecularFactor(viewDir, normal);
computeDeluxeLight(lightDir, normal, viewDir, lightColor, lambertTerm, diffuse, modifiedSpecular, color);
#else // !USE_REFLECTIVE_SPECULAR
computeDeluxeLight(lightDir, normal, viewDir, lightColor, lambertTerm, diffuse, material, color);
#endif // !USE_REFLECTIVE_SPECULAR
#else
computeLight(lightColor, diffuse, color);
#endif
// Blend dynamic lights.
#if defined(r_realtimeLighting)
computeDynamicLights(var_Position, normal, viewDir, diffuse, material, color, u_LightTiles);
#endif
// Add Rim Lighting to highlight the edges on model entities.
#if defined(r_rimLighting) && defined(USE_MODEL_SURFACE) && defined(USE_GRID_LIGHTING)
float rim = pow(1.0 - clamp(dot(normal, viewDir), 0.0, 1.0), r_RimExponent);
vec3 emission = ambientColor * rim * rim * 0.2;
color.rgb += 0.7 * emission;
#endif
#if defined(r_glowMapping)
// Blend glow map.
vec3 glow = texture2D(u_GlowMap, texCoords).rgb;
color.rgb += glow;
#endif
SHADER_PROFILER_SET( color )
outputColor = color;
// Debugging.
#if defined(r_showNormalMaps)
// Convert normal to [0,1] color space.
normal = normal * 0.5 + 0.5;
outputColor = vec4(normal, 1.0);
#elif defined(r_showMaterialMaps)
outputColor = material;
#elif defined(r_showLightMaps) && defined(USE_LIGHT_MAPPING)
outputColor = texture2D(u_LightMap, var_TexLight);
#elif defined(r_showDeluxeMaps) && defined(USE_DELUXE_MAPPING)
outputColor = texture2D(u_DeluxeMap, var_TexLight);
#elif defined(USE_REFLECTIVE_SPECULAR) && defined(r_showReflectionMaps)
vec4 envColor0 = textureCube(u_EnvironmentMap0, reflect(-viewDir, normal));
vec4 envColor1 = textureCube(u_EnvironmentMap1, reflect(-viewDir, normal));
outputColor = vec4( mix(envColor0, envColor1, u_EnvironmentInterpolation).rgb, 1.0 );
#elif defined(r_showVertexColors)
/* We need to keep the texture alpha channel so impact
marks like creep don't fully overwrite the world texture. */
#if defined(USE_BSP_SURFACE)
outputColor.rgb = vec3(1.0, 1.0, 1.0);
outputColor *= var_Color;
#else
outputColor.rgb = vec3(0.0, 0.0, 0.0);
#endif
#elif defined(USE_MATERIAL_SYSTEM) && defined(r_showGlobalMaterials)
outputColor.rgb = u_MaterialColour + lightColor.rgb * u_MaterialColour;
#endif
}