aboutsummaryrefslogtreecommitdiff
path: root/tests/spec/arb_es2_compatibility/ge7.frag
diff options
context:
space:
mode:
Diffstat (limited to 'tests/spec/arb_es2_compatibility/ge7.frag')
-rw-r--r--tests/spec/arb_es2_compatibility/ge7.frag710
1 files changed, 710 insertions, 0 deletions
diff --git a/tests/spec/arb_es2_compatibility/ge7.frag b/tests/spec/arb_es2_compatibility/ge7.frag
new file mode 100644
index 00000000..2d354eab
--- /dev/null
+++ b/tests/spec/arb_es2_compatibility/ge7.frag
@@ -0,0 +1,710 @@
+//!GL2
+#define GE_PIXEL_SHADER
+#define GE_PRECISION mediump
+#define ATMOSPHERE_OFF
+#define GROUND
+#define SUN_OFF
+#define OVERLAY
+#define ENABLE_VERTEX_REJECT
+#if defined(GL_ES)
+precision GE_PRECISION float;
+#else
+#define lowp
+#define mediump
+#define highp
+#endif
+
+uniform mat4 ig_ModelViewMatrix;
+uniform mat4 ig_ModelViewProjectionMatrix;
+uniform mat4 ig_TextureMatrix;
+uniform vec4 ig_LightDirectionInModelSpace;
+uniform vec4 ig_env_atmosphere_custom_state_value;
+uniform lowp vec4 ig_env_atmosphere_custom_color_value;
+uniform lowp float alpha_ref_value;
+
+float saturate(float v) { return clamp(v, 0.0, 1.0); }
+vec2 saturate(vec2 v) { return clamp(v, 0.0, 1.0); }
+vec3 saturate(vec3 v) { return clamp(v, 0.0, 1.0); }
+vec4 saturate(vec4 v) { return clamp(v, 0.0, 1.0); }
+
+// Returns the quadrant portion of the given vertex flags.
+float getQuadrant(vec4 vertexQuadrant) {
+ return dot(vertexQuadrant, vec4(1.0, 2.0, 4.0, 8.0));
+}
+
+// Both getMasked methods assume that quadrantMask has a single 1 and the
+// rest are 0.
+
+vec4 getMaskedVertex(vec4 pos, vec4 quadrantMask, vec4 vertexQuadrant) {
+ return pos * dot(quadrantMask, vertexQuadrant);
+}
+
+float getMaskedAlpha(vec4 quadrantAlphas, vec4 vertexQuadrant) {
+ return dot(quadrantAlphas, vertexQuadrant);
+}
+
+// Computes a vertex color to show which quadrant a vertex is in. Also marks
+// vertices that would be rejected and error conditions (e.g. invalid
+// quadrant).
+vec4 getDebugVertexColor(vec4 quadrantMask, vec4 vertexQuadrant) {
+ vec4 color;
+ float quadrant = getQuadrant(vertexQuadrant);
+ if (quadrant == 1.0) {
+ // Red
+ color = vec4(1.0, 0.0, 0.0, 1.0);
+ } else if (quadrant == 2.0) {
+ // Green
+ color = vec4(0.0, 1.0, 0.0, 1.0);
+ } else if (quadrant == 4.0) {
+ // Blue
+ color = vec4(0.0, 0.0, 1.0, 1.0);
+ } else if (quadrant == 8.0) {
+ // Cyan
+ color = vec4(0.0, 1.0, 1.0, 1.0);
+ } else if (quadrant == 0.0) {
+ // Vertex didn't have a quadrant bit set. Mark as saturated Yellow.
+ color = vec4(10.0, 10.0, 0.0, 1.0);
+ } else if (quadrant == 15.0) {
+ // All quadrant bits were set. Mark as White.
+ color = vec4(10.0, 10.0, 10.0, 1.0);
+ } else {
+ // More than one quadrant bit was set or a quadrant bit was set to
+ // something other than 1.0, so flag verts in saturated Magenta.
+ color = vec4(10.0, 0.0, 10.0, 1.0);
+ }
+ // Make hidden quadrants dimmer.
+ if (dot(quadrantMask, vertexQuadrant) == 0.)
+ color *= .5;
+ return color;
+}
+
+#ifdef DEBUG_QUADRANT_COLORS
+// Used by the pixel shader to show quadrants, culled verts and error
+// conditions when DEBUG_QUADRANT_COLORS is defined.
+varying vec4 vout_debug_color;
+#endif
+
+// The \"discard\" instruction is not available for vertex shaders, so
+// this function needs to be excluded when parsing a vertex shader.
+#ifdef GE_PIXEL_SHADER
+
+// When debugging is on, modulates the pixel color by the debug color output
+// from the vertex shader. Otherwise, the given pixel color is returned
+// unchanged.
+vec4 computeDebugPixelColor(vec4 pixelShaderColor) {
+// OGL ES 2.0 does not support alpha test, so need to do it in the
+// shader.
+#if defined(GL_ES) && !defined(FORCE_NO_ALPHA_TEST)
+// Terrain and sky don't use alpha test.
+#if defined(OVERLAY) || defined(MODEL)
+ // alpha_ref_value is set by igVisualContext, and will be -1 if alpha test
+ // is off.
+ if (pixelShaderColor.a < alpha_ref_value) {
+ discard;
+ }
+#endif // defined(OVERLAY) || defined(MODEL)
+#endif // defined(GL_ES) && !defined(FORCE_NO_ALPHA_TEST)
+
+#ifdef DEBUG_QUADRANT_COLORS
+ return pixelShaderColor * vout_debug_color;
+#else
+ return pixelShaderColor;
+#endif
+}
+
+#endif // GE_PIXEL_SHADER
+// Constant g for phase function used for Mie scattering.
+const float gMieConst = -0.990;
+const float gMieConst2 = gMieConst * gMieConst;
+
+varying vec4 vout_texCoordAndFogFactor;
+#if defined(QUADRANT_ALPHAS)
+varying float vout_alpha;
+#endif
+
+uniform lowp sampler2D groundTexture;
+uniform lowp vec4 groundColor;
+
+#if defined(OVERLAY)
+uniform vec4 groundOverlayExtent;
+float GetMaskedOverlayAlpha(float alpha, vec2 texCoord) {
+ return ((texCoord.s - groundOverlayExtent.x) *
+ (groundOverlayExtent.y - texCoord.s) >= 0. &&
+ (texCoord.t - groundOverlayExtent.z) *
+ (groundOverlayExtent.w - texCoord.t) >= 0. ? alpha : 0.0);
+}
+
+#endif // defined(OVERLAY)
+
+#if defined(USE_IMPROVED_SHADER_VARIATION)
+// x: atmosphere density.
+// y: atmosphere angle falloff.
+// z: night intensity.
+// w: camera exposure.
+uniform vec4 atmosphereTweaks;
+
+#endif // defined(USE_IMPROVED_SHADER_VARIATION)
+
+//", '=' <repeats 30 times>, " ground sun off
+#if defined(ATMOSPHERE_ON) && defined(GROUND) && defined(SUN_OFF)
+
+#if !defined(USE_SIMPLIFIED_SHADER_VARIATION)
+varying vec4 vout_blendTexCoordAndRayleighT;
+#endif
+
+uniform lowp sampler2D groundRayleighMap;
+uniform vec4 groundSunOffPixelParams;
+uniform lowp vec4 groundFogColor;
+
+#if defined(DEBUG_GE_BUILD)
+uniform lowp vec4 sidedb_color;
+#endif
+
+void AtmosphereGroundSunOffFragShader() {
+ // Get the texture color for the object.
+ lowp vec4 texColor = texture2D(groundTexture, vout_texCoordAndFogFactor.st);
+
+#if defined(DEBUG_GE_BUILD)
+ if (sidedb_color.a > 0.0) {
+ texColor = mix(texColor, sidedb_color, 0.1);
+ }
+#endif
+ texColor *= groundColor;
+
+ lowp vec4 color;
+ #if defined(USE_SIMPLIFIED_SHADER_VARIATION)
+ color = texColor;
+ #else
+ // The rayleigh map's s-coordinate depends on camera height and is computed
+ // on the CPU.
+ float rayleighS = groundSunOffPixelParams.x;
+ lowp vec4 rayleigh = texture2D(groundRayleighMap, vec2(rayleighS, vout_blendTexCoordAndRayleighT.z));
+ texColor.rgb += rayleigh.rgb;
+ lowp float fogFactor = vout_texCoordAndFogFactor.w;
+ color.rgb = mix(groundFogColor.rgb, texColor.rgb, fogFactor);
+ color.a = texColor.a;
+ #endif
+
+ gl_FragColor = computeDebugPixelColor(color);
+}
+
+//", '=' <repeats 30 times>, " ground sun off overlay
+#if defined(OVERLAY)
+uniform lowp sampler2D groundRayleighOverlayMap;
+
+void AtmosphereGroundSunOffOverlayFragShader() {
+ // Get the texture color for the object. The projective component is to
+ // allow us to do Arbitrary Ground Overlays.
+ lowp vec4 texColor =
+ texture2DProj(groundTexture, vout_texCoordAndFogFactor.stp) *
+ groundColor;
+ // Note that we do not allow texture blend for overlays.
+ // Perform texture edge clamping for ground overlays by setting alpha to zero
+ // outside of texture coordinate range [0, 1]
+ vec2 stOverZ = vout_texCoordAndFogFactor.xy / vout_texCoordAndFogFactor.z;
+ texColor.a = GetMaskedOverlayAlpha(texColor.a, stOverZ);
+
+ // The rayleigh map's s-coordinate depends on camera height and is computed
+ // on the CPU.
+ float rayleighS = groundSunOffPixelParams.x;
+ lowp vec4 rayleigh = texture2D(
+ groundRayleighOverlayMap,
+ vec2(rayleighS, vout_blendTexCoordAndRayleighT.z));
+ texColor.rgb += rayleigh.rgb;
+ lowp float fogFactor = vout_texCoordAndFogFactor.w;
+ lowp vec4 color;
+ color.rgb = mix(groundFogColor.rgb, texColor.rgb, fogFactor);
+ color.a = texColor.a;
+ gl_FragColor = computeDebugPixelColor(color);
+}
+#endif // defined(OVERLAY)
+#endif // defined(ATMOSPHERE_ON) && defined(GROUND) && defined(SUN_OFF)
+
+//", '=' <repeats 30 times>, " ground sun on (default)
+#if defined(ATMOSPHERE_ON) && defined(GROUND) && defined(SUN_ON) && !defined(USE_IMPROVED_SHADER_VARIATION)
+varying vec3 vout_rayleigh;
+varying vec3 vout_adjustedMie;
+uniform vec4 fogColor;
+
+#if defined(MODEL)
+uniform float has_texture;
+uniform lowp vec4 global_color;
+#endif
+
+void AtmosphereGroundSunOnFragShader() {
+ // If texturing is off, use white as diffuse color. Otherwise use color
+ // from texture.
+#if defined(MODEL)
+ lowp vec4 texColor = mix(
+ global_color,
+ texture2D(groundTexture, vout_texCoordAndFogFactor.st) * global_color,
+ has_texture);
+#else
+ lowp vec4 texColor = ig_env_atmosphere_custom_state_value.y != 0.0 ?
+ texture2D(groundTexture, vout_texCoordAndFogFactor.st) * groundColor :
+ groundColor;
+#endif // defined(MODEL)
+ vec3 scatteredColor = vout_rayleigh.rgb + texColor.rgb * vout_adjustedMie.rgb;
+ float fogFactor = vout_texCoordAndFogFactor.w;
+ vec4 color;
+ color.rgb = mix(fogColor.rgb, scatteredColor, fogFactor);
+ color.a = texColor.a;
+ gl_FragColor = computeDebugPixelColor(color);
+}
+
+
+//", '=' <repeats 29 times>, " ground sun on overlay (default)
+#if defined(OVERLAY)
+// Similar to above, but sets output alpha to zero when the projected texture
+// coordinates are outside of the [0,1] range.
+void AtmosphereGroundSunOnOverlayFragShader() {
+ // Get the texture color for the object. The projective component is to
+ // allow us to do Arbitrary Ground Overlays.
+ // If texturing is off, use white as diffuse color. Otherwise use color
+ // from texture.
+ lowp vec4 texColor = (ig_env_atmosphere_custom_state_value.y == 0.0) ?
+ groundColor :
+ (texture2DProj(groundTexture, vout_texCoordAndFogFactor.xyz) *
+ groundColor);
+ // Perform texture edge clamping for ground overlays by setting alpha to zero
+ // outside of texture coordinate range [0, 1]
+ vec2 stOverZ = vout_texCoordAndFogFactor.xy / vout_texCoordAndFogFactor.z;
+ texColor.a = GetMaskedOverlayAlpha(texColor.a, stOverZ);
+
+ vec3 scatteredColor = vout_rayleigh.rgb + texColor.rgb * vout_adjustedMie.rgb;
+ float fogFactor = vout_texCoordAndFogFactor.w;
+ vec4 color;
+ color.rgb = mix(fogColor.rgb, scatteredColor, fogFactor);
+ color.a = texColor.a;
+ gl_FragColor = computeDebugPixelColor(color);
+}
+#endif // defined(OVERLAY)
+#endif // defined(ATMOSPHERE_ON) && defined(GROUND) && defined(SUN_ON) && !defined(USE_IMPROVED_SHADER_VARIATION)
+
+//", '=' <repeats 30 times>, " ground sun on (improved)
+#if defined(ATMOSPHERE_ON) && defined(GROUND) && defined(SUN_ON) && defined(USE_IMPROVED_SHADER_VARIATION)
+uniform vec3 worldOriginInView;
+// The direction vector to the light source.
+uniform vec4 cameraToSunDirAndExposure;
+// xyz: Extra ambient color that is stronger during sunsets (and sunrises).
+// w: density used in fog exp2 function.
+uniform vec4 sunsetAmbientAndFogDensity;
+uniform vec4 fogColor;
+
+varying vec4 vout_viewPosAndNormalDotSun;
+#if defined(MORPH_VERTICES)
+varying vec4 vout_blendTexCoord;
+#endif // defined(MORPH_VERTICES)
+
+// Implements the abstract function defined in atmosphere.glsllib.
+// Returns a fading factor to attenuate the atmospheric effects when the camera
+// altitude decreases, unless the view zenith angle gets close to the horizon
+// angle.
+float atmosphereTweak(float r, float mu) {
+ float r0 = max(kMinCameraRadius, cameraAndSunState.x);
+ float muHoriz = -sqrt(1.0 - 1.0 / (r * r));
+ float angleFalloff = pow((1.0 + mu) / (1.0 + muHoriz), atmosphereTweaks.y);
+ return clamp(angleFalloff, 0.1, 1.0) * atmosphereTweaks.x;
+}
+
+vec4 ImprovedAtmosphereGroundSunOnAboveWater(vec4 texColor) {
+ // Computes the ground albedo, i.e. the proportion of incident ligth reflected
+ // by the ground, for each r,g,b wavelength, divided by pi. Ideally the ground
+ // texture would directly contain this physical quantity, but in fact it
+ // contains some uncalibrated values. Assuming that these values correctly
+ // represent the albedo, and that they are simply gamma corrected as in almost
+ // all images with a gamma value of 2.2, we can compute the albedo with a
+ // pow(color.rgb, 2.2) or approximate it with a square to avoid a costly pow
+ // function:
+ vec3 albedoOverPi = texColor.rgb * texColor.rgb * (0.55 / kPi);
+
+ // Computes the fragment position in geocentric coordinates.
+ vec3 groundPos = vout_viewPosAndNormalDotSun.xyz - worldOriginInView.xyz;
+
+ // Computes the radiance of the Sun reaching groundPos, relatively to the
+ // outer Sun radiance. This is the transmittance of the atmosphere from the
+ // ground to the top atmosphere boundary in the Sun direction.
+ float gR = length(groundPos);
+ float gMuS = dot(groundPos, cameraToSunDirAndExposure.xyz) / gR;
+ vec3 sunRadiance = atmoTex(gR, gMuS).rgb;
+
+ // Computes the irradiance due to the sky dome (excluding the Sun).
+ vec3 skyIrradiance = skyTex(gR, gMuS) * atmosphereTweaks.x;
+ // Tweaks the sky irradiance to avoid a dark ground during night.
+ float night = smoothstep(0.0, 0.2, -gMuS) * atmosphereTweaks.z;
+ vec3 gSkyIrradiance = max(skyIrradiance, vec3(0.002, 0.005, 0.01) * night);
+
+ // Computes the radiance reflected by the ground (using a Lambertian BRDF).
+ vec3 groundL = albedoOverPi *
+ (max(vout_viewPosAndNormalDotSun.w, 0.0) * sunRadiance + gSkyIrradiance);
+
+ vec3 pixel = aerialPerspective(groundL, -worldOriginInView, groundPos,
+ cameraToSunDirAndExposure.xyz, atmosphereTweaks.w);
+ return vec4(pixel, texColor.a);
+}
+
+vec4 ImprovedAtmosphereGroundSunOnBelowWater(vec4 texColor) {
+ // The following shading is completely ad-hoc and not physically-based at all.
+ // For instance distant water is always blue, even at night, which is of
+ // course wrong. Also the Sun light is not attenuated with depth, so that the
+ // sea bottom is always visible (in reality everything becomes completely dark
+ // at a few dozens meters below the surface).
+ texColor.rgb *= 0.66 * max(vout_viewPosAndNormalDotSun.w, 0.33);
+ float fogDistSq = dot(vout_viewPosAndNormalDotSun.xyz,
+ vout_viewPosAndNormalDotSun.xyz);
+ float fogFactor = exp(-2.0 * sunsetAmbientAndFogDensity.w * sqrt(fogDistSq));
+ return vec4(mix(fogColor.rgb, texColor.rgb, fogFactor), texColor.a);
+}
+
+void ImprovedAtmosphereGroundSunOnFragShader() {
+#if defined(OVERLAY)
+ // Get the texture color for the object. The projective component is to
+ // allow us to do Arbitrary Ground Overlays.
+ // If texturing is off, use white as diffuse color. Otherwise use color
+ // from texture.
+ lowp vec4 texColor = (ig_env_atmosphere_custom_state_value.y == 0.0) ?
+ vec4(1.0) : texture2DProj(groundTexture, vout_texCoordAndFogFactor.xyz);
+ // Perform texture edge clamping for ground overlays by setting alpha to zero
+ // outside of texture coordinate range [0, 1]
+ vec2 stOverZ = vout_texCoordAndFogFactor.xy / vout_texCoordAndFogFactor.z;
+ texColor.a = GetMaskedOverlayAlpha(texColor.a, stOverZ);
+#else
+ // If texturing is off, use white as diffuse color. Otherwise use color
+ // from texture.
+ vec4 texColor;
+ if (ig_env_atmosphere_custom_state_value.y != 0.0) {
+ texColor = texture2D(groundTexture, vout_texCoordAndFogFactor.st);
+ #if defined(MORPH_VERTICES)
+ float blend_param = blendUnpopPixelParams[0];
+ if (blend_param != 0.) {
+ // We are blending between 2 textures.
+ vec4 blendBlendColor = texture2D(blendTexture, vout_blendTexCoord.st);
+ // Compute final pixel color, blend between texture 1 and texture 2
+ texColor = mix(texColor, blendBlendColor, blend_param);
+ }
+ #endif // defined(MORPH_VERTICES)
+ } else {
+ texColor = vec4(1.0);
+ }
+#endif
+
+ vec4 color;
+ // TODO(ebruneton): water level may not always be exactly at r=1,
+ // how can we detect that?
+ if (cameraAndSunState.x < 1.0) {
+ color = ImprovedAtmosphereGroundSunOnBelowWater(texColor);
+ } else {
+ color = ImprovedAtmosphereGroundSunOnAboveWater(texColor);
+ }
+ #if defined(MORPH_VERTICES)
+ float unpop_alpha = blendUnpopPixelParams[1];
+ color.a *= unpop_alpha;
+ #endif // defined(MORPH_VERTICES)
+ gl_FragColor = computeDebugPixelColor(color);
+}
+#endif // defined(ATMOSPHERE_ON) && defined(GROUND) && defined(SUN_ON) && defined(USE_IMPROVED_SHADER_VARIATION)
+
+//", '=' <repeats 32 times>, " sky sun off", '=' <repeats 26 times>, "
+#if defined(ATMOSPHERE_ON) && defined(SKY) && defined(SUN_OFF)
+varying vec4 vout_rayleighT;
+uniform vec4 skySunOffPixelParams;
+uniform lowp sampler2D skyMap;
+
+void AtmosphereSkySunOffFragShader() {
+ // The rayleigh map's s-coordinate depends on camera height and is computed
+ // on the CPU.
+ float rayleighS = skySunOffPixelParams.x;
+ lowp vec4 color = texture2D(skyMap, vec2(rayleighS, vout_rayleighT.x));
+ gl_FragColor = color;
+}
+#endif // defined(ATMOSPHERE_ON) && defined(SKY) && defined(SUN_OFF)
+
+//", '=' <repeats 32 times>, " sky sun on (default)", '=' <repeats 22 times>, "
+#if defined(ATMOSPHERE_ON) && defined(SKY) && defined(SUN_ON) && !defined(USE_IMPROVED_SHADER_VARIATION)
+varying vec4 vout_rayleighColorAndSkyOpacity;
+varying vec4 vout_vertToCameraDir;
+// The direction vector to the light source in View coordinate system.
+uniform vec4 cameraToSunDirAndExposure;
+// xyz: Attribute for Mie color corresponding to the brightest spot in the
+// sky (i.e. usually the sun's front color during the day, and black
+// during the night).
+// This is computed on the CPU in double floating precision to avoid
+// precision problems on the GPU.
+// w: Sun strength: [0, 1] where 0 = no sun, 1 = full strength.
+uniform vec4 brightestMieColorAndSunStrength;
+
+// Calculates the Rayleigh phase function.
+float getRayleighPhase(float cosAngle2) {
+ return 0.75 + 0.75 * cosAngle2;
+}
+
+// Calculates the Mie phase function.
+float getMiePhase(float cosAngle, float cosAngle2) {
+ return 1.5 * ((1.0 - gMieConst2) / (2.0 + gMieConst2)) * (1.0 + cosAngle2) /
+ pow(1.0 + gMieConst2 - 2.0 * gMieConst * cosAngle, 1.5);
+}
+
+// Returns the luminance of an RGB color.
+float getLuminance(vec3 color) {
+ const vec3 luminance = vec3(0.3, 0.59, 0.11);
+ return dot(luminance, color);
+}
+
+void AtmosphereSkySunOnFragShader() {
+ // Variables needed to compute Rayleigh and Mie phases.
+ float cosAngle = dot(cameraToSunDirAndExposure.xyz,
+ vout_vertToCameraDir.xyz) / length(vout_vertToCameraDir.xyz);
+ // Tweak cosAngle by sunStrength. This dims the sun strength for lower
+ // values of sunStrength.
+ cosAngle *= brightestMieColorAndSunStrength.w;
+ float cosAngle2 = cosAngle * cosAngle;
+ // Compute final color using Rayleigh and Mie phases.
+ // The alpha component gets overwritten later.
+ vec4 color;
+ color.rgb = getRayleighPhase(cosAngle2) * vout_rayleighColorAndSkyOpacity.rgb +
+ getMiePhase(cosAngle, cosAngle2) * brightestMieColorAndSunStrength.rgb;
+ // Tone HDR using constant exposure for the whole scene.
+ color.rgb = vec3(1.0) - exp(color.rgb * -cameraToSunDirAndExposure.w);
+ // Use color's luminance to compute its opacity.
+ float luminanceAlphaComponent = 2.0 * getLuminance(color.rgb);
+ color.a = luminanceAlphaComponent + vout_rayleighColorAndSkyOpacity.a;
+ gl_FragColor = color;
+}
+#endif // defined(ATMOSPHERE_ON) && defined(SKY) && defined(SUN_ON) && !defined(USE_IMPROVED_SHADER_VARIATION)
+
+//", '=' <repeats 32 times>, " sky sun on (improved)", '=' <repeats 22 times>, "
+#if defined(ATMOSPHERE_ON) && defined(SKY) && defined(SUN_ON) && defined(USE_IMPROVED_SHADER_VARIATION)
+
+// The radius of the atmosphere mesh, divided by the Earth radius.
+const float kAtmosphereMeshRadius = (6378.0 + 170.0) / 6378.0;
+
+uniform vec3 worldOriginInView;
+// The direction vector to the light source.
+uniform vec4 cameraToSunDirAndExposure;
+
+varying vec3 vout_viewPos; // Vertex position in view coordinates.
+varying vec3 vout_sunPos; // Vertex position in Sun coordinates.
+
+// Implements the abstract function defined in atmosphere.glsllib.
+float atmosphereTweak(float r, float mu) {
+ return atmosphereTweaks.x;
+}
+
+// Computes the final pixel color and alpha value from its radiance. The color
+// is computed with a tone mapping operator to map the high dynamic range of the
+// radiance values to the low dynamic range of the screen. The alpha value is
+// used to approximate the correct compositing, which should in theory occur
+// before tone mapping, and not after as we do for stars (see below). This alpha
+// value is computed with an adhoc formula so that stars only appear in the very
+// dark areas of the sky (i.e at night).
+vec4 fragColor(vec3 pixelL) {
+ pixelL = toneMapping(pixelL, atmosphereTweaks.w);
+ return vec4(pixelL, dot(pixelL, vec3(2.0)));
+}
+
+void ImprovedAtmosphereSkySunOnFragShader() {
+ // Computes the view ray direction in view and Sun coordinates.
+ vec3 viewViewRayDir = normalize(vout_viewPos);
+ vec3 sunViewRayDir = normalize(vout_sunPos);
+
+ // Computes the radiance of the background behind the atmosphere. This should
+ // includes the Sun, the Moon and the stars, but here we only take the Sun
+ // into account. The Moon would not be difficult to handle, but rendering the
+ // stars here would require a very high res skymap. Instead, we render them
+ // with points, before rendering the sky, and we approximate the correct
+ // compositing, toneMapping(starL * transmittance + inscatterL), with alpha
+ // blending, i.e. with toneMapping(inscatterL) + (1 - a) * starL. We compute
+ // alpha with an adhoc formula based on toneMapping(inscatterL) -- see the
+ // fragColor function.
+ vec3 backgroundL = outerSunRadiance(sunViewRayDir);
+
+ // Computes the camera to Earth center distance r, the view direction zenith
+ // angle cosinus mu, the Sun zenith angle cosinus muS, and the phase angle
+ // cosinus nu.
+ float r = cameraAndSunState.x;
+ float rMu = -dot(worldOriginInView.xyz, viewViewRayDir);
+ float rMuS = -dot(worldOriginInView.xyz, cameraToSunDirAndExposure.xyz);
+ float nu = dot(viewViewRayDir, cameraToSunDirAndExposure.xyz);
+ bool hitAtmosphere = true;
+
+ // If the camera is outside the atmosphere, moves it to the entry point of the
+ // view ray inside the atmosphere, if it exists (otherwise the view ray does
+ // not traverse the atmosphere, and so we can return the background radiance).
+ if (r > kAtmosphereRadius) {
+ // Computes the distance from the view ray to the Earth center, squared.
+ float hSq = r * r - rMu * rMu;
+ // Computes the distance to the view ray entry point in the atmosphere.
+ float delta = kAtmosphereRadius * kAtmosphereRadius - hSq;
+ float distanceToAtmosphereEntryPoint = -rMu - sqrt(delta);
+ if (delta < 0.0 || distanceToAtmosphereEntryPoint < 0.0) {
+ // The view ray does not hit the atmosphere, return the background color,
+ // i.e the Sun color. In order to avoid discontinuities when switching
+ // from the Sun color computed here, to the Sun color resulting from the
+ // Sun billboard, we use an alpha value going from 1 at kAtmosphereRadius
+ // to 0 at kAtmosphereMeshRadius.
+ const float kAtmosphereRadiusSq = kAtmosphereRadius * kAtmosphereRadius;
+ const float kMeshRadiusSq = kAtmosphereMeshRadius * kAtmosphereMeshRadius;
+ float a = (kMeshRadiusSq - hSq) / (kMeshRadiusSq - kAtmosphereRadiusSq);
+ gl_FragColor = vec4(toneMapping(backgroundL, atmosphereTweaks.w) * a, a);
+ hitAtmosphere = false;
+ } else {
+ // Moves the camera to the view ray entry point inside the atmosphere.
+ r = kAtmosphereRadius;
+ rMu += distanceToAtmosphereEntryPoint;
+ rMuS += distanceToAtmosphereEntryPoint * nu;
+ }
+ }
+
+ if (hitAtmosphere) {
+ // Computes the light which is scattered towards the viewer along the view
+ // ray, and the transmittance of the atmosphere along this ray.
+ vec3 transmittance;
+ vec3 inscatterL = inscatter(r, rMu / r, rMuS / r, nu, atmosphereTweaks.w,
+ transmittance);
+
+ // The pixel radiance is the background radiance, multiplied by the
+ // atmosphere transmittance and augmented by the inscattered light.
+ vec3 pixelL = backgroundL * transmittance + inscatterL;
+
+ gl_FragColor = fragColor(pixelL);
+ }
+}
+#endif // defined(ATMOSPHERE_ON) && defined(SKY) && defined(SUN_ON) && defined(USE_IMPROVED_SHADER_VARIATION)
+
+// ", '=' <repeats 65 times>, "
+#if defined(ATMOSPHERE_OFF) && defined(SUN_OFF)
+varying vec4 vout_groundTexCoord; // Transformed texture coordinate.
+
+void NoAtmosphereSunOffFragShader() {
+ vec4 diffuseColor = texture2D(groundTexture, vout_groundTexCoord.st);
+ gl_FragColor = computeDebugPixelColor(diffuseColor);
+}
+#endif // defined(ATMOSPHERE_OFF) && defined(SUN_OFF)
+
+// ", '=' <repeats 68 times>, "
+#if defined(ATMOSPHERE_OFF) && defined(SUN_ON)
+varying vec4 vout_transformedCoords;
+varying float vout_diffuse_factor;
+
+void NoAtmosphereSunOnFragShader() {
+ // Get the texture color for the object.
+ vec4 diffuseColor = texture2D(groundTexture, vout_transformedCoords.xy);
+ diffuseColor.rgb *= vout_diffuse_factor;
+ gl_FragColor = computeDebugPixelColor(diffuseColor);
+}
+#endif // defined(ATMOSPHERE_OFF) && defined(SUN_ON)
+
+// ", '=' <repeats 67 times>, "
+#if defined(ATMOSPHERE_OFF) && defined(GROUND) && defined(OVERLAY)
+varying vec4 vout_texCoord;
+
+void NoAtmosphereGroundOverlayFragShader() {
+ // Get the texture color for the object. The projective component is to
+ // allow us to do Arbitrary Ground Overlays.
+ vec4 texColor = (texture2DProj(groundTexture, vout_texCoord.xyw)) *
+ groundColor;
+
+ // Compute projected texture coordinates
+ vec2 stOverW = vout_texCoord.xy / vout_texCoord.w;
+ // Zero out alpha outside of texture edges.
+ texColor.a = GetMaskedOverlayAlpha(texColor.a, stOverW);
+ gl_FragColor = computeDebugPixelColor(texColor);
+}
+#endif // defined(ATMOSPHERE_OFF) && defined(GROUND) && defined(OVERLAY)
+
+// ", '=' <repeats 64 times>, "
+// Forward-declare top-level functions. (This may fix some pre-processor issues
+// when loading the shaders on Mali embedded GPUs.)
+void AtmosphereGroundSunOnOverlayFragShader();
+void AtmosphereGroundSunOnFragShader();
+void AtmosphereGroundSunOffOverlayFragShader();
+void AtmosphereGroundSunOffFragShader();
+void AtmosphereSkySunOnFragShader();
+void AtmosphereSkySunOffFragShader();
+void ImprovedAtmosphereGroundSunOnFragShader();
+void ImprovedAtmosphereSkySunOnFragShader();
+void NoAtmosphereSunOnFragShader();
+void NoAtmosphereSunOffFragShader();
+void NoAtmosphereGroundOverlayFragShader();
+
+void main()
+{
+ // All #elif directives have been replaced with #else + nested #if.
+ // Do not use #elif directives in shader files because they cause errors
+ // when loaded on Mali-400 based devices. See bug #6662252.
+#if defined(ATMOSPHERE_ON)
+ #if defined(GROUND)
+ #if defined(SUN_ON)
+ #if defined(OVERLAY)
+ #if defined(USE_IMPROVED_SHADER_VARIATION)
+ ImprovedAtmosphereGroundSunOnFragShader();
+ #else
+ AtmosphereGroundSunOnOverlayFragShader();
+ #endif
+ #else
+ #if defined(USE_IMPROVED_SHADER_VARIATION)
+ ImprovedAtmosphereGroundSunOnFragShader();
+ #else
+ AtmosphereGroundSunOnFragShader();
+ #endif
+ #endif
+ #else
+ #if defined(SUN_OFF)
+ #if defined(OVERLAY)
+ AtmosphereGroundSunOffOverlayFragShader();
+ #else
+ AtmosphereGroundSunOffFragShader();
+ #endif
+ #else
+ #error Invalid shader config 1
+ #endif
+ #endif
+ #if defined(QUADRANT_ALPHAS)
+ gl_FragColor.a *= vout_alpha;
+ #endif
+ #else
+ #if defined(SKY)
+ #if defined(SUN_ON)
+ #if defined(USE_IMPROVED_SHADER_VARIATION)
+ ImprovedAtmosphereSkySunOnFragShader();
+ #else
+ AtmosphereSkySunOnFragShader();
+ #endif
+ #else
+ #if defined(SUN_OFF)
+ AtmosphereSkySunOffFragShader();
+ #else
+ #error Invalid shader config 2
+ #endif
+ #endif
+ #else
+ #if defined(USE_IMPROVED_SHADER_VARIATION)
+ gl_FragColor = computeInscatter(gl_FragCoord.xy, atmosphereTweaks.w);
+ #else
+ #error Invalid shader config 3
+ #endif
+ #endif
+ #endif
+#elif defined(ATMOSPHERE_OFF)
+ #if defined(GROUND) && defined(OVERLAY)
+ NoAtmosphereGroundOverlayFragShader();
+ #else
+ #if defined(SUN_ON)
+ NoAtmosphereSunOnFragShader();
+ #elif defined(SUN_OFF)
+ NoAtmosphereSunOffFragShader();
+ #else
+ #error Invalid shader config 4
+ #endif
+ #endif
+ #if defined(QUADRANT_ALPHAS)
+ gl_FragColor.a *= vout_alpha;
+ #endif
+#else
+ #error Invalid shader config 6
+#endif
+
+ // Added by BrianP
+ gl_FragColor = vec4(0, 1, 0, 0);
+}
+