Three.js standard materials vertex and fragment shaders reference

When playing around and experimenting with Three.js ShaderMaterial I often want to take a look at how the standard Three.js materials are done. Looking through the code or constantly outputting the shaders in the javascript console is a pain in the arse. I though I would post them here for future reference and in case anyone else was interested. These were output from Three.js version 70.

MeshBasicMaterial

Vertex Shader

#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP )

varying vec2 vUv;
uniform vec4 offsetRepeat;

#endif

#ifdef USE_LIGHTMAP

varying vec2 vUv2;

#endif
#if defined( USE_ENVMAP ) && ! defined( USE_BUMPMAP ) && ! defined( USE_NORMALMAP ) && ! defined( PHONG )

varying vec3 vReflect;

uniform float refractionRatio;

#endif

#ifdef USE_COLOR

varying vec3 vColor;

#endif
#ifdef USE_MORPHTARGETS

#ifndef USE_MORPHNORMALS

uniform float morphTargetInfluences[ 8 ];

#else

uniform float morphTargetInfluences[ 4 ];

#endif

#endif
#ifdef USE_SKINNING

uniform mat4 bindMatrix;
uniform mat4 bindMatrixInverse;

#ifdef BONE_TEXTURE

uniform sampler2D boneTexture;
uniform int boneTextureWidth;
uniform int boneTextureHeight;

mat4 getBoneMatrix( const in float i ) {

float j = i * 4.0;
float x = mod( j, float( boneTextureWidth ) );
float y = floor( j / float( boneTextureWidth ) );

float dx = 1.0 / float( boneTextureWidth );
float dy = 1.0 / float( boneTextureHeight );

y = dy * ( y + 0.5 );

vec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );
vec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );
vec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );
vec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );

mat4 bone = mat4( v1, v2, v3, v4 );

return bone;

}

#else

uniform mat4 boneGlobalMatrices[ MAX_BONES ];

mat4 getBoneMatrix( const in float i ) {

mat4 bone = boneGlobalMatrices[ int(i) ];
return bone;

}

#endif

#endif

#ifdef USE_SHADOWMAP

varying vec4 vShadowCoord[ MAX_SHADOWS ];
uniform mat4 shadowMatrix[ MAX_SHADOWS ];

#endif
#ifdef USE_LOGDEPTHBUF

#ifdef USE_LOGDEPTHBUF_EXT

varying float vFragDepth;

#endif

uniform float logDepthBufFC;

#endif
void main() {
#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP )

vUv = uv * offsetRepeat.zw + offsetRepeat.xy;

#endif
#ifdef USE_LIGHTMAP

vUv2 = uv2;

#endif
#ifdef USE_COLOR

#ifdef GAMMA_INPUT

vColor = color * color;

#else

vColor = color;

#endif

#endif
#ifdef USE_SKINNING

mat4 boneMatX = getBoneMatrix( skinIndex.x );
mat4 boneMatY = getBoneMatrix( skinIndex.y );
mat4 boneMatZ = getBoneMatrix( skinIndex.z );
mat4 boneMatW = getBoneMatrix( skinIndex.w );

#endif
#ifdef USE_ENVMAP
#ifdef USE_MORPHNORMALS

vec3 morphedNormal = vec3( 0.0 );

morphedNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];
morphedNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];
morphedNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];
morphedNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];

morphedNormal += normal;

#endif
#ifdef USE_SKINNING

mat4 skinMatrix = mat4( 0.0 );
skinMatrix += skinWeight.x * boneMatX;
skinMatrix += skinWeight.y * boneMatY;
skinMatrix += skinWeight.z * boneMatZ;
skinMatrix += skinWeight.w * boneMatW;
skinMatrix  = bindMatrixInverse * skinMatrix * bindMatrix;

#ifdef USE_MORPHNORMALS

vec4 skinnedNormal = skinMatrix * vec4( morphedNormal, 0.0 );

#else

vec4 skinnedNormal = skinMatrix * vec4( normal, 0.0 );

#endif

#endif

#ifdef USE_SKINNING

vec3 objectNormal = skinnedNormal.xyz;

#elif defined( USE_MORPHNORMALS )

vec3 objectNormal = morphedNormal;

#else

vec3 objectNormal = normal;

#endif

#ifdef FLIP_SIDED

objectNormal = -objectNormal;

#endif

vec3 transformedNormal = normalMatrix * objectNormal;

#endif
#ifdef USE_MORPHTARGETS

vec3 morphed = vec3( 0.0 );
morphed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];
morphed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];
morphed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];
morphed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];

#ifndef USE_MORPHNORMALS

morphed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];
morphed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];
morphed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];
morphed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];

#endif

morphed += position;

#endif
#ifdef USE_SKINNING

#ifdef USE_MORPHTARGETS

vec4 skinVertex = bindMatrix * vec4( morphed, 1.0 );

#else

vec4 skinVertex = bindMatrix * vec4( position, 1.0 );

#endif

vec4 skinned = vec4( 0.0 );
skinned += boneMatX * skinVertex * skinWeight.x;
skinned += boneMatY * skinVertex * skinWeight.y;
skinned += boneMatZ * skinVertex * skinWeight.z;
skinned += boneMatW * skinVertex * skinWeight.w;
skinned  = bindMatrixInverse * skinned;

#endif

#ifdef USE_SKINNING

vec4 mvPosition = modelViewMatrix * skinned;

#elif defined( USE_MORPHTARGETS )

vec4 mvPosition = modelViewMatrix * vec4( morphed, 1.0 );

#else

vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );

#endif

gl_Position = projectionMatrix * mvPosition;

#ifdef USE_LOGDEPTHBUF

gl_Position.z = log2(max(1e-6, gl_Position.w + 1.0)) * logDepthBufFC;

#ifdef USE_LOGDEPTHBUF_EXT

vFragDepth = 1.0 + gl_Position.w;

#else

gl_Position.z = (gl_Position.z - 1.0) * gl_Position.w;

#endif

#endif
#if defined( USE_ENVMAP ) || defined( PHONG ) || defined( LAMBERT ) || defined ( USE_SHADOWMAP )

#ifdef USE_SKINNING

vec4 worldPosition = modelMatrix * skinned;

#elif defined( USE_MORPHTARGETS )

vec4 worldPosition = modelMatrix * vec4( morphed, 1.0 );

#else

vec4 worldPosition = modelMatrix * vec4( position, 1.0 );

#endif

#endif

#if defined( USE_ENVMAP ) && ! defined( USE_BUMPMAP ) && ! defined( USE_NORMALMAP ) && ! defined( PHONG )

vec3 worldNormal = mat3( modelMatrix[ 0 ].xyz, modelMatrix[ 1 ].xyz, modelMatrix[ 2 ].xyz ) * objectNormal;
worldNormal = normalize( worldNormal );

vec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );

#ifdef ENVMAP_MODE_REFLECTION

vReflect = reflect( cameraToVertex, worldNormal );

#else

vReflect = refract( cameraToVertex, worldNormal, refractionRatio );

#endif

#endif

#ifdef USE_SHADOWMAP

for( int i = 0; i < MAX_SHADOWS; i ++ ) {

vShadowCoord[ i ] = shadowMatrix[ i ] * worldPosition;

}

#endif
}

Fragment Shader

uniform vec3 diffuse;
uniform float opacity;
#ifdef USE_COLOR

varying vec3 vColor;

#endif

#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP )

varying vec2 vUv;

#endif

#ifdef USE_MAP

uniform sampler2D map;

#endif
#ifdef USE_ALPHAMAP

uniform sampler2D alphaMap;

#endif

#ifdef USE_LIGHTMAP

varying vec2 vUv2;
uniform sampler2D lightMap;

#endif
#ifdef USE_ENVMAP

uniform float reflectivity;
#ifdef ENVMAP_TYPE_CUBE
uniform samplerCube envMap;
#else
uniform sampler2D envMap;
#endif
uniform float flipEnvMap;

#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )

uniform float refractionRatio;

#else

varying vec3 vReflect;

#endif

#endif

#ifdef USE_FOG

uniform vec3 fogColor;

#ifdef FOG_EXP2

uniform float fogDensity;

#else

uniform float fogNear;
uniform float fogFar;
#endif

#endif
#ifdef USE_SHADOWMAP

uniform sampler2D shadowMap[ MAX_SHADOWS ];
uniform vec2 shadowMapSize[ MAX_SHADOWS ];

uniform float shadowDarkness[ MAX_SHADOWS ];
uniform float shadowBias[ MAX_SHADOWS ];

varying vec4 vShadowCoord[ MAX_SHADOWS ];

float unpackDepth( const in vec4 rgba_depth ) {

const vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );
float depth = dot( rgba_depth, bit_shift );
return depth;

}

#endif
#ifdef USE_SPECULARMAP

uniform sampler2D specularMap;

#endif
#ifdef USE_LOGDEPTHBUF

uniform float logDepthBufFC;

#ifdef USE_LOGDEPTHBUF_EXT

#extension GL_EXT_frag_depth : enable
varying float vFragDepth;

#endif

