Skip to content

Commit 65a49de

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

File tree

5 files changed

+72
-60
lines changed

5 files changed

+72
-60
lines changed

Source/Scene/Scene.js

+1
Original file line numberDiff line numberDiff line change
@@ -3342,6 +3342,7 @@ Scene.prototype.updateEnvironment = function () {
33423342

33433343
var clearGlobeDepth = (environmentState.clearGlobeDepth =
33443344
defined(globe) &&
3345+
globe.show &&
33453346
(!globe.depthTestAgainstTerrain || this.mode === SceneMode.SCENE2D));
33463347
var useDepthPlane = (environmentState.useDepthPlane =
33473348
clearGlobeDepth &&

Source/Scene/SkyAtmosphere.js

+14-4
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,
@@ -160,7 +169,8 @@ 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 = this.perFragmentAtmosphere || translucent;
164174

165175
var command = this._command;
166176

@@ -193,7 +203,7 @@ SkyAtmosphere.prototype.update = function (frameState) {
193203
});
194204
}
195205

196-
var flags = colorCorrect | (globeTranslucent << 2);
206+
var flags = colorCorrect | (perFragmentAtmosphere << 2);
197207

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

207-
if (globeTranslucent) {
208-
defines.push("GLOBE_TRANSLUCENT");
217+
if (perFragmentAtmosphere) {
218+
defines.push("PER_FRAGMENT_ATMOSPHERE");
209219
}
210220

211221
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)