Sky from atmosphere! Fix normalization

This commit is contained in:
Evert Prants 2020-03-31 15:07:23 +03:00
parent ba2bc1a43c
commit 46026ab9b9
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
3 changed files with 38 additions and 21 deletions

View File

@ -30,35 +30,50 @@ uniform mat4 uModelMatrix;
uniform mat4 uViewMatrix; uniform mat4 uViewMatrix;
uniform mat4 uProjectionMatrix; uniform mat4 uProjectionMatrix;
float scale(float fCos) float scale(float fCos) {
{
float x = 1.0 - fCos; float x = 1.0 - fCos;
return fScaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25)))); return fScaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25))));
} }
void main(void)
{ void main(void) {
// Get the ray from the camera to the vertex and its length (which is the far point of the ray passing through the atmosphere) // Get the ray from the camera to the vertex and its length (which is the far point of the ray passing through the atmosphere)
vec3 v3Ray = aVertexPosition - v3CameraPosition; vec3 v3Ray = aVertexPosition - v3CameraPosition;
float fFar = length(v3Ray); float fFar = length(v3Ray);
v3Ray /= fFar; v3Ray /= fFar;
// Calculate the closest intersection of the ray with the outer atmosphere (which is the near point of the ray passing through the atmosphere)
float B = 2.0 * dot(v3CameraPosition, v3Ray); vec3 v3Start;
float C = fCameraHeight2 - fOuterRadius2; float fStartAngle;
float fDet = max(0.0, B*B - 4.0 * C); float fStartDepth;
float fNear = 0.5 * (-B - sqrt(fDet)); float fStartOffset;
// Calculate the ray's starting position, then calculate its scattering offset
vec3 v3Start = v3CameraPosition + v3Ray * fNear; if (fCameraHeight > fOuterRadius) {
fFar -= fNear; // Sky from space
float fStartAngle = dot(v3Ray, v3Start) / fOuterRadius; // Calculate the closest intersection of the ray with the outer atmosphere (which is the near point of the ray passing through the atmosphere)
float fStartDepth = exp(-1.0 / fScaleDepth); float B = 2.0 * dot(v3CameraPosition, v3Ray);
float fStartOffset = fStartDepth * scale(fStartAngle); float C = fCameraHeight2 - fOuterRadius2;
//c0 = vec3(1.0, 0, 0) * fStartAngle; float fDet = max(0.0, B*B - 4.0 * C);
float fNear = 0.5 * (-B - sqrt(fDet));
// Calculate the ray's starting position, then calculate its scattering offset
v3Start = v3CameraPosition + v3Ray * fNear;
fFar -= fNear;
fStartAngle = dot(v3Ray, v3Start) / fOuterRadius;
fStartDepth = exp(-1.0 / fScaleDepth);
fStartOffset = fStartDepth * scale(fStartAngle);
} else {
// Sky from within the atmosphere
v3Start = v3CameraPosition;
fStartDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fCameraHeight));
fStartAngle = dot(v3Ray, v3Start) / length(v3Start);
fStartOffset = fStartDepth*scale(fStartAngle);
}
// Initialize the scattering loop variables // Initialize the scattering loop variables
float fSampleLength = fFar / fSamples; float fSampleLength = fFar / fSamples;
float fScaledLength = fSampleLength * fScale; float fScaledLength = fSampleLength * fScale;
vec3 v3SampleRay = v3Ray * fSampleLength; vec3 v3SampleRay = v3Ray * fSampleLength;
vec3 v3SamplePoint = v3Start + v3SampleRay * 0.5; vec3 v3SamplePoint = v3Start + v3SampleRay * 0.5;
//gl_FrontColor = vec4(0.0, 0.0, 0.0, 0.0);
// Now loop through the sample rays // Now loop through the sample rays
vec3 v3FrontColor = vec3(0.0, 0.0, 0.0); vec3 v3FrontColor = vec3(0.0, 0.0, 0.0);
for(int i=0; i<nSamples; i++) for(int i=0; i<nSamples; i++)
@ -72,6 +87,7 @@ void main(void)
v3FrontColor += v3Attenuate * (fDepth * fScaledLength); v3FrontColor += v3Attenuate * (fDepth * fScaledLength);
v3SamplePoint += v3SampleRay; v3SamplePoint += v3SampleRay;
} }
// Finally, scale the Mie and Rayleigh colors and set up the varying variables for the pixel shader // Finally, scale the Mie and Rayleigh colors and set up the varying variables for the pixel shader
gl_Position = uProjectionMatrix * uViewMatrix * uModelMatrix * vec4(aVertexPosition,1); gl_Position = uProjectionMatrix * uViewMatrix * uModelMatrix * vec4(aVertexPosition,1);
c0 = v3FrontColor * (v3InvWavelength * fKrESun); c0 = v3FrontColor * (v3InvWavelength * fKrESun);

View File

@ -11,7 +11,7 @@ class Atmosphere extends MeshInstance {
this.wavelength = wavelength this.wavelength = wavelength
this.Kr = 0.0025 this.Kr = 0.0025
this.Km = 0.0010 this.Km = 0.0020
this.ESun = 20.0 this.ESun = 20.0
this.g = -0.950 this.g = -0.950
this.scaleDepth = 0.25 this.scaleDepth = 0.25
@ -23,9 +23,10 @@ class Atmosphere extends MeshInstance {
gl.uniformMatrix4fv(shader.getUniformLocation(gl, 'uModelMatrix'), false, this.transform) gl.uniformMatrix4fv(shader.getUniformLocation(gl, 'uModelMatrix'), false, this.transform)
const camHeight = vec3.length(subv3(camera.pos, this.pos)) const camHeight = vec3.length(subv3(camera.pos, this.pos))
const invWavelength = [1 / Math.pow(this.wavelength[0], 4), 1 / Math.pow(this.wavelength[1], 4), 1 / Math.pow(this.wavelength[2], 4)]
gl.uniform3fv(shader.getUniformLocation(gl, 'v3CameraPosition'), camera.pos) gl.uniform3fv(shader.getUniformLocation(gl, 'v3CameraPosition'), camera.pos)
gl.uniform3fv(shader.getUniformLocation(gl, 'v3LightPosition'), normalv3(sun.pos.slice())) gl.uniform3fv(shader.getUniformLocation(gl, 'v3LightPosition'), normalv3(sun.pos))
gl.uniform3f(shader.getUniformLocation(gl, 'v3InvWavelength'), 1 / Math.pow(this.wavelength[0], 4), 1 / Math.pow(this.wavelength[1], 4), 1 / Math.pow(this.wavelength[2], 4)) gl.uniform3fv(shader.getUniformLocation(gl, 'v3InvWavelength'), invWavelength)
gl.uniform1f(shader.getUniformLocation(gl, 'fCameraHeight'), camHeight) gl.uniform1f(shader.getUniformLocation(gl, 'fCameraHeight'), camHeight)
gl.uniform1f(shader.getUniformLocation(gl, 'fCameraHeight2'), camHeight * camHeight) gl.uniform1f(shader.getUniformLocation(gl, 'fCameraHeight2'), camHeight * camHeight)
gl.uniform1f(shader.getUniformLocation(gl, 'fInnerRadius'), this.innerRadius) gl.uniform1f(shader.getUniformLocation(gl, 'fInnerRadius'), this.innerRadius)

View File

@ -57,7 +57,7 @@ export function divv3 (one, two) {
} }
export function normalv3 (vec) { export function normalv3 (vec) {
const res = vec const res = []
vec3.normalize(res, vec) vec3.normalize(res, vec)
return res return res
} }