#endif
void main() {
gl_FragColor = vec4( diffuse, opacity );
#if defined(USE_LOGDEPTHBUF) && defined(USE_LOGDEPTHBUF_EXT)

gl_FragDepthEXT = log2(vFragDepth) * logDepthBufFC * 0.5;

#endif
#ifdef USE_MAP

vec4 texelColor = texture2D( map, vUv );

#ifdef GAMMA_INPUT

texelColor.xyz *= texelColor.xyz;

#endif

gl_FragColor = gl_FragColor * texelColor;

#endif
#ifdef USE_ALPHAMAP

gl_FragColor.a *= texture2D( alphaMap, vUv ).g;

#endif

#ifdef ALPHATEST

if ( gl_FragColor.a < ALPHATEST ) discard;

#endif

float specularStrength;

#ifdef USE_SPECULARMAP

vec4 texelSpecular = texture2D( specularMap, vUv );
specularStrength = texelSpecular.r;

#else

specularStrength = 1.0;

#endif
#ifdef USE_LIGHTMAP

gl_FragColor = gl_FragColor * texture2D( lightMap, vUv2 );

#endif
#ifdef USE_COLOR

gl_FragColor = gl_FragColor * vec4( vColor, 1.0 );

#endif
#ifdef USE_ENVMAP

#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )

vec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );

// http://en.wikibooks.org/wiki/GLSL_Programming/Applying_Matrix_Transforma... // Transforming Normal Vectors with the Inverse Transformation

vec3 worldNormal = normalize( vec3( vec4( normal, 0.0 ) * viewMatrix ) );

#ifdef ENVMAP_MODE_REFLECTION

vec3 reflectVec = reflect( cameraToVertex, worldNormal );

#else

vec3 reflectVec = refract( cameraToVertex, worldNormal, refractionRatio );

#endif

#else

vec3 reflectVec = vReflect;

#endif

#ifdef DOUBLE_SIDED
float flipNormal = ( -1.0 + 2.0 * float( gl_FrontFacing ) );
#else
float flipNormal = 1.0;
#endif

#ifdef ENVMAP_TYPE_CUBE
vec4 envColor = textureCube( envMap, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );

#elif defined( ENVMAP_TYPE_EQUIREC )
vec2 sampleUV;
sampleUV.y = clamp( flipNormal * reflectVec.y * 0.5 + 0.5, 0.0, 1.0);
sampleUV.x = atan( flipNormal * reflectVec.z, flipNormal * reflectVec.x ) * 0.15915494309189533576888376337251 + 0.5; // reciprocal( 2 PI ) + 0.5
vec4 envColor = texture2D( envMap, sampleUV );

#elif defined( ENVMAP_TYPE_SPHERE )
vec3 reflectView = flipNormal * normalize((viewMatrix * vec4( reflectVec, 0.0 )).xyz + vec3(0.0,0.0,1.0));
vec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );
#endif

#ifdef GAMMA_INPUT

envColor.xyz *= envColor.xyz;

#endif

#ifdef ENVMAP_BLENDING_MULTIPLY

gl_FragColor.xyz = mix( gl_FragColor.xyz, gl_FragColor.xyz * envColor.xyz, specularStrength * reflectivity );

#elif defined( ENVMAP_BLENDING_MIX )

gl_FragColor.xyz = mix( gl_FragColor.xyz, envColor.xyz, specularStrength * reflectivity );

#elif defined( ENVMAP_BLENDING_ADD )

gl_FragColor.xyz += envColor.xyz * specularStrength * reflectivity;

#endif

#endif

#ifdef USE_SHADOWMAP

#ifdef SHADOWMAP_DEBUG

vec3 frustumColors[3];
frustumColors[0] = vec3( 1.0, 0.5, 0.0 );
frustumColors[1] = vec3( 0.0, 1.0, 0.8 );
frustumColors[2] = vec3( 0.0, 0.5, 1.0 );

#endif

#ifdef SHADOWMAP_CASCADE

int inFrustumCount = 0;

#endif

float fDepth;
vec3 shadowColor = vec3( 1.0 );

for( int i = 0; i < MAX_SHADOWS; i ++ ) {

vec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;

// if ( something && something ) breaks ATI OpenGL shader compiler
// if ( all( something, something ) ) using this instead

bvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );
bool inFrustum = all( inFrustumVec );

// don't shadow pixels outside of light frustum
// use just first frustum (for cascades)
// don't shadow pixels behind far plane of light frustum

#ifdef SHADOWMAP_CASCADE

inFrustumCount += int( inFrustum );
bvec3 frustumTestVec = bvec3( inFrustum, inFrustumCount == 1, shadowCoord.z <= 1.0 );

#else

bvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );

#endif

bool frustumTest = all( frustumTestVec );

if ( frustumTest ) {

shadowCoord.z += shadowBias[ i ];

#if defined( SHADOWMAP_TYPE_PCF )

// Percentage-close filtering
// (9 pixel kernel)
// http://fabiensanglard.net/shadowmappingPCF/
float shadow = 0.0;

/*
// nested loops breaks shader compiler / validator on some ATI cards when using OpenGL
// must enroll loop manually

for ( float y = -1.25; y <= 1.25; y += 1.25 )
for ( float x = -1.25; x <= 1.25; x += 1.25 ) {

vec4 rgbaDepth = texture2D( shadowMap[ i ], vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy );

// doesn't seem to produce any noticeable visual difference compared to simple texture2D lookup
//vec4 rgbaDepth = texture2DProj( shadowMap[ i ], vec4( vShadowCoord[ i ].w * ( vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy ), 0.05, vShadowCoord[ i ].w ) );

float fDepth = unpackDepth( rgbaDepth );

if ( fDepth < shadowCoord.z )
shadow += 1.0;

}

shadow /= 9.0;

*/

const float shadowDelta = 1.0 / 9.0;

float xPixelOffset = 1.0 / shadowMapSize[ i ].x;
float yPixelOffset = 1.0 / shadowMapSize[ i ].y;

float dx0 = -1.25 * xPixelOffset;
float dy0 = -1.25 * yPixelOffset;
float dx1 = 1.25 * xPixelOffset;
float dy1 = 1.25 * yPixelOffset;

fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;

fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;

fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;

fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;

fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;

fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;

fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;

fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;

fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;

shadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );

#elif defined( SHADOWMAP_TYPE_PCF_SOFT )

// Percentage-close filtering
// (9 pixel kernel)
// http://fabiensanglard.net/shadowmappingPCF/
float shadow = 0.0;

float xPixelOffset = 1.0 / shadowMapSize[ i ].x;
float yPixelOffset = 1.0 / shadowMapSize[ i ].y;

float dx0 = -1.0 * xPixelOffset;
float dy0 = -1.0 * yPixelOffset;
float dx1 = 1.0 * xPixelOffset;
float dy1 = 1.0 * yPixelOffset;

mat3 shadowKernel;
mat3 depthKernel;

depthKernel[0][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );
depthKernel[0][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );
depthKernel[0][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );
depthKernel[1][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );
depthKernel[1][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );
depthKernel[1][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );
depthKernel[2][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );
depthKernel[2][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );
depthKernel[2][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );

vec3 shadowZ = vec3( shadowCoord.z );
shadowKernel[0] = vec3(lessThan(depthKernel[0], shadowZ ));
shadowKernel[0] *= vec3(0.25);

shadowKernel[1] = vec3(lessThan(depthKernel[1], shadowZ ));
shadowKernel[1] *= vec3(0.25);

shadowKernel[2] = vec3(lessThan(depthKernel[2], shadowZ ));
shadowKernel[2] *= vec3(0.25);

vec2 fractionalCoord = 1.0 - fract( shadowCoord.xy * shadowMapSize[i].xy );

shadowKernel[0] = mix( shadowKernel[1], shadowKernel[0], fractionalCoord.x );
shadowKernel[1] = mix( shadowKernel[2], shadowKernel[1], fractionalCoord.x );

vec4 shadowValues;
shadowValues.x = mix( shadowKernel[0][1], shadowKernel[0][0], fractionalCoord.y );
shadowValues.y = mix( shadowKernel[0][2], shadowKernel[0][1], fractionalCoord.y );
shadowValues.z = mix( shadowKernel[1][1], shadowKernel[1][0], fractionalCoord.y );
shadowValues.w = mix( shadowKernel[1][2], shadowKernel[1][1], fractionalCoord.y );

shadow = dot( shadowValues, vec4( 1.0 ) );

shadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );

#else

vec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );
float fDepth = unpackDepth( rgbaDepth );

if ( fDepth < shadowCoord.z )

// spot with multiple shadows is darker

shadowColor = shadowColor * vec3( 1.0 - shadowDarkness[ i ] );

// spot with multiple shadows has the same color as single shadow spot

// shadowColor = min( shadowColor, vec3( shadowDarkness[ i ] ) );

#endif

}


#ifdef SHADOWMAP_DEBUG

#ifdef SHADOWMAP_CASCADE

if ( inFrustum && inFrustumCount == 1 ) gl_FragColor.xyz *= frustumColors[ i ];

#else

if ( inFrustum ) gl_FragColor.xyz *= frustumColors[ i ];

#endif

#endif

}

#ifdef GAMMA_OUTPUT

shadowColor *= shadowColor;

#endif

gl_FragColor.xyz = gl_FragColor.xyz * shadowColor;

#endif

#ifdef GAMMA_OUTPUT

