fragmentShader
fragmentShader: string = `// Exposure correction gives more subtle gradients on the ground.#define CORRECT_EXPOSURE 1#define FADE_DEPTH 1#define NIGHT_LOCAL 1precision highp float;precision highp int;#ifdef CORRECT_COLORuniform vec3 u_hsvCorrection; // Hue, saturation, brightness#endifuniform vec3 u_atmosphereEnv; // Atmosphere inner and outer radius, camera heightuniform vec3 u_eyePositionWorld;uniform vec3 u_lightDirectionWorld;const float g = -0.95;const float g2 = g * g;varying vec3 v_rayleighColor;varying vec3 v_mieColor;varying vec3 v_vertToCamera;varying vec3 v_vertToOrigin;${AtmosphereShaderChunks.atmosphere_fragment_utils}void main(void){float fInnerRadius = u_atmosphereEnv.x;float fOuterRadius = u_atmosphereEnv.y;float fCameraHeight = u_atmosphereEnv.z;#ifdef DYNAMIC_LIGHTvec3 vLightDir = u_lightDirectionWorld;#elsevec3 vLightDir = u_eyePositionWorld;#endifvLightDir = normalize(vLightDir);// GPU gems mix of ground solution, with custom alpha settingsvec3 cRgb = v_mieColor + 0.25 * v_rayleighColor;// Not needed for HDR frame buffer#if !defined(HDR_FRAME_BUFFER) && defined(CORRECT_EXPOSURE)// Interesting results with exposure factor: 2.0, 3.5, 4.0cRgb = correctExposure(cRgb, 3.0);#endif#ifdef CORRECT_COLORcRgb = correctColor(cRgb, u_hsvCorrection);#endif// Base atmosphere opacityfloat fAtmosphereAlpha = 1.0;// Factor based on the distance of camera atmosphere and ground, results are:// 0.0 = camera on the ground surface,// 1.0 = at the outer edge of the atmosphere.float fDepthFactor = clamp((fCameraHeight - fInnerRadius) /(fOuterRadius - fInnerRadius), 0.0, 1.0);#ifdef FADE_DEPTH// Fade alpha based on the distance of camera between atmosphere layers#ifdef FADE_DEPTH_LINEARfAtmosphereAlpha *= fDepthFactor;#elsefAtmosphereAlpha *= pow(fDepthFactor, 1.5);#endif#endif#if defined(FADE_NIGHT) || defined(DARKEN_NIGHT)#ifdef DYNAMIC_LIGHT// Adjust factor based on time of day, results are:// 0.0 = night,// 1.0 = day.#ifdef NIGHT_GLOBAL// Global night fade based on camera and light orientationfloat fNightFactor = clamp(dot(normalize(u_eyePositionWorld), vLightDir), 0.0, 1.0);fNightFactor = pow(fNightFactor, 0.5);#else // NIGHT_LOCALfloat fNightFactor =clamp(dot(v_vertToOrigin, vLightDir) / length(v_vertToOrigin), 0.0, 1.0);fNightFactor = pow(fNightFactor, 0.8);#endif#elsefloat fNightFactor = 1.0;#endif#endif#ifdef FADE_NIGHT// Adjust alpha for night side of the globefAtmosphereAlpha *= fNightFactor;#endif#ifdef DARKEN_NIGHT// Change the brightness depending on night / day side.// NOTE: Darkening should be rather applied in HSV space, without loss on saturation,// but it is much more GPU consuming.const float minBrightness = 0.5;float fDarkenFactor = clamp(fNightFactor, minBrightness, 1.0);cRgb *= fDarkenFactor;#endif#ifdef EXPOSURE_DEPTH// Control exposure depending from ground distancefloat exposureBoost = 3.0 - fDepthFactor;cRgb = correctExposure(cRgb, exposureBoost);#endif// Experimental fading out of focus point - similar to fresnel effect in top view.// This fade is handy to better expose cartographic/map features in screen center.float fFocusFactor = 1.0 - clamp(dot(normalize(v_vertToCamera), v_vertToOrigin), 0.0, 1.0) + 0.1;fFocusFactor = pow(fFocusFactor, 2.5);fAtmosphereAlpha *= fFocusFactor;// Integrate all featuresgl_FragColor = vec4(cRgb, fAtmosphereAlpha);}`
vertexShader
vertexShader: string = `#define IMPROVE_INTERSECT_PRECISION 1#define IMPROVE_DOT_PRECISION 1precision highp float;precision highp int;attribute vec4 position;// Base mandatory uniformsuniform mat4 u_modelViewProjection;uniform vec3 u_eyePositionWorld;uniform vec3 u_lightDirectionWorld;uniform vec3 u_atmosphereEnv; // Atmosphere inner and outer radius, camera heightuniform vec3 u_hsvCorrection;const float Pi = 3.141592653589793;const float Kr = 0.0025;const float Km = 0.0015;const float Kr4PI = Kr * 4.0 * Pi;const float Km4PI = Km * 4.0 * Pi;const float ESun = 25.0; // should be 15.0const float KmESun = Km * ESun;const float KrESun = Kr * ESun;const vec3 InvWavelength = vec3(1.0 / pow(0.650, 4.0), // Red1.0 / pow(0.570, 4.0), // Green1.0 / pow(0.475, 4.0)); // Blueconst int nSamples = 2;const float fSamples = 2.0;varying vec3 v_rayleighColor;varying vec3 v_mieColor;varying vec3 v_vertToCamera;varying vec3 v_vertToOrigin;${AtmosphereShaderChunks.atmosphere_vertex_utils}//// Computes rayleight and mia atmosphere factors for ground.//// Code based on GPU Gems article.//// Author: Sean O'Neil//// Copyright (c) 2004 Sean O'Neil//// https://developer.nvidia.com/gpugems/gpugems2/part-ii-shading-lighting-and-shadows/chapter-16-accurate-atmospheric-scattering//// Further modifications by HERE.//AtmosphereColor computeGroundAtmosphere(vec3 v3Pos, vec3 vLightDir){// Retrieve environment variablesfloat fInnerRadius = u_atmosphereEnv.x;float fOuterRadius = u_atmosphereEnv.y;float fCameraHeight = u_atmosphereEnv.z;// All that may be moved to const or define(s) at further optimizations:float fScale = 1.0 / (fOuterRadius - fInnerRadius);float fScaleOverScaleDepth = fScale / RayleighScaleDepth;float fCameraHeight2 = fCameraHeight * fCameraHeight;float fOuterRadius2 = fOuterRadius * fOuterRadius;// 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 v3Ray = v3Pos - u_eyePositionWorld;float fFar = length(v3Ray);v3Ray /= fFar;#if !defined(IMPROVE_DOT_PRECISION)vec3 v3Dir = normalize(v3Pos);#endif#ifdef CAMERA_IN_SPACE// Calculate first point of camera ray and sphere intersection.float fNear = getNearSphereIntersect(u_eyePositionWorld, v3Ray, fCameraHeight2, fOuterRadius2);// Make far relative to first atmosphere intersection, setting it to// the length of ray passed through atmospherefFar -= fNear;// Compute the ray's starting position within the atmosphere, then// calculate its scattering offsetvec3 v3Start = u_eyePositionWorld + v3Ray * fNear;float fDepth = exp((fInnerRadius - fOuterRadius) / RayleighScaleDepth);#else // CAMERA_IN_ATMOSPHERE// The ray starts already in atmospherevec3 v3Start = u_eyePositionWorld;// Virtually fNear is just at eye position, so ray passing through atmosphere does not shorten// fFar -= 0.0;float fDepth = exp((fInnerRadius - fCameraHeight) / RayleighScaleDepth);#endif#if defined(IMPROVE_DOT_PRECISION)float fCameraAngle = dot(-v3Ray, v3Pos) / length(v3Pos);#elsefloat fCameraAngle = dot(-v3Ray, v3Dir);#endiffloat fCameraScale = scale(fCameraAngle);#ifdef DYNAMIC_LIGHT// When we want the atmosphere to be uniform over the globe so it is set to 1.0.#if defined(IMPROVE_DOT_PRECISION)// The light angle for given light source may be calculated as:// angle = dot(vLightDir, v3Dir) / length(v3Dir);// where v3Dir holds normalized vertex position, but for precision issues we v3Pos (un-normalized)float fLightAngle = dot(vLightDir, v3Pos) / length(v3Pos);#elsefloat fLightAngle = dot(vLightDir, v3Dir);#endif#elsefloat fLightAngle = 1.0;#endiffloat fLightScale = scale(fLightAngle);float fCameraOffset = fDepth * fCameraScale;float fTemp = (fLightScale + fCameraScale);// Initialize the scattering loop variablesfloat fSampleLength = fFar / fSamples;float fScaledLength = fSampleLength * fScale;vec3 v3SampleRay = v3Ray * fSampleLength;vec3 v3SamplePoint = v3Start + v3SampleRay * 0.5;// Now loop through the sample raysvec3 v3BaseColor = vec3(0.0);vec3 v3Attenuate = vec3(0.0);for(int i = 0; i < nSamples; i++){float fHeight = length(v3SamplePoint);float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight));float fScatter = fDepth * fTemp - fCameraOffset;// Compute color factorsv3Attenuate = exp(-fScatter * (InvWavelength * Kr4PI + Km4PI));v3BaseColor += v3Attenuate * (fDepth * fScaledLength);// Move to the next pointv3SamplePoint += v3SampleRay;}AtmosphereColor color;color.mie = v3BaseColor * (InvWavelength * KrESun + KmESun);// Calculate the attenuation factor for the groundcolor.rayleigh = v3Attenuate;return color;}void main(void){#ifdef DYNAMIC_LIGHTvec3 vLightDir = u_lightDirectionWorld;#elsevec3 vLightDir = u_eyePositionWorld;#endifvLightDir = normalize(vLightDir);AtmosphereColor atmColor = computeGroundAtmosphere(position.xyz, vLightDir);v_mieColor = atmColor.mie;v_rayleighColor = atmColor.rayleigh;v_vertToCamera = u_eyePositionWorld - position.xyz;v_vertToOrigin = normalize(position.xyz);gl_Position = u_modelViewProjection * position;}`
uniforms
uniforms: object
bottomColor
bottomColor: Uniform = new THREE.Uniform(new THREE.Color(0xffffff))
exponent
exponent: Uniform = new THREE.Uniform(0.6)
fogColor
fogColor: Uniform = new THREE.Uniform(new THREE.Color(0x0077ff))
fogFar
fogFar: Uniform = new THREE.Uniform(new THREE.Color(0xffffff))
fogNear
fogNear: Uniform = new THREE.Uniform(new THREE.Color(0x0077ff))
offset
offset: Uniform = new THREE.Uniform(33.0)
topColor
topColor: Uniform = new THREE.Uniform(new THREE.Color(0x0077ff))
u_atmosphereEnv
u_atmosphereEnv: Uniform = new THREE.Uniform(new THREE.Vector3(// Maximum inner radiusEQUATORIAL_RADIUS * 1.001,// Maximum outer radiusEQUATORIAL_RADIUS * 1.025,// Camera height0))
u_eyePositionWorld
u_eyePositionWorld: Uniform = new THREE.Uniform(new THREE.Vector3())
u_hsvCorrection
u_hsvCorrection: Uniform = new THREE.Uniform(new THREE.Vector3(0, 0, 0))
u_lightDirectionWorld
u_lightDirectionWorld: Uniform = new THREE.Uniform(new THREE.Vector3(0, 1, 0))
u_modelViewProjection
u_modelViewProjection: Uniform = new THREE.Uniform(new THREE.Matrix4())
@here/harp-materials
Overview
This module is a container for the different Materials used by
harp.gl
based on the definition bythree.js
. A Material describes the appearance of an object.