diff --git a/Apps/Sandcastle/gallery/Atmosphere.html b/Apps/Sandcastle/gallery/Atmosphere.html new file mode 100644 index 000000000000..d84f7ce6455e --- /dev/null +++ b/Apps/Sandcastle/gallery/Atmosphere.html @@ -0,0 +1,174 @@ + + + + + + + + + Cesium Demo + + + + + + +
+

Loading...

+
+ + + + + + + + + + + + + + + + + +
Lighting Fade Out Distance + + +
Lighting Fade In Distance + + +
Night Fade Out Distance + + +
Night Fade In Distance + + +
+
+ + + diff --git a/Apps/Sandcastle/gallery/Atmosphere.jpg b/Apps/Sandcastle/gallery/Atmosphere.jpg new file mode 100644 index 000000000000..9e3d7aa4a630 Binary files /dev/null and b/Apps/Sandcastle/gallery/Atmosphere.jpg differ diff --git a/CHANGES.md b/CHANGES.md index 476790972176..67216eb2e5c1 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,8 @@ Change Log * Update [gltf-pipeline](https://github.com/AnalyticalGraphicsInc/gltf-pipeline/) to 2.0. [#6805](https://github.com/AnalyticalGraphicsInc/cesium/pull/6805) * Added `cartographicLimitRectangle` to `Globe`. Use this to limit terrain and imagery to a specific `Rectangle` area. [#6987](https://github.com/AnalyticalGraphicsInc/cesium/pull/6987) * Added `OpenCageGeocoderService`, which provides geocoding via [OpenCage](https://opencagedata.com/). [#7015](https://github.com/AnalyticalGraphicsInc/cesium/pull/7015) +* Added ground atmosphere lighting in 3D. This can be toggled with `Globe.showGroundAtmosphere`. [6877](https://github.com/AnalyticalGraphicsInc/cesium/pull/6877) + * Added `Globe.nightFadeOutDistance` and `Globe.nightFadeInDistance` to configure when ground atmosphere night lighting fades in and out. [6877](https://github.com/AnalyticalGraphicsInc/cesium/pull/6877) ##### Fixes :wrench: * Fixed picking for overlapping translucent primitives. [#7039](https://github.com/AnalyticalGraphicsInc/cesium/pull/7039) diff --git a/Source/Scene/Globe.js b/Source/Scene/Globe.js index cfc30e5adbf6..046831302706 100644 --- a/Source/Scene/Globe.js +++ b/Source/Scene/Globe.js @@ -131,27 +131,53 @@ define([ * Enable lighting the globe with the sun as a light source. * * @type {Boolean} - * @default false + * @default true */ this.enableLighting = false; + /** + * Enable the ground atmosphere. + * + * @type {Boolean} + * @default true + */ + this.showGroundAtmosphere = true; + /** * The distance where everything becomes lit. This only takes effect * when enableLighting is true. * * @type {Number} - * @default 6500000.0 + * @default 10000000.0 */ - this.lightingFadeOutDistance = 6500000.0; + this.lightingFadeOutDistance = 1.0e7; /** * The distance where lighting resumes. This only takes effect * when enableLighting is true. * * @type {Number} - * @default 9000000.0 + * @default 20000000.0 + */ + this.lightingFadeInDistance = 2.0e7; + + /** + * The distance where the darkness of night from the ground atmosphere fades out to a lit ground atmosphere. + * This only takes effect when showGroundAtmosphere and enableLighting are true. + * + * @type {Number} + * @default 10000000.0 + */ + this.nightFadeOutDistance = 1.0e7; + + /** + * The distance where the darkness of night from the ground atmosphere fades in to an unlit ground atmosphere. + * This only takes effect when showGroundAtmosphere and enableLighting are true. + * + * @type {Number} + * @default 50000000.0 */ - this.lightingFadeInDistance = 9000000.0; + this.nightFadeInDistance = 5.0e7; /** * True if an animated wave effect should be shown in areas of the globe @@ -187,7 +213,7 @@ define([ this.shadows = ShadowMode.RECEIVE_ONLY; this._oceanNormalMap = undefined; - this._zoomedOutOceanSpecularIntensity = 0.5; + this._zoomedOutOceanSpecularIntensity = undefined; } defineProperties(Globe.prototype, { @@ -372,7 +398,7 @@ define([ var requireNormals = defined(globe._material) && (globe._material.shaderSource.match(/slope/) || globe._material.shaderSource.match('normalEC')); - var fragmentSources = []; + var fragmentSources = [GroundAtmosphere]; if (defined(globe._material) && (!requireNormals || globe._terrainProvider.requestVertexNormals)) { fragmentSources.push(globe._material.shaderSource); defines.push('APPLY_MATERIAL'); @@ -640,11 +666,10 @@ define([ var mode = frameState.mode; if (pass.render) { - // Don't show the ocean specular highlights when zoomed out in 2D and Columbus View. - if (mode === SceneMode.SCENE3D) { - this._zoomedOutOceanSpecularIntensity = 0.5; + if (this.showGroundAtmosphere) { + this._zoomedOutOceanSpecularIntensity = 0.4; } else { - this._zoomedOutOceanSpecularIntensity = 0.0; + this._zoomedOutOceanSpecularIntensity = 0.5; } surface.maximumScreenSpaceError = this.maximumScreenSpaceError; @@ -653,10 +678,13 @@ define([ tileProvider.terrainProvider = this.terrainProvider; tileProvider.lightingFadeOutDistance = this.lightingFadeOutDistance; tileProvider.lightingFadeInDistance = this.lightingFadeInDistance; - tileProvider.zoomedOutOceanSpecularIntensity = this._zoomedOutOceanSpecularIntensity; + tileProvider.nightFadeOutDistance = this.nightFadeOutDistance; + tileProvider.nightFadeInDistance = this.nightFadeInDistance; + tileProvider.zoomedOutOceanSpecularIntensity = mode === SceneMode.SCENE3D ? this._zoomedOutOceanSpecularIntensity : 0.0; tileProvider.hasWaterMask = hasWaterMask; tileProvider.oceanNormalMap = this._oceanNormalMap; tileProvider.enableLighting = this.enableLighting; + tileProvider.showGroundAtmosphere = this.showGroundAtmosphere; tileProvider.shadows = this.shadows; surface.beginFrame(frameState); diff --git a/Source/Scene/GlobeSurfaceShaderSet.js b/Source/Scene/GlobeSurfaceShaderSet.js index 2a8b5b24df08..158106712f56 100644 --- a/Source/Scene/GlobeSurfaceShaderSet.js +++ b/Source/Scene/GlobeSurfaceShaderSet.js @@ -66,7 +66,29 @@ define([ return useWebMercatorProjection ? get2DYPositionFractionMercatorProjection : get2DYPositionFractionGeographicProjection; } - GlobeSurfaceShaderSet.prototype.getShaderProgram = function(frameState, surfaceTile, numberOfDayTextures, applyBrightness, applyContrast, applyHue, applySaturation, applyGamma, applyAlpha, applySplit, showReflectiveOcean, showOceanWaves, enableLighting, hasVertexNormals, useWebMercatorProjection, enableFog, enableClippingPlanes, clippingPlanes, clippedByBoundaries) { + GlobeSurfaceShaderSet.prototype.getShaderProgram = function(options) { + var frameState = options.frameState; + var surfaceTile = options.surfaceTile; + var numberOfDayTextures = options.numberOfDayTextures; + var applyBrightness = options.applyBrightness; + var applyContrast = options.applyContrast; + var applyHue = options.applyHue; + var applySaturation = options.applySaturation; + var applyGamma = options.applyGamma; + var applyAlpha = options.applyAlpha; + var applySplit = options.applySplit; + var showReflectiveOcean = options.showReflectiveOcean; + var showOceanWaves = options.showOceanWaves; + var enableLighting = options.enableLighting; + var showGroundAtmosphere = options.showGroundAtmosphere; + var perFragmentGroundAtmosphere = options.perFragmentGroundAtmosphere; + var hasVertexNormals = options.hasVertexNormals; + var useWebMercatorProjection = options.useWebMercatorProjection; + var enableFog = options.enableFog; + var enableClippingPlanes = options.enableClippingPlanes; + var clippingPlanes = options.clippingPlanes; + var clippedByBoundaries = options.clippedByBoundaries; + var quantization = 0; var quantizationDefine = ''; @@ -102,14 +124,16 @@ define([ (showReflectiveOcean << 8) | (showOceanWaves << 9) | (enableLighting << 10) | - (hasVertexNormals << 11) | - (useWebMercatorProjection << 12) | - (enableFog << 13) | - (quantization << 14) | - (applySplit << 15) | - (enableClippingPlanes << 16) | - (vertexLogDepth << 17) | - (cartographicLimitRectangleFlag << 18); + (showGroundAtmosphere << 11) | + (perFragmentGroundAtmosphere << 12) | + (hasVertexNormals << 13) | + (useWebMercatorProjection << 14) | + (enableFog << 15) | + (quantization << 16) | + (applySplit << 17) | + (enableClippingPlanes << 18) | + (vertexLogDepth << 19) | + (cartographicLimitRectangleFlag << 20); var currentClippingShaderState = 0; if (defined(clippingPlanes)) { @@ -180,6 +204,14 @@ define([ } } + if (showGroundAtmosphere) { + vs.defines.push('GROUND_ATMOSPHERE'); + fs.defines.push('GROUND_ATMOSPHERE'); + if (perFragmentGroundAtmosphere) { + fs.defines.push('PER_FRAGMENT_GROUND_ATMOSPHERE'); + } + } + vs.defines.push('INCLUDE_WEB_MERCATOR_Y'); fs.defines.push('INCLUDE_WEB_MERCATOR_Y'); diff --git a/Source/Scene/GlobeSurfaceTileProvider.js b/Source/Scene/GlobeSurfaceTileProvider.js index 6823dd8bd2e6..b1156145831b 100644 --- a/Source/Scene/GlobeSurfaceTileProvider.js +++ b/Source/Scene/GlobeSurfaceTileProvider.js @@ -127,6 +127,7 @@ define([ this.oceanNormalMap = undefined; this.zoomedOutOceanSpecularIntensity = 0.5; this.enableLighting = false; + this.showGroundAtmosphere = false; this.shadows = ShadowMode.RECEIVE_ONLY; this._quadtree = undefined; @@ -877,6 +878,9 @@ define([ u_lightingFadeDistance : function() { return this.properties.lightingFadeDistance; }, + u_nightFadeDistance : function() { + return this.properties.nightFadeDistance; + }, u_center3D : function() { return this.properties.center3D; }, @@ -982,6 +986,7 @@ define([ zoomedOutOceanSpecularIntensity : 0.5, oceanNormalMap : undefined, lightingFadeDistance : new Cartesian2(6500000.0, 9000000.0), + nightFadeDistance : new Cartesian2(10000000.0, 40000000.0), center3D : undefined, rtc : new Cartesian3(), @@ -1135,6 +1140,29 @@ define([ })(); var otherPassesInitialColor = new Cartesian4(0.0, 0.0, 0.0, 0.0); + var surfaceShaderSetOptionsScratch = { + frameState : undefined, + surfaceTile : undefined, + numberOfDayTextures : undefined, + applyBrightness : undefined, + applyContrast : undefined, + applyHue : undefined, + applySaturation : undefined, + applyGamma : undefined, + applyAlpha : undefined, + applySplit : undefined, + showReflectiveOcean : undefined, + showOceanWaves : undefined, + enableLighting : undefined, + showGroundAtmosphere : undefined, + perFragmentGroundAtmosphere : undefined, + hasVertexNormals : undefined, + useWebMercatorProjection : undefined, + enableFog : undefined, + enableClippingPlanes : undefined, + clippingPlanes : undefined, + clippedByBoundaries : undefined + }; function addDrawCommandsForTile(tileProvider, tile, frameState) { var surfaceTile = tile.data; @@ -1157,9 +1185,27 @@ define([ var showOceanWaves = showReflectiveOcean && defined(oceanNormalMap); var hasVertexNormals = tileProvider.terrainProvider.ready && tileProvider.terrainProvider.hasVertexNormals; var enableFog = frameState.fog.enabled; + var showGroundAtmosphere = tileProvider.showGroundAtmosphere; var castShadows = ShadowMode.castShadows(tileProvider.shadows); var receiveShadows = ShadowMode.receiveShadows(tileProvider.shadows); + var perFragmentGroundAtmosphere = false; + if (showGroundAtmosphere) { + var mode = frameState.mode; + var camera = frameState.camera; + var cameraDistance; + if (mode === SceneMode.SCENE2D || mode === SceneMode.COLUMBUS_VIEW) { + cameraDistance = camera.positionCartographic.height; + } else { + cameraDistance = Cartesian3.magnitude(camera.positionWC); + } + var fadeOutDistance = tileProvider.nightFadeOutDistance; + if (mode !== SceneMode.SCENE3D) { + fadeOutDistance -= frameState.mapProjection.ellipsoid.maximumRadius; + } + perFragmentGroundAtmosphere = cameraDistance > fadeOutDistance; + } + if (showReflectiveOcean) { --maxTextures; } @@ -1229,6 +1275,18 @@ define([ } } + var surfaceShaderSetOptions = surfaceShaderSetOptionsScratch; + surfaceShaderSetOptions.frameState = frameState; + surfaceShaderSetOptions.surfaceTile = surfaceTile; + surfaceShaderSetOptions.showReflectiveOcean = showReflectiveOcean; + surfaceShaderSetOptions.showOceanWaves = showOceanWaves; + surfaceShaderSetOptions.enableLighting = tileProvider.enableLighting; + surfaceShaderSetOptions.showGroundAtmosphere = showGroundAtmosphere; + surfaceShaderSetOptions.perFragmentGroundAtmosphere = perFragmentGroundAtmosphere; + surfaceShaderSetOptions.hasVertexNormals = hasVertexNormals; + surfaceShaderSetOptions.useWebMercatorProjection = useWebMercatorProjection; + surfaceShaderSetOptions.clippedByBoundaries = surfaceTile.clippedByBoundaries; + var tileImageryCollection = surfaceTile.imagery; var imageryIndex = 0; var imageryLen = tileImageryCollection.length; @@ -1287,6 +1345,8 @@ define([ uniformMapProperties.oceanNormalMap = oceanNormalMap; uniformMapProperties.lightingFadeDistance.x = tileProvider.lightingFadeOutDistance; uniformMapProperties.lightingFadeDistance.y = tileProvider.lightingFadeInDistance; + uniformMapProperties.nightFadeDistance.x = tileProvider.nightFadeOutDistance; + uniformMapProperties.nightFadeDistance.y = tileProvider.nightFadeInDistance; uniformMapProperties.zoomedOutOceanSpecularIntensity = tileProvider.zoomedOutOceanSpecularIntensity; uniformMapProperties.center3D = surfaceTile.center; @@ -1414,7 +1474,19 @@ define([ uniformMap = combine(uniformMap, tileProvider.uniformMap); } - command.shaderProgram = tileProvider._surfaceShaderSet.getShaderProgram(frameState, surfaceTile, numberOfDayTextures, applyBrightness, applyContrast, applyHue, applySaturation, applyGamma, applyAlpha, applySplit, showReflectiveOcean, showOceanWaves, tileProvider.enableLighting, hasVertexNormals, useWebMercatorProjection, applyFog, clippingPlanesEnabled, clippingPlanes, surfaceTile.clippedByBoundaries); + surfaceShaderSetOptions.numberOfDayTextures = numberOfDayTextures; + surfaceShaderSetOptions.applyBrightness = applyBrightness; + surfaceShaderSetOptions.applyContrast = applyContrast; + surfaceShaderSetOptions.applyHue = applyHue; + surfaceShaderSetOptions.applySaturation = applySaturation; + surfaceShaderSetOptions.applyGamma = applyGamma; + surfaceShaderSetOptions.applyAlpha = applyAlpha; + surfaceShaderSetOptions.applySplit = applySplit; + surfaceShaderSetOptions.enableFog = applyFog; + surfaceShaderSetOptions.enableClippingPlanes = clippingPlanesEnabled; + surfaceShaderSetOptions.clippingPlanes = clippingPlanes; + + command.shaderProgram = tileProvider._surfaceShaderSet.getShaderProgram(surfaceShaderSetOptions); command.castShadows = castShadows; command.receiveShadows = receiveShadows; command.renderState = renderState; diff --git a/Source/Shaders/GlobeFS.glsl b/Source/Shaders/GlobeFS.glsl index fcae7dcb54c5..980b44484a8b 100644 --- a/Source/Shaders/GlobeFS.glsl +++ b/Source/Shaders/GlobeFS.glsl @@ -1,4 +1,3 @@ -//#define SHOW_TILE_BOUNDARIES uniform vec4 u_initialColor; #if TEXTURE_UNITS > 0 @@ -47,7 +46,7 @@ uniform float u_zoomedOutOceanSpecularIntensity; uniform sampler2D u_oceanNormalMap; #endif -#ifdef ENABLE_DAYNIGHT_SHADING +#if defined(ENABLE_DAYNIGHT_SHADING) || defined(GROUND_ATMOSPHERE) uniform vec2 u_lightingFadeDistance; #endif @@ -55,13 +54,17 @@ uniform vec2 u_lightingFadeDistance; uniform vec4 u_cartographicLimitRectangle; #endif +#ifdef GROUND_ATMOSPHERE +uniform vec2 u_nightFadeDistance; +#endif + #ifdef ENABLE_CLIPPING_PLANES uniform sampler2D u_clippingPlanes; uniform mat4 u_clippingPlanesMatrix; uniform vec4 u_clippingPlanesEdgeStyle; #endif -#if defined(FOG) && (defined(ENABLE_VERTEX_LIGHTING) || defined(ENABLE_DAYNIGHT_SHADING)) +#if defined(FOG) && (defined(ENABLE_VERTEX_LIGHTING) || defined(ENABLE_DAYNIGHT_SHADING)) || defined(GROUND_ATMOSPHERE) uniform float u_minimumBrightness; #endif @@ -76,8 +79,13 @@ varying float v_height; varying float v_slope; #endif -#ifdef FOG +#if defined(FOG) || defined(GROUND_ATMOSPHERE) varying float v_distance; +varying vec3 v_fogRayleighColor; +varying vec3 v_fogMieColor; +#endif + +#ifdef GROUND_ATMOSPHERE varying vec3 v_rayleighColor; varying vec3 v_mieColor; #endif @@ -155,7 +163,7 @@ vec4 sampleAndBlend( } vec4 computeDayColor(vec4 initialColor, vec3 textureCoordinates); -vec4 computeWaterColor(vec3 positionEyeCoordinates, vec2 textureCoordinates, mat3 enuToEye, vec4 imageryColor, float specularMapValue); +vec4 computeWaterColor(vec3 positionEyeCoordinates, vec2 textureCoordinates, mat3 enuToEye, vec4 imageryColor, float specularMapValue, float fade); void main() { @@ -191,6 +199,33 @@ void main() vec3 normalEC = czm_normal3D * normalMC; // normalized surface normal in eye coordiantes #endif +#if defined(ENABLE_DAYNIGHT_SHADING) || defined(GROUND_ATMOSPHERE) + float cameraDist; + if (czm_sceneMode == czm_sceneMode2D) + { + cameraDist = max(czm_frustumPlanes.x - czm_frustumPlanes.y, czm_frustumPlanes.w - czm_frustumPlanes.z) * 0.5; + } + else if (czm_sceneMode == czm_sceneModeColumbusView) + { + cameraDist = -czm_view[3].z; + } + else + { + cameraDist = length(czm_view[3]); + } + float fadeOutDist = u_lightingFadeDistance.x; + float fadeInDist = u_lightingFadeDistance.y; + if (czm_sceneMode != czm_sceneMode3D) { + vec3 radii = czm_getWgs84EllipsoidEC().radii; + float maxRadii = max(radii.x, max(radii.y, radii.z)); + fadeOutDist -= maxRadii; + fadeInDist -= maxRadii; + } + float fade = clamp((cameraDist - fadeOutDist) / (fadeInDist - fadeOutDist), 0.0, 1.0); +#else + float fade = 0.0; +#endif + #ifdef SHOW_REFLECTIVE_OCEAN vec2 waterMaskTranslation = u_waterMaskTranslationAndScale.xy; vec2 waterMaskScale = u_waterMaskTranslationAndScale.zw; @@ -208,7 +243,7 @@ void main() vec2 textureCoordinates = mix(ellipsoidTextureCoordinates, ellipsoidFlippedTextureCoordinates, czm_morphTime * smoothstep(0.9, 0.95, normalMC.z)); - color = computeWaterColor(v_positionEC, textureCoordinates, enuToEye, color, mask); + color = computeWaterColor(v_positionEC, textureCoordinates, enuToEye, color, mask, fade); } #endif @@ -222,34 +257,12 @@ void main() color.xyz = mix(color.xyz, material.diffuse, material.alpha); #endif -#ifdef ENABLE_VERTEX_LIGHTING +#if defined(ENABLE_VERTEX_LIGHTING) float diffuseIntensity = clamp(czm_getLambertDiffuse(czm_sunDirectionEC, normalize(v_normalEC)) * 0.9 + 0.3, 0.0, 1.0); vec4 finalColor = vec4(color.rgb * diffuseIntensity, color.a); #elif defined(ENABLE_DAYNIGHT_SHADING) float diffuseIntensity = clamp(czm_getLambertDiffuse(czm_sunDirectionEC, normalEC) * 5.0 + 0.3, 0.0, 1.0); - float cameraDist; - if (czm_sceneMode == czm_sceneMode2D) - { - cameraDist = max(czm_frustumPlanes.x - czm_frustumPlanes.y, czm_frustumPlanes.w - czm_frustumPlanes.z) * 0.5; - } - else if (czm_sceneMode == czm_sceneModeColumbusView) - { - cameraDist = -czm_view[3].z; - } - else - { - cameraDist = length(czm_view[3]); - } - float fadeOutDist = u_lightingFadeDistance.x; - float fadeInDist = u_lightingFadeDistance.y; - if (czm_sceneMode != czm_sceneMode3D) { - vec3 radii = czm_getWgs84EllipsoidEC().radii; - float maxRadii = max(radii.x, max(radii.y, radii.z)); - fadeOutDist -= maxRadii; - fadeInDist -= maxRadii; - } - float t = clamp((cameraDist - fadeOutDist) / (fadeInDist - fadeOutDist), 0.0, 1.0); - diffuseIntensity = mix(1.0, diffuseIntensity, t); + diffuseIntensity = mix(1.0, diffuseIntensity, fade); vec4 finalColor = vec4(color.rgb * diffuseIntensity, color.a); #else vec4 finalColor = color; @@ -266,20 +279,60 @@ void main() } #endif -#ifdef FOG +#if defined(FOG) || defined(GROUND_ATMOSPHERE) const float fExposure = 2.0; - vec3 fogColor = v_mieColor + finalColor.rgb * v_rayleighColor; + vec3 fogColor = v_fogMieColor + finalColor.rgb * v_fogRayleighColor; fogColor = vec3(1.0) - exp(-fExposure * fogColor); +#endif +#ifdef FOG #if defined(ENABLE_VERTEX_LIGHTING) || defined(ENABLE_DAYNIGHT_SHADING) float darken = clamp(dot(normalize(czm_viewerPositionWC), normalize(czm_sunPositionWC)), u_minimumBrightness, 1.0); fogColor *= darken; #endif - gl_FragColor = vec4(czm_fog(v_distance, finalColor.rgb, fogColor), finalColor.a); + finalColor = vec4(czm_fog(v_distance, finalColor.rgb, fogColor), finalColor.a); +#endif + +#ifdef GROUND_ATMOSPHERE + if (czm_sceneMode != czm_sceneMode3D) + { + gl_FragColor = finalColor; + return; + } + +#if defined(PER_FRAGMENT_GROUND_ATMOSPHERE) && (defined(ENABLE_DAYNIGHT_SHADING) || defined(ENABLE_VERTEX_LIGHTING)) + czm_ellipsoid ellipsoid = czm_getWgs84EllipsoidEC(); + + float mpp = czm_metersPerPixel(vec4(0.0, 0.0, -czm_currentFrustum.x, 1.0)); + vec2 xy = gl_FragCoord.xy / czm_viewport.zw * 2.0 - vec2(1.0); + xy *= czm_viewport.zw * mpp * 0.5; + + vec3 direction = normalize(vec3(xy, -czm_currentFrustum.x)); + czm_ray ray = czm_ray(vec3(0.0), direction); + + czm_raySegment intersection = czm_rayEllipsoidIntersectionInterval(ray, ellipsoid); + + vec3 ellipsoidPosition = czm_pointAlongRay(ray, intersection.start); + ellipsoidPosition = (czm_inverseView * vec4(ellipsoidPosition, 1.0)).xyz; + AtmosphereColor atmosColor = computeGroundAtmosphereFromSpace(ellipsoidPosition, true); + + vec3 groundAtmosphereColor = atmosColor.mie + finalColor.rgb * atmosColor.rayleigh; + groundAtmosphereColor = vec3(1.0) - exp(-fExposure * groundAtmosphereColor); + + fadeInDist = u_nightFadeDistance.x; + fadeOutDist = u_nightFadeDistance.y; + + float sunlitAtmosphereIntensity = clamp((cameraDist - fadeOutDist) / (fadeInDist - fadeOutDist), 0.0, 1.0); + groundAtmosphereColor = mix(groundAtmosphereColor, fogColor, sunlitAtmosphereIntensity); #else - gl_FragColor = finalColor; + vec3 groundAtmosphereColor = fogColor; #endif + + finalColor = vec4(mix(finalColor.rgb, groundAtmosphereColor, fade), finalColor.a); +#endif + + gl_FragColor = finalColor; } #ifdef SHOW_REFLECTIVE_OCEAN @@ -309,7 +362,7 @@ const float oceanFrequencyHighAltitude = 125000.0; const float oceanAnimationSpeedHighAltitude = 0.008; const float oceanOneOverAmplitudeHighAltitude = 1.0 / 2.0; -vec4 computeWaterColor(vec3 positionEyeCoordinates, vec2 textureCoordinates, mat3 enuToEye, vec4 imageryColor, float maskValue) +vec4 computeWaterColor(vec3 positionEyeCoordinates, vec2 textureCoordinates, mat3 enuToEye, vec4 imageryColor, float maskValue, float fade) { vec3 positionToEyeEC = -positionEyeCoordinates; float positionToEyeECLength = length(positionToEyeEC); @@ -352,7 +405,7 @@ vec4 computeWaterColor(vec3 positionEyeCoordinates, vec2 textureCoordinates, mat // Use diffuse light to highlight the waves float diffuseIntensity = czm_getLambertDiffuse(czm_sunDirectionEC, normalEC) * maskValue; - vec3 diffuseHighlight = waveHighlightColor * diffuseIntensity; + vec3 diffuseHighlight = waveHighlightColor * diffuseIntensity * (1.0 - fade); #ifdef SHOW_OCEAN_WAVES // Where diffuse light is low or non-existent, use wave highlights based solely on diff --git a/Source/Shaders/GlobeVS.glsl b/Source/Shaders/GlobeVS.glsl index 30c2afc014a6..f7c1bb25263e 100644 --- a/Source/Shaders/GlobeVS.glsl +++ b/Source/Shaders/GlobeVS.glsl @@ -27,10 +27,10 @@ varying float v_slope; varying float v_height; #endif -#ifdef FOG +#if defined(FOG) || defined(GROUND_ATMOSPHERE) varying float v_distance; -varying vec3 v_mieColor; -varying vec3 v_rayleighColor; +varying vec3 v_fogMieColor; +varying vec3 v_fogRayleighColor; #endif // These functions are generated at runtime. @@ -158,19 +158,19 @@ void main() #if defined(ENABLE_VERTEX_LIGHTING) || defined(GENERATE_POSITION_AND_NORMAL) || defined(APPLY_MATERIAL) v_positionEC = (u_modifiedModelView * vec4(position, 1.0)).xyz; - v_positionMC = position3DWC; // position in model coordinates + v_positionMC = position3DWC; // position in model coordinates vec3 normalMC = czm_octDecode(encodedNormal); v_normalMC = normalMC; v_normalEC = czm_normal3D * v_normalMC; #elif defined(SHOW_REFLECTIVE_OCEAN) || defined(ENABLE_DAYNIGHT_SHADING) || defined(GENERATE_POSITION) v_positionEC = (u_modifiedModelView * vec4(position, 1.0)).xyz; - v_positionMC = position3DWC; // position in model coordinates + v_positionMC = position3DWC; // position in model coordinates #endif -#ifdef FOG - AtmosphereColor atmosColor = computeGroundAtmosphereFromSpace(position3DWC); - v_mieColor = atmosColor.mie; - v_rayleighColor = atmosColor.rayleigh; +#if defined(FOG) || defined(GROUND_ATMOSPHERE) + AtmosphereColor atmosFogColor = computeGroundAtmosphereFromSpace(position3DWC, false); + v_fogMieColor = atmosFogColor.mie; + v_fogRayleighColor = atmosFogColor.rayleigh; v_distance = length((czm_modelView3D * vec4(position3DWC, 1.0)).xyz); #endif diff --git a/Source/Shaders/GroundAtmosphere.glsl b/Source/Shaders/GroundAtmosphere.glsl index 98115f017b5a..4ac25eead7f3 100644 --- a/Source/Shaders/GroundAtmosphere.glsl +++ b/Source/Shaders/GroundAtmosphere.glsl @@ -3,11 +3,11 @@ * * Copyright (c) 2000-2005, Sean O'Neil (s_p_oneil@hotmail.com) * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, @@ -16,7 +16,7 @@ * * Neither the name of the project nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -30,7 +30,7 @@ * * Modifications made by Analytical Graphics, Inc. */ - + // Atmosphere: // Code: http://sponeil.net/ // GPU Gems 2 Article: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter16.html @@ -67,7 +67,7 @@ float scale(float fCos) return fScaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25)))); } -AtmosphereColor computeGroundAtmosphereFromSpace(vec3 v3Pos) +AtmosphereColor computeGroundAtmosphereFromSpace(vec3 v3Pos, bool useSunLighting) { vec3 v3InvWavelength = vec3(1.0 / pow(0.650, 4.0), 1.0 / pow(0.570, 4.0), 1.0 / pow(0.475, 4.0)); @@ -75,11 +75,11 @@ AtmosphereColor computeGroundAtmosphereFromSpace(vec3 v3Pos) vec3 v3Ray = v3Pos - czm_viewerPositionWC; float fFar = length(v3Ray); v3Ray /= fFar; - + float fCameraHeight = length(czm_viewerPositionWC); float fCameraHeight2 = fCameraHeight * fCameraHeight; - // This next line is an ANGLE workaround. It is equivalent to B = 2.0 * dot(czm_viewerPositionWC, v3Ray), + // This next line is an ANGLE workaround. It is equivalent to B = 2.0 * dot(czm_viewerPositionWC, v3Ray), // which is what it should be, but there are problems at the poles. float B = 2.0 * length(czm_viewerPositionWC) * dot(normalize(czm_viewerPositionWC), v3Ray); float C = fCameraHeight2 - fOuterRadius2; @@ -90,11 +90,11 @@ AtmosphereColor computeGroundAtmosphereFromSpace(vec3 v3Pos) vec3 v3Start = czm_viewerPositionWC + v3Ray * fNear; fFar -= fNear; float fDepth = exp((fInnerRadius - fOuterRadius) / fScaleDepth); - + // The light angle based on the sun position would be: // dot(czm_sunDirectionWC, v3Pos) / length(v3Pos); - // We want the atmosphere to be uniform over the globe so it is set to 1.0. - float fLightAngle = 1.0; + // When we want the atmosphere to be uniform over the globe so it is set to 1.0. + float fLightAngle = useSunLighting ? dot(czm_sunDirectionWC, v3Pos) / length(v3Pos) : 1.0; float fCameraAngle = dot(-v3Ray, v3Pos) / length(v3Pos); float fCameraScale = scale(fCameraAngle); float fLightScale = scale(fLightAngle); @@ -119,11 +119,11 @@ AtmosphereColor computeGroundAtmosphereFromSpace(vec3 v3Pos) v3FrontColor += v3Attenuate * (fDepth * fScaledLength); v3SamplePoint += v3SampleRay; } - + AtmosphereColor color; color.mie = v3FrontColor * (v3InvWavelength * fKrESun + fKmESun); color.rayleigh = v3Attenuate; // Calculate the attenuation factor for the ground - + return color; } diff --git a/Source/Shaders/SkyAtmosphereFS.glsl b/Source/Shaders/SkyAtmosphereFS.glsl index 678ec9b35432..52935fbe6986 100644 --- a/Source/Shaders/SkyAtmosphereFS.glsl +++ b/Source/Shaders/SkyAtmosphereFS.glsl @@ -58,8 +58,6 @@ void main (void) vec3 rgb = rayleighPhase * v_rayleighColor + miePhase * v_mieColor; rgb = vec3(1.0) - exp(-exposure * rgb); - // Compute luminance before color correction to avoid strangely gray night skies - float l = czm_luminance(rgb); #ifdef COLOR_CORRECT // Convert rgb color to hsb @@ -70,9 +68,6 @@ void main (void) hsb.z = hsb.z > czm_epsilon7 ? hsb.z + u_hsbShift.z : 0.0; // brightness // Convert shifted hsb back to rgb rgb = czm_HSBToRGB(hsb); - - // Check if correction decreased the luminance to 0 - l = min(l, czm_luminance(rgb)); #endif // Alter alpha based on how close the viewer is to the ground (1.0 = on ground, 0.0 = at edge of atmosphere)