gl_FragColor.xyz = sqrt( gl_FragColor.xyz );

#endif
#ifdef USE_FOG

#ifdef USE_LOGDEPTHBUF_EXT

float depth = gl_FragDepthEXT / gl_FragCoord.w;

#else

float depth = gl_FragCoord.z / gl_FragCoord.w;

#endif

#ifdef FOG_EXP2

const float LOG2 = 1.442695;
float fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );
fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );

#else

float fogFactor = smoothstep( fogNear, fogFar, depth );

#endif

gl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );

#endif
}

MeshLambertMaterial

Vertex Shader

#define LAMBERT
varying vec3 vLightFront;
#ifdef DOUBLE_SIDED
varying vec3 vLightBack;
#endif
#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP )

varying vec2 vUv;
uniform vec4 offsetRepeat;

#endif

#ifdef USE_LIGHTMAP

varying vec2 vUv2;

#endif
#if defined( USE_ENVMAP ) && ! defined( USE_BUMPMAP ) && ! defined( USE_NORMALMAP ) && ! defined( PHONG )

varying vec3 vReflect;

uniform float refractionRatio;

#endif

uniform vec3 ambient;
uniform vec3 diffuse;
uniform vec3 emissive;

uniform vec3 ambientLightColor;

#if MAX_DIR_LIGHTS > 0

uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];
uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];

#endif

#if MAX_HEMI_LIGHTS > 0

uniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];
uniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];
uniform vec3 hemisphereLightDirection[ MAX_HEMI_LIGHTS ];

#endif

#if MAX_POINT_LIGHTS > 0

uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];
uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];
uniform float pointLightDistance[ MAX_POINT_LIGHTS ];

#endif

#if MAX_SPOT_LIGHTS > 0

uniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];
uniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];
uniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];
uniform float spotLightDistance[ MAX_SPOT_LIGHTS ];
uniform float spotLightAngleCos[ MAX_SPOT_LIGHTS ];
uniform float spotLightExponent[ MAX_SPOT_LIGHTS ];

#endif

#ifdef WRAP_AROUND

uniform vec3 wrapRGB;

#endif

#ifdef USE_COLOR

varying vec3 vColor;

#endif
#ifdef USE_MORPHTARGETS

#ifndef USE_MORPHNORMALS

uniform float morphTargetInfluences[ 8 ];

#else

uniform float morphTargetInfluences[ 4 ];

#endif

#endif
#ifdef USE_SKINNING

uniform mat4 bindMatrix;
uniform mat4 bindMatrixInverse;

#ifdef BONE_TEXTURE

uniform sampler2D boneTexture;
uniform int boneTextureWidth;
uniform int boneTextureHeight;

mat4 getBoneMatrix( const in float i ) {

float j = i * 4.0;
float x = mod( j, float( boneTextureWidth ) );
float y = floor( j / float( boneTextureWidth ) );

float dx = 1.0 / float( boneTextureWidth );
float dy = 1.0 / float( boneTextureHeight );

y = dy * ( y + 0.5 );

vec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );
vec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );
vec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );
vec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );

mat4 bone = mat4( v1, v2, v3, v4 );

return bone;

}

#else

uniform mat4 boneGlobalMatrices[ MAX_BONES ];

mat4 getBoneMatrix( const in float i ) {

mat4 bone = boneGlobalMatrices[ int(i) ];
return bone;

}

#endif

#endif

#ifdef USE_SHADOWMAP

varying vec4 vShadowCoord[ MAX_SHADOWS ];
uniform mat4 shadowMatrix[ MAX_SHADOWS ];

#endif
#ifdef USE_LOGDEPTHBUF

#ifdef USE_LOGDEPTHBUF_EXT

varying float vFragDepth;

#endif

uniform float logDepthBufFC;

#endif
void main() {
#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP )

vUv = uv * offsetRepeat.zw + offsetRepeat.xy;

#endif
#ifdef USE_LIGHTMAP

vUv2 = uv2;

#endif
#ifdef USE_COLOR

#ifdef GAMMA_INPUT

vColor = color * color;

#else

vColor = color;

#endif

#endif
#ifdef USE_MORPHNORMALS

vec3 morphedNormal = vec3( 0.0 );

morphedNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];
morphedNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];
morphedNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];
morphedNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];

morphedNormal += normal;

#endif
#ifdef USE_SKINNING

mat4 boneMatX = getBoneMatrix( skinIndex.x );
mat4 boneMatY = getBoneMatrix( skinIndex.y );
mat4 boneMatZ = getBoneMatrix( skinIndex.z );
mat4 boneMatW = getBoneMatrix( skinIndex.w );

#endif
#ifdef USE_SKINNING

mat4 skinMatrix = mat4( 0.0 );
skinMatrix += skinWeight.x * boneMatX;
skinMatrix += skinWeight.y * boneMatY;
skinMatrix += skinWeight.z * boneMatZ;
skinMatrix += skinWeight.w * boneMatW;
skinMatrix  = bindMatrixInverse * skinMatrix * bindMatrix;

#ifdef USE_MORPHNORMALS

vec4 skinnedNormal = skinMatrix * vec4( morphedNormal, 0.0 );

#else

vec4 skinnedNormal = skinMatrix * vec4( normal, 0.0 );

#endif

#endif

#ifdef USE_SKINNING

vec3 objectNormal = skinnedNormal.xyz;

#elif defined( USE_MORPHNORMALS )

vec3 objectNormal = morphedNormal;

#else

vec3 objectNormal = normal;

#endif

#ifdef FLIP_SIDED

objectNormal = -objectNormal;

#endif

vec3 transformedNormal = normalMatrix * objectNormal;

#ifdef USE_MORPHTARGETS

vec3 morphed = vec3( 0.0 );
morphed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];
morphed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];
morphed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];
morphed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];

#ifndef USE_MORPHNORMALS

morphed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];
morphed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];
morphed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];
morphed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];

#endif

morphed += position;

#endif
#ifdef USE_SKINNING

#ifdef USE_MORPHTARGETS

vec4 skinVertex = bindMatrix * vec4( morphed, 1.0 );

#else

vec4 skinVertex = bindMatrix * vec4( position, 1.0 );

#endif

vec4 skinned = vec4( 0.0 );
skinned += boneMatX * skinVertex * skinWeight.x;
skinned += boneMatY * skinVertex * skinWeight.y;
skinned += boneMatZ * skinVertex * skinWeight.z;
skinned += boneMatW * skinVertex * skinWeight.w;
skinned  = bindMatrixInverse * skinned;

#endif

#ifdef USE_SKINNING

vec4 mvPosition = modelViewMatrix * skinned;

#elif defined( USE_MORPHTARGETS )

vec4 mvPosition = modelViewMatrix * vec4( morphed, 1.0 );

#else

vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );

#endif

gl_Position = projectionMatrix * mvPosition;

#ifdef USE_LOGDEPTHBUF

gl_Position.z = log2(max(1e-6, gl_Position.w + 1.0)) * logDepthBufFC;

#ifdef USE_LOGDEPTHBUF_EXT

vFragDepth = 1.0 + gl_Position.w;

#else

gl_Position.z = (gl_Position.z - 1.0) * gl_Position.w;

#endif

#endif
#if defined( USE_ENVMAP ) || defined( PHONG ) || defined( LAMBERT ) || defined ( USE_SHADOWMAP )

#ifdef USE_SKINNING

vec4 worldPosition = modelMatrix * skinned;

#elif defined( USE_MORPHTARGETS )

vec4 worldPosition = modelMatrix * vec4( morphed, 1.0 );

#else

vec4 worldPosition = modelMatrix * vec4( position, 1.0 );

#endif

#endif

#if defined( USE_ENVMAP ) && ! defined( USE_BUMPMAP ) && ! defined( USE_NORMALMAP ) && ! defined( PHONG )

vec3 worldNormal = mat3( modelMatrix[ 0 ].xyz, modelMatrix[ 1 ].xyz, modelMatrix[ 2 ].xyz ) * objectNormal;
worldNormal = normalize( worldNormal );

vec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );

#ifdef ENVMAP_MODE_REFLECTION

vReflect = reflect( cameraToVertex, worldNormal );

#else

vReflect = refract( cameraToVertex, worldNormal, refractionRatio );

#endif

#endif

vLightFront = vec3( 0.0 );

#ifdef DOUBLE_SIDED

vLightBack = vec3( 0.0 );

#endif

transformedNormal = normalize( transformedNormal );

#if MAX_DIR_LIGHTS > 0

for( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {

vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );
vec3 dirVector = normalize( lDirection.xyz );

float dotProduct = dot( transformedNormal, dirVector );
vec3 directionalLightWeighting = vec3( max( dotProduct, 0.0 ) );

#ifdef DOUBLE_SIDED

vec3 directionalLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );

#ifdef WRAP_AROUND

vec3 directionalLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );

#endif

#endif

#ifdef WRAP_AROUND

vec3 directionalLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );
directionalLightWeighting = mix( directionalLightWeighting, directionalLightWeightingHalf, wrapRGB );

#ifdef DOUBLE_SIDED

directionalLightWeightingBack = mix( directionalLightWeightingBack, directionalLightWeightingHalfBack, wrapRGB );

#endif

#endif

