diff options
-rw-r--r-- | tests/all.tests | 1 | ||||
-rw-r--r-- | tests/spec/arb_es2_compatibility/CMakeLists.gl.txt | 1 | ||||
-rw-r--r-- | tests/spec/arb_es2_compatibility/arb_es2_compatibility-releaseshadercompiler-ge7.c | 126 | ||||
-rw-r--r-- | tests/spec/arb_es2_compatibility/ge7.frag | 710 | ||||
-rw-r--r-- | tests/spec/arb_es2_compatibility/ge7.vert | 814 |
5 files changed, 1652 insertions, 0 deletions
diff --git a/tests/all.tests b/tests/all.tests index 145312c8..fbfc32b6 100644 --- a/tests/all.tests +++ b/tests/all.tests @@ -868,6 +868,7 @@ add_plain_test(arb_es2_compatibility, 'arb_es2_compatibility-getshaderprecisionf add_plain_test(arb_es2_compatibility, 'arb_es2_compatibility-maxvectors') add_plain_test(arb_es2_compatibility, 'arb_es2_compatibility-shadercompiler') add_plain_test(arb_es2_compatibility, 'arb_es2_compatibility-releaseshadercompiler') +add_plain_test(arb_es2_compatibility, 'arb_es2_compatibility-releaseshadercompiler-ge7') add_plain_test(arb_es2_compatibility, 'arb_es2_compatibility-fixed-type') add_plain_test(arb_es2_compatibility, 'fbo-missing-attachment-clear') arb_es2_compatibility['FBO blit to missing attachment (ES2 completeness rules)'] = PlainExecTest(['fbo-missing-attachment-blit', '-auto', 'es2', 'to']) diff --git a/tests/spec/arb_es2_compatibility/CMakeLists.gl.txt b/tests/spec/arb_es2_compatibility/CMakeLists.gl.txt index 99937fa5..fe69ea3a 100644 --- a/tests/spec/arb_es2_compatibility/CMakeLists.gl.txt +++ b/tests/spec/arb_es2_compatibility/CMakeLists.gl.txt @@ -15,6 +15,7 @@ piglit_add_executable (arb_es2_compatibility-depthrangef arb_es2_compatibility-d piglit_add_executable (arb_es2_compatibility-drawbuffers arb_es2_compatibility-drawbuffers.c) piglit_add_executable (arb_es2_compatibility-maxvectors arb_es2_compatibility-maxvectors.c) piglit_add_executable (arb_es2_compatibility-releaseshadercompiler arb_es2_compatibility-releaseshadercompiler.c) +piglit_add_executable (arb_es2_compatibility-releaseshadercompiler-ge7 arb_es2_compatibility-releaseshadercompiler-ge7.c) piglit_add_executable (arb_es2_compatibility-shadercompiler arb_es2_compatibility-shadercompiler.c) piglit_add_executable (arb_es2_compatibility-getshaderprecisionformat arb_es2_compatibility-getshaderprecisionformat.c) piglit_add_executable (arb_es2_compatibility-fixed-type arb_es2_compatibility-fixed-type.c) diff --git a/tests/spec/arb_es2_compatibility/arb_es2_compatibility-releaseshadercompiler-ge7.c b/tests/spec/arb_es2_compatibility/arb_es2_compatibility-releaseshadercompiler-ge7.c new file mode 100644 index 00000000..e713e511 --- /dev/null +++ b/tests/spec/arb_es2_compatibility/arb_es2_compatibility-releaseshadercompiler-ge7.c @@ -0,0 +1,126 @@ +/* + * Copyright © 2010 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt <eric@anholt.net> (original program) + * Brian Paul (this variation on Eric's program) + * + */ + +/** @file arb_es2_compatibility-releasecompiler-ge7.c + * + * This tests glReleaseShaderCompiler() between compilation and linking. + * + * At the time of writing, this causes Mesa to crash with Google Earth + * version 7 because the linker is trying to use data that was + * generated by the compiler but freed by glReleaseShaderCompiler(). + * + * This test passes with NVIDIA's driver. + * + * The vertex/fragment shaders are captured from Google Earth v7. + * Simpler shaders don't always trigger the bug we're testing for. + */ + +#include "piglit-util-gl-common.h" + +PIGLIT_GL_TEST_CONFIG_BEGIN + + config.supports_gl_compat_version = 10; + + config.window_visual = PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_ALPHA | PIGLIT_GL_VISUAL_DOUBLE; + +PIGLIT_GL_TEST_CONFIG_END + +#ifdef GL_ARB_ES2_compatibility + +void +draw(void) +{ + GLuint vs, fs, prog; + + vs = piglit_compile_shader(GL_VERTEX_SHADER, + "spec/arb_es2_compatibility/ge7.vert"); + fs = piglit_compile_shader(GL_FRAGMENT_SHADER, + "spec/arb_es2_compatibility/ge7.frag"); + + /* NOTE: we're calling glReleaseShaderCompiler() between compiling + * and linking. + */ + glReleaseShaderCompiler(); + + prog = piglit_link_simple_program(vs, fs); + piglit_link_check_status(prog); + + glDeleteShader(vs); + glDeleteShader(fs); + + glUseProgram(prog); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glDeleteProgram(prog); +} +#endif + +enum piglit_result +piglit_display(void) +{ +#ifdef GL_ARB_ES2_compatibility + static const float green[] = {0.0, 1.0, 0.0, 0.0}; + GLboolean pass = GL_TRUE; + + glClearColor(0.5, 0.5, 0.5, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + + draw(); + + pass &= piglit_probe_pixel_rgba(piglit_width / 4, piglit_height / 2, + green); + + assert(!glGetError()); + + piglit_present_results(); + + return pass ? PIGLIT_PASS : PIGLIT_FAIL; +#else + return PIGLIT_SKIP; +#endif /* GL_ARB_ES2_compatibility */ +} + +void +piglit_init(int argc, char **argv) +{ +#ifdef GL_ARB_ES2_compatibility + static const float verts[] = { + -1.0, 1.0, 0.0, 1.0, + -1.0, -1.0, 0.0, 1.0, + +0.0, 1.0, 0.0, 1.0, + +0.0, -1.0, 0.0, 1.0, + }; + + piglit_require_gl_version(20); + piglit_require_extension("GL_ARB_ES2_compatibility"); + + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 4, + verts); + glEnableVertexAttribArray(0); +#endif +} 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); +} + diff --git a/tests/spec/arb_es2_compatibility/ge7.vert b/tests/spec/arb_es2_compatibility/ge7.vert new file mode 100644 index 00000000..2fc7a324 --- /dev/null +++ b/tests/spec/arb_es2_compatibility/ge7.vert @@ -0,0 +1,814 @@ +//!GL2 +#define GE_VERTEX_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 +#if defined(PACKED_VERTS) +#define igv_Vertex ig_VertexAttr0 +#define igv_MultiTexCoord0 ig_VertexAttr1 +attribute vec3 igv_Vertex; +attribute vec2 igv_MultiTexCoord0; +#else +#define igv_Vertex ig_Vertex +#define igv_MultiTexCoord0 ig_MultiTexCoord0 +attribute vec4 igv_Vertex; +attribute vec4 igv_MultiTexCoord0; +#endif + +attribute vec3 ig_Normal; +attribute vec4 ig_Color; + +uniform vec3 worldOriginInView; +uniform vec4 dirToCameraAndFogDensity; +uniform vec4 groundSunOffVertexParams; +uniform vec4 projScalingFactor; +uniform vec4 quadrantMask; + +#if defined(SUN_ON) +// The direction vector to the light source. +uniform vec4 cameraToSunDirAndExposure; +// .y has Normalized Camera Dot Light +// .z has Max Camera Angle subtended by planet +// .w has Camera Height * Camera Height +uniform vec4 cameraLightInfo; +// .x has ground shader start depth +// .y has scatter power coefficient +// .z has rayleighToneDown Coefficient +// .w has atmosphere rayleigh opacity alpha +uniform vec4 startupConsts; +// xyz: Extra ambient color that is stronger during sunsets (and sunrises). +// w: density used in fog exp2 function. +uniform vec4 sunsetAmbientAndFogDensity; +#endif + +#if defined(ATMOSPHERE_ON) && defined(GROUND) +// XYZ: The x, y, and w-coordinates of the projective rayleighTure coordinate. +// We use projective rayleighTures for Arbitrary Ground Overlays. +// W: fog_factor between 0 (no fog) and 1 (full fog). +varying vec4 vout_texCoordAndFogFactor; +#endif // defined(ATMOSPHERE_ON) && defined(GROUND) + +#if defined(QUADRANT_ALPHAS) +uniform vec4 quadrantAlphas; // Alpha 0-1 per quadrant. +// TODO(jrohlf): Combine with vec4 if possible. +varying float vout_alpha; // Single alpha for entire tri, 0-1. +#endif + +//", '=' <repeats 22 times>, " Constants ", '=' <repeats 33 times>, " +// The number of sample points taken along the ray. +const int samples = 2; +// Reciprocal of the sun light color. +const vec3 invWavelength = 1.0 / + vec3(0.17850625, 0.10556001, 0.050906640625); +// Altitude of Atmosphere in km +const float atmosphereAltiude = 170.0; +// Radius of planet in km +const float planetRadius = 6378.0; +// Relative Radius of the planet. +const float innerRadius = 1.0; +const float innerRadius2 = innerRadius * innerRadius; +// Radius of the outer atmosphere. +const float outerRadius = innerRadius + (atmosphereAltiude / planetRadius); +const float outerRadius2 = outerRadius * outerRadius; +// Rayleigh scattering constant. +const float kr = 0.0025; +// Brightness of the sun. +const float eSun = 25.0; +// Mie scattering constant. +const float km = 0.001; +// Pi. +const float pi = 3.1415926535897932384626433832795; +// Convenience constants. +const float krESun = kr * eSun; +const float kmESun = km * eSun; +const float kr4Pi = kr * 4.0 * pi; +const float km4Pi = km * 4.0 * pi; + +// The scale depth (the altitude at which the average atmospheric density is +// found). +const float scaleDepth = 0.15; +const float invScaleDepth = 1.0 / scaleDepth; +// Reciprocal of the atmosphere's depth. +const float atmosphereDepthInv = 1.0 / (outerRadius - innerRadius); +const float scaleOverScaleDepth = atmosphereDepthInv / scaleDepth; + +// In Fixed function, we use a trick of Sun's color to be of intensity +// 3.0 to get better correlation between time of day and nDotL. +// Using the same trick in shaders. +const float kSunColor = 3.0; + +// Transparent color used for hiding white seams behind terrain cracks. +// Note: all four components must be 0.0 due to the (more or less) additive +// blending function. +const vec4 kTransparent = vec4(0.0); + +//", '=' <repeats 22 times>, " Functions ", '=' <repeats 30 times>, " +// The scale equation calculated by Vernier's Graphical Analysis. +float scale(float cosAngle) { + float x = 1.0 - cosAngle; + return scaleDepth * + exp(-0.00287 + x * (0.459 + x * (3.83 + x * (-6.80 + x * 5.25)))); +} + +// Returns the near intersection point of a line and a sphere centered around +// the origin. +float getNearIntersection(vec3 vertPos, vec3 rayDir, float distance2, float fRadius2) { + float b = 2.0 * dot(vertPos, rayDir); + float c = distance2 - fRadius2; + float determ = max(0.0, b * b - 4.0 * c); + return 0.5 * (-b - sqrt(determ)); +} + +// Returns the far intersection point of a line and a sphere centered around +// the origin. +float getFarIntersection(vec3 vertPos, vec3 rayDir, float distance2, float fRadius2) { + float b = 2.0 * dot(vertPos, rayDir); + float c = distance2 - fRadius2; + float determ = max(0.0, b * b - 4.0 * c); + return 0.5 * (-b + sqrt(determ)); +} + +// 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); +} + +//", '=' <repeats 30 times>, " ground sun off vertex +#if defined(ATMOSPHERE_ON) && defined(GROUND) && defined(SUN_OFF) + +// Multiplier for rayleigh result; when 0, scattering calculation are omitted +uniform vec4 rayleighAttenuator; + +#if !defined(USE_SIMPLIFIED_SHADER_VARIATION) +// Texcoord for blending between 2 textures on same geometry and rayleighT +// param stuffed in z component. +varying vec4 vout_blendTexCoordAndRayleighT; +#endif + +// Vertex shader program. +void AtmosphereGroundSunOffVertexShader() { + vec4 position = vec4(igv_Vertex.xyz, 1.0); + vec4 texCoord = vec4(igv_MultiTexCoord0.xy, 0.0, 1.0); + +#if !defined(USE_SIMPLIFIED_SHADER_VARIATION) + // We project the vertex direction (from the planet origin) onto the + // camera direction (from the planet origin) to compute the rayleigh + // map's t-coordinate. + vec3 posInView = (ig_ModelViewMatrix * projScalingFactor.x * position).xyz; + vec3 dirToPos = normalize(posInView - worldOriginInView); + vec3 dirToCamera = dirToCameraAndFogDensity.xyz; + float projected_length = dot(dirToCamera, dirToPos); + float rayleighTTranslation = groundSunOffVertexParams.x; + float rayleighTScale = groundSunOffVertexParams.y; + float rayleighT = (projected_length + rayleighTTranslation) * + rayleighTScale; + rayleighT = rayleighT * rayleighAttenuator.x + (1.0 - rayleighAttenuator.x); +#endif + + vec4 vert_pos_clip = ig_ModelViewProjectionMatrix * position; + +#if !defined(USE_SIMPLIFIED_SHADER_VARIATION) + // Compute fog factor. + float fogDensity = dirToCameraAndFogDensity.w; + float fogTemp = fogDensity * vert_pos_clip.z; + float fogFactor = exp(-(fogTemp * fogTemp)); + vout_texCoordAndFogFactor.w = fogFactor; +#endif + + vec4 transformedTexCoord = ig_TextureMatrix * texCoord; + vout_texCoordAndFogFactor.xyz = transformedTexCoord.xyw; +#if !defined(USE_SIMPLIFIED_SHADER_VARIATION) + vout_blendTexCoordAndRayleighT.x = rayleighT; + vout_blendTexCoordAndRayleighT.y = rayleighT; + vout_blendTexCoordAndRayleighT.z = rayleighT; + vout_blendTexCoordAndRayleighT.w = rayleighT; +#endif + + gl_Position = vert_pos_clip; +} +#endif // defined(ATMOSPHERE_ON) && defined(GROUND) && defined(SUN_OFF) + +//", '=' <repeats 33 times>, " Ground sun on + +#if defined(ATMOSPHERE_ON) && defined(GROUND) && defined(SUN_ON) + +// has_lighting tracks the igVisualContext lighting enabled state. +// Diorama buildings that do not have normals have lighting turned off in the +// scene-graph and should do lighting using the vertex normal. +// Detecting 0-length normals in the shader does not appear to +// work for diormam buildings (perhaps because the normal data is garbage, +// instead of being absent like it is in the terrain data). +// TODO(baustin): Remove the has_lighting test once the 0-length check can be +// made to work for diorama buildings. +uniform float has_lighting; + +#if defined(USE_IMPROVED_SHADER_VARIATION) +// Vertex position in view coordinates and dot product between normal and Sun. +varying vec4 vout_viewPosAndNormalDotSun; +#else +// Vertex shader's output. +// RGB: The Rayleigh color. +varying vec3 vout_rayleigh; +// RGB: The adjusted Mie color. +varying vec3 vout_adjustedMie; +#endif + +// Vertex shader program. +void AtmosphereGroundSunOnVertexShader() { + vec4 position = vec4(igv_Vertex.xyz, 1.0); + vec4 texCoord = vec4(igv_MultiTexCoord0.xy, 0.0, 1.0); + vec3 normal = ig_Normal; + + // projScalingFactor is some kind of hack to handle poor precision on + // some platforms, I dunno the details. + mat4 hackedModelView = ig_ModelViewMatrix * projScalingFactor.x; + + highp vec4 posInView = hackedModelView * position; + // Compute vertex's color using its position projected at sea level. + // This avoids artifacts when the vertex is outside the frustum and makes + // it easier to compute the distance to the horizon. + highp vec3 unprojectedVertPos = posInView.xyz - worldOriginInView; + highp vec3 vertNorm = normalize(unprojectedVertPos); + + // If normals are not supplied or lighting is turned off, use sphere normals. + highp vec3 normToUse = vertNorm; + if (has_lighting == 1.0) { + highp float normalLen = dot(normal.xyz, normal.xyz); + // Not sure how fast this if-test is. + // TODO(jrohlf,baustin): See if ? or mix() might be faster (mix() isn't + // working for diorama buildings, possibly because the normals aren't + // normalized. + if (normalLen > 0.0) { + // NOTE: normal xform should use inverse transpose but I don't think we + // have any scales in modelview. + normToUse = (hackedModelView * vec4(normal, 0.0)).xyz; + normToUse = normalize(normToUse); + } + } + + highp float nDotL = dot(normToUse, cameraToSunDirAndExposure.xyz); + +#if !defined(USE_IMPROVED_SHADER_VARIATION) + // Multiply by Sun Color which is really high intensity and saturate + nDotL = saturate(kSunColor * nDotL); + + // Create new coordinate system with the view orientation but world origin. + // All computation is done in this new coordinate system. + highp vec3 cameraPos = -worldOriginInView; + highp float cameraHeight = cameraLightInfo.x; + highp float cameraHeight2 = cameraLightInfo.w; + + // Get the ray from the camera to the vertex and its length. + highp vec3 rayDir = unprojectedVertPos - cameraPos; + highp float farDist = length(rayDir); + rayDir /= farDist; + + highp vec3 startPos = cameraPos; + // Initial scattering offset. + highp float startDepth = startupConsts.x; + // We use power function to create gradient for limiting rayleigh + // affect closer horizon. Lower the exponent, more scattering we + // get all over planet. To get scattering glow on planet when viewed + // from distance, horizonExp depends on altitude. + highp float horizonExp = startupConsts.y; + // Since we have not using exposure function in fragment shader for + // ground, rayleigh component adds to the existing color and the result + // tends to saturate much too soon. Hence we add a tonedown scale which + // is function of altitude and proximity to horizon. + highp float rayleighToneDownScale = startupConsts.z; + + // Calculate where our ray hits the atmosphere to find the point where + // we start accumulating its color. + // TODO(quarup): Get rid of this conditional. + if (cameraHeight >= outerRadius) { + // Camera is outside the atmosphere. + // Calculate the closest intersection of the ray with the outer atmosphere + // (which is the near point of the ray passing through the atmosphere). + highp float nearDist = getNearIntersection(cameraPos, rayDir, cameraHeight2, outerRadius2); + // Ray's start position within the atmosphere. + startPos += rayDir * nearDist; + // Ray's distance within the atmosphere. + farDist -= nearDist; + } + + // Initialize constants needed for the scattering equations. + // vertNorm is normalized + highp float cameraAngle = max(0.0, dot(-rayDir, vertNorm)); + highp float lightAngle = dot(cameraToSunDirAndExposure.xyz, vertNorm); + highp float cameraScale = scale(cameraAngle); + highp float lightScale = scale(lightAngle); + highp float cameraOffset = startDepth * cameraScale; + highp float scaleSum = lightScale + cameraScale; + + // Initialize the scattering loop variables. + highp float sampleLength = farDist / float(samples); + highp float scaledLength = sampleLength * atmosphereDepthInv; + highp vec3 sampleRay = rayDir * sampleLength; + highp vec3 samplePoint = startPos + sampleRay * 0.5; + + // Now loop through sample points on the ray and accumulate the color + // using the scattering equations (including surface-scattering). + highp vec3 frontColor = vec3(0.0, 0.0, 0.0); + highp vec3 attenuate; + for(int i = 0; i < samples; i++) { + highp float sampleHeight = length(samplePoint); + highp float sampleDepth = + exp(scaleOverScaleDepth * (innerRadius - sampleHeight)); + highp float sampleScatter = sampleDepth * scaleSum - cameraOffset; + attenuate = exp(-sampleScatter * (invWavelength * kr4Pi + km4Pi)); + frontColor += attenuate * (sampleDepth * scaledLength); + samplePoint += sampleRay; + } + + // Compute how \"close\" the vertex is to the horizon. Vertices close + // to the horizon correspond to one, and vertices under the camera + // correspond to zero. + highp float closeToHorizon = 1.0 - cameraAngle; + highp float closeToCamera = 1.0 - closeToHorizon*closeToHorizon; + // Compute rayleigh scale factor. Higher closer to horizon and + // at higher altitudes. + highp float scaledRayleighFactor = rayleighToneDownScale * pow(closeToHorizon, horizonExp); + + // Base ambient color for dark shaded ground objects. + highp vec3 kBaseAmbientColor = vec3(0.12, 0.12, 0.15); + // Add ambient light to geometry with low N.L shading. This allows the + // user to always see the dark areas of mountains, buildings, etc. + highp float darkShadedAmbientFactor = 1.0 - nDotL; + // Compute night ambient color factor so that it is strongest at night + // (i.e. low attenuate luminance) and weakest during the day + // (i.e. high attenuate luminance). This allows the user to always see + // ground objects at night. + highp float nightAmbientTemp = getLuminance(attenuate); + highp float nightAmbientFactor = 1.0 - nightAmbientTemp * nightAmbientTemp; + // Compute ambient contribution. Make ambient light stronger + // for nearby vertices, which creates a \"head lamp\" effect. + highp float ambientFactor = + closeToCamera * (darkShadedAmbientFactor + nightAmbientFactor); + highp vec3 headlampAmbientContribution = kBaseAmbientColor * ambientFactor; + // The extra sunset ambient contribution keeps the planet from looking too + // dark during sunset and sunrise. + highp vec3 sunsetAmbient = sunsetAmbientAndFogDensity.xyz; + highp vec3 ambientContribution = headlampAmbientContribution + sunsetAmbient; + + // Compute how close to noon it is. + highp float closeToNoon = cameraLightInfo.y; + // When it is close to noon, add light close to the camera in order + // to show full contrast of the textures near the user. + highp float closeToNoonFactor = closeToCamera * closeToNoon; + + // Compute fog factor. + highp float fogDensity = sunsetAmbientAndFogDensity.w; + highp float fogTemp = fogDensity * farDist; + highp float fogFactor = exp(-(fogTemp * fogTemp)); +#endif + + // Transform vertex position. + gl_Position = ig_ModelViewProjectionMatrix * position; +#if defined(USE_IMPROVED_SHADER_VARIATION) + vout_viewPosAndNormalDotSun = vec4(posInView.xyz, nDotL); + float fogFactor = 0.0; +#else + // Compute Rayleigh color and make it strongest at the horizon. + const vec3 kMaxRayleighContribution = vec3(0.5, 0.5, 0.8); + vout_rayleigh.rgb = min(kMaxRayleighContribution, + frontColor * (invWavelength * krESun + kmESun) * scaledRayleighFactor); + // Compute Mie color. + highp vec3 mieColor = attenuate; + highp vec3 adjustedMieColor = saturate( + (mieColor + vec3(closeToNoonFactor)) * nDotL + ambientContribution); + vout_adjustedMie.rgb = adjustedMieColor; +#endif + // Set transformed texture coordinates. + highp vec4 transformedTexCoord = ig_TextureMatrix * texCoord; + vout_texCoordAndFogFactor.xyz = transformedTexCoord.xyw; + vout_texCoordAndFogFactor.w = fogFactor; +} +#endif // defined(ATMOSPHERE_ON) && defined(GROUND) && defined(SUN_ON) + +//", '=' <repeats 38 times>, " sky sun off + +#if defined(ATMOSPHERE_ON) && defined(SKY) && defined(SUN_OFF) + +uniform vec4 skySunOffVertexParams; + +// X: Rayleigh map's t-coordinate. +varying vec4 vout_rayleighT; + +// Vertex shader program. +void AtmosphereSkySunOffVertexShader() { + vec4 position = vec4(igv_Vertex.xyz, 1.0); + + // From the position's Y-coordinate (in atmosphere space), we can + // compute its rayleigh color from the rayleigh map. + float rayleighTTranslation = skySunOffVertexParams.x; + float rayleighTScale = skySunOffVertexParams.y; + // Look-up's t-coordinate. + float rayleighT = (position.y + rayleighTTranslation) * rayleighTScale; + gl_Position = ig_ModelViewProjectionMatrix * position; + + // Clamp vertex depth to the far plane. This forces the sky to always + // be drawn even if the far plane is closer than the outer atmosphere. + // Some drivers have problems when z == w, so ensure z is strictly smaller. + gl_Position.z = min(gl_Position.z, gl_Position.w * 0.99999); + + vout_rayleighT = vec4(rayleighT); +} +#endif // defined(ATMOSPHERE_ON) && defined(SKY) && defined(SUN_OFF) + +//", '=' <repeats 39 times>, " sky sun on +#if defined(ATMOSPHERE_ON) && defined(SKY) && defined(SUN_ON) + +#if defined(USE_IMPROVED_SHADER_VARIATION) +// Transformation from view to Sun coordinates. This coordinate system is +// centered on the Earth and its z axis points towards the Sun. +uniform mat4 viewToSun; + +varying vec3 vout_viewPos; // Vertex position in view coordinates. +varying vec3 vout_sunPos; // Vertex position in Sun coordinates. +#else +varying vec4 vout_rayleighColorAndSkyOpacity; // The Rayleigh color +varying vec4 vout_vertToCameraDir; // Dir from ray to camera. +#endif + +// Vertex shader program. +void AtmosphereSkySunOnVertexShader() { + + vec4 position = vec4(igv_Vertex.xyz, 1.0); + // projScalingFactor is some kind of hack to handle poor precision on + // some platforms, I dunno the details. + mat4 hackedModelView = ig_ModelViewMatrix * projScalingFactor.x; + +#if !defined(USE_IMPROVED_SHADER_VARIATION) + // Make up a new coordinate system with the view orientation but world origin. + // All computation is done in this new coordinate system. + vec3 cameraPos = -worldOriginInView; + float cameraHeight = cameraLightInfo.x; + float cameraHeightInv = 1.0 / cameraHeight; + float cameraHeight2 = cameraLightInfo.w; + vec4 posInView = hackedModelView * position; + vec3 vertPos = posInView.xyz - worldOriginInView; + + // Get the ray from the camera to the vertex and its length (which is the + // far point of the ray passing through the atmosphere). + vec3 rayDir = vertPos - cameraPos; + float farDist = length(rayDir); + rayDir /= farDist; + + vec3 startPos; + float startAngle; + float startOffset; + // Calculate where our ray hits the atmosphere to find the point where + // we start accumulating its color. + // TODO(quarup): Get rid of this conditional. + if (cameraHeight < outerRadius) { + // If we're inside the atmosphere, then start accumulating from the + // camera position. + startPos = cameraPos; + // Initial scattering constants. + float startDepth = exp(scaleOverScaleDepth * (innerRadius - cameraHeight)); + startAngle = dot(rayDir, startPos) * cameraHeightInv; + startOffset = startDepth * scale(startAngle); + } else { + // Camera is outside the atmosphere. + // Calculate the closest intersection of the ray with the outer atmosphere + // (which is the near point of the ray passing through the atmosphere). + float nearDist = getNearIntersection(cameraPos, rayDir, cameraHeight2, outerRadius2); + // Ray's start position within the atmosphere. + startPos = cameraPos + rayDir * nearDist; + // Ray's distance within the atmosphere. + farDist -= nearDist; + // Initial scattering constants. + startAngle = dot(rayDir, startPos) / outerRadius; + float startDepth = exp(-invScaleDepth); + startOffset = startDepth * scale(startAngle); + } + + // Initialize the scattering loop variables. + float sampleLength = farDist / float(samples); + float scaledLength = sampleLength * atmosphereDepthInv; + vec3 sampleRay = rayDir * sampleLength; + vec3 samplePoint = startPos + sampleRay * 0.5; + + // Now loop through sample points on the ray and accumulate the color + // using the scattering equations. + vec3 frontColor = vec3(0.0, 0.0, 0.0); + vec3 attenuate; + for(int i = 0; i < samples; i++) { + // TODO(quarup): Simplify this. + float sampleHeight = length(samplePoint); + float sampleDepth = exp(scaleOverScaleDepth * (innerRadius - sampleHeight)); + float lightAngle = dot(cameraToSunDirAndExposure.xyz, samplePoint), sampleHeight; + float cameraAngle = dot(rayDir, samplePoint) / sampleHeight; + float sampleScatter = + (startOffset + sampleDepth*(scale(lightAngle) - scale(cameraAngle))); + attenuate = exp(-sampleScatter * (invWavelength * kr4Pi + km4Pi)); + frontColor += attenuate * (sampleDepth * scaledLength); + samplePoint += sampleRay; + } +#endif + + // Finally, scale the Mie and Rayleigh colors and set up the varying + // variables for the pixel shader. + gl_Position = ig_ModelViewProjectionMatrix * position; + + // Clamp vertex depth to the far plane. This forces the sky to always + // be drawn even if the far plane is closer than the outer atmosphere. + // Some drivers have problems when z == w, so ensure z is strictly smaller. + gl_Position.z = min(gl_Position.z, gl_Position.w * 0.99999); + +#if defined(USE_IMPROVED_SHADER_VARIATION) + vout_viewPos = (hackedModelView * position).xyz; + vout_sunPos = (viewToSun * vec4(vout_viewPos, 0.0)).xyz; +#else + // Handle White Seams here. + // Idea is that we make the part of sphere occluded by planet transparent. + // Therefore terrain cracks show the color buffer's clear color instead. + // (Note: opaque colors (instead of transparent) are distorted by the HDR + // tonemap computation and the (more or less) additive blending function.) + // cosAngleByPlanet: cosine of angle subtended by planet at camera + // cosVertAngle : cosine of angle subtended by current vertex at camera + float cosAngleByPlanet = cameraLightInfo.z; + float cosVertAngle = -dot(rayDir, cameraPos) * cameraHeightInv; + vec4 computedRayleighColorAndSkyOpacity = + vec4(frontColor * (invWavelength * krESun), startupConsts.w); + vout_rayleighColorAndSkyOpacity = cosVertAngle > cosAngleByPlanet ? + kTransparent : computedRayleighColorAndSkyOpacity; + vout_vertToCameraDir.xyz = cameraPos - vertPos; + // Fix for a driver bug on ATI Mobility FireGL V3200 (Driver 8.362.0.0) + // for OpenGL mode. + // Problem: The textures looked distorted. + // Reason: Two sets of shaders (atmosphere_ground and atomsphere_model_space) + // used different length of TEXCOORD1 with my last change. With this + // change, TEXCOORD1.w in atmosphere_groud fragment shader was getting + // 0 irrespective of whatever value you set in vertexshader. It seems + // that some validation for length of texture coordinates was missing + // in driver when fragment programs were switched. + // Workaround: Add TEXCOORD1.w back in all shaders. Avoid any computation by + //", ' ' <repeats 13 times>, "just setting it to 1.0 + vout_vertToCameraDir.w = 1.0; +#endif +} +#endif // defined(ATMOSPHERE_ON) && defined(SKY) && defined(SUN_ON) + +// ", '=' <repeats 74 times>, " +#if defined(ATMOSPHERE_ON) + #if defined(GROUND) + void AtmosphereGroundVertexShader() { + #if defined(SUN_ON) + AtmosphereGroundSunOnVertexShader(); + #elif defined(SUN_OFF) + AtmosphereGroundSunOffVertexShader(); + #else + #error Invalid shader config 1 + #endif + #if defined(ENABLE_VERTEX_REJECT) + gl_Position = getMaskedVertex(gl_Position, quadrantMask, ig_Color); + #endif + #if defined(DEBUG_QUADRANT_COLORS) + vout_debug_color = getDebugVertexColor(quadrantMask, ig_Color); + #endif + #if defined(QUADRANT_ALPHAS) + vout_alpha = getMaskedAlpha(quadrantAlphas, ig_Color); + #endif + } + #elif defined(SKY) + void AtmosphereSkyVertexShader() { + #if defined(SUN_ON) + AtmosphereSkySunOnVertexShader(); + #elif defined(SUN_OFF) + AtmosphereSkySunOffVertexShader(); + #else + #error Invalid shader config 2 + #endif + } + #elif defined(USE_IMPROVED_SHADER_VARIATION) + void AtmosphereLookupTableShader() { + gl_Position = vec4(igv_Vertex.xy, 0.0, 1.0); + } + #endif +#endif // ATMOSPHERE_ON + + +#if defined(ATMOSPHERE_OFF) +//", '=' <repeats 35 times>, " Sun off +#if defined(SUN_OFF) +varying vec4 vout_groundTexCoord; // Transformed texture coordinate. + +// Vertex shader program. +void NoAtmosphereSunOffVertexShader() { + vec4 position = vec4(igv_Vertex.xyz, 1.0); + vec4 groundTexCoord = vec4(igv_MultiTexCoord0.xy, 0.0, 1.0); + + // Transform coordinate and texture coordinates. + gl_Position = ig_ModelViewProjectionMatrix * position; + vout_groundTexCoord = ig_TextureMatrix * groundTexCoord; +} +#endif // SUNOFF + +//", '=' <repeats 35 times>, " Sun on +#if defined(SUN_ON) +// xy: base texture coordinates. +// zw: blend texture coordinates. +varying vec4 vout_transformedCoords; // Transformed texture coordinate. +// x: diffuse factor that contains N.L and ambient contribution. +varying float vout_diffuse_factor; + +// Vertex shader program. +void NoAtmosphereSunOnVertexShader() { + vec4 position = vec4(igv_Vertex.xyz, 1.0); + vec4 groundTexCoord = vec4(igv_MultiTexCoord0.xy, 0.0, 1.0); + vec3 normal = ig_Normal; + + // normalLen should be 0 if normals not supplied or 1 if supplied - assumes + // normals are normalized. This allows us to use multiplies instead + // of slow if or ?. TODO(jrohlf): See if ? might be faster. + highp float normalLen = dot(normal.xyz, normal.xyz); + // If normals not supplied use sphere normals. + // NOTE: normal xform should use inverse transpose but I don't think we + // have any scales in modelview. + highp vec3 normToUse = mix( + (ig_ModelViewMatrix * position).xyz - worldOriginInView, + (ig_ModelViewMatrix * vec4(normal, 0.)).xyz, + normalLen); + normToUse = normalize(normToUse); + highp float nDotL = dot(normToUse, cameraToSunDirAndExposure.xyz); + // When atmosphere shaders are off, the ambient contribution comes in + // the \"exposure\" variable. + float ambient_light = cameraToSunDirAndExposure.w; + // Transform coordinate and texture coordinates. + gl_Position = ig_ModelViewProjectionMatrix * position; + vout_transformedCoords.xy = (ig_TextureMatrix * groundTexCoord).xy; + vout_transformedCoords.zw = vec2(0.0, 0.0); + vout_diffuse_factor = min(1.0, ambient_light + max(0.0, nDotL)); +} +#endif // SUN_ON + +//", '=' <repeats 26 times>, " Ground overlay no atmosphere +#if defined(GROUND) && defined(OVERLAY) +varying vec4 vout_texCoord; +void NoAtmosphereGroundOverlayVertexShader() { + vec4 position = vec4(igv_Vertex.xyz, 1.0); + vec4 texCoord = vec4(igv_MultiTexCoord0.xy, 0.0, 1.0); + + // Very simple pixel shader, handles modelview/projection matrix and + // texture matrix just like fixed function, but when specifying a pixel + // shader, we must have a vertex shader. + gl_Position = ig_ModelViewProjectionMatrix * position; + vout_texCoord = ig_TextureMatrix * texCoord; +} +#endif // GROUND AND OVERLAY +#endif // ATMOSPHERE_OFF + +// ", '=' <repeats 74 times>, " +void main() { +#if defined(ATMOSPHERE_ON) + #if defined(GROUND) + AtmosphereGroundVertexShader(); + #elif defined(SKY) + AtmosphereSkyVertexShader(); + #elif defined(USE_IMPROVED_SHADER_VARIATION) + AtmosphereLookupTableShader(); + #else + #error Invalid shader config 3 + #endif +#elif defined(ATMOSPHERE_OFF) + #if defined(GROUND) && defined(OVERLAY) + NoAtmosphereGroundOverlayVertexShader(); + #else + #if defined(SUN_ON) + NoAtmosphereSunOnVertexShader(); + #elif defined(SUN_OFF) + NoAtmosphereSunOffVertexShader(); + #else + #error Invalid shader config 4 + #endif + #endif + #if defined(ENABLE_VERTEX_REJECT) + gl_Position = + getMaskedVertex(gl_Position, quadrantMask, ig_Color); + #endif + #if defined(DEBUG_QUADRANT_COLORS) + vout_debug_color = getDebugVertexColor(quadrantMask, ig_Color); + #endif + #if defined(QUADRANT_ALPHAS) + vout_alpha = getMaskedAlpha(quadrantAlphas, ig_Color); + #endif +#else + #error Invalid shader config 6 +#endif + + // Added by BrianP: + gl_Position = gl_Vertex; +} + |