-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
/
Copy pathimageLightDiffused.frag
82 lines (71 loc) · 2.6 KB
/
imageLightDiffused.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
precision highp float;
varying vec3 localPos;
// the HDR cubemap converted (can be from an equirectangular environment map.)
uniform sampler2D environmentMap;
varying vec2 vTexCoord;
const float PI = 3.14159265359;
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;
}
float random(vec2 p) {
vec3 p3 = fract(vec3(p.xyx) * .1031);
p3 += dot(p3, p3.yzx + 33.33);
return fract((p3.x + p3.y) * p3.z);
}
void main()
{
// the sample direction equals the hemisphere's orientation
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 normal = vec3( x, y, z);
// Discretely sampling the hemisphere given the integral's
// spherical coordinates translates to the following fragment code:
vec3 irradiance = vec3(0.0);
vec3 up = vec3(0.0, 1.0, 0.0);
vec3 right = normalize(cross(up, normal));
up = normalize(cross(normal, right));
// We specify a fixed sampleDelta delta value to traverse
// the hemisphere; decreasing or increasing the sample delta
// will increase or decrease the accuracy respectively.
const float sampleDelta = 0.100;
float nrSamples = 0.0;
float randomOffset = random(gl_FragCoord.xy) * sampleDelta;
for(float rawPhi = 0.0; rawPhi < 2.0 * PI; rawPhi += sampleDelta)
{
float phi = rawPhi + randomOffset;
for(float rawTheta = 0.0; rawTheta < ( 0.5 ) * PI; rawTheta += sampleDelta)
{
float theta = rawTheta + randomOffset;
// spherical to cartesian (in tangent space) // tangent space to world // add each sample result to irradiance
float x = sin(theta) * cos(phi);
float y = sin(theta) * sin(phi);
float z = cos(theta);
vec3 tangentSample = vec3( x, y, z);
vec3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * normal;
irradiance += (texture2D(environmentMap, nTOE(sampleVec)).xyz) * cos(theta) * sin(theta);
nrSamples++;
}
}
// divide by the total number of samples taken, giving us the average sampled irradiance.
irradiance = PI * irradiance * (1.0 / float(nrSamples )) ;
gl_FragColor = vec4(irradiance, 1.0);
}