Skip to content

Commit

Permalink
Render full sky atmosphere when globe is hidden
Browse files Browse the repository at this point in the history
  • Loading branch information
lilleyse committed May 17, 2020
1 parent 908615a commit 65a49de
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 60 deletions.
1 change: 1 addition & 0 deletions Source/Scene/Scene.js
Original file line number Diff line number Diff line change
Expand Up @@ -3342,6 +3342,7 @@ Scene.prototype.updateEnvironment = function () {

var clearGlobeDepth = (environmentState.clearGlobeDepth =
defined(globe) &&
globe.show &&
(!globe.depthTestAgainstTerrain || this.mode === SceneMode.SCENE2D));
var useDepthPlane = (environmentState.useDepthPlane =
clearGlobeDepth &&
Expand Down
18 changes: 14 additions & 4 deletions Source/Scene/SkyAtmosphere.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ function SkyAtmosphere(ellipsoid) {
*/
this.show = true;

/**
* Compute atmosphere per-fragment instead of per-vertex.
* This produces better looking atmosphere with a slight performance penalty.
*
* @type {Boolean}
* @default true
*/
this.perFragmentAtmosphere = true;

this._ellipsoid = ellipsoid;
this._command = new DrawCommand({
owner: this,
Expand Down Expand Up @@ -160,7 +169,8 @@ SkyAtmosphere.prototype.update = function (frameState) {
var context = frameState.context;

var colorCorrect = hasColorCorrection(this);
var globeTranslucent = frameState.globeTranslucencyState.translucent;
var translucent = frameState.globeTranslucencyState.translucent;
var perFragmentAtmosphere = this.perFragmentAtmosphere || translucent;

var command = this._command;

Expand Down Expand Up @@ -193,7 +203,7 @@ SkyAtmosphere.prototype.update = function (frameState) {
});
}

var flags = colorCorrect | (globeTranslucent << 2);
var flags = colorCorrect | (perFragmentAtmosphere << 2);

if (flags !== this._flags) {
this._flags = flags;
Expand All @@ -204,8 +214,8 @@ SkyAtmosphere.prototype.update = function (frameState) {
defines.push("COLOR_CORRECT");
}

if (globeTranslucent) {
defines.push("GLOBE_TRANSLUCENT");
if (perFragmentAtmosphere) {
defines.push("PER_FRAGMENT_ATMOSPHERE");
}

var vs = new ShaderSource({
Expand Down
60 changes: 48 additions & 12 deletions Source/Shaders/SkyAtmosphereCommon.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -102,16 +102,58 @@ void calculateRayScatteringFromGround(in vec3 positionWC, in vec3 ray, in float
startOffset = depth*scale(startAngle);
}

void calculateMieColorAndRayleighColor(vec3 positionWC, vec3 outerPosition, vec3 lightDirection, bool intersectsEllipsoid, out vec3 mieColor, out vec3 rayleighColor)
czm_raySegment rayEllipsoidIntersection(czm_ray ray, vec3 ellipsoid_center, vec3 ellipsoid_inverseRadii)
{
float cameraHeight = length(positionWC);
vec3 o = ellipsoid_inverseRadii * (czm_inverseModelView * vec4(ray.origin, 1.0)).xyz;
vec3 d = ellipsoid_inverseRadii * (czm_inverseModelView * vec4(ray.direction, 0.0)).xyz;

float a = dot(d, d);
float b = dot(d, o);
float c = dot(o, o) - 1.0;
float discriminant = b * b - a * c;
if (discriminant < 0.0)
{
return czm_emptyRaySegment;
}
discriminant = sqrt(discriminant);
float t1 = (-b + (-discriminant)) / a;
float t2 = (-b + (discriminant)) / a;

if (t1 < 0.0 && t2 < 0.0)
{
return czm_emptyRaySegment;
}

if (t1 < 0.0 && t2 >= 0.0)
{
t1 = 0.0;
}

return czm_raySegment(t1, t2);
}

void calculateMieColorAndRayleighColor(vec3 outerPositionWC, float ellipsoidScaleFactor, out vec3 mieColor, out vec3 rayleighColor)
{
vec3 directionWC = normalize(outerPositionWC - czm_viewerPositionWC);
vec3 directionEC = czm_viewRotation * directionWC;
czm_ray viewRay = czm_ray(vec3(0.0), directionEC);
czm_raySegment raySegment = rayEllipsoidIntersection(viewRay, vec3(czm_view[3]), czm_ellipsoidInverseRadii * ellipsoidScaleFactor);
bool intersectsEllipsoid = raySegment.start >= 0.0;

vec3 startPositionWC = czm_viewerPositionWC;
if (intersectsEllipsoid)
{
startPositionWC = czm_viewerPositionWC + raySegment.stop * directionWC;
}

vec3 lightDirection = getLightDirection(startPositionWC);

// Unpack attributes
float outerRadius = u_radiiAndDynamicAtmosphereColor.x;
float innerRadius = u_radiiAndDynamicAtmosphereColor.y;

// Get the ray from the start position to the outer position and its length (which is the far point of the ray passing through the atmosphere)
vec3 ray = outerPosition - positionWC;
vec3 ray = outerPositionWC - startPositionWC;
float far = length(ray);
ray /= far;
float atmosphereScale = 1.0 / (outerRadius - innerRadius);
Expand All @@ -122,14 +164,14 @@ void calculateMieColorAndRayleighColor(vec3 positionWC, vec3 outerPosition, vec3
#ifdef SKY_FROM_SPACE
if (intersectsEllipsoid)
{
calculateRayScatteringFromGround(positionWC, ray, atmosphereScale, innerRadius, start, startOffset);
calculateRayScatteringFromGround(startPositionWC, ray, atmosphereScale, innerRadius, start, startOffset);
}
else
{
calculateRayScatteringFromSpace(positionWC, ray, outerRadius, far, start, startOffset);
calculateRayScatteringFromSpace(startPositionWC, ray, outerRadius, far, start, startOffset);
}
#else
calculateRayScatteringFromGround(positionWC, ray, atmosphereScale, innerRadius, start, startOffset);
calculateRayScatteringFromGround(startPositionWC, ray, atmosphereScale, innerRadius, start, startOffset);
#endif

// Initialize the scattering loop variables
Expand Down Expand Up @@ -167,12 +209,6 @@ vec4 calculateFinalColor(vec3 positionWC, vec3 toCamera, vec3 lightDirection, ve

vec3 rgb = rayleighPhase * rayleighColor + miePhase * mieColor;

if (rgb.b > 1000000.0)
{
// Discard colors that exceed some large number value to prevent against NaN's from the exponent calculation below
return vec4(0.0);
}

const float exposure = 2.0;
vec3 rgbExposure = vec3(1.0) - exp(-exposure * rgb);

Expand Down
40 changes: 6 additions & 34 deletions Source/Shaders/SkyAtmosphereFS.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -35,49 +35,21 @@

varying vec3 v_outerPositionWC;

#ifndef GLOBE_TRANSLUCENT
#ifndef PER_FRAGMENT_ATMOSPHERE
varying vec3 v_rayleighColor;
varying vec3 v_mieColor;
#endif

// Enlarge the ellipsoid slightly to avoid atmosphere artifacts when the camera is slightly below the ellipsoid
const float epsilon = 1.000001;

void main (void)
{
#ifdef GLOBE_TRANSLUCENT
vec3 outerPositionWC = v_outerPositionWC;
vec3 directionWC = normalize(outerPositionWC - czm_viewerPositionWC);
vec3 directionEC = czm_viewRotation * directionWC;
czm_ray viewRay = czm_ray(vec3(0.0), directionEC);
czm_raySegment raySegment = czm_rayEllipsoidIntersectionInterval(viewRay, vec3(czm_view[3]), czm_ellipsoidInverseRadii * epsilon);
bool intersectsEllipsoid = raySegment.start >= 0.0;

vec3 startPositionWC = czm_viewerPositionWC;
if (intersectsEllipsoid)
{
startPositionWC = czm_viewerPositionWC + raySegment.stop * directionWC;
}

vec3 toCamera = startPositionWC - outerPositionWC;
vec3 lightDirection = getLightDirection(startPositionWC);

vec3 toCamera = czm_viewerPositionWC - v_outerPositionWC;
vec3 lightDirection = getLightDirection(czm_viewerPositionWC);
#ifdef PER_FRAGMENT_ATMOSPHERE
vec3 mieColor;
vec3 rayleighColor;

calculateMieColorAndRayleighColor(
startPositionWC,
outerPositionWC,
lightDirection,
intersectsEllipsoid,
mieColor,
rayleighColor
);

gl_FragColor = calculateFinalColor(startPositionWC, toCamera, lightDirection, rayleighColor, mieColor);
calculateMieColorAndRayleighColor(v_outerPositionWC, 1.0, mieColor, rayleighColor);
gl_FragColor = calculateFinalColor(czm_viewerPositionWC, toCamera, lightDirection, rayleighColor, mieColor);
#else
vec3 toCamera = czm_viewerPositionWC - v_outerPositionWC;
vec3 lightDirection = getLightDirection(czm_viewerPositionWC);
gl_FragColor = calculateFinalColor(czm_viewerPositionWC, toCamera, lightDirection, v_rayleighColor, v_mieColor);
#endif
}
13 changes: 3 additions & 10 deletions Source/Shaders/SkyAtmosphereVS.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -37,22 +37,15 @@ attribute vec4 position;

varying vec3 v_outerPositionWC;

#ifndef GLOBE_TRANSLUCENT
#ifndef PER_FRAGMENT_ATMOSPHERE
varying vec3 v_rayleighColor;
varying vec3 v_mieColor;
#endif

void main(void)
{
#ifndef GLOBE_TRANSLUCENT
calculateMieColorAndRayleighColor(
czm_viewerPositionWC,
position.xyz,
getLightDirection(czm_viewerPositionWC),
false,
v_mieColor,
v_rayleighColor
);
#ifndef PER_FRAGMENT_ATMOSPHERE
calculateMieColorAndRayleighColor(position.xyz, 1.002, v_mieColor, v_rayleighColor);
#endif
v_outerPositionWC = position.xyz;
gl_Position = czm_modelViewProjection * position;
Expand Down

0 comments on commit 65a49de

Please sign in to comment.