title: OutlineEffect error when fog is enabled, invalid shaders ERROR: 0:204: 'fogDepth' : redefinition
body: <p>I'm trying to build a three.js scene using the OutlineEffect.js from the examples (<a href="https://github.com/mrdoob/three.js/blob/dev/examples/js/effects/OutlineEffect.js" rel="nofollow noreferrer">https://github.com/mrdoob/three.js/blob/dev/examples/js/effects/OutlineEffect.js</a>).  This works great. </p>
  
  <p>However, when I add fog to the scene, I then get this error, and the outline doesn't show up: </p>
  
  <pre><code>THREE.WebGLProgram: shader error:  1282 gl.VALIDATE_STATUS false gl.getProgramInfoLog invalid shaders ERROR: 0:204: 'fogDepth' : redefinition
  </code></pre>
  
  <p>The relevant parts of the code (I hope) are: </p>
  
  <pre><code>var outline = new THREE.OutlineEffect(window.renderer, {
    defaultThickness : window.sceneSettings.lineThickness
  });
  
  if (window.sceneSettings.useFog) {
    var newFog = new THREE.Fog(0xffffff, window.sceneSettings.fogNear, window.sceneSettings.fogFar)
    scene.fog = newFog
  }
  
  function render(e) {
    outline.render(scene, window.camera)
  }
  </code></pre>
  
  <p>I apologize if this question is naive; I'm not really a js or threejs person, I'm a data scientist trying to feel my way around this. </p>
  
  <p>Thank you in advance for any advice!</p>
  
  <p>EDIT:  </p>
  
  <p>More from the logs:</p>
  
  <p>The first error is <code>three.module.js:16963 THREE.WebGLShader: Shader couldn't compile.</code> with the following source dump:</p>
  
  <pre><code>THREE.WebGLShader: gl.getShaderInfoLog() vertex ERROR: 0:178: 'fogDepth' : redefinition
   1: precision highp float;
  2: precision highp int;
  3: #define SHADER_NAME ShaderMaterial
  4: #define VERTEX_TEXTURES
  5: #define GAMMA_FACTOR 2
  6: #define MAX_BONES 0
  7: #define USE_FOG
  8: #define BONE_TEXTURE
  9: #define FLIP_SIDED
  10: uniform mat4 modelMatrix;
  11: uniform mat4 modelViewMatrix;
  12: uniform mat4 projectionMatrix;
  13: uniform mat4 viewMatrix;
  14: uniform mat3 normalMatrix;
  15: uniform vec3 cameraPosition;
  16: attribute vec3 position;
  17: attribute vec3 normal;
  18: attribute vec2 uv;
  19: #ifdef USE_COLOR
  20:     attribute vec3 color;
  21: #endif
  22: #ifdef USE_MORPHTARGETS
  23:     attribute vec3 morphTarget0;
  24:     attribute vec3 morphTarget1;
  25:     attribute vec3 morphTarget2;
  26:     attribute vec3 morphTarget3;
  27:     #ifdef USE_MORPHNORMALS
  28:         attribute vec3 morphNormal0;
  29:         attribute vec3 morphNormal1;
  30:         attribute vec3 morphNormal2;
  31:         attribute vec3 morphNormal3;
  32:     #else
  33:         attribute vec3 morphTarget4;
  34:         attribute vec3 morphTarget5;
  35:         attribute vec3 morphTarget6;
  36:         attribute vec3 morphTarget7;
  37:     #endif
  38: #endif
  39: #ifdef USE_SKINNING
  40:     attribute vec4 skinIndex;
  41:     attribute vec4 skinWeight;
  42: #endif
  43: 
  44: #define PI 3.14159265359
  45: #define PI2 6.28318530718
  46: #define PI_HALF 1.5707963267949
  47: #define RECIPROCAL_PI 0.31830988618
  48: #define RECIPROCAL_PI2 0.15915494
  49: #define LOG2 1.442695
  50: #define EPSILON 1e-6
  51: #define saturate(a) clamp( a, 0.0, 1.0 )
  52: #define whiteCompliment(a) ( 1.0 - saturate( a ) )
  53: float pow2( const in float x ) { return x*x; }
  54: float pow3( const in float x ) { return x*x*x; }
  55: float pow4( const in float x ) { float x2 = x*x; return x2*x2; }
  56: float average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }
  57: highp float rand( const in vec2 uv ) {
  58:     const highp float a = 12.9898, b = 78.233, c = 43758.5453;
  59:     highp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );
  60:     return fract(sin(sn) * c);
  61: }
  62: struct IncidentLight {
  63:     vec3 color;
  64:     vec3 direction;
  65:     bool visible;
  66: };
  67: struct ReflectedLight {
  68:     vec3 directDiffuse;
  69:     vec3 directSpecular;
  70:     vec3 indirectDiffuse;
  71:     vec3 indirectSpecular;
  72: };
  73: struct GeometricContext {
  74:     vec3 position;
  75:     vec3 normal;
  76:     vec3 viewDir;
  77: };
  78: vec3 transformDirection( in vec3 dir, in mat4 matrix ) {
  79:     return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );
  80: }
  81: vec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {
  82:     return normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );
  83: }
  84: vec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {
  85:     float distance = dot( planeNormal, point - pointOnPlane );
  86:     return - distance * planeNormal + point;
  87: }
  88: float sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {
  89:     return sign( dot( point - pointOnPlane, planeNormal ) );
  90: }
  91: vec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {
  92:     return lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;
  93: }
  94: mat3 transposeMat3( const in mat3 m ) {
  95:     mat3 tmp;
  96:     tmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );
  97:     tmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );
  98:     tmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );
  99:     return tmp;
  100: }
  101: float linearToRelativeLuminance( const in vec3 color ) {
  102:    vec3 weights = vec3( 0.2126, 0.7152, 0.0722 );
  103:    return dot( weights, color.rgb );
  104: }
  105: 
  106: #if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )
  107:    varying vec2 vUv;
  108:    uniform mat3 uvTransform;
  109: #endif
  110: 
  111: #if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )
  112:    attribute vec2 uv2;
  113:    varying vec2 vUv2;
  114: #endif
  115: #ifdef USE_ENVMAP
  116:    #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )
  117:        varying vec3 vWorldPosition;
  118:    #else
  119:        varying vec3 vReflect;
  120:        uniform float refractionRatio;
  121:    #endif
  122: #endif
  123: 
  124: #ifdef USE_COLOR
  125:    varying vec3 vColor;
  126: #endif
  127: #ifdef USE_FOG
  128:   varying float fogDepth;
  129: #endif
  130: 
  131: #ifdef USE_MORPHTARGETS
  132:    #ifndef USE_MORPHNORMALS
  133:    uniform float morphTargetInfluences[ 8 ];
  134:    #else
  135:    uniform float morphTargetInfluences[ 4 ];
  136:    #endif
  137: #endif
  138: #ifdef USE_SKINNING
  139:    uniform mat4 bindMatrix;
  140:    uniform mat4 bindMatrixInverse;
  141:    #ifdef BONE_TEXTURE
  142:        uniform sampler2D boneTexture;
  143:        uniform int boneTextureSize;
  144:        mat4 getBoneMatrix( const in float i ) {
  145:            float j = i * 4.0;
  146:            float x = mod( j, float( boneTextureSize ) );
  147:            float y = floor( j / float( boneTextureSize ) );
  148:            float dx = 1.0 / float( boneTextureSize );
  149:            float dy = 1.0 / float( boneTextureSize );
  150:            y = dy * ( y + 0.5 );
  151:            vec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );
  152:            vec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );
  153:            vec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );
  154:            vec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );
  155:            mat4 bone = mat4( v1, v2, v3, v4 );
  156:            return bone;
  157:        }
  158:    #else
  159:        uniform mat4 boneMatrices[ MAX_BONES ];
  160:        mat4 getBoneMatrix( const in float i ) {
  161:            mat4 bone = boneMatrices[ int(i) ];
  162:            return bone;
  163:        }
  164:    #endif
  165: #endif
  166: 
  167: #ifdef USE_LOGDEPTHBUF
  168:    #ifdef USE_LOGDEPTHBUF_EXT
  169:        varying float vFragDepth;
  170:    #endif
  171:    uniform float logDepthBufFC;
  172: #endif
  173: #if 0 &gt; 0 &amp;&amp; ! defined( PHYSICAL ) &amp;&amp; ! defined( PHONG )
  174:    varying vec3 vViewPosition;
  175: #endif
  176: 
  177: #ifdef USE_FOG
  178:   varying float fogDepth;
  179: #endif
  180: 
  181: uniform float outlineThickness;
  182: vec4 calculateOutline( vec4 pos, vec3 objectNormal, vec4 skinned ) {
  183:    float thickness = outlineThickness;
  184:    const float ratio = 1.0;
  185:    vec4 pos2 = projectionMatrix * modelViewMatrix * vec4( skinned.xyz + objectNormal, 1.0 );
  186:    vec4 norm = normalize( pos - pos2 );
  187:    return pos + norm * thickness * pos.w * ratio;
  188: }
  189: void main() {
  190: #if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )
  191:    vUv = ( uvTransform * vec3( uv, 1 ) ).xy;
  192: #endif
  193: #if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )
  194:    vUv2 = uv2;
  195: #endif
  196: #ifdef USE_COLOR
  197:    vColor.xyz = color.xyz;
  198: #endif
  199: #ifdef USE_SKINNING
  200:    mat4 boneMatX = getBoneMatrix( skinIndex.x );
  201:    mat4 boneMatY = getBoneMatrix( skinIndex.y );
  202:    mat4 boneMatZ = getBoneMatrix( skinIndex.z );
  203:    mat4 boneMatW = getBoneMatrix( skinIndex.w );
  204: #endif
  205:    #ifdef USE_ENVMAP
  206: 
  207: vec3 objectNormal = vec3( normal );
  208: 
  209: #ifdef USE_MORPHNORMALS
  210:    objectNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];
  211:    objectNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];
  212:    objectNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];
  213:    objectNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];
  214: #endif
  215: 
  216: #ifdef USE_SKINNING
  217:    mat4 skinMatrix = mat4( 0.0 );
  218:    skinMatrix += skinWeight.x * boneMatX;
  219:    skinMatrix += skinWeight.y * boneMatY;
  220:    skinMatrix += skinWeight.z * boneMatZ;
  221:    skinMatrix += skinWeight.w * boneMatW;
  222:    skinMatrix  = bindMatrixInverse * skinMatrix * bindMatrix;
  223:    objectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;
  224: #endif
  225: 
  226: vec3 transformedNormal = normalMatrix * objectNormal;
  227: #ifdef FLIP_SIDED
  228:    transformedNormal = - transformedNormal;
  229: #endif
  230: 
  231:    #endif
  232: 
  233: vec3 transformed = vec3( position );
  234: 
  235: #ifdef USE_MORPHTARGETS
  236:    transformed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];
  237:    transformed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];
  238:    transformed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];
  239:    transformed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];
  240:    #ifndef USE_MORPHNORMALS
  241:    transformed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];
  242:    transformed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];
  243:    transformed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];
  244:    transformed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];
  245:    #endif
  246: #endif
  247: 
  248: #ifdef USE_SKINNING
  249:    vec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );
  250:    vec4 skinned = vec4( 0.0 );
  251:    skinned += boneMatX * skinVertex * skinWeight.x;
  252:    skinned += boneMatY * skinVertex * skinWeight.y;
  253:    skinned += boneMatZ * skinVertex * skinWeight.z;
  254:    skinned += boneMatW * skinVertex * skinWeight.w;
  255:    transformed = ( bindMatrixInverse * skinned ).xyz;
  256: #endif
  257: 
  258: vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );
  259: gl_Position = projectionMatrix * mvPosition;
  260: 
  261: #ifdef USE_LOGDEPTHBUF
  262:    #ifdef USE_LOGDEPTHBUF_EXT
  263:        vFragDepth = 1.0 + gl_Position.w;
  264:    #else
  265:        gl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;
  266:        gl_Position.z *= gl_Position.w;
  267:    #endif
  268: #endif
  269: 
  270: #if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )
  271:    vec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );
  272: #endif
  273: 
  274: #if 0 &gt; 0 &amp;&amp; ! defined( PHYSICAL ) &amp;&amp; ! defined( PHONG )
  275:    vViewPosition = - mvPosition.xyz;
  276: #endif
  277: 
  278: #ifdef USE_ENVMAP
  279:    #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )
  280:        vWorldPosition = worldPosition.xyz;
  281:    #else
  282:        vec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );
  283:        vec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );
  284:        #ifdef ENVMAP_MODE_REFLECTION
  285:            vReflect = reflect( cameraToVertex, worldNormal );
  286:        #else
  287:            vReflect = refract( cameraToVertex, worldNormal, refractionRatio );
  288:        #endif
  289:    #endif
  290: #endif
  291: 
  292: 
  293: #ifdef USE_FOG
  294: fogDepth = -mvPosition.z;
  295: #endif
  296: #if ! defined( LAMBERT ) &amp;&amp; ! defined( PHONG ) &amp;&amp; ! defined( TOON ) &amp;&amp; ! defined( PHYSICAL )
  297:    #ifndef USE_ENVMAP
  298:        vec3 objectNormal = normalize( normal );
  299:    #endif
  300: #endif
  301: #ifdef FLIP_SIDED
  302:    objectNormal = -objectNormal;
  303: #endif
  304: #ifdef DECLARE_TRANSFORMED
  305:    vec3 transformed = vec3( position );
  306: #endif
  307: gl_Position = calculateOutline( gl_Position, objectNormal, vec4( transformed, 1.0 ) );
  308: 
  309: #ifdef USE_FOG
  310: fogDepth = -mvPosition.z;
  311: #endif
  312: }
  </code></pre>
  
  <p>That code isn't in the OutlineEffect source.  But the way OutlineEffect works, it includes this code where it redefines the vertex shader code using a regex:</p>
  
  <pre><code>var vertexShader = originalVertexShader
              // put vertexShaderChunk right before "void main() {...}"
              .replace( /void\s+main\s*\(\s*\)/, vertexShaderChunk + '\nvoid main()' )
              // put vertexShaderChunk2 the end of "void main() {...}"
              // Note: here assums originalVertexShader ends with "}" of "void main() {...}"
              .replace( /\}\s*$/, vertexShaderChunk2 + '\n}' )
              // remove any light related lines
              // Note: here is very sensitive to originalVertexShader
              // TODO: consider safer way
              .replace( /#include\s+&lt;[\w_]*light[\w_]*&gt;/g, '' );
  </code></pre>
  
  <p>And here is the source dump from the error that refers to line 204 (note that I'm cutting these lengthy source dumps after the relevant line)</p>
  
  <pre><code>gl.getShaderInfoLog() vertex ERROR: 0:204: 'fogDepth' : redefinition
   1: precision highp float;
  2: precision highp int;
  3: #define SHADER_NAME ShaderMaterial
  4: #define VERTEX_TEXTURES
  5: #define GAMMA_FACTOR 2
  6: #define MAX_BONES 0
  7: #define USE_FOG
  8: #define BONE_TEXTURE
  9: #define FLIP_SIDED
  10: uniform mat4 modelMatrix;
  11: uniform mat4 modelViewMatrix;
  12: uniform mat4 projectionMatrix;
  13: uniform mat4 viewMatrix;
  14: uniform mat3 normalMatrix;
  15: uniform vec3 cameraPosition;
  16: attribute vec3 position;
  17: attribute vec3 normal;
  18: attribute vec2 uv;
  19: #ifdef USE_COLOR
  20:     attribute vec3 color;
  21: #endif
  22: #ifdef USE_MORPHTARGETS
  23:     attribute vec3 morphTarget0;
  24:     attribute vec3 morphTarget1;
  25:     attribute vec3 morphTarget2;
  26:     attribute vec3 morphTarget3;
  27:     #ifdef USE_MORPHNORMALS
  28:         attribute vec3 morphNormal0;
  29:         attribute vec3 morphNormal1;
  30:         attribute vec3 morphNormal2;
  31:         attribute vec3 morphNormal3;
  32:     #else
  33:         attribute vec3 morphTarget4;
  34:         attribute vec3 morphTarget5;
  35:         attribute vec3 morphTarget6;
  36:         attribute vec3 morphTarget7;
  37:     #endif
  38: #endif
  39: #ifdef USE_SKINNING
  40:     attribute vec4 skinIndex;
  41:     attribute vec4 skinWeight;
  42: #endif
  43: 
  44: #define PHONG
  45: varying vec3 vViewPosition;
  46: #ifndef FLAT_SHADED
  47:     varying vec3 vNormal;
  48: #endif
  49: #define PI 3.14159265359
  50: #define PI2 6.28318530718
  51: #define PI_HALF 1.5707963267949
  52: #define RECIPROCAL_PI 0.31830988618
  53: #define RECIPROCAL_PI2 0.15915494
  54: #define LOG2 1.442695
  55: #define EPSILON 1e-6
  56: #define saturate(a) clamp( a, 0.0, 1.0 )
  57: #define whiteCompliment(a) ( 1.0 - saturate( a ) )
  58: float pow2( const in float x ) { return x*x; }
  59: float pow3( const in float x ) { return x*x*x; }
  60: float pow4( const in float x ) { float x2 = x*x; return x2*x2; }
  61: float average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }
  62: highp float rand( const in vec2 uv ) {
  63:     const highp float a = 12.9898, b = 78.233, c = 43758.5453;
  64:     highp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );
  65:     return fract(sin(sn) * c);
  66: }
  67: struct IncidentLight {
  68:     vec3 color;
  69:     vec3 direction;
  70:     bool visible;
  71: };
  72: struct ReflectedLight {
  73:     vec3 directDiffuse;
  74:     vec3 directSpecular;
  75:     vec3 indirectDiffuse;
  76:     vec3 indirectSpecular;
  77: };
  78: struct GeometricContext {
  79:     vec3 position;
  80:     vec3 normal;
  81:     vec3 viewDir;
  82: };
  83: vec3 transformDirection( in vec3 dir, in mat4 matrix ) {
  84:     return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );
  85: }
  86: vec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {
  87:     return normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );
  88: }
  89: vec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {
  90:     float distance = dot( planeNormal, point - pointOnPlane );
  91:     return - distance * planeNormal + point;
  92: }
  93: float sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {
  94:     return sign( dot( point - pointOnPlane, planeNormal ) );
  95: }
  96: vec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {
  97:     return lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;
  98: }
  99: mat3 transposeMat3( const in mat3 m ) {
  100:    mat3 tmp;
  101:    tmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );
  102:    tmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );
  103:    tmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );
  104:    return tmp;
  105: }
  106: float linearToRelativeLuminance( const in vec3 color ) {
  107:    vec3 weights = vec3( 0.2126, 0.7152, 0.0722 );
  108:    return dot( weights, color.rgb );
  109: }
  110: 
  111: #if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )
  112:    varying vec2 vUv;
  113:    uniform mat3 uvTransform;
  114: #endif
  115: 
  116: #if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )
  117:    attribute vec2 uv2;
  118:    varying vec2 vUv2;
  119: #endif
  120: #ifdef USE_DISPLACEMENTMAP
  121:    uniform sampler2D displacementMap;
  122:    uniform float displacementScale;
  123:    uniform float displacementBias;
  124: #endif
  125: 
  126: #ifdef USE_ENVMAP
  127:    #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )
  128:        varying vec3 vWorldPosition;
  129:    #else
  130:        varying vec3 vReflect;
  131:        uniform float refractionRatio;
  132:    #endif
  133: #endif
  134: 
  135: #ifdef USE_COLOR
  136:    varying vec3 vColor;
  137: #endif
  138: #ifdef USE_FOG
  139:   varying float fogDepth;
  140: #endif
  141: 
  142: #ifdef USE_MORPHTARGETS
  143:    #ifndef USE_MORPHNORMALS
  144:    uniform float morphTargetInfluences[ 8 ];
  145:    #else
  146:    uniform float morphTargetInfluences[ 4 ];
  147:    #endif
  148: #endif
  149: #ifdef USE_SKINNING
  150:    uniform mat4 bindMatrix;
  151:    uniform mat4 bindMatrixInverse;
  152:    #ifdef BONE_TEXTURE
  153:        uniform sampler2D boneTexture;
  154:        uniform int boneTextureSize;
  155:        mat4 getBoneMatrix( const in float i ) {
  156:            float j = i * 4.0;
  157:            float x = mod( j, float( boneTextureSize ) );
  158:            float y = floor( j / float( boneTextureSize ) );
  159:            float dx = 1.0 / float( boneTextureSize );
  160:            float dy = 1.0 / float( boneTextureSize );
  161:            y = dy * ( y + 0.5 );
  162:            vec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );
  163:            vec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );
  164:            vec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );
  165:            vec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );
  166:            mat4 bone = mat4( v1, v2, v3, v4 );
  167:            return bone;
  168:        }
  169:    #else
  170:        uniform mat4 boneMatrices[ MAX_BONES ];
  171:        mat4 getBoneMatrix( const in float i ) {
  172:            mat4 bone = boneMatrices[ int(i) ];
  173:            return bone;
  174:        }
  175:    #endif
  176: #endif
  177: 
  178: #ifdef USE_SHADOWMAP
  179:    #if 1 &gt; 0
  180:        uniform mat4 directionalShadowMatrix[ 1 ];
  181:        varying vec4 vDirectionalShadowCoord[ 1 ];
  182:    #endif
  183:    #if 0 &gt; 0
  184:        uniform mat4 spotShadowMatrix[ 0 ];
  185:        varying vec4 vSpotShadowCoord[ 0 ];
  186:    #endif
  187:    #if 4 &gt; 0
  188:        uniform mat4 pointShadowMatrix[ 4 ];
  189:        varying vec4 vPointShadowCoord[ 4 ];
  190:    #endif
  191: #endif
  192: 
  193: #ifdef USE_LOGDEPTHBUF
  194:    #ifdef USE_LOGDEPTHBUF_EXT
  195:        varying float vFragDepth;
  196:    #endif
  197:    uniform float logDepthBufFC;
  198: #endif
  199: #if 0 &gt; 0 &amp;&amp; ! defined( PHYSICAL ) &amp;&amp; ! defined( PHONG )
  200:    varying vec3 vViewPosition;
  201: #endif
  202: 
  203: #ifdef USE_FOG
  204:   varying float fogDepth;
  205: #endif
  206: 
  207: uniform float outlineThickness;
  208: vec4 calculateOutline( vec4 pos, vec3 objectNormal, vec4 skinned ) {
  209:    float thickness = outlineThickness;
  210:    const float ratio = 1.0;
  211:    vec4 pos2 = projectionMatrix * modelViewMatrix * vec4( skinned.xyz + objectNormal, 1.0 );
  212:    vec4 norm = normalize( pos - pos2 );
  213:    return pos + norm * thickness * pos.w * ratio;
  214: }
  215: void main() {
  216: #if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )
  217:    vUv = ( uvTransform * vec3( uv, 1 ) ).xy;
  218: #endif
  219: #if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )
  220:    vUv2 = uv2;
  221: #endif
  222: #ifdef USE_COLOR
  223:    vColor.xyz = color.xyz;
  224: #endif
  225: 
  226: vec3 objectNormal = vec3( normal );
  227: 
  228: #ifdef USE_MORPHNORMALS
  229:    objectNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];
  230:    objectNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];
  231:    objectNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];
  232:    objectNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];
  233: #endif
  234: 
  235: #ifdef USE_SKINNING
  236:    mat4 boneMatX = getBoneMatrix( skinIndex.x );
  237:    mat4 boneMatY = getBoneMatrix( skinIndex.y );
  238:    mat4 boneMatZ = getBoneMatrix( skinIndex.z );
  239:    mat4 boneMatW = getBoneMatrix( skinIndex.w );
  240: #endif
  241: #ifdef USE_SKINNING
  242:    mat4 skinMatrix = mat4( 0.0 );
  243:    skinMatrix += skinWeight.x * boneMatX;
  244:    skinMatrix += skinWeight.y * boneMatY;
  245:    skinMatrix += skinWeight.z * boneMatZ;
  246:    skinMatrix += skinWeight.w * boneMatW;
  247:    skinMatrix  = bindMatrixInverse * skinMatrix * bindMatrix;
  248:    objectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;
  249: #endif
  250: 
  251: vec3 transformedNormal = normalMatrix * objectNormal;
  252: #ifdef FLIP_SIDED
  253:    transformedNormal = - transformedNormal;
  254: #endif
  255: 
  256: #ifndef FLAT_SHADED
  257:    vNormal = normalize( transformedNormal );
  258: #endif
  259: 
  260: vec3 transformed = vec3( position );
  261: 
  262: #ifdef USE_MORPHTARGETS
  263:    transformed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];
  264:    transformed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];
  265:    transformed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];
  266:    transformed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];
  267:    #ifndef USE_MORPHNORMALS
  268:    transformed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];
  269:    transformed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];
  270:    transformed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];
  271:    transformed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];
  272:    #endif
  273: #endif
  274: 
  275: #ifdef USE_SKINNING
  276:    vec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );
  277:    vec4 skinned = vec4( 0.0 );
  278:    skinned += boneMatX * skinVertex * skinWeight.x;
  279:    skinned += boneMatY * skinVertex * skinWeight.y;
  280:    skinned += boneMatZ * skinVertex * skinWeight.z;
  281:    skinned += boneMatW * skinVertex * skinWeight.w;
  282:    transformed = ( bindMatrixInverse * skinned ).xyz;
  283: #endif
  284: 
  285: #ifdef USE_DISPLACEMENTMAP
  286:    transformed += normalize( objectNormal ) * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );
  287: #endif
  288: 
  289: vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );
  290: gl_Position = projectionMatrix * mvPosition;
  291: 
  292: #ifdef USE_LOGDEPTHBUF
  293:    #ifdef USE_LOGDEPTHBUF_EXT
  294:        vFragDepth = 1.0 + gl_Position.w;
  295:    #else
  296:        gl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;
  297:        gl_Position.z *= gl_Position.w;
  298:    #endif
  299: #endif
  300: 
  301: #if 0 &gt; 0 &amp;&amp; ! defined( PHYSICAL ) &amp;&amp; ! defined( PHONG )
  302:    vViewPosition = - mvPosition.xyz;
  303: #endif
  304: 
  305:    vViewPosition = - mvPosition.xyz;
  306: #if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )
  307:    vec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );
  308: #endif
  309: 
  310: #ifdef USE_ENVMAP
  311:    #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )
  312:        vWorldPosition = worldPosition.xyz;
  313:    #else
  314:        vec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );
  315:        vec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );
  316:        #ifdef ENVMAP_MODE_REFLECTION
  317:            vReflect = reflect( cameraToVertex, worldNormal );
  318:        #else
  319:            vReflect = refract( cameraToVertex, worldNormal, refractionRatio );
  320:        #endif
  321:    #endif
  322: #endif
  323: 
  324: #ifdef USE_SHADOWMAP
  325:    #if 1 &gt; 0
  326:    
  327:        vDirectionalShadowCoord[ 0 ] = directionalShadowMatrix[ 0 ] * worldPosition;
  328:    
  329:    #endif
  330:    #if 0 &gt; 0
  331:    
  332:    #endif
  333:    #if 4 &gt; 0
  334:    
  335:        vPointShadowCoord[ 0 ] = pointShadowMatrix[ 0 ] * worldPosition;
  336:    
  337:        vPointShadowCoord[ 1 ] = pointShadowMatrix[ 1 ] * worldPosition;
  338:    
  339:        vPointShadowCoord[ 2 ] = pointShadowMatrix[ 2 ] * worldPosition;
  340:    
  341:        vPointShadowCoord[ 3 ] = pointShadowMatrix[ 3 ] * worldPosition;
  342:    
  343:    #endif
  344: #endif
  345: 
  346: 
  347: #ifdef USE_FOG
  348: fogDepth = -mvPosition.z;
  349: #endif
  350: #if ! defined( LAMBERT ) &amp;&amp; ! defined( PHONG ) &amp;&amp; ! defined( TOON ) &amp;&amp; ! defined( PHYSICAL )
  351:    #ifndef USE_ENVMAP
  352:        vec3 objectNormal = normalize( normal );
  353:    #endif
  354: #endif
  355: #ifdef FLIP_SIDED
  356:    objectNormal = -objectNormal;
  357: #endif
  358: #ifdef DECLARE_TRANSFORMED
  359:    vec3 transformed = vec3( position );
  360: #endif
  361: gl_Position = calculateOutline( gl_Position, objectNormal, vec4( transformed, 1.0 ) );
  362: 
  363: #ifdef USE_FOG
  364: fogDepth = -mvPosition.z;
  365: #endif
  366: }
  </code></pre>