-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
/
Copy pathimageLightSpecular.frag
112 lines (93 loc) · 2.79 KB
/
imageLightSpecular.frag
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
precision highp float;
varying vec3 localPos;
varying vec2 vTexCoord;
// our texture
uniform sampler2D environmentMap;
uniform float roughness;
const float PI = 3.14159265359;
float VanDerCorput(int bits);
vec2 HammersleyNoBitOps(int i, int N);
vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness);
vec2 nTOE( vec3 v ){
// x = r sin(phi) cos(theta)
// y = r cos(phi)
// z = r sin(phi) sin(theta)
float phi = acos( v.y );
// if phi is 0, then there are no x, z components
float theta = 0.0;
// else
theta = acos(v.x / sin(phi));
float sinTheta = v.z / sin(phi);
if (sinTheta < 0.0) {
// Turn it into -theta, but in the 0-2PI range
theta = 2.0 * PI - theta;
}
theta = theta / (2.0 * 3.14159);
phi = phi / 3.14159 ;
vec2 angles = vec2( phi, theta );
return angles;
}
void main(){
const int SAMPLE_COUNT = 1024; // 4096
float totalWeight = 0.0;
vec3 prefilteredColor = vec3(0.0);
float phi = vTexCoord.x * 2.0 * PI;
float theta = vTexCoord.y * PI;
float x = sin(theta) * cos(phi);
float y = sin(theta) * sin(phi);
float z = cos(theta);
vec3 N = vec3(x,y,z);
vec3 V = N;
for (int i = 0; i < SAMPLE_COUNT; ++i)
{
vec2 Xi = HammersleyNoBitOps(i, SAMPLE_COUNT);
vec3 H = ImportanceSampleGGX(Xi, N, roughness);
vec3 L = normalize(2.0 * dot(V, H) * H - V);
float NdotL = max(dot(N, L), 0.0);
if (NdotL > 0.0)
{
prefilteredColor += texture2D(environmentMap, nTOE(L)).xyz * NdotL;
totalWeight += NdotL;
}
}
prefilteredColor = prefilteredColor / totalWeight;
gl_FragColor = vec4(prefilteredColor, 1.0);
}
vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness){
float a = roughness * roughness;
float phi = 2.0 * PI * Xi.x;
float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a * a - 1.0) * Xi.y));
float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
// from spherical coordinates to cartesian coordinates
vec3 H;
H.x = cos(phi) * sinTheta;
H.y = sin(phi) * sinTheta;
H.z = cosTheta;
// from tangent-space vector to world-space sample vector
vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
vec3 tangent = normalize(cross(up, N));
vec3 bitangent = cross(N, tangent);
vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;
return normalize(sampleVec);
}
float VanDerCorput(int n, int base)
{
float invBase = 1.0 / float(base);
float denom = 1.0;
float result = 0.0;
for (int i = 0; i < 32; ++i)
{
if (n > 0)
{
denom = mod(float(n), 2.0);
result += denom * invBase;
invBase = invBase / 2.0;
n = int(float(n) / 2.0);
}
}
return result;
}
vec2 HammersleyNoBitOps(int i, int N)
{
return vec2(float(i) / float(N), VanDerCorput(i, 2));
}