Skip to content

Commit 746f8ac

Browse files
authored
Merge pull request #8868 from epranka/day-night-textures
dayAlpha and nightAlpha in the ImageryLayer
2 parents 38bb637 + e3b0f02 commit 746f8ac

9 files changed

+157
-11
lines changed

Apps/Sandcastle/gallery/Earth at Night.html

+34
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,40 @@
3939
var viewer = new Cesium.Viewer("cesiumContainer", {
4040
imageryProvider: new Cesium.IonImageryProvider({ assetId: 3812 }),
4141
});
42+
43+
// The rest of the code is for dynamic lighting
44+
var dynamicLighting = false;
45+
46+
viewer.clock.multiplier = 4000;
47+
48+
var imageryLayers = viewer.imageryLayers;
49+
var nightLayer = imageryLayers.get(0);
50+
var dayLayer = imageryLayers.addImageryProvider(
51+
new Cesium.IonImageryProvider({
52+
assetId: 3845,
53+
})
54+
);
55+
imageryLayers.lowerToBottom(dayLayer);
56+
57+
function updateLighting(dynamicLighting) {
58+
dayLayer.show = dynamicLighting;
59+
viewer.scene.globe.enableLighting = dynamicLighting;
60+
viewer.clock.shouldAnimate = dynamicLighting;
61+
62+
// If dynamic lighting is enabled, make the night imagery invisible
63+
// on the lit side of the globe.
64+
nightLayer.dayAlpha = dynamicLighting ? 0.0 : 1.0;
65+
}
66+
67+
updateLighting(dynamicLighting);
68+
69+
Sandcastle.addToggleButton(
70+
"Dynamic lighting",
71+
dynamicLighting,
72+
function (checked) {
73+
updateLighting(checked);
74+
}
75+
);
4276
//Sandcastle_End
4377
Sandcastle.finishedLoading();
4478
}

