-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Expand file tree
/
Copy pathIBLKernels.frag
More file actions
111 lines (100 loc) · 3.38 KB
/
IBLKernels.frag
File metadata and controls
111 lines (100 loc) · 3.38 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
/**
* This code is based on the following articles:
* https://learnopengl.com/PBR/IBL/Diffuse-irradiance
* https://learnopengl.com/PBR/IBL/Specular-IBL
* - Riccardo Balbo
*/
#import "Common/ShaderLib/GLSLCompat.glsllib"
#import "Common/IBL/Math.glsl"
in vec2 TexCoords;
in vec3 LocalPos;
uniform samplerCube m_EnvMap;
uniform float m_Roughness;
uniform int m_FaceId;
void brdfKernel(){
float NdotV=TexCoords.x;
float roughness=TexCoords.y;
float alpha = roughness * roughness;
vec3 V;
V.x = sqrt(1.0 - NdotV*NdotV);
V.y = 0.0;
V.z = NdotV;
float A = 0.0;
float B = 0.0;
vec3 N = vec3(0.0, 0.0, 1.0);
const uint SAMPLE_COUNT = 1024u;
for(uint i = 0u; i < SAMPLE_COUNT; i++){
vec4 Xi = Hammersley(i, SAMPLE_COUNT);
vec3 H = ImportanceSampleGGX(Xi, alpha, N);
vec3 L = normalize(2.0 * dot(V, H) * H - V);
float NdotL = max(L.z, 0.0);
float NdotH = max(H.z, 0.0);
float VdotH = max(dot(V, H), 0.0);
if(NdotL > 0.0){
float G = GeometrySmith(N, V, L, alpha);
float G_Vis = (G * VdotH) / (NdotH * NdotV);
float Fc = pow(1.0 - VdotH, 5.0);
A += (1.0 - Fc) * G_Vis;
B += Fc * G_Vis;
}
}
A /= float(SAMPLE_COUNT);
B /= float(SAMPLE_COUNT);
outFragColor.rg=vec2(A, B);
outFragColor.ba=vec2(0);
}
void irradianceKernel(){
// the sample direction equals the hemisphere's orientation
vec3 N = normalize(LocalPos);
vec3 irradiance = vec3(0.0);
vec3 up = vec3(0.0, 1.0, 0.0);
vec3 right = cross(up, N);
up = cross(N, right);
float sampleDelta = 0.025;
float nrSamples = 0.0;
for(float phi = 0.0; phi < 2.0 * PI; phi += sampleDelta){
for(float theta = 0.0; theta < 0.5 * PI; theta += sampleDelta){
// spherical to cartesian (in tangent space)
vec3 tangentSample = vec3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta));
// tangent space to world
vec3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * N;
irradiance += texture(m_EnvMap, sampleVec).rgb * cos(theta) * sin(theta);
nrSamples++;
}
}
irradiance = PI * irradiance * (1.0 / float(nrSamples));
outFragColor = vec4(irradiance, 1.0);
}
void prefilteredEnvKernel(){
vec3 N = normalize(LocalPos);
vec3 R = N;
vec3 V = R;
float roughness = clamp(m_Roughness, 0.0, 1.0);
float alpha = roughness * roughness;
const uint SAMPLE_COUNT = 1024u;
float totalWeight = 0.0;
vec3 prefilteredColor = vec3(0.0);
for(uint i = 0u; i < SAMPLE_COUNT; ++i) {
vec4 Xi = Hammersley(i, SAMPLE_COUNT);
vec3 H = ImportanceSampleGGX(Xi, alpha, N);
float VoH = max(dot(V, H), 0.0);
vec3 L = normalize(2.0 * VoH * H - V);
float NdotL = max(dot(N, L), 0.0);
if(NdotL > 0.0) {
vec3 sampleColor = texture(m_EnvMap, L).rgb;
prefilteredColor += sampleColor * NdotL;
totalWeight += NdotL;
}
}
if(totalWeight > 0.001) prefilteredColor /= totalWeight;
outFragColor = vec4(prefilteredColor, 1.0);
}
void main(){
#if defined(SIBL)
prefilteredEnvKernel();
#elif defined(IRRADIANCE)
irradianceKernel();
#else
brdfKernel();
#endif
}