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 0c74a4c
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 69 deletions.
16 changes: 8 additions & 8 deletions Source/Scene/Scene.js
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,6 @@ function Scene(options) {

isSunVisible: false,
isMoonVisible: false,
isReadyForAtmosphere: false,
isSkyAtmosphereVisible: false,

clearGlobeDepth: false,
Expand Down Expand Up @@ -3311,11 +3310,11 @@ Scene.prototype.updateEnvironment = function () {
globe.enableLighting && globe.dynamicAtmosphereLighting,
globe.dynamicAtmosphereLightingFromSun
);
environmentState.isReadyForAtmosphere =
environmentState.isReadyForAtmosphere ||
globe._surface._tilesToRender.length > 0;
}
environmentState.skyAtmosphereCommand = skyAtmosphere.update(frameState);
environmentState.skyAtmosphereCommand = skyAtmosphere.update(
frameState,
this._globe
);
if (defined(environmentState.skyAtmosphereCommand)) {
this.updateDerivedCommands(environmentState.skyAtmosphereCommand);
}
Expand All @@ -3342,6 +3341,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 Expand Up @@ -3373,9 +3373,9 @@ Scene.prototype.updateEnvironment = function () {
cullingVolume = scratchCullingVolume;

// Determine visibility of celestial and terrestrial environment effects.
environmentState.isSkyAtmosphereVisible =
defined(environmentState.skyAtmosphereCommand) &&
environmentState.isReadyForAtmosphere;
environmentState.isSkyAtmosphereVisible = defined(
environmentState.skyAtmosphereCommand
);
environmentState.isSunVisible = this.isVisible(
environmentState.sunDrawCommand,
cullingVolume,
Expand Down
24 changes: 19 additions & 5 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 @@ -142,7 +151,7 @@ SkyAtmosphere.prototype.setDynamicAtmosphereColor = function (
/**
* @private
*/
SkyAtmosphere.prototype.update = function (frameState) {
SkyAtmosphere.prototype.update = function (frameState, globe) {
if (!this.show) {
return undefined;
}
Expand All @@ -160,7 +169,12 @@ 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 ||
(defined(globe) &&
(!globe.show || globe._surface._tilesToRender.length === 0));

var command = this._command;

Expand Down Expand Up @@ -193,7 +207,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 +218,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 0c74a4c

Please sign in to comment.