CHANGES.md

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
- Added `Cesium3DTileset.extensions` to get the extensions property from the tileset JSON. [#8829](https://github.com/CesiumGS/cesium/pull/8829)
2222
- Added `frustumSplits` option to `DebugCameraPrimitive`. [8849](https://github.com/CesiumGS/cesium/pull/8849)
2323
- Added `SkyAtmosphere.perFragmentAtmosphere` to switch between per-vertex and per-fragment atmosphere shading. [#8866](https://github.com/CesiumGS/cesium/pull/8866)
24+
- Added `Globe.undergroundColor` and `Globe.undergroundColorAlphaByDistance` for controlling how the back side of the globe is rendered when the camera is underground or the globe is translucent. [#8867](https://github.com/CesiumGS/cesium/pull/8867)
25+
- Added `nightAlpha` and `dayAlpha` properties to `ImageryLayer` to control alpha separately for the night and day sides of the globe. [#8868](https://github.com/CesiumGS/cesium/pull/8868)
2426
- Added a new sandcastle example to show how to add fog using a `PostProcessStage` [#8798](https://github.com/CesiumGS/cesium/pull/8798)
2527
- Supported `#rgba` and `#rrggbbaa` formats in `Color.fromCssColorString`. [8873](https://github.com/CesiumGS/cesium/pull/8873)
2628
- Added `Camera.completeFlight`, which causes the current camera flight to immediately jump to the final destination and call its complete callback. [#8788](https://github.com/CesiumGS/cesium/pull/8788)

CONTRIBUTORS.md

+1
Original file line numberDiff line numberDiff line change
@@ -256,4 +256,5 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute to Cesiu
256256
- [SungHo Lim](https://github.com/SambaLim)
257257
- [Michael Fink](https://github.com/vividos)
258258
- [Jakub Vrana](https://github.com/vrana)
259+
- [Edvinas Pranka](https://github.com/epranka)
259260
- [James Bromwell](https://github.com/thw0rted)

Source/Scene/GlobeSurfaceShaderSet.js

+13-3
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ GlobeSurfaceShaderSet.prototype.getShaderProgram = function (options) {
8080
var applySaturation = options.applySaturation;
8181
var applyGamma = options.applyGamma;
8282
var applyAlpha = options.applyAlpha;
83+
var applyDayNightAlpha = options.applyDayNightAlpha;
8384
var applySplit = options.applySplit;
8485
var showReflectiveOcean = options.showReflectiveOcean;
8586
var showOceanWaves = options.showOceanWaves;
@@ -155,7 +156,8 @@ GlobeSurfaceShaderSet.prototype.getShaderProgram = function (options) {
155156
(highlightFillTile << 24) |
156157
(colorToAlpha << 25) |
157158
(showUndergroundColor << 26) |
158-
(translucent << 27);
159+
(translucent << 27) |
160+
(applyDayNightAlpha << 28);
159161

160162
var currentClippingShaderState = 0;
161163
if (defined(clippingPlanes) && clippingPlanes.length > 0) {
@@ -221,6 +223,9 @@ GlobeSurfaceShaderSet.prototype.getShaderProgram = function (options) {
221223
if (applyAlpha) {
222224
fs.defines.push("APPLY_ALPHA");
223225
}
226+
if (applyDayNightAlpha) {
227+
fs.defines.push("APPLY_DAY_NIGHT_ALPHA");
228+
}
224229
if (showReflectiveOcean) {
225230
fs.defines.push("SHOW_REFLECTIVE_OCEAN");
226231
vs.defines.push("SHOW_REFLECTIVE_OCEAN");
@@ -290,7 +295,7 @@ GlobeSurfaceShaderSet.prototype.getShaderProgram = function (options) {
290295

291296
var computeDayColor =
292297
"\
293-
vec4 computeDayColor(vec4 initialColor, vec3 textureCoordinates)\n\
298+
vec4 computeDayColor(vec4 initialColor, vec3 textureCoordinates, float nightBlend)\n\
294299
{\n\
295300
vec4 color = initialColor;\n";
296301

@@ -333,6 +338,10 @@ GlobeSurfaceShaderSet.prototype.getShaderProgram = function (options) {
333338
(applyAlpha ? "u_dayTextureAlpha[" + i + "]" : "1.0") +
334339
",\n\
335340
" +
341+
(applyDayNightAlpha ? "u_dayTextureNightAlpha[" + i + "]" : "1.0") +
342+
",\n" +
343+
(applyDayNightAlpha ? "u_dayTextureDayAlpha[" + i + "]" : "1.0") +
344+
",\n" +
336345
(applyBrightness ? "u_dayTextureBrightness[" + i + "]" : "0.0") +
337346
",\n\
338347
" +
@@ -352,7 +361,8 @@ GlobeSurfaceShaderSet.prototype.getShaderProgram = function (options) {
352361
",\n\
353362
" +
354363
(colorToAlpha ? "u_colorsToAlpha[" + i + "]" : "vec4(0.0)") +
355-
"\n\
364+
",\n\
365+
nightBlend\
356366
);\n";
357367
if (hasImageryLayerCutout) {
358368
computeDayColor +=

Source/Scene/GlobeSurfaceTileProvider.js

+23
Original file line numberDiff line numberDiff line change
@@ -1560,6 +1560,12 @@ function createTileUniformMap(frameState, globeSurfaceTileProvider) {
15601560
u_dayTextureAlpha: function () {
15611561
return this.properties.dayTextureAlpha;
15621562
},
1563+
u_dayTextureNightAlpha: function () {
1564+
return this.properties.dayTextureNightAlpha;
1565+
},
1566+
u_dayTextureDayAlpha: function () {
1567+
return this.properties.dayTextureDayAlpha;
1568+
},
15631569
u_dayTextureBrightness: function () {
15641570
return this.properties.dayTextureBrightness;
15651571
},
@@ -1674,6 +1680,8 @@ function createTileUniformMap(frameState, globeSurfaceTileProvider) {
16741680
dayTextureTexCoordsRectangle: [],
16751681
dayTextureUseWebMercatorT: [],
16761682
dayTextureAlpha: [],
1683+
dayTextureNightAlpha: [],
1684+
dayTextureDayAlpha: [],
16771685
dayTextureBrightness: [],
16781686
dayTextureContrast: [],
16791687
dayTextureHue: [],
@@ -1880,6 +1888,7 @@ var surfaceShaderSetOptionsScratch = {
18801888
applySaturation: undefined,
18811889
applyGamma: undefined,
18821890
applyAlpha: undefined,
1891+
applyDayNightAlpha: undefined,
18831892
applySplit: undefined,
18841893
showReflectiveOcean: undefined,
18851894
showOceanWaves: undefined,
@@ -2324,6 +2333,7 @@ function addDrawCommandsForTile(tileProvider, tile, frameState) {
23242333
var applySaturation = false;
23252334
var applyGamma = false;
23262335
var applyAlpha = false;
2336+
var applyDayNightAlpha = false;
23272337
var applySplit = false;
23282338
var applyCutout = false;
23292339
var applyColorToAlpha = false;
@@ -2380,6 +2390,18 @@ function addDrawCommandsForTile(tileProvider, tile, frameState) {
23802390
applyAlpha ||
23812391
uniformMapProperties.dayTextureAlpha[numberOfDayTextures] !== 1.0;
23822392

2393+
uniformMapProperties.dayTextureNightAlpha[numberOfDayTextures] =
2394+
imageryLayer.nightAlpha;
2395+
applyDayNightAlpha =
2396+
applyDayNightAlpha ||
2397+
uniformMapProperties.dayTextureNightAlpha[numberOfDayTextures] !== 1.0;
2398+
2399+
uniformMapProperties.dayTextureDayAlpha[numberOfDayTextures] =
2400+
imageryLayer.dayAlpha;
2401+
applyDayNightAlpha =
2402+
applyDayNightAlpha ||
2403+
uniformMapProperties.dayTextureDayAlpha[numberOfDayTextures] !== 1.0;
2404+
23832405
uniformMapProperties.dayTextureBrightness[numberOfDayTextures] =
23842406
imageryLayer.brightness;
23852407
applyBrightness =
@@ -2527,6 +2549,7 @@ function addDrawCommandsForTile(tileProvider, tile, frameState) {
25272549
surfaceShaderSetOptions.applySaturation = applySaturation;
25282550
surfaceShaderSetOptions.applyGamma = applyGamma;
25292551
surfaceShaderSetOptions.applyAlpha = applyAlpha;
2552+
surfaceShaderSetOptions.applyDayNightAlpha = applyDayNightAlpha;
25302553
surfaceShaderSetOptions.applySplit = applySplit;
25312554
surfaceShaderSetOptions.enableFog = applyFog;
25322555
surfaceShaderSetOptions.enableClippingPlanes = clippingPlanesEnabled;

Source/Scene/ImageryLayer.js

+36
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,18 @@ import TileImagery from "./TileImagery.js";
5454
* current frame state, this layer, and the x, y, and level coordinates of the
5555
* imagery tile for which the alpha is required, and it is expected to return
5656
* the alpha value to use for the tile.
57+
* @param {Number|Function} [options.nightAlpha=1.0] The alpha blending value of this layer on the night side of the globe, from 0.0 to 1.0.
58+
* This can either be a simple number or a function with the signature
59+
* <code>function(frameState, layer, x, y, level)</code>. The function is passed the
60+
* current frame state, this layer, and the x, y, and level coordinates of the
61+
* imagery tile for which the alpha is required, and it is expected to return
62+
* the alpha value to use for the tile. This only takes effect when <code>enableLighting</code> is <code>true</code>.
63+
* @param {Number|Function} [options.dayAlpha=1.0] The alpha blending value of this layer on the day side of the globe, from 0.0 to 1.0.
64+
* This can either be a simple number or a function with the signature
65+
* <code>function(frameState, layer, x, y, level)</code>. The function is passed the
66+
* current frame state, this layer, and the x, y, and level coordinates of the
67+
* imagery tile for which the alpha is required, and it is expected to return
68+
* the alpha value to use for the tile. This only takes effect when <code>enableLighting</code> is <code>true</code>.
5769
* @param {Number|Function} [options.brightness=1.0] The brightness of this layer. 1.0 uses the unmodified imagery
5870
* color. Less than 1.0 makes the imagery darker while greater than 1.0 makes it brighter.
5971
* This can either be a simple number or a function with the signature
@@ -131,6 +143,30 @@ function ImageryLayer(imageryProvider, options) {
131143
defaultValue(imageryProvider.defaultAlpha, 1.0)
132144
);
133145

146+
/**
147+
* The alpha blending value of this layer on the night side of the globe, with 0.0 representing fully transparent and
148+
* 1.0 representing fully opaque. This only takes effect when {@link Globe#enableLighting} is <code>true</code>.
149+
*
150+
* @type {Number}
151+
* @default 1.0
152+
*/
153+
this.nightAlpha = defaultValue(
154+
options.nightAlpha,
155+
defaultValue(imageryProvider.defaultNightAlpha, 1.0)
156+
);
157+
158+
/**
159+
* The alpha blending value of this layer on the day side of the globe, with 0.0 representing fully transparent and
160+
* 1.0 representing fully opaque. This only takes effect when {@link Globe#enableLighting} is <code>true</code>.
161+
*
162+
* @type {Number}
163+
* @default 1.0
164+
*/
165+
this.dayAlpha = defaultValue(
166+
options.dayAlpha,
167+
defaultValue(imageryProvider.defaultDayAlpha, 1.0)
168+
);
169+
134170
/**
135171
* The brightness of this layer. 1.0 uses the unmodified imagery color. Less than 1.0
136172
* makes the imagery darker while greater than 1.0 makes it brighter.

Source/Scene/ImageryProvider.js

+18
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,24 @@ function ImageryProvider() {
4141
*/
4242
this.defaultAlpha = undefined;
4343

44+
/**
45+
* The default alpha blending value on the night side of the globe of this provider, with 0.0 representing fully transparent and
46+
* 1.0 representing fully opaque.
47+
*
48+
* @type {Number}
49+
* @default undefined
50+
*/
51+
this.defaultNightAlpha = undefined;
52+
53+
/**
54+
* The default alpha blending value on the day side of the globe of this provider, with 0.0 representing fully transparent and
55+
* 1.0 representing fully opaque.
56+
*
57+
* @type {Number}
58+
* @default undefined
59+
*/
60+
this.defaultDayAlpha = undefined;
61+
4462
/**
4563
* The default brightness of this provider. 1.0 uses the unmodified imagery color. Less than 1.0
4664
* makes the imagery darker while greater than 1.0 makes it brighter.

Source/Shaders/GlobeFS.glsl

+26-8
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ uniform bool u_dayTextureUseWebMercatorT[TEXTURE_UNITS];
99
uniform float u_dayTextureAlpha[TEXTURE_UNITS];
1010
#endif
1111

12+
#ifdef APPLY_DAY_NIGHT_ALPHA
13+
uniform float u_dayTextureNightAlpha[TEXTURE_UNITS];
14+
uniform float u_dayTextureDayAlpha[TEXTURE_UNITS];
15+
#endif
16+
1217
#ifdef APPLY_SPLIT
1318
uniform float u_dayTextureSplit[TEXTURE_UNITS];
1419
#endif
@@ -158,13 +163,16 @@ vec4 sampleAndBlend(
158163
vec4 textureCoordinateRectangle,
159164
vec4 textureCoordinateTranslationAndScale,
160165
float textureAlpha,
166+
float textureNightAlpha,
167+
float textureDayAlpha,
161168
float textureBrightness,
162169
float textureContrast,
163170
float textureHue,
164171
float textureSaturation,
165172
float textureOneOverGamma,
166173
float split,
167-
vec4 colorToAlpha)
174+
vec4 colorToAlpha,
175+
float nightBlend)
168176
{
169177
// This crazy step stuff sets the alpha to 0.0 if this following condition is true:
170178
// tileTextureCoordinates.s < textureCoordinateRectangle.s ||
@@ -179,6 +187,10 @@ vec4 sampleAndBlend(
179187
alphaMultiplier = step(vec2(0.0), textureCoordinateRectangle.pq - tileTextureCoordinates);
180188
textureAlpha = textureAlpha * alphaMultiplier.x * alphaMultiplier.y;
181189

190+
#if defined(APPLY_DAY_NIGHT_ALPHA) && defined(ENABLE_DAYNIGHT_SHADING)
191+
textureAlpha *= mix(textureDayAlpha, textureNightAlpha, nightBlend);
192+
#endif
193+
182194
vec2 translation = textureCoordinateTranslationAndScale.xy;
183195
vec2 scale = textureCoordinateTranslationAndScale.zw;
184196
vec2 textureCoordinates = tileTextureCoordinates * scale + translation;
@@ -269,7 +281,7 @@ vec3 colorCorrect(vec3 rgb) {
269281
return rgb;
270282
}
271283

272-
vec4 computeDayColor(vec4 initialColor, vec3 textureCoordinates);
284+
vec4 computeDayColor(vec4 initialColor, vec3 textureCoordinates, float nightBlend);
273285
vec4 computeWaterColor(vec3 positionEyeCoordinates, vec2 textureCoordinates, mat3 enuToEye, vec4 imageryColor, float specularMapValue, float fade);
274286

275287
#ifdef GROUND_ATMOSPHERE
@@ -292,11 +304,22 @@ void main()
292304
float clipDistance = clip(gl_FragCoord, u_clippingPlanes, u_clippingPlanesMatrix);
293305
#endif
294306

307+
#if defined(SHOW_REFLECTIVE_OCEAN) || defined(ENABLE_DAYNIGHT_SHADING) || defined(HDR)
308+
vec3 normalMC = czm_geodeticSurfaceNormal(v_positionMC, vec3(0.0), vec3(1.0)); // normalized surface normal in model coordinates
309+
vec3 normalEC = czm_normal3D * normalMC; // normalized surface normal in eye coordiantes
310+
#endif
311+
312+
#if defined(APPLY_DAY_NIGHT_ALPHA) && defined(ENABLE_DAYNIGHT_SHADING)
313+
float nightBlend = 1.0 - clamp(czm_getLambertDiffuse(czm_lightDirectionEC, normalEC) * 5.0, 0.0, 1.0);
314+
#else
315+
float nightBlend = 0.0;
316+
#endif
317+
295318
// The clamp below works around an apparent bug in Chrome Canary v23.0.1241.0
296319
// where the fragment shader sees textures coordinates < 0.0 and > 1.0 for the
297320
// fragments on the edges of tiles even though the vertex shader is outputting
298321
// coordinates strictly in the 0-1 range.
299-
vec4 color = computeDayColor(u_initialColor, clamp(v_textureCoordinates, 0.0, 1.0));
322+
vec4 color = computeDayColor(u_initialColor, clamp(v_textureCoordinates, 0.0, 1.0), nightBlend);
300323

301324
#ifdef SHOW_TILE_BOUNDARIES
302325
if (v_textureCoordinates.x < (1.0/256.0) || v_textureCoordinates.x > (255.0/256.0) ||
@@ -306,11 +329,6 @@ void main()
306329
}
307330
#endif
308331

309-
#if defined(SHOW_REFLECTIVE_OCEAN) || defined(ENABLE_DAYNIGHT_SHADING) || defined(HDR)
310-
vec3 normalMC = czm_geodeticSurfaceNormal(v_positionMC, vec3(0.0), vec3(1.0)); // normalized surface normal in model coordinates
311-
vec3 normalEC = czm_normal3D * normalMC; // normalized surface normal in eye coordiantes
312-
#endif
313-
314332
#if defined(ENABLE_DAYNIGHT_SHADING) || defined(GROUND_ATMOSPHERE)
315333
float cameraDist;
316334
if (czm_sceneMode == czm_sceneMode2D)

Specs/Scene/GlobeSurfaceTileProviderSpec.js

+4
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,8 @@ describe(
622622
);
623623

624624
layer.alpha = 0.123;
625+
layer.nightAlpha = 0.658;
626+
layer.dayAlpha = 0.356;
625627
layer.brightness = 0.456;
626628
layer.contrast = 0.654;
627629
layer.gamma = 0.321;
@@ -651,6 +653,8 @@ describe(
651653
++tileCommandCount;
652654

653655
expect(uniforms.u_dayTextureAlpha()).toEqual([0.123]);
656+
expect(uniforms.u_dayTextureNightAlpha()).toEqual([0.658]);
657+
expect(uniforms.u_dayTextureDayAlpha()).toEqual([0.356]);
654658
expect(uniforms.u_dayTextureBrightness()).toEqual([0.456]);
655659
expect(uniforms.u_dayTextureContrast()).toEqual([0.654]);
656660
expect(uniforms.u_dayTextureOneOverGamma()).toEqual([1.0 / 0.321]);

0 commit comments

Comments
 (0)