vLightFront += directionalLightColor[ i ] * directionalLightWeighting;

#ifdef DOUBLE_SIDED

vLightBack += directionalLightColor[ i ] * directionalLightWeightingBack;

#endif

}

#endif

#if MAX_POINT_LIGHTS > 0

for( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {

vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );
vec3 lVector = lPosition.xyz - mvPosition.xyz;

float lDistance = 1.0;
if ( pointLightDistance[ i ] > 0.0 )
lDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );

lVector = normalize( lVector );
float dotProduct = dot( transformedNormal, lVector );

vec3 pointLightWeighting = vec3( max( dotProduct, 0.0 ) );

#ifdef DOUBLE_SIDED

vec3 pointLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );

#ifdef WRAP_AROUND

vec3 pointLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );

#endif

#endif

#ifdef WRAP_AROUND

vec3 pointLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );
pointLightWeighting = mix( pointLightWeighting, pointLightWeightingHalf, wrapRGB );

#ifdef DOUBLE_SIDED

pointLightWeightingBack = mix( pointLightWeightingBack, pointLightWeightingHalfBack, wrapRGB );

#endif

#endif

vLightFront += pointLightColor[ i ] * pointLightWeighting * lDistance;

#ifdef DOUBLE_SIDED

vLightBack += pointLightColor[ i ] * pointLightWeightingBack * lDistance;

#endif

}

#endif

#if MAX_SPOT_LIGHTS > 0

for( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {

vec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );
vec3 lVector = lPosition.xyz - mvPosition.xyz;

float spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - worldPosition.xyz ) );

if ( spotEffect > spotLightAngleCos[ i ] ) {

spotEffect = max( pow( max( spotEffect, 0.0 ), spotLightExponent[ i ] ), 0.0 );

float lDistance = 1.0;
if ( spotLightDistance[ i ] > 0.0 )
lDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );

lVector = normalize( lVector );

float dotProduct = dot( transformedNormal, lVector );
vec3 spotLightWeighting = vec3( max( dotProduct, 0.0 ) );

#ifdef DOUBLE_SIDED

vec3 spotLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );

#ifdef WRAP_AROUND

vec3 spotLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );

#endif

#endif

#ifdef WRAP_AROUND

vec3 spotLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );
spotLightWeighting = mix( spotLightWeighting, spotLightWeightingHalf, wrapRGB );

#ifdef DOUBLE_SIDED

spotLightWeightingBack = mix( spotLightWeightingBack, spotLightWeightingHalfBack, wrapRGB );

#endif

#endif

vLightFront += spotLightColor[ i ] * spotLightWeighting * lDistance * spotEffect;

#ifdef DOUBLE_SIDED

vLightBack += spotLightColor[ i ] * spotLightWeightingBack * lDistance * spotEffect;

#endif

}

}

#endif

#if MAX_HEMI_LIGHTS > 0

for( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {

vec4 lDirection = viewMatrix * vec4( hemisphereLightDirection[ i ], 0.0 );
vec3 lVector = normalize( lDirection.xyz );

float dotProduct = dot( transformedNormal, lVector );

float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;
float hemiDiffuseWeightBack = -0.5 * dotProduct + 0.5;

vLightFront += mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );

#ifdef DOUBLE_SIDED

vLightBack += mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeightBack );

#endif

}

#endif

vLightFront = vLightFront * diffuse + ambient * ambientLightColor + emissive;

#ifdef DOUBLE_SIDED

vLightBack = vLightBack * diffuse + ambient * ambientLightColor + emissive;

#endif
#ifdef USE_SHADOWMAP

for( int i = 0; i < MAX_SHADOWS; i ++ ) {

vShadowCoord[ i ] = shadowMatrix[ i ] * worldPosition;

}

#endif
}

Fragment Shader

uniform float opacity;
varying vec3 vLightFront;
#ifdef DOUBLE_SIDED
varying vec3 vLightBack;
#endif
#ifdef USE_COLOR

varying vec3 vColor;

#endif

#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP )

varying vec2 vUv;

#endif

#ifdef USE_MAP

uniform sampler2D map;

#endif
#ifdef USE_ALPHAMAP

uniform sampler2D alphaMap;

#endif

#ifdef USE_LIGHTMAP

varying vec2 vUv2;
uniform sampler2D lightMap;

#endif
#ifdef USE_ENVMAP

uniform float reflectivity;
#ifdef ENVMAP_TYPE_CUBE
uniform samplerCube envMap;
#else
uniform sampler2D envMap;
#endif
uniform float flipEnvMap;

#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )

uniform float refractionRatio;

#else

varying vec3 vReflect;

#endif

#endif

#ifdef USE_FOG

uniform vec3 fogColor;

#ifdef FOG_EXP2

uniform float fogDensity;

#else

uniform float fogNear;
uniform float fogFar;
#endif

#endif
#ifdef USE_SHADOWMAP

uniform sampler2D shadowMap[ MAX_SHADOWS ];
uniform vec2 shadowMapSize[ MAX_SHADOWS ];

uniform float shadowDarkness[ MAX_SHADOWS ];
uniform float shadowBias[ MAX_SHADOWS ];

varying vec4 vShadowCoord[ MAX_SHADOWS ];

float unpackDepth( const in vec4 rgba_depth ) {

const vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );
float depth = dot( rgba_depth, bit_shift );
return depth;

}

#endif
#ifdef USE_SPECULARMAP

uniform sampler2D specularMap;

#endif
#ifdef USE_LOGDEPTHBUF

uniform float logDepthBufFC;

#ifdef USE_LOGDEPTHBUF_EXT

#extension GL_EXT_frag_depth : enable
varying float vFragDepth;

#endif

#endif
void main() {
gl_FragColor = vec4( vec3( 1.0 ), opacity );
#if defined(USE_LOGDEPTHBUF) && defined(USE_LOGDEPTHBUF_EXT)

gl_FragDepthEXT = log2(vFragDepth) * logDepthBufFC * 0.5;

#endif
#ifdef USE_MAP

vec4 texelColor = texture2D( map, vUv );

#ifdef GAMMA_INPUT

texelColor.xyz *= texelColor.xyz;

#endif

gl_FragColor = gl_FragColor * texelColor;

#endif
#ifdef USE_ALPHAMAP

gl_FragColor.a *= texture2D( alphaMap, vUv ).g;

#endif

#ifdef ALPHATEST

if ( gl_FragColor.a < ALPHATEST ) discard;

#endif

float specularStrength;

#ifdef USE_SPECULARMAP

vec4 texelSpecular = texture2D( specularMap, vUv );
specularStrength = texelSpecular.r;

#else

specularStrength = 1.0;

#endif
#ifdef DOUBLE_SIDED
if ( gl_FrontFacing )
gl_FragColor.xyz *= vLightFront;
else
gl_FragColor.xyz *= vLightBack;
#else
gl_FragColor.xyz *= vLightFront;
#endif
#ifdef USE_LIGHTMAP

gl_FragColor = gl_FragColor * texture2D( lightMap, vUv2 );

#endif
#ifdef USE_COLOR

gl_FragColor = gl_FragColor * vec4( vColor, 1.0 );

#endif
#ifdef USE_ENVMAP

#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )

vec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );

// http://en.wikibooks.org/wiki/GLSL_Programming/Applying_Matrix_Transforma... // Transforming Normal Vectors with the Inverse Transformation

vec3 worldNormal = normalize( vec3( vec4( normal, 0.0 ) * viewMatrix ) );

#ifdef ENVMAP_MODE_REFLECTION

vec3 reflectVec = reflect( cameraToVertex, worldNormal );

#else

vec3 reflectVec = refract( cameraToVertex, worldNormal, refractionRatio );

#endif

#else

vec3 reflectVec = vReflect;

#endif

#ifdef DOUBLE_SIDED
float flipNormal = ( -1.0 + 2.0 * float( gl_FrontFacing ) );
#else
float flipNormal = 1.0;
#endif

#ifdef ENVMAP_TYPE_CUBE
vec4 envColor = textureCube( envMap, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );

#elif defined( ENVMAP_TYPE_EQUIREC )
vec2 sampleUV;
sampleUV.y = clamp( flipNormal * reflectVec.y * 0.5 + 0.5, 0.0, 1.0);
sampleUV.x = atan( flipNormal * reflectVec.z, flipNormal * reflectVec.x ) * 0.15915494309189533576888376337251 + 0.5; // reciprocal( 2 PI ) + 0.5
vec4 envColor = texture2D( envMap, sampleUV );

#elif defined( ENVMAP_TYPE_SPHERE )
vec3 reflectView = flipNormal * normalize((viewMatrix * vec4( reflectVec, 0.0 )).xyz + vec3(0.0,0.0,1.0));
vec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );
#endif

#ifdef GAMMA_INPUT

envColor.xyz *= envColor.xyz;

#endif

#ifdef ENVMAP_BLENDING_MULTIPLY

gl_FragColor.xyz = mix( gl_FragColor.xyz, gl_FragColor.xyz * envColor.xyz, specularStrength * reflectivity );

#elif defined( ENVMAP_BLENDING_MIX )

gl_FragColor.xyz = mix( gl_FragColor.xyz, envColor.xyz, specularStrength * reflectivity );

