-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Image Light Feature - GSOC 2023 #6255
Changes from 3 commits
50a0c14
dfa600c
0521694
b155bac
34e6438
916f5be
c59ae6c
8b1e19c
5287a4f
b05bca6
f6899a8
8cd5775
3c9bf12
701cbee
4c63de5
b9837dc
5546093
98af50f
8dbbff5
711c5f5
52c4d42
0121439
8e9cd8a
7cf062d
93a2428
d1c19b3
b803601
dc0ef6a
f0f3a19
02d6f00
9a0c3fc
0860bd7
0ade514
07371e8
25a711b
c04d916
9dbe8a0
5cac577
5547d7d
ff3973d
b37afe5
69008c0
d713b35
6656e90
374051b
b964403
0e7c3bc
14aed59
5d99712
4fe2890
6fec78a
94e639b
f2c0f1e
e68f9f0
6df91ec
fe5e0db
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
precision mediump 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.141; | ||
|
||
vec2 normalToEquirectangular( vec3 v){ | ||
vec2 uv; | ||
// taking the arctangent of the v.z and v.x components and dividing it by the circumference of a circle | ||
// Adding 0.5 ensures that the resulting value is in the range [0, 1]. | ||
uv.x = atan(v.z, v.x) / 3.14159 + 0.5; | ||
// taking the arcsine of the v.y component and dividing it by the half circumference of a circle | ||
uv.y = asin(v.y) / 3.14159 + 0.5; | ||
|
||
|
||
return uv; | ||
} | ||
|
||
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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe where we use 3.14159 right now we can use the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure, I'll clean up this file. It has some extra code as well. |
||
phi = phi / 3.14159 ; | ||
|
||
vec2 angles = vec2( phi, theta ); | ||
return angles; | ||
} | ||
|
||
// vec2 func( vec3 localPos ){ | ||
// // x = r sin(phi) cos(theta) | ||
// // y = r cos(phi) | ||
// // z = r sin(phi) sin(theta) | ||
// float phi = acos( localPos.y ); | ||
// // if phi is 0, then there are no x, z components | ||
// float theta = 0.0; | ||
// // else | ||
// theta = acos(normal.x / sin(phi)); | ||
// float sinTheta = normal.z / sin(phi); | ||
// if (sinTheta < 0.0) { | ||
// // Turn it into -theta, but in the 0-2PI range | ||
// theta = 2.0 * PI - theta; | ||
// } | ||
|
||
// vec2 angles = vec2( theta, phi ); | ||
// return angles; | ||
// } | ||
|
||
void main() | ||
{ | ||
// the sample direction equals the hemisphere's orientation | ||
// vec2 angles = func( localPos ); | ||
// float theta = angles.a; | ||
// float phi = angles.b; | ||
// float x = sin(theta) * cos(phi); | ||
// float y = sin(theta) * sin(phi); | ||
// float z = cos(theta); | ||
// vec3 normal = vec3( x, y, z); | ||
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); | ||
// vec3 normal = abs(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.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) // 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); | ||
// gl_FragColor = vec4(normal.x, normal.y, normal.z, 1.0); | ||
// gl_FragColor = vec4(normal.x, 0.0, 0.0, 1.0); | ||
// gl_FragColor = vec4(0.0, normal.y, 0.0, 1.0); | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
attribute vec3 aPosition; | ||
attribute vec3 aNormal; | ||
attribute vec2 aTexCoord; | ||
|
||
varying vec3 localPos; | ||
varying vec3 vWorldNormal; | ||
varying vec3 vWorldPosition; | ||
varying vec2 vTexCoord; | ||
|
||
uniform mat4 uModelViewMatrix; | ||
uniform mat4 uProjectionMatrix; | ||
uniform mat3 uNormalMatrix; | ||
|
||
void main() { | ||
// Multiply the position by the matrix. | ||
vec4 viewModelPosition = uModelViewMatrix * vec4(aPosition, 1.0); | ||
gl_Position = uProjectionMatrix * viewModelPosition; | ||
|
||
// orient the normals and pass to the fragment shader | ||
vWorldNormal = uNormalMatrix * aNormal; | ||
|
||
// send the view position to the fragment shader | ||
vWorldPosition = (uModelViewMatrix * vec4(aPosition, 1.0)).xyz; | ||
|
||
localPos = vWorldPosition; | ||
vTexCoord = aTexCoord; | ||
} | ||
|
||
|
||
/* | ||
in the vertex shader we'll compute the world position and world oriented normal of the vertices and pass those to the fragment shader as varyings. | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we use this function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope, I actually re-wrote the function in line 22. The function N2E is the one being used for now. I think I should remove the function on line 10 and rename the function at line 22.