forked from Sibras/OpenGL4-Tutorials
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDeferred1stFrag.glsl
More file actions
286 lines (226 loc) · 10.6 KB
/
Deferred1stFrag.glsl
File metadata and controls
286 lines (226 loc) · 10.6 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
279
280
281
282
283
284
285
286
#version 430 core
layout(binding = 1) uniform CameraData {
mat4 m4ViewProjection;
vec3 v3CameraPosition;
};
layout(binding = 3) uniform ReflectPlaneData {
mat4 m4ReflectVP;
};
layout(location = 1) uniform float fEmissivePower;
layout(location = 3) uniform float fBumpScale;
layout(binding = 0) uniform sampler2D s2DiffuseTexture;
layout(binding = 1) uniform sampler2D s2SpecularTexture;
layout(binding = 2) uniform sampler2D s2RoughnessTexture;
layout(binding = 3) uniform samplerCube scRefractMapTexture;
layout(binding = 4) uniform sampler2D s2ReflectTexture;
layout(binding = 5) uniform samplerCube scReflectMapTexture;
layout(binding = 9) uniform sampler2D s2NormalTexture;
layout(binding = 10) uniform sampler2D s2BumpTexture;
#define M_RCPPI 0.31830988618379067153776752674503f
#define M_PI 3.1415926535897932384626433832795f
layout(location = 0) in vec3 v3PositionIn;
layout(location = 1) in vec3 v3NormalIn;
layout(location = 2) in vec2 v2UVIn;
layout(location = 3) in vec3 v3TangentIn;
layout(location = 0) out vec3 v3AccumulationOut;
layout(location = 1) out vec2 v2NormalOut;
layout(location = 2) out vec3 v3DiffuseOut;
layout(location = 3) out vec4 v4SpecularRoughOut;
subroutine vec3 Emissive(vec3, vec3);
subroutine vec3 RefractMap(vec3, vec3, vec3, vec4, vec3);
subroutine vec3 ReflectMap(vec3, vec3, vec3, vec3, float);
layout(location = 0) subroutine uniform Emissive EmissiveUniform;
layout(location = 1) subroutine uniform RefractMap RefractMapUniform;
layout(location = 2) subroutine uniform ReflectMap ReflectMapUniform;
vec3 normalMap(in vec3 v3Normal, in vec3 v3Tangent, in vec3 v3BiTangent, in vec2 v2LocalUV)
{
// Get normal map value
vec2 v2NormalMap = (texture(s2NormalTexture, v2LocalUV).rg - 0.5f) * 2.0f;
vec3 v3NormalMap = vec3(v2NormalMap, sqrt(1.0f - dot(v2NormalMap, v2NormalMap)));
// Convert from tangent space
vec3 v3RetNormal = mat3(v3Tangent,
v3BiTangent,
v3Normal) * v3NormalMap;
return normalize(v3RetNormal);
}
vec2 parallaxMap(in vec3 v3Normal, in vec3 v3Tangent, in vec3 v3BiTangent, in vec3 v3ViewDirection)
{
// Get tangent space view direction
vec3 v3TangentView = vec3(dot(v3ViewDirection, v3Tangent),
dot(v3ViewDirection, v3BiTangent),
dot(v3ViewDirection, v3Normal));
v3TangentView = normalize(v3TangentView);
// Get number of layers based on view direction
const float fMinLayers = 5.0f;
const float fMaxLayers = 15.0f;
float fNumLayers = round(mix(fMaxLayers, fMinLayers, abs(v3TangentView.z)));
// Determine layer height
float fLayerHeight = 1.0f / fNumLayers;
// Determine texture offset per layer
vec2 v2DTex = fBumpScale * v3TangentView.xy / (v3TangentView.z * fNumLayers);
// Get texture gradients to allow for dynamic branching
vec2 v2Dx = dFdx(v2UVIn);
vec2 v2Dy = dFdy(v2UVIn);
// Initialise height from texture
vec2 v2CurrUV = v2UVIn;
float fCurrHeight = textureGrad(s2BumpTexture, v2CurrUV, v2Dx, v2Dy).r;
// Loop over each step until lower height is found
float fViewHeight = 1.0f;
float fLastHeight = 1.0f;
vec2 v2LastUV;
for (int i = 0; i < int(fNumLayers); i++) {
if (fCurrHeight >= fViewHeight)
break;
// Set current values as previous
fLastHeight = fCurrHeight;
v2LastUV = v2CurrUV;
// Go to next layer
fViewHeight -= fLayerHeight;
// Shift UV coordinates
v2CurrUV -= v2DTex;
// Get new texture height
fCurrHeight = textureGrad(s2BumpTexture, v2CurrUV, v2Dx, v2Dy).r;
}
// Get heights for linear interpolation
float fNextHeight = fCurrHeight - fViewHeight;
float fPrevHeight = fLastHeight - (fViewHeight + fLayerHeight);
// Interpolate based on height difference
float fWeight = fNextHeight / (fNextHeight - fPrevHeight);
return mix(v2CurrUV, v2LastUV, fWeight);
}
vec3 schlickFresnel(in vec3 v3LightDirection, in vec3 v3Normal, in vec3 v3SpecularColour)
{
// Schlick Fresnel approximation
float fLH = dot(v3LightDirection, v3Normal);
return v3SpecularColour + (1.0f - v3SpecularColour) * pow(1.0f - fLH, 5);
}
float GGXVisibility(in vec3 v3Normal, in vec3 v3LightDirection, in vec3 v3ViewDirection, in float fRoughness)
{
// GGX Visibility function
float fNL = max(dot(v3Normal, v3LightDirection), 0.0f);
float fNV = max(dot(v3Normal, v3ViewDirection), 0.0f);
float fRSq = fRoughness * fRoughness;
float fRMod = 1.0f - fRSq;
float fRecipG1 = fNL + sqrt(fRSq + (fRMod * fNL * fNL));
float fRecipG2 = fNV + sqrt(fRSq + (fRMod * fNV * fNV));
return 1.0f / (fRecipG1 * fRecipG2);
}
vec3 SpecularTransmit(in vec3 v3Normal, in vec3 v3ViewDirection, in vec3 v3DiffuseColour, in vec3 v3SpecularColour)
{
// Calculate index of refraction from Fresnel term
float fRootF0 = sqrt(v3SpecularColour.x);
float fIOR = (1.0f - fRootF0) / (1.0f + fRootF0);
// Get refraction direction
vec3 v3Refract = refract(-v3ViewDirection, v3Normal, fIOR);
// Get refraction map data
vec3 v3RefractColour = texture(scRefractMapTexture, v3Refract).rgb;
// Evaluate specular transmittance
vec3 v3RetColour = fIOR * (1.0f - schlickFresnel(v3Refract, -v3Normal, v3SpecularColour));
v3RetColour *= v3DiffuseColour;
// Combine with incoming light value
v3RetColour *= v3RefractColour;
return v3RetColour;
}
vec3 GGXReflect(in vec3 v3Normal, in vec3 v3ReflectDirection, in vec3 v3ViewDirection, in vec3 v3ReflectRadiance, in vec3 v3SpecularColour, in float fRoughness)
{
// Calculate Toorance-Sparrow components
vec3 v3F = schlickFresnel(v3ReflectDirection, v3Normal, v3SpecularColour);
float fV = GGXVisibility(v3Normal, v3ReflectDirection, v3ViewDirection, fRoughness);
// Combine specular
vec3 v3RetColour = v3F * fV;
// Modify by pdf
v3RetColour *= (4.0f * dot(v3ViewDirection, v3Normal));
// Multiply by view angle
v3RetColour *= max(dot(v3Normal, v3ReflectDirection), 0.0f);
// Combine with incoming light value
v3RetColour *= v3ReflectRadiance;
return v3RetColour;
}
layout(index = 0) subroutine(Emissive) vec3 noEmissive(vec3 v3ColourOut, vec3 v3DiffuseColour)
{
// Return colour unmodified
return v3ColourOut;
}
layout(index = 1) subroutine(Emissive) vec3 textureEmissive(vec3 v3ColourOut, vec3 v3DiffuseColour)
{
// Add in emissive contribution
return v3ColourOut + (fEmissivePower * v3DiffuseColour);
}
layout(index = 2) subroutine(RefractMap) vec3 noRefractMap(vec3 v3ColourOut, vec3 v3Normal, vec3 v3ViewDirection, vec4 v4DiffuseColour, vec3 v3SpecularColour)
{
// Return colour unmodified
return v3ColourOut;
}
layout(index = 3) subroutine(RefractMap) vec3 textureRefractMap(vec3 v3ColourOut, vec3 v3Normal, vec3 v3ViewDirection, vec4 v4DiffuseColour, vec3 v3SpecularColour)
{
// Get specular transmittance term
vec3 v3Transmit = SpecularTransmit(v3Normal, v3ViewDirection, v4DiffuseColour.rgb, v3SpecularColour);
// Add in transparent contribution and blend with existing
return mix(v3Transmit, v3ColourOut, v4DiffuseColour.w);
}
layout(index = 4) subroutine(ReflectMap) vec3 noReflectMap(vec3 v3ColourOut, vec3 v3Normal, vec3 v3ViewDirection, vec3 v3SpecularColour, float fRoughness)
{
return v3ColourOut;
}
layout(index = 5) subroutine(ReflectMap) vec3 textureReflectPlane(vec3 v3ColourOut, vec3 v3Normal, vec3 v3ViewDirection, vec3 v3SpecularColour, float fRoughness)
{
// Get position in reflection texture
vec4 v4RVPPosition = m4ReflectVP * vec4(v3PositionIn, 1.0f);
vec2 v2ReflectUV = v4RVPPosition.xy / v4RVPPosition.w;
v2ReflectUV = (v2ReflectUV + 1.0f) * 0.5f;
// Calculate LOD offset
float fLOD = textureQueryLod(s2ReflectTexture, v2ReflectUV).y;
float fGloss = 1.0f - fRoughness;
fLOD += ((2.0f / (fGloss * fGloss)) - 1.0f);
// Get reflect texture data
vec3 v3ReflectRadiance = textureLod(s2ReflectTexture, v2ReflectUV, fLOD).rgb;
// Get reflect direction
vec3 v3ReflectDirection = normalize(reflect(-v3ViewDirection, v3Normal));
// Perform shading
vec3 v3RetColour = GGXReflect(v3Normal, v3ReflectDirection, v3ViewDirection, v3ReflectRadiance, v3SpecularColour, fRoughness);
return v3ColourOut + v3RetColour;
}
layout(index = 6) subroutine(ReflectMap) vec3 textureReflectCube(vec3 v3ColourOut, vec3 v3Normal, vec3 v3ViewDirection, vec3 v3SpecularColour, float fRoughness)
{
// Get reflect direction
vec3 v3ReflectDirection = normalize(reflect(-v3ViewDirection, v3Normal));
// Calculate LOD offset
float fLOD = textureQueryLod(scReflectMapTexture, v3ReflectDirection).y;
float fGloss = 1.0f - fRoughness;
fLOD += ((2.0f / (fGloss * fGloss)) - 1.0f);
// Get reflect texture data
vec3 v3ReflectRadiance = textureLod(scReflectMapTexture, v3ReflectDirection, fLOD).xyz;
// Perform shading
vec3 v3RetColour = GGXReflect(v3Normal, v3ReflectDirection, v3ViewDirection, v3ReflectRadiance, v3SpecularColour, fRoughness);
return v3ColourOut + v3RetColour;
}
void main() {
// Normalise the inputs
vec3 v3Normal = normalize(v3NormalIn);
vec3 v3ViewDirection = normalize(v3CameraPosition - v3PositionIn);
vec3 v3Tangent = normalize(v3TangentIn);
// Generate bitangent
vec3 v3BiTangent = cross(v3Normal, v3Tangent);
// Perform Parallax Occlusion Mapping
vec2 v2UVPO = parallaxMap(v3Normal, v3Tangent, v3BiTangent, v3ViewDirection);
// Perform Bump Mapping
v3Normal = normalMap(v3Normal, v3Tangent, v3BiTangent, v2UVPO);
// Get texture data
vec4 v4DiffuseColour = texture(s2DiffuseTexture, v2UVPO);
vec3 v3DiffuseColour = v4DiffuseColour.rgb;
vec3 v3SpecularColour = texture(s2SpecularTexture, v2UVPO).rgb;
float fRoughness = texture(s2RoughnessTexture, v2UVPO).r;
// Add in ambient contribution
vec3 v3RetColour = v3DiffuseColour * vec3(0.3f);
// Add in any reflection contribution
v3RetColour = ReflectMapUniform(v3RetColour, v3Normal, v3ViewDirection, v3SpecularColour, fRoughness);
// Add in any refraction contribution
v3RetColour = RefractMapUniform(v3RetColour, v3Normal, v3ViewDirection, v4DiffuseColour, v3SpecularColour);
// Add in any emissive contribution
v3RetColour = EmissiveUniform(v3RetColour, v3DiffuseColour);
// Output to deferred G-Buffers
v3AccumulationOut = v3RetColour;
v2NormalOut = v3Normal.xy / (1.0f + v3Normal.z);
v3DiffuseOut = v3DiffuseColour;
v4SpecularRoughOut = vec4(v3SpecularColour, fRoughness);
}