#elif defined( ENVMAP_BLENDING_ADD )

gl_FragColor.xyz += envColor.xyz * specularStrength * reflectivity;

#endif

#endif

#ifdef USE_SHADOWMAP

#ifdef SHADOWMAP_DEBUG

vec3 frustumColors[3];
frustumColors[0] = vec3( 1.0, 0.5, 0.0 );
frustumColors[1] = vec3( 0.0, 1.0, 0.8 );
frustumColors[2] = vec3( 0.0, 0.5, 1.0 );

#endif

#ifdef SHADOWMAP_CASCADE

int inFrustumCount = 0;

#endif

float fDepth;
vec3 shadowColor = vec3( 1.0 );

for( int i = 0; i < MAX_SHADOWS; i ++ ) {

vec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;

// if ( something && something ) breaks ATI OpenGL shader compiler
// if ( all( something, something ) ) using this instead

bvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );
bool inFrustum = all( inFrustumVec );

// don't shadow pixels outside of light frustum
// use just first frustum (for cascades)
// don't shadow pixels behind far plane of light frustum

#ifdef SHADOWMAP_CASCADE

inFrustumCount += int( inFrustum );
bvec3 frustumTestVec = bvec3( inFrustum, inFrustumCount == 1, shadowCoord.z <= 1.0 );

#else

bvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );

#endif

bool frustumTest = all( frustumTestVec );

if ( frustumTest ) {

shadowCoord.z += shadowBias[ i ];

#if defined( SHADOWMAP_TYPE_PCF )

// Percentage-close filtering
// (9 pixel kernel)
// http://fabiensanglard.net/shadowmappingPCF/
float shadow = 0.0;

/*
// nested loops breaks shader compiler / validator on some ATI cards when using OpenGL
// must enroll loop manually

for ( float y = -1.25; y <= 1.25; y += 1.25 )
for ( float x = -1.25; x <= 1.25; x += 1.25 ) {

vec4 rgbaDepth = texture2D( shadowMap[ i ], vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy );

// doesn't seem to produce any noticeable visual difference compared to simple texture2D lookup
//vec4 rgbaDepth = texture2DProj( shadowMap[ i ], vec4( vShadowCoord[ i ].w * ( vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy ), 0.05, vShadowCoord[ i ].w ) );

float fDepth = unpackDepth( rgbaDepth );

if ( fDepth < shadowCoord.z )
shadow += 1.0;

}

shadow /= 9.0;

*/

const float shadowDelta = 1.0 / 9.0;

float xPixelOffset = 1.0 / shadowMapSize[ i ].x;
float yPixelOffset = 1.0 / shadowMapSize[ i ].y;

float dx0 = -1.25 * xPixelOffset;
float dy0 = -1.25 * yPixelOffset;
float dx1 = 1.25 * xPixelOffset;
float dy1 = 1.25 * yPixelOffset;

fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;

fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;

fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;

fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;

fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;

fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;

fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;

fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;

fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;

shadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );

#elif defined( SHADOWMAP_TYPE_PCF_SOFT )

// Percentage-close filtering
// (9 pixel kernel)
// http://fabiensanglard.net/shadowmappingPCF/
float shadow = 0.0;

float xPixelOffset = 1.0 / shadowMapSize[ i ].x;
float yPixelOffset = 1.0 / shadowMapSize[ i ].y;

float dx0 = -1.0 * xPixelOffset;
float dy0 = -1.0 * yPixelOffset;
float dx1 = 1.0 * xPixelOffset;
float dy1 = 1.0 * yPixelOffset;

mat3 shadowKernel;
mat3 depthKernel;

depthKernel[0][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );
depthKernel[0][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );
depthKernel[0][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );
depthKernel[1][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );
depthKernel[1][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );
depthKernel[1][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );
depthKernel[2][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );
depthKernel[2][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );
depthKernel[2][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );

vec3 shadowZ = vec3( shadowCoord.z );
shadowKernel[0] = vec3(lessThan(depthKernel[0], shadowZ ));
shadowKernel[0] *= vec3(0.25);

shadowKernel[1] = vec3(lessThan(depthKernel[1], shadowZ ));
shadowKernel[1] *= vec3(0.25);

shadowKernel[2] = vec3(lessThan(depthKernel[2], shadowZ ));
shadowKernel[2] *= vec3(0.25);

vec2 fractionalCoord = 1.0 - fract( shadowCoord.xy * shadowMapSize[i].xy );

shadowKernel[0] = mix( shadowKernel[1], shadowKernel[0], fractionalCoord.x );
shadowKernel[1] = mix( shadowKernel[2], shadowKernel[1], fractionalCoord.x );

vec4 shadowValues;
shadowValues.x = mix( shadowKernel[0][1], shadowKernel[0][0], fractionalCoord.y );
shadowValues.y = mix( shadowKernel[0][2], shadowKernel[0][1], fractionalCoord.y );
shadowValues.z = mix( shadowKernel[1][1], shadowKernel[1][0], fractionalCoord.y );
shadowValues.w = mix( shadowKernel[1][2], shadowKernel[1][1], fractionalCoord.y );

shadow = dot( shadowValues, vec4( 1.0 ) );

shadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );

#else

vec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );
float fDepth = unpackDepth( rgbaDepth );

if ( fDepth < shadowCoord.z )

// spot with multiple shadows is darker

shadowColor = shadowColor * vec3( 1.0 - shadowDarkness[ i ] );

// spot with multiple shadows has the same color as single shadow spot

// shadowColor = min( shadowColor, vec3( shadowDarkness[ i ] ) );

#endif

}


#ifdef SHADOWMAP_DEBUG

#ifdef SHADOWMAP_CASCADE

if ( inFrustum && inFrustumCount == 1 ) gl_FragColor.xyz *= frustumColors[ i ];

#else

if ( inFrustum ) gl_FragColor.xyz *= frustumColors[ i ];

#endif

#endif

}

#ifdef GAMMA_OUTPUT

shadowColor *= shadowColor;

#endif

gl_FragColor.xyz = gl_FragColor.xyz * shadowColor;

#endif

#ifdef GAMMA_OUTPUT

gl_FragColor.xyz = sqrt( gl_FragColor.xyz );

#endif
#ifdef USE_FOG

#ifdef USE_LOGDEPTHBUF_EXT

float depth = gl_FragDepthEXT / gl_FragCoord.w;

#else

float depth = gl_FragCoord.z / gl_FragCoord.w;

#endif

#ifdef FOG_EXP2

const float LOG2 = 1.442695;
float fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );
fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );

#else

float fogFactor = smoothstep( fogNear, fogFar, depth );

#endif

gl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );

#endif
}

MeshPhongMaterial

Vertex Shader

#define PHONG
varying vec3 vViewPosition;
varying vec3 vNormal;
#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP )

varying vec2 vUv;
uniform vec4 offsetRepeat;

#endif

#ifdef USE_LIGHTMAP

varying vec2 vUv2;

#endif
#if defined( USE_ENVMAP ) && ! defined( USE_BUMPMAP ) && ! defined( USE_NORMALMAP ) && ! defined( PHONG )

varying vec3 vReflect;

uniform float refractionRatio;

#endif

#if MAX_SPOT_LIGHTS > 0 || defined( USE_BUMPMAP ) || defined( USE_ENVMAP )

varying vec3 vWorldPosition;

#endif

#ifdef USE_COLOR

varying vec3 vColor;

#endif
#ifdef USE_MORPHTARGETS

#ifndef USE_MORPHNORMALS

uniform float morphTargetInfluences[ 8 ];

#else

uniform float morphTargetInfluences[ 4 ];

#endif

#endif
#ifdef USE_SKINNING

uniform mat4 bindMatrix;
uniform mat4 bindMatrixInverse;

#ifdef BONE_TEXTURE

uniform sampler2D boneTexture;
uniform int boneTextureWidth;
uniform int boneTextureHeight;

mat4 getBoneMatrix( const in float i ) {

float j = i * 4.0;
float x = mod( j, float( boneTextureWidth ) );
float y = floor( j / float( boneTextureWidth ) );

float dx = 1.0 / float( boneTextureWidth );
float dy = 1.0 / float( boneTextureHeight );

y = dy * ( y + 0.5 );

vec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );
vec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );
vec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );
vec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );

mat4 bone = mat4( v1, v2, v3, v4 );

return bone;

}

#else

uniform mat4 boneGlobalMatrices[ MAX_BONES ];

mat4 getBoneMatrix( const in float i ) {

mat4 bone = boneGlobalMatrices[ int(i) ];
return bone;

}

#endif

#endif

#ifdef USE_SHADOWMAP

varying vec4 vShadowCoord[ MAX_SHADOWS ];
uniform mat4 shadowMatrix[ MAX_SHADOWS ];

#endif
#ifdef USE_LOGDEPTHBUF

#ifdef USE_LOGDEPTHBUF_EXT

varying float vFragDepth;

#endif

uniform float logDepthBufFC;

#endif
void main() {
#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP )

vUv = uv * offsetRepeat.zw + offsetRepeat.xy;

#endif
#ifdef USE_LIGHTMAP

vUv2 = uv2;

#endif
#ifdef USE_COLOR

#ifdef GAMMA_INPUT

vColor = color * color;

#else

vColor = color;

#endif

#endif
#ifdef USE_MORPHNORMALS

vec3 morphedNormal = vec3( 0.0 );

morphedNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];
morphedNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];
morphedNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];
morphedNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];

