Skip to content

Commit 0c74a4c

Browse files
committed
Render full sky atmosphere when globe is hidden
1 parent 908615a commit 0c74a4c

File tree

5 files changed

+84
-69
lines changed

5 files changed

+84
-69
lines changed

Source/Scene/Scene.js

+8-8
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,6 @@ function Scene(options) {
633633

634634
isSunVisible: false,
635635
isMoonVisible: false,
636-
isReadyForAtmosphere: false,
637636
isSkyAtmosphereVisible: false,
638637

639638
clearGlobeDepth: false,
@@ -3311,11 +3310,11 @@ Scene.prototype.updateEnvironment = function () {
33113310
globe.enableLighting && globe.dynamicAtmosphereLighting,
33123311
globe.dynamicAtmosphereLightingFromSun
33133312
);
3314-
environmentState.isReadyForAtmosphere =
3315-
environmentState.isReadyForAtmosphere ||
3316-
globe._surface._tilesToRender.length > 0;
33173313
}
3318-
environmentState.skyAtmosphereCommand = skyAtmosphere.update(frameState);
3314+
environmentState.skyAtmosphereCommand = skyAtmosphere.update(
3315+
frameState,
3316+
this._globe
3317+
);
33193318
if (defined(environmentState.skyAtmosphereCommand)) {
33203319
this.updateDerivedCommands(environmentState.skyAtmosphereCommand);
33213320
}
@@ -3342,6 +3341,7 @@ Scene.prototype.updateEnvironment = function () {
33423341

33433342
var clearGlobeDepth = (environmentState.clearGlobeDepth =
33443343
defined(globe) &&
3344+
globe.show &&
33453345
(!globe.depthTestAgainstTerrain || this.mode === SceneMode.SCENE2D));
33463346
var useDepthPlane = (environmentState.useDepthPlane =
33473347
clearGlobeDepth &&
@@ -3373,9 +3373,9 @@ Scene.prototype.updateEnvironment = function () {
33733373
cullingVolume = scratchCullingVolume;
33743374

33753375
// Determine visibility of celestial and terrestrial environment effects.
3376-
environmentState.isSkyAtmosphereVisible =
3377-
defined(environmentState.skyAtmosphereCommand) &&
3378-
environmentState.isReadyForAtmosphere;
3376+
environmentState.isSkyAtmosphereVisible = defined(
3377+
environmentState.skyAtmosphereCommand
3378+
);
33793379
environmentState.isSunVisible = this.isVisible(
33803380
environmentState.sunDrawCommand,
33813381
cullingVolume,

Source/Scene/SkyAtmosphere.js

+19-5
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,15 @@ function SkyAtmosphere(ellipsoid) {
5151
*/
5252
this.show = true;
5353

54+
/**
55+
* Compute atmosphere per-fragment instead of per-vertex.
56+
* This produces better looking atmosphere with a slight performance penalty.
57+
*
58+
* @type {Boolean}
59+
* @default true
60+
*/
61+
this.perFragmentAtmosphere = true;
62+
5463
this._ellipsoid = ellipsoid;
5564
this._command = new DrawCommand({
5665
owner: this,
@@ -142,7 +151,7 @@ SkyAtmosphere.prototype.setDynamicAtmosphereColor = function (
142151
/**
143152
* @private
144153
*/
145-
SkyAtmosphere.prototype.update = function (frameState) {
154+
SkyAtmosphere.prototype.update = function (frameState, globe) {
146155
if (!this.show) {
147156
return undefined;
148157
}
@@ -160,7 +169,12 @@ SkyAtmosphere.prototype.update = function (frameState) {
160169
var context = frameState.context;
161170

162171
var colorCorrect = hasColorCorrection(this);
163-
var globeTranslucent = frameState.globeTranslucencyState.translucent;
172+
var translucent = frameState.globeTranslucencyState.translucent;
173+
var perFragmentAtmosphere =
174+
this.perFragmentAtmosphere ||
175+
translucent ||
176+
(defined(globe) &&
177+
(!globe.show || globe._surface._tilesToRender.length === 0));
164178

165179
var command = this._command;
166180

@@ -193,7 +207,7 @@ SkyAtmosphere.prototype.update = function (frameState) {
193207
});
194208
}
195209

196-
var flags = colorCorrect | (globeTranslucent << 2);
210+
var flags = colorCorrect | (perFragmentAtmosphere << 2);
197211

198212
if (flags !== this._flags) {
199213
this._flags = flags;
@@ -204,8 +218,8 @@ SkyAtmosphere.prototype.update = function (frameState) {
204218
defines.push("COLOR_CORRECT");
205219
}
206220

207-
if (globeTranslucent) {
208-
defines.push("GLOBE_TRANSLUCENT");
221+
if (perFragmentAtmosphere) {
222+
defines.push("PER_FRAGMENT_ATMOSPHERE");
209223
}
210224

211225
var vs = new ShaderSource({

Source/Shaders/SkyAtmosphereCommon.glsl

+48-12
Original file line numberDiff line numberDiff line change
@@ -102,16 +102,58 @@ void calculateRayScatteringFromGround(in vec3 positionWC, in vec3 ray, in float
102102
startOffset = depth*scale(startAngle);
103103
}
104104

105-
void calculateMieColorAndRayleighColor(vec3 positionWC, vec3 outerPosition, vec3 lightDirection, bool intersectsEllipsoid, out vec3 mieColor, out vec3 rayleighColor)
105+
czm_raySegment rayEllipsoidIntersection(czm_ray ray, vec3 ellipsoid_center, vec3 ellipsoid_inverseRadii)
106106
{
107-
float cameraHeight = length(positionWC);
107+
vec3 o = ellipsoid_inverseRadii * (czm_inverseModelView * vec4(ray.origin, 1.0)).xyz;
108+
vec3 d = ellipsoid_inverseRadii * (czm_inverseModelView * vec4(ray.direction, 0.0)).xyz;
109+
110+
float a = dot(d, d);
111+
float b = dot(d, o);
112+
float c = dot(o, o) - 1.0;
113+
float discriminant = b * b - a * c;
114+
if (discriminant < 0.0)
115+
{
116+
return czm_emptyRaySegment;
117+
}
118+
discriminant = sqrt(discriminant);
119+
float t1 = (-b + (-discriminant)) / a;
120+
float t2 = (-b + (discriminant)) / a;
121+
122+
if (t1 < 0.0 && t2 < 0.0)
123+
{
124+
return czm_emptyRaySegment;
125+
}
126+
127+
if (t1 < 0.0 && t2 >= 0.0)
128+
{
129+
t1 = 0.0;
130+
}
131+
132+
return czm_raySegment(t1, t2);
133+
}
134+
135+
void calculateMieColorAndRayleighColor(vec3 outerPositionWC, float ellipsoidScaleFactor, out vec3 mieColor, out vec3 rayleighColor)
136+
{
137+
vec3 directionWC = normalize(outerPositionWC - czm_viewerPositionWC);
138+
vec3 directionEC = czm_viewRotation * directionWC;
139+
czm_ray viewRay = czm_ray(vec3(0.0), directionEC);
140+
czm_raySegment raySegment = rayEllipsoidIntersection(viewRay, vec3(czm_view[3]), czm_ellipsoidInverseRadii * ellipsoidScaleFactor);
141+
bool intersectsEllipsoid = raySegment.start >= 0.0;
142+
143+
vec3 startPositionWC = czm_viewerPositionWC;
144+
if (intersectsEllipsoid)
145+
{
146+
startPositionWC = czm_viewerPositionWC + raySegment.stop * directionWC;
147+
}
148+
149+
vec3 lightDirection = getLightDirection(startPositionWC);
108150

109151
// Unpack attributes
110152
float outerRadius = u_radiiAndDynamicAtmosphereColor.x;
111153
float innerRadius = u_radiiAndDynamicAtmosphereColor.y;
112154

113155
// 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)
114-
vec3 ray = outerPosition - positionWC;
156+
vec3 ray = outerPositionWC - startPositionWC;
115157
float far = length(ray);
116158
ray /= far;
117159
float atmosphereScale = 1.0 / (outerRadius - innerRadius);
@@ -122,14 +164,14 @@ void calculateMieColorAndRayleighColor(vec3 positionWC, vec3 outerPosition, vec3
122164
#ifdef SKY_FROM_SPACE
123165
if (intersectsEllipsoid)
124166
{
125-
calculateRayScatteringFromGround(positionWC, ray, atmosphereScale, innerRadius, start, startOffset);
167+
calculateRayScatteringFromGround(startPositionWC, ray, atmosphereScale, innerRadius, start, startOffset);
126168
}
127169
else
128170
{
129-
calculateRayScatteringFromSpace(positionWC, ray, outerRadius, far, start, startOffset);
171+
calculateRayScatteringFromSpace(startPositionWC, ray, outerRadius, far, start, startOffset);
130172
}
131173
#else
132-
calculateRayScatteringFromGround(positionWC, ray, atmosphereScale, innerRadius, start, startOffset);
174+
calculateRayScatteringFromGround(startPositionWC, ray, atmosphereScale, innerRadius, start, startOffset);
133175
#endif
134176

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

168210
vec3 rgb = rayleighPhase * rayleighColor + miePhase * mieColor;
169211

170-
if (rgb.b > 1000000.0)
171-
{
172-
// Discard colors that exceed some large number value to prevent against NaN's from the exponent calculation below
173-
return vec4(0.0);
174-
}
175-
176212
const float exposure = 2.0;
177213
vec3 rgbExposure = vec3(1.0) - exp(-exposure * rgb);
178214

Source/Shaders/SkyAtmosphereFS.glsl

+6-34
Original file line numberDiff line numberDiff line change
@@ -35,49 +35,21 @@
3535

3636
varying vec3 v_outerPositionWC;
3737

38-
#ifndef GLOBE_TRANSLUCENT
38+
#ifndef PER_FRAGMENT_ATMOSPHERE
3939
varying vec3 v_rayleighColor;
4040
varying vec3 v_mieColor;
4141
#endif
4242

43-
// Enlarge the ellipsoid slightly to avoid atmosphere artifacts when the camera is slightly below the ellipsoid
44-
const float epsilon = 1.000001;
45-
4643
void main (void)
4744
{
48-
#ifdef GLOBE_TRANSLUCENT
49-
vec3 outerPositionWC = v_outerPositionWC;
50-
vec3 directionWC = normalize(outerPositionWC - czm_viewerPositionWC);
51-
vec3 directionEC = czm_viewRotation * directionWC;
52-
czm_ray viewRay = czm_ray(vec3(0.0), directionEC);
53-
czm_raySegment raySegment = czm_rayEllipsoidIntersectionInterval(viewRay, vec3(czm_view[3]), czm_ellipsoidInverseRadii * epsilon);
54-
bool intersectsEllipsoid = raySegment.start >= 0.0;
55-
56-
vec3 startPositionWC = czm_viewerPositionWC;
57-
if (intersectsEllipsoid)
58-
{
59-
startPositionWC = czm_viewerPositionWC + raySegment.stop * directionWC;
60-
}
61-
62-
vec3 toCamera = startPositionWC - outerPositionWC;
63-
vec3 lightDirection = getLightDirection(startPositionWC);
64-
45+
vec3 toCamera = czm_viewerPositionWC - v_outerPositionWC;
46+
vec3 lightDirection = getLightDirection(czm_viewerPositionWC);
47+
#ifdef PER_FRAGMENT_ATMOSPHERE
6548
vec3 mieColor;
6649
vec3 rayleighColor;
67-
68-
calculateMieColorAndRayleighColor(
69-
startPositionWC,
70-
outerPositionWC,
71-
lightDirection,
72-
intersectsEllipsoid,
73-
mieColor,
74-
rayleighColor
75-
);
76-
77-
gl_FragColor = calculateFinalColor(startPositionWC, toCamera, lightDirection, rayleighColor, mieColor);
50+
calculateMieColorAndRayleighColor(v_outerPositionWC, 1.0, mieColor, rayleighColor);
51+
gl_FragColor = calculateFinalColor(czm_viewerPositionWC, toCamera, lightDirection, rayleighColor, mieColor);
7852
#else
79-
vec3 toCamera = czm_viewerPositionWC - v_outerPositionWC;
80-
vec3 lightDirection = getLightDirection(czm_viewerPositionWC);
8153
gl_FragColor = calculateFinalColor(czm_viewerPositionWC, toCamera, lightDirection, v_rayleighColor, v_mieColor);
8254
#endif
8355
}

Source/Shaders/SkyAtmosphereVS.glsl

+3-10
Original file line numberDiff line numberDiff line change
@@ -37,22 +37,15 @@ attribute vec4 position;
3737

3838
varying vec3 v_outerPositionWC;
3939

40-
#ifndef GLOBE_TRANSLUCENT
40+
#ifndef PER_FRAGMENT_ATMOSPHERE
4141
varying vec3 v_rayleighColor;
4242
varying vec3 v_mieColor;
4343
#endif
4444

4545
void main(void)
4646
{
47-
#ifndef GLOBE_TRANSLUCENT
48-
calculateMieColorAndRayleighColor(
49-
czm_viewerPositionWC,
50-
position.xyz,
51-
getLightDirection(czm_viewerPositionWC),
52-
false,
53-
v_mieColor,
54-
v_rayleighColor
55-
);
47+
#ifndef PER_FRAGMENT_ATMOSPHERE
48+
calculateMieColorAndRayleighColor(position.xyz, 1.002, v_mieColor, v_rayleighColor);
5649
#endif
5750
v_outerPositionWC = position.xyz;
5851
gl_Position = czm_modelViewProjection * position;

0 commit comments

Comments
 (0)