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 uProjectionMatrix;
float scale(float fCos)
{
float scale(float fCos) {
float x = 1.0 - fCos;
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)
vec3 v3Ray = aVertexPosition - v3CameraPosition;
float fFar = length(v3Ray);
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);
float C = fCameraHeight2 - fOuterRadius2;
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
vec3 v3Start = v3CameraPosition + v3Ray * fNear;
fFar -= fNear;
float fStartAngle = dot(v3Ray, v3Start) / fOuterRadius;
float fStartDepth = exp(-1.0 / fScaleDepth);
float fStartOffset = fStartDepth * scale(fStartAngle);
//c0 = vec3(1.0, 0, 0) * fStartAngle;
vec3 v3Start;
float fStartAngle;
float fStartDepth;
float fStartOffset;
if (fCameraHeight > fOuterRadius) {
// Sky from space
// 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);
float C = fCameraHeight2 - fOuterRadius2;
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
float fSampleLength = fFar / fSamples;
float fScaledLength = fSampleLength * fScale;
vec3 v3SampleRay = v3Ray * fSampleLength;
vec3 v3SamplePoint = v3Start + v3SampleRay * 0.5;
//gl_FrontColor = vec4(0.0, 0.0, 0.0, 0.0);
// Now loop through the sample rays
vec3 v3FrontColor = vec3(0.0, 0.0, 0.0);
for(int i=0; i<nSamples; i++)
@ -72,6 +87,7 @@ void main(void)
v3FrontColor += v3Attenuate * (fDepth * fScaledLength);
v3SamplePoint += v3SampleRay;
}
// 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);
c0 = v3FrontColor * (v3InvWavelength * fKrESun);

View File

@ -11,7 +11,7 @@ class Atmosphere extends MeshInstance {
this.wavelength = wavelength
this.Kr = 0.0025
this.Km = 0.0010
this.Km = 0.0020
this.ESun = 20.0
this.g = -0.950
this.scaleDepth = 0.25
@ -23,9 +23,10 @@ class Atmosphere extends MeshInstance {
gl.uniformMatrix4fv(shader.getUniformLocation(gl, 'uModelMatrix'), false, this.transform)
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, 'v3LightPosition'), normalv3(sun.pos.slice()))
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, 'v3LightPosition'), normalv3(sun.pos))
gl.uniform3fv(shader.getUniformLocation(gl, 'v3InvWavelength'), invWavelength)
gl.uniform1f(shader.getUniformLocation(gl, 'fCameraHeight'), camHeight)
gl.uniform1f(shader.getUniformLocation(gl, 'fCameraHeight2'), camHeight * camHeight)
gl.uniform1f(shader.getUniformLocation(gl, 'fInnerRadius'), this.innerRadius)

View File

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