morphedNormal += normal;

#endif
#ifdef USE_SKINNING

mat4 boneMatX = getBoneMatrix( skinIndex.x );
mat4 boneMatY = getBoneMatrix( skinIndex.y );
mat4 boneMatZ = getBoneMatrix( skinIndex.z );
mat4 boneMatW = getBoneMatrix( skinIndex.w );

#endif
#ifdef USE_SKINNING

mat4 skinMatrix = mat4( 0.0 );
skinMatrix += skinWeight.x * boneMatX;
skinMatrix += skinWeight.y * boneMatY;
skinMatrix += skinWeight.z * boneMatZ;
skinMatrix += skinWeight.w * boneMatW;
skinMatrix  = bindMatrixInverse * skinMatrix * bindMatrix;

#ifdef USE_MORPHNORMALS

vec4 skinnedNormal = skinMatrix * vec4( morphedNormal, 0.0 );

#else

vec4 skinnedNormal = skinMatrix * vec4( normal, 0.0 );

#endif

#endif

#ifdef USE_SKINNING

vec3 objectNormal = skinnedNormal.xyz;

#elif defined( USE_MORPHNORMALS )

vec3 objectNormal = morphedNormal;

#else

vec3 objectNormal = normal;

#endif

#ifdef FLIP_SIDED

objectNormal = -objectNormal;

#endif

vec3 transformedNormal = normalMatrix * objectNormal;

vNormal = normalize( transformedNormal );
#ifdef USE_MORPHTARGETS

vec3 morphed = vec3( 0.0 );
morphed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];
morphed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];
morphed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];
morphed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];

#ifndef USE_MORPHNORMALS

morphed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];
morphed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];
morphed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];
morphed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];

#endif

morphed += position;

#endif
#ifdef USE_SKINNING

#ifdef USE_MORPHTARGETS

vec4 skinVertex = bindMatrix * vec4( morphed, 1.0 );

#else

vec4 skinVertex = bindMatrix * vec4( position, 1.0 );

#endif

vec4 skinned = vec4( 0.0 );
skinned += boneMatX * skinVertex * skinWeight.x;
skinned += boneMatY * skinVertex * skinWeight.y;
skinned += boneMatZ * skinVertex * skinWeight.z;
skinned += boneMatW * skinVertex * skinWeight.w;
skinned  = bindMatrixInverse * skinned;

#endif

#ifdef USE_SKINNING

vec4 mvPosition = modelViewMatrix * skinned;

#elif defined( USE_MORPHTARGETS )

vec4 mvPosition = modelViewMatrix * vec4( morphed, 1.0 );

#else

vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );

#endif

gl_Position = projectionMatrix * mvPosition;

#ifdef USE_LOGDEPTHBUF

gl_Position.z = log2(max(1e-6, gl_Position.w + 1.0)) * logDepthBufFC;

#ifdef USE_LOGDEPTHBUF_EXT

vFragDepth = 1.0 + gl_Position.w;

#else

gl_Position.z = (gl_Position.z - 1.0) * gl_Position.w;

#endif

#endif
vViewPosition = -mvPosition.xyz;
#if defined( USE_ENVMAP ) || defined( PHONG ) || defined( LAMBERT ) || defined ( USE_SHADOWMAP )

#ifdef USE_SKINNING

vec4 worldPosition = modelMatrix * skinned;

#elif defined( USE_MORPHTARGETS )

vec4 worldPosition = modelMatrix * vec4( morphed, 1.0 );

#else

vec4 worldPosition = modelMatrix * vec4( position, 1.0 );

#endif

#endif

#if defined( USE_ENVMAP ) && ! defined( USE_BUMPMAP ) && ! defined( USE_NORMALMAP ) && ! defined( PHONG )

vec3 worldNormal = mat3( modelMatrix[ 0 ].xyz, modelMatrix[ 1 ].xyz, modelMatrix[ 2 ].xyz ) * objectNormal;
worldNormal = normalize( worldNormal );

vec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );

#ifdef ENVMAP_MODE_REFLECTION

vReflect = reflect( cameraToVertex, worldNormal );

#else

vReflect = refract( cameraToVertex, worldNormal, refractionRatio );

#endif

#endif

#if MAX_SPOT_LIGHTS > 0 || defined( USE_BUMPMAP ) || defined( USE_ENVMAP )

vWorldPosition = worldPosition.xyz;

#endif
#ifdef USE_SHADOWMAP

for( int i = 0; i < MAX_SHADOWS; i ++ ) {

vShadowCoord[ i ] = shadowMatrix[ i ] * worldPosition;

}

#endif
}

Fragment Shader

#define PHONG
uniform vec3 diffuse;
uniform float opacity;
uniform vec3 ambient;
uniform vec3 emissive;
uniform vec3 specular;
uniform float shininess;
#ifdef USE_COLOR

varying vec3 vColor;

#endif

#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP )

varying vec2 vUv;

#endif

#ifdef USE_MAP

uniform sampler2D map;

#endif
#ifdef USE_ALPHAMAP

uniform sampler2D alphaMap;

#endif

#ifdef USE_LIGHTMAP

varying vec2 vUv2;
uniform sampler2D lightMap;

#endif
#ifdef USE_ENVMAP

uniform float reflectivity;
#ifdef ENVMAP_TYPE_CUBE
uniform samplerCube envMap;
#else
uniform sampler2D envMap;
#endif
uniform float flipEnvMap;

#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )

uniform float refractionRatio;

#else

varying vec3 vReflect;

#endif

#endif

#ifdef USE_FOG

uniform vec3 fogColor;

#ifdef FOG_EXP2

uniform float fogDensity;

#else

uniform float fogNear;
uniform float fogFar;
#endif

#endif
uniform vec3 ambientLightColor;

#if MAX_DIR_LIGHTS > 0

uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];
uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];

#endif

#if MAX_HEMI_LIGHTS > 0

uniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];
uniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];
uniform vec3 hemisphereLightDirection[ MAX_HEMI_LIGHTS ];

#endif

#if MAX_POINT_LIGHTS > 0

uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];

uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];
uniform float pointLightDistance[ MAX_POINT_LIGHTS ];

#endif

#if MAX_SPOT_LIGHTS > 0

uniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];
uniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];
uniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];
uniform float spotLightAngleCos[ MAX_SPOT_LIGHTS ];
uniform float spotLightExponent[ MAX_SPOT_LIGHTS ];

uniform float spotLightDistance[ MAX_SPOT_LIGHTS ];

#endif

#if MAX_SPOT_LIGHTS > 0 || defined( USE_BUMPMAP ) || defined( USE_ENVMAP )

varying vec3 vWorldPosition;

#endif

#ifdef WRAP_AROUND

uniform vec3 wrapRGB;

#endif

varying vec3 vViewPosition;
varying vec3 vNormal;
#ifdef USE_SHADOWMAP

uniform sampler2D shadowMap[ MAX_SHADOWS ];
uniform vec2 shadowMapSize[ MAX_SHADOWS ];

uniform float shadowDarkness[ MAX_SHADOWS ];
uniform float shadowBias[ MAX_SHADOWS ];

varying vec4 vShadowCoord[ MAX_SHADOWS ];

float unpackDepth( const in vec4 rgba_depth ) {

const vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );
float depth = dot( rgba_depth, bit_shift );
return depth;

}

#endif
#ifdef USE_BUMPMAP

uniform sampler2D bumpMap;
uniform float bumpScale;

// Derivative maps - bump mapping unparametrized surfaces by Morten Mikkelsen
// http://mmikkelsen3d.blogspot.sk/2011/07/derivative-maps.html
// Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2)

vec2 dHdxy_fwd() {

vec2 dSTdx = dFdx( vUv );
vec2 dSTdy = dFdy( vUv );

float Hll = bumpScale * texture2D( bumpMap, vUv ).x;
float dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;
float dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;

return vec2( dBx, dBy );

}

vec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {

vec3 vSigmaX = dFdx( surf_pos );
vec3 vSigmaY = dFdy( surf_pos );
vec3 vN = surf_norm; // normalized

vec3 R1 = cross( vSigmaY, vN );
vec3 R2 = cross( vN, vSigmaX );

float fDet = dot( vSigmaX, R1 );

vec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );
return normalize( abs( fDet ) * surf_norm - vGrad );

}

#endif
#ifdef USE_NORMALMAP

uniform sampler2D normalMap;
uniform vec2 normalScale;

// Per-Pixel Tangent Space Normal Mapping
// hacksoflife.blogspot.ch/2009/11/per-pixel-tangent-space-normal-mapping . html

vec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {

vec3 q0 = dFdx( eye_pos.xyz );
vec3 q1 = dFdy( eye_pos.xyz );
vec2 st0 = dFdx( vUv.st );
vec2 st1 = dFdy( vUv.st );

vec3 S = normalize( q0 * st1.t - q1 * st0.t );
vec3 T = normalize( -q0 * st1.s + q1 * st0.s );
vec3 N = normalize( surf_norm );

vec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;
mapN.xy = normalScale * mapN.xy;
mat3 tsn = mat3( S, T, N );
return normalize( tsn * mapN );

}

#endif

#ifdef USE_SPECULARMAP

uniform sampler2D specularMap;

#endif
#ifdef USE_LOGDEPTHBUF

uniform float logDepthBufFC;

#ifdef USE_LOGDEPTHBUF_EXT

#extension GL_EXT_frag_depth : enable
varying float vFragDepth;

#endif

#endif
void main() {
gl_FragColor = vec4( vec3( 1.0 ), opacity );
#if defined(USE_LOGDEPTHBUF) && defined(USE_LOGDEPTHBUF_EXT)

gl_FragDepthEXT = log2(vFragDepth) * logDepthBufFC * 0.5;

#endif
#ifdef USE_MAP

vec4 texelColor = texture2D( map, vUv );

#ifdef GAMMA_INPUT

texelColor.xyz *= texelColor.xyz;

#endif

gl_FragColor = gl_FragColor * texelColor;

#endif
#ifdef USE_ALPHAMAP

gl_FragColor.a *= texture2D( alphaMap, vUv ).g;

#endif

#ifdef ALPHATEST

if ( gl_FragColor.a < ALPHATEST ) discard;

#endif

float specularStrength;

#ifdef USE_SPECULARMAP

vec4 texelSpecular = texture2D( specularMap, vUv );
specularStrength = texelSpecular.r;

#else

specularStrength = 1.0;

#endif
vec3 normal = normalize( vNormal );
vec3 viewPosition = normalize( vViewPosition );

#ifdef DOUBLE_SIDED

normal = normal * ( -1.0 + 2.0 * float( gl_FrontFacing ) );

#endif

#ifdef USE_NORMALMAP

normal = perturbNormal2Arb( -vViewPosition, normal );

#elif defined( USE_BUMPMAP )

normal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );

#endif

#if MAX_POINT_LIGHTS > 0

vec3 pointDiffuse = vec3( 0.0 );
vec3 pointSpecular = vec3( 0.0 );

for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {

vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );
vec3 lVector = lPosition.xyz + vViewPosition.xyz;

float lDistance = 1.0;
if ( pointLightDistance[ i ] > 0.0 )
lDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );

lVector = normalize( lVector );

// diffuse

float dotProduct = dot( normal, lVector );

#ifdef WRAP_AROUND

float pointDiffuseWeightFull = max( dotProduct, 0.0 );
float pointDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );

vec3 pointDiffuseWeight = mix( vec3( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );

#else

float pointDiffuseWeight = max( dotProduct, 0.0 );

#endif

pointDiffuse += diffuse * pointLightColor[ i ] * pointDiffuseWeight * lDistance;

// specular

vec3 pointHalfVector = normalize( lVector + viewPosition );
float pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );
float pointSpecularWeight = specularStrength * max( pow( pointDotNormalHalf, shininess ), 0.0 );

float specularNormalization = ( shininess + 2.0 ) / 8.0;

vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, pointHalfVector ), 0.0 ), 5.0 );
pointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance * specularNormalization;

}

#endif

#if MAX_SPOT_LIGHTS > 0

vec3 spotDiffuse = vec3( 0.0 );
vec3 spotSpecular = vec3( 0.0 );

for ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {

vec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );
vec3 lVector = lPosition.xyz + vViewPosition.xyz;

float lDistance = 1.0;
if ( spotLightDistance[ i ] > 0.0 )
lDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );

lVector = normalize( lVector );

float spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) );

if ( spotEffect > spotLightAngleCos[ i ] ) {

spotEffect = max( pow( max( spotEffect, 0.0 ), spotLightExponent[ i ] ), 0.0 );

// diffuse

float dotProduct = dot( normal, lVector );

#ifdef WRAP_AROUND

float spotDiffuseWeightFull = max( dotProduct, 0.0 );
float spotDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );

vec3 spotDiffuseWeight = mix( vec3( spotDiffuseWeightFull ), vec3( spotDiffuseWeightHalf ), wrapRGB );

#else

float spotDiffuseWeight = max( dotProduct, 0.0 );

#endif

spotDiffuse += diffuse * spotLightColor[ i ] * spotDiffuseWeight * lDistance * spotEffect;

// specular

vec3 spotHalfVector = normalize( lVector + viewPosition );
float spotDotNormalHalf = max( dot( normal, spotHalfVector ), 0.0 );
float spotSpecularWeight = specularStrength * max( pow( spotDotNormalHalf, shininess ), 0.0 );

float specularNormalization = ( shininess + 2.0 ) / 8.0;

vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, spotHalfVector ), 0.0 ), 5.0 );
spotSpecular += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * specularNormalization * spotEffect;

}

}

#endif

#if MAX_DIR_LIGHTS > 0

vec3 dirDiffuse = vec3( 0.0 );
vec3 dirSpecular = vec3( 0.0 );

for( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {

vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );
vec3 dirVector = normalize( lDirection.xyz );

// diffuse

float dotProduct = dot( normal, dirVector );

#ifdef WRAP_AROUND

float dirDiffuseWeightFull = max( dotProduct, 0.0 );
float dirDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );

vec3 dirDiffuseWeight = mix( vec3( dirDiffuseWeightFull ), vec3( dirDiffuseWeightHalf ), wrapRGB );

#else

float dirDiffuseWeight = max( dotProduct, 0.0 );

#endif

dirDiffuse += diffuse * directionalLightColor[ i ] * dirDiffuseWeight;

// specular

vec3 dirHalfVector = normalize( dirVector + viewPosition );
float dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );
float dirSpecularWeight = specularStrength * max( pow( dirDotNormalHalf, shininess ), 0.0 );

/*
// fresnel term from skin shader
const float F0 = 0.128;

float base = 1.0 - dot( viewPosition, dirHalfVector );
float exponential = pow( base, 5.0 );

float fresnel = exponential + F0 * ( 1.0 - exponential );
*/

/*
// fresnel term from fresnel shader
const float mFresnelBias = 0.08;
const float mFresnelScale = 0.3;
const float mFresnelPower = 5.0;

float fresnel = mFresnelBias + mFresnelScale * pow( 1.0 + dot( normalize( -viewPosition ), normal ), mFresnelPower );
*/

float specularNormalization = ( shininess + 2.0 ) / 8.0;

// dirSpecular += specular * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization * fresnel;

vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( dirVector, dirHalfVector ), 0.0 ), 5.0 );
dirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;


}

#endif

#if MAX_HEMI_LIGHTS > 0

vec3 hemiDiffuse = vec3( 0.0 );
vec3 hemiSpecular = vec3( 0.0 );

for( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {

vec4 lDirection = viewMatrix * vec4( hemisphereLightDirection[ i ], 0.0 );
vec3 lVector = normalize( lDirection.xyz );

// diffuse

float dotProduct = dot( normal, lVector );
float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;

vec3 hemiColor = mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );

hemiDiffuse += diffuse * hemiColor;

// specular (sky light)

vec3 hemiHalfVectorSky = normalize( lVector + viewPosition );
float hemiDotNormalHalfSky = 0.5 * dot( normal, hemiHalfVectorSky ) + 0.5;
float hemiSpecularWeightSky = specularStrength * max( pow( max( hemiDotNormalHalfSky, 0.0 ), shininess ), 0.0 );

// specular (ground light)

vec3 lVectorGround = -lVector;

vec3 hemiHalfVectorGround = normalize( lVectorGround + viewPosition );
float hemiDotNormalHalfGround = 0.5 * dot( normal, hemiHalfVectorGround ) + 0.5;
float hemiSpecularWeightGround = specularStrength * max( pow( max( hemiDotNormalHalfGround, 0.0 ), shininess ), 0.0 );

float dotProductGround = dot( normal, lVectorGround );

float specularNormalization = ( shininess + 2.0 ) / 8.0;

vec3 schlickSky = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, hemiHalfVectorSky ), 0.0 ), 5.0 );
vec3 schlickGround = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVectorGround, hemiHalfVectorGround ), 0.0 ), 5.0 );
hemiSpecular += hemiColor * specularNormalization * ( schlickSky * hemiSpecularWeightSky * max( dotProduct, 0.0 ) + schlickGround * hemiSpecularWeightGround * max( dotProductGround, 0.0 ) );

}

#endif

vec3 totalDiffuse = vec3( 0.0 );
vec3 totalSpecular = vec3( 0.0 );

#if MAX_DIR_LIGHTS > 0

totalDiffuse += dirDiffuse;
totalSpecular += dirSpecular;

#endif

#if MAX_HEMI_LIGHTS > 0

totalDiffuse += hemiDiffuse;
totalSpecular += hemiSpecular;

#endif

#if MAX_POINT_LIGHTS > 0

totalDiffuse += pointDiffuse;
totalSpecular += pointSpecular;

#endif

#if MAX_SPOT_LIGHTS > 0

totalDiffuse += spotDiffuse;
totalSpecular += spotSpecular;

#endif

#ifdef METAL

gl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient + totalSpecular );

#else

gl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient ) + totalSpecular;

#endif
#ifdef USE_LIGHTMAP

gl_FragColor = gl_FragColor * texture2D( lightMap, vUv2 );

#endif
#ifdef USE_COLOR

gl_FragColor = gl_FragColor * vec4( vColor, 1.0 );

#endif
#ifdef USE_ENVMAP

#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )

vec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );

// http://en.wikibooks.org/wiki/GLSL_Programming/Applying_Matrix_Transforma... // Transforming Normal Vectors with the Inverse Transformation

vec3 worldNormal = normalize( vec3( vec4( normal, 0.0 ) * viewMatrix ) );

#ifdef ENVMAP_MODE_REFLECTION

vec3 reflectVec = reflect( cameraToVertex, worldNormal );

#else

vec3 reflectVec = refract( cameraToVertex, worldNormal, refractionRatio );

#endif

#else

vec3 reflectVec = vReflect;

#endif

#ifdef DOUBLE_SIDED
float flipNormal = ( -1.0 + 2.0 * float( gl_FrontFacing ) );
#else
float flipNormal = 1.0;
#endif

#ifdef ENVMAP_TYPE_CUBE
vec4 envColor = textureCube( envMap, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );

#elif defined( ENVMAP_TYPE_EQUIREC )
vec2 sampleUV;
sampleUV.y = clamp( flipNormal * reflectVec.y * 0.5 + 0.5, 0.0, 1.0);
sampleUV.x = atan( flipNormal * reflectVec.z, flipNormal * reflectVec.x ) * 0.15915494309189533576888376337251 + 0.5; // reciprocal( 2 PI ) + 0.5
vec4 envColor = texture2D( envMap, sampleUV );

#elif defined( ENVMAP_TYPE_SPHERE )
vec3 reflectView = flipNormal * normalize((viewMatrix * vec4( reflectVec, 0.0 )).xyz + vec3(0.0,0.0,1.0));
vec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );
#endif

#ifdef GAMMA_INPUT

envColor.xyz *= envColor.xyz;

#endif

#ifdef ENVMAP_BLENDING_MULTIPLY

gl_FragColor.xyz = mix( gl_FragColor.xyz, gl_FragColor.xyz * envColor.xyz, specularStrength * reflectivity );

#elif defined( ENVMAP_BLENDING_MIX )

gl_FragColor.xyz = mix( gl_FragColor.xyz, envColor.xyz, specularStrength * reflectivity );

#elif defined( ENVMAP_BLENDING_ADD )

gl_FragColor.xyz += envColor.xyz * specularStrength * reflectivity;

#endif

#endif

#ifdef USE_SHADOWMAP

#ifdef SHADOWMAP_DEBUG

vec3 frustumColors[3];
frustumColors[0] = vec3( 1.0, 0.5, 0.0 );
frustumColors[1] = vec3( 0.0, 1.0, 0.8 );
frustumColors[2] = vec3( 0.0, 0.5, 1.0 );

#endif

#ifdef SHADOWMAP_CASCADE

int inFrustumCount = 0;

#endif

float fDepth;
vec3 shadowColor = vec3( 1.0 );

for( int i = 0; i < MAX_SHADOWS; i ++ ) {

vec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;

// if ( something && something ) breaks ATI OpenGL shader compiler
// if ( all( something, something ) ) using this instead

bvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );
bool inFrustum = all( inFrustumVec );

// don't shadow pixels outside of light frustum
// use just first frustum (for cascades)
// don't shadow pixels behind far plane of light frustum

#ifdef SHADOWMAP_CASCADE

inFrustumCount += int( inFrustum );
bvec3 frustumTestVec = bvec3( inFrustum, inFrustumCount == 1, shadowCoord.z <= 1.0 );

#else

bvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );

#endif

bool frustumTest = all( frustumTestVec );

if ( frustumTest ) {

shadowCoord.z += shadowBias[ i ];

#if defined( SHADOWMAP_TYPE_PCF )

// Percentage-close filtering
// (9 pixel kernel)
// http://fabiensanglard.net/shadowmappingPCF/
float shadow = 0.0;

/*
// nested loops breaks shader compiler / validator on some ATI cards when using OpenGL
// must enroll loop manually

for ( float y = -1.25; y <= 1.25; y += 1.25 )
for ( float x = -1.25; x <= 1.25; x += 1.25 ) {

vec4 rgbaDepth = texture2D( shadowMap[ i ], vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy );

// doesn't seem to produce any noticeable visual difference compared to simple texture2D lookup
//vec4 rgbaDepth = texture2DProj( shadowMap[ i ], vec4( vShadowCoord[ i ].w * ( vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy ), 0.05, vShadowCoord[ i ].w ) );

float fDepth = unpackDepth( rgbaDepth );

if ( fDepth < shadowCoord.z )
shadow += 1.0;

}

shadow /= 9.0;

*/

const float shadowDelta = 1.0 / 9.0;

float xPixelOffset = 1.0 / shadowMapSize[ i ].x;
float yPixelOffset = 1.0 / shadowMapSize[ i ].y;

float dx0 = -1.25 * xPixelOffset;
float dy0 = -1.25 * yPixelOffset;
float dx1 = 1.25 * xPixelOffset;
float dy1 = 1.25 * yPixelOffset;

fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;

fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;

fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;

fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;

fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;

fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;

fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;

fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;

fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );
if ( fDepth < shadowCoord.z ) shadow += shadowDelta;

shadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );

#elif defined( SHADOWMAP_TYPE_PCF_SOFT )

// Percentage-close filtering
// (9 pixel kernel)
// http://fabiensanglard.net/shadowmappingPCF/
float shadow = 0.0;

float xPixelOffset = 1.0 / shadowMapSize[ i ].x;
float yPixelOffset = 1.0 / shadowMapSize[ i ].y;

float dx0 = -1.0 * xPixelOffset;
float dy0 = -1.0 * yPixelOffset;
float dx1 = 1.0 * xPixelOffset;
float dy1 = 1.0 * yPixelOffset;

mat3 shadowKernel;
mat3 depthKernel;

depthKernel[0][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );
depthKernel[0][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );
depthKernel[0][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );
depthKernel[1][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );
depthKernel[1][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );
depthKernel[1][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );
depthKernel[2][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );
depthKernel[2][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );
depthKernel[2][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );

vec3 shadowZ = vec3( shadowCoord.z );
shadowKernel[0] = vec3(lessThan(depthKernel[0], shadowZ ));
shadowKernel[0] *= vec3(0.25);

shadowKernel[1] = vec3(lessThan(depthKernel[1], shadowZ ));
shadowKernel[1] *= vec3(0.25);

shadowKernel[2] = vec3(lessThan(depthKernel[2], shadowZ ));
shadowKernel[2] *= vec3(0.25);

vec2 fractionalCoord = 1.0 - fract( shadowCoord.xy * shadowMapSize[i].xy );

shadowKernel[0] = mix( shadowKernel[1], shadowKernel[0], fractionalCoord.x );
shadowKernel[1] = mix( shadowKernel[2], shadowKernel[1], fractionalCoord.x );

vec4 shadowValues;
shadowValues.x = mix( shadowKernel[0][1], shadowKernel[0][0], fractionalCoord.y );
shadowValues.y = mix( shadowKernel[0][2], shadowKernel[0][1], fractionalCoord.y );
shadowValues.z = mix( shadowKernel[1][1], shadowKernel[1][0], fractionalCoord.y );
shadowValues.w = mix( shadowKernel[1][2], shadowKernel[1][1], fractionalCoord.y );

shadow = dot( shadowValues, vec4( 1.0 ) );

shadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );

#else

vec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );
float fDepth = unpackDepth( rgbaDepth );

if ( fDepth < shadowCoord.z )

// spot with multiple shadows is darker

shadowColor = shadowColor * vec3( 1.0 - shadowDarkness[ i ] );

// spot with multiple shadows has the same color as single shadow spot

// shadowColor = min( shadowColor, vec3( shadowDarkness[ i ] ) );

#endif

}


#ifdef SHADOWMAP_DEBUG

#ifdef SHADOWMAP_CASCADE

if ( inFrustum && inFrustumCount == 1 ) gl_FragColor.xyz *= frustumColors[ i ];

#else

if ( inFrustum ) gl_FragColor.xyz *= frustumColors[ i ];

#endif

#endif

}

#ifdef GAMMA_OUTPUT

shadowColor *= shadowColor;

#endif

gl_FragColor.xyz = gl_FragColor.xyz * shadowColor;

#endif

#ifdef GAMMA_OUTPUT

gl_FragColor.xyz = sqrt( gl_FragColor.xyz );

#endif
#ifdef USE_FOG

#ifdef USE_LOGDEPTHBUF_EXT

float depth = gl_FragDepthEXT / gl_FragCoord.w;

#else

float depth = gl_FragCoord.z / gl_FragCoord.w;

#endif

#ifdef FOG_EXP2

const float LOG2 = 1.442695;
float fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );
fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );

#else

float fogFactor = smoothstep( fogNear, fogFar, depth );

#endif

gl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );

#endif
}

Comments

Hi, This is very interesting; helps me a lot. Was it a very manual process to compile these? Only I note you don't include ShaderMaterial itself. Perhaps it is substantially different; it seems to have a problem working with bones, which is what got me here. I'll keep digging.

Firefox console has a shader editor. I just put them here for easy reference.

Add new comment

You must have Javascript enabled to use this form.