three library
Exports
Properties
final ShaderChunk #
get ShaderChunk {
if (__ShaderChunk == null) {
__ShaderChunk = {
// FOG
"fog_pars_fragment": [
"#ifdef USE_FOG",
"uniform vec3 fogColor;",
"#ifdef FOG_EXP2",
"uniform float fogDensity;",
"#else",
"uniform float fogNear;",
"uniform float fogFar;",
"#endif",
"#endif"
].join("\n"),
"fog_fragment": [
"#ifdef USE_FOG",
"float depth = gl_FragCoord.z / gl_FragCoord.w;",
"#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"
].join("\n"),
// ENVIRONMENT MAP
"envmap_pars_fragment": [
"#ifdef USE_ENVMAP",
"uniform float reflectivity;",
"uniform samplerCube envMap;",
"uniform float flipEnvMap;",
"uniform int combine;",
"#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )",
"uniform bool useRefract;",
"uniform float refractionRatio;",
"#else",
"varying vec3 vReflect;",
"#endif",
"#endif"
].join("\n"),
"envmap_fragment": [
"#ifdef USE_ENVMAP",
"vec3 reflectVec;",
"#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )",
"vec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );",
"if ( useRefract ) {",
"reflectVec = refract( cameraToVertex, normal, refractionRatio );",
"} else { ",
"reflectVec = reflect( cameraToVertex, normal );",
"}",
"#else",
"reflectVec = vReflect;",
"#endif",
"#ifdef DOUBLE_SIDED",
"float flipNormal = ( -1.0 + 2.0 * float( gl_FrontFacing ) );",
"vec4 cubeColor = textureCube( envMap, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );",
"#else",
"vec4 cubeColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );",
"#endif",
"#ifdef GAMMA_INPUT",
"cubeColor.xyz *= cubeColor.xyz;",
"#endif",
"if ( combine == 1 ) {",
"gl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularStrength * reflectivity );",
"} else if ( combine == 2 ) {",
"gl_FragColor.xyz += cubeColor.xyz * specularStrength * reflectivity;",
"} else {",
"gl_FragColor.xyz = mix( gl_FragColor.xyz, gl_FragColor.xyz * cubeColor.xyz, specularStrength * reflectivity );",
"}",
"#endif"
].join("\n"),
"envmap_pars_vertex": [
"#if defined( USE_ENVMAP ) && ! defined( USE_BUMPMAP ) && ! defined( USE_NORMALMAP )",
"varying vec3 vReflect;",
"uniform float refractionRatio;",
"uniform bool useRefract;",
"#endif"
].join("\n"),
"worldpos_vertex" : [
"#if defined( USE_ENVMAP ) || defined( PHONG ) || defined( LAMBERT ) || defined ( USE_SHADOWMAP )",
"#ifdef USE_SKINNING",
"vec4 worldPosition = modelMatrix * skinned;",
"#endif",
"#if defined( USE_MORPHTARGETS ) && ! defined( USE_SKINNING )",
"vec4 worldPosition = modelMatrix * vec4( morphed, 1.0 );",
"#endif",
"#if ! defined( USE_MORPHTARGETS ) && ! defined( USE_SKINNING )",
"vec4 worldPosition = modelMatrix * vec4( position, 1.0 );",
"#endif",
"#endif"
].join("\n"),
"envmap_vertex" : [
"#if defined( USE_ENVMAP ) && ! defined( USE_BUMPMAP ) && ! defined( USE_NORMALMAP )",
"vec3 worldNormal = mat3( modelMatrix[ 0 ].xyz, modelMatrix[ 1 ].xyz, modelMatrix[ 2 ].xyz ) * objectNormal;",
"worldNormal = normalize( worldNormal );",
"vec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );",
"if ( useRefract ) {",
"vReflect = refract( cameraToVertex, worldNormal, refractionRatio );",
"} else {",
"vReflect = reflect( cameraToVertex, worldNormal );",
"}",
"#endif"
].join("\n"),
// COLOR MAP (particles)
"map_particle_pars_fragment": [
"#ifdef USE_MAP",
"uniform sampler2D map;",
"#endif"
].join("\n"),
"map_particle_fragment": [
"#ifdef USE_MAP",
"gl_FragColor = gl_FragColor * texture2D( map, vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y ) );",
"#endif"
].join("\n"),
// COLOR MAP (triangles)
"map_pars_vertex": [
"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP )",
"varying vec2 vUv;",
"uniform vec4 offsetRepeat;",
"#endif"
].join("\n"),
"map_pars_fragment": [
"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP )",
"varying vec2 vUv;",
"#endif",
"#ifdef USE_MAP",
"uniform sampler2D map;",
"#endif"
].join("\n"),
"map_vertex": [
"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP )",
"vUv = uv * offsetRepeat.zw + offsetRepeat.xy;",
"#endif"
].join("\n"),
"map_fragment": [
"#ifdef USE_MAP",
"vec4 texelColor = texture2D( map, vUv );",
"#ifdef GAMMA_INPUT",
"texelColor.xyz *= texelColor.xyz;",
"#endif",
"gl_FragColor = gl_FragColor * texelColor;",
"#endif"
].join("\n"),
// LIGHT MAP
"lightmap_pars_fragment": [
"#ifdef USE_LIGHTMAP",
"varying vec2 vUv2;",
"uniform sampler2D lightMap;",
"#endif"
].join("\n"),
"lightmap_pars_vertex": [
"#ifdef USE_LIGHTMAP",
"varying vec2 vUv2;",
"#endif"
].join("\n"),
"lightmap_fragment": [
"#ifdef USE_LIGHTMAP",
"gl_FragColor = gl_FragColor * texture2D( lightMap, vUv2 );",
"#endif"
].join("\n"),
"lightmap_vertex": [
"#ifdef USE_LIGHTMAP",
"vUv2 = uv2;",
"#endif"
].join("\n"),
// BUMP MAP
"bumpmap_pars_fragment": [
"#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"
].join("\n"),
// NORMAL MAP
"normalmap_pars_fragment": [
"#ifdef USE_NORMALMAP",
"uniform sampler2D normalMap;",
"uniform vec2 normalScale;",
// Per-Pixel Tangent Space Normal Mapping
// http://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"
].join("\n"),
// SPECULAR MAP
"specularmap_pars_fragment": [
"#ifdef USE_SPECULARMAP",
"uniform sampler2D specularMap;",
"#endif"
].join("\n"),
"specularmap_fragment": [
"float specularStrength;",
"#ifdef USE_SPECULARMAP",
"vec4 texelSpecular = texture2D( specularMap, vUv );",
"specularStrength = texelSpecular.r;",
"#else",
"specularStrength = 1.0;",
"#endif"
].join("\n"),
// LIGHTS LAMBERT
"lights_lambert_pars_vertex": [
"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"
].join("\n"),
"lights_lambert_vertex": [
"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( spotEffect, 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"
].join("\n"),
// LIGHTS PHONG
"lights_phong_pars_vertex": [
"#ifndef PHONG_PER_PIXEL",
"#if MAX_POINT_LIGHTS > 0",
"uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
"uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
"varying vec4 vPointLight[ MAX_POINT_LIGHTS ];",
"#endif",
"#if MAX_SPOT_LIGHTS > 0",
"uniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];",
"uniform float spotLightDistance[ MAX_SPOT_LIGHTS ];",
"varying vec4 vSpotLight[ MAX_SPOT_LIGHTS ];",
"#endif",
"#endif",
"#if MAX_SPOT_LIGHTS > 0 || defined( USE_BUMPMAP )",
"varying vec3 vWorldPosition;",
"#endif"
].join("\n"),
"lights_phong_vertex": [
"#ifndef PHONG_PER_PIXEL",
"#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 );",
"vPointLight[ i ] = vec4( lVector, lDistance );",
"}",
"#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 lDistance = 1.0;",
"if ( spotLightDistance[ i ] > 0.0 )",
"lDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );",
"vSpotLight[ i ] = vec4( lVector, lDistance );",
"}",
"#endif",
"#endif",
"#if MAX_SPOT_LIGHTS > 0 || defined( USE_BUMPMAP )",
"vWorldPosition = worldPosition.xyz;",
"#endif"
].join("\n"),
"lights_phong_pars_fragment": [
"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 ];",
"#ifdef PHONG_PER_PIXEL",
"uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
"uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
"#else",
"varying vec4 vPointLight[ MAX_POINT_LIGHTS ];",
"#endif",
"#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 ];",
"#ifdef PHONG_PER_PIXEL",
"uniform float spotLightDistance[ MAX_SPOT_LIGHTS ];",
"#else",
"varying vec4 vSpotLight[ MAX_SPOT_LIGHTS ];",
"#endif",
"#endif",
"#if MAX_SPOT_LIGHTS > 0 || defined( USE_BUMPMAP )",
"varying vec3 vWorldPosition;",
"#endif",
"#ifdef WRAP_AROUND",
"uniform vec3 wrapRGB;",
"#endif",
"varying vec3 vViewPosition;",
"varying vec3 vNormal;"
].join("\n"),
"lights_phong_fragment": [
"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( -viewPosition, 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 ++ ) {",
"#ifdef PHONG_PER_PIXEL",
"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 );",
"#else",
"vec3 lVector = normalize( vPointLight[ i ].xyz );",
"float lDistance = vPointLight[ i ].w;",
"#endif",
// 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 );",
"#ifdef PHYSICALLY_BASED_SHADING",
// 2.0 => 2.0001 is hack to work around ANGLE bug
"float specularNormalization = ( shininess + 2.0001 ) / 8.0;",
"vec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, pointHalfVector ), 5.0 );",
"pointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance * specularNormalization;",
"#else",
"pointSpecular += specular * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance;",
"#endif",
"}",
"#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 ++ ) {",
"#ifdef PHONG_PER_PIXEL",
"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 );",
"#else",
"vec3 lVector = normalize( vSpotLight[ i ].xyz );",
"float lDistance = vSpotLight[ i ].w;",
"#endif",
"float spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) );",
"if ( spotEffect > spotLightAngleCos[ i ] ) {",
"spotEffect = max( pow( spotEffect, 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 );",
"#ifdef PHYSICALLY_BASED_SHADING",
// 2.0 => 2.0001 is hack to work around ANGLE bug
"float specularNormalization = ( shininess + 2.0001 ) / 8.0;",
"vec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, spotHalfVector ), 5.0 );",
"spotSpecular += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * specularNormalization * spotEffect;",
"#else",
"spotSpecular += specular * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * spotEffect;",
"#endif",
"}",
"}",
"#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 );",
"#ifdef PHYSICALLY_BASED_SHADING",
/*
// 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 );",
*/
// 2.0 => 2.0001 is hack to work around ANGLE bug
"float specularNormalization = ( shininess + 2.0001 ) / 8.0;",
//"dirSpecular += specular * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization * fresnel;",
"vec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( dirVector, dirHalfVector ), 5.0 );",
"dirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;",
"#else",
"dirSpecular += specular * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight;",
"#endif",
"}",
"#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( hemiDotNormalHalfSky, 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( hemiDotNormalHalfGround, shininess ), 0.0 );",
"#ifdef PHYSICALLY_BASED_SHADING",
"float dotProductGround = dot( normal, lVectorGround );",
// 2.0 => 2.0001 is hack to work around ANGLE bug
"float specularNormalization = ( shininess + 2.0001 ) / 8.0;",
"vec3 schlickSky = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, hemiHalfVectorSky ), 5.0 );",
"vec3 schlickGround = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVectorGround, hemiHalfVectorGround ), 5.0 );",
"hemiSpecular += hemiColor * specularNormalization * ( schlickSky * hemiSpecularWeightSky * max( dotProduct, 0.0 ) + schlickGround * hemiSpecularWeightGround * max( dotProductGround, 0.0 ) );",
"#else",
"hemiSpecular += specular * hemiColor * ( hemiSpecularWeightSky + hemiSpecularWeightGround ) * hemiDiffuseWeight;",
"#endif",
"}",
"#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"
].join("\n"),
// VERTEX COLORS
"color_pars_fragment": [
"#ifdef USE_COLOR",
"varying vec3 vColor;",
"#endif"
].join("\n"),
"color_fragment": [
"#ifdef USE_COLOR",
"gl_FragColor = gl_FragColor * vec4( vColor, opacity );",
"#endif"
].join("\n"),
"color_pars_vertex": [
"#ifdef USE_COLOR",
"varying vec3 vColor;",
"#endif"
].join("\n"),
"color_vertex": [
"#ifdef USE_COLOR",
"#ifdef GAMMA_INPUT",
"vColor = color * color;",
"#else",
"vColor = color;",
"#endif",
"#endif"
].join("\n"),
// SKINNING
"skinning_pars_vertex": [
"#ifdef USE_SKINNING",
"#ifdef BONE_TEXTURE",
"uniform sampler2D boneTexture;",
"mat4 getBoneMatrix( const in float i ) {",
"float j = i * 4.0;",
"float x = mod( j, N_BONE_PIXEL_X );",
"float y = floor( j / N_BONE_PIXEL_X );",
"const float dx = 1.0 / N_BONE_PIXEL_X;",
"const float dy = 1.0 / N_BONE_PIXEL_Y;",
"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"
].join("\n"),
"skinbase_vertex": [
"#ifdef USE_SKINNING",
"mat4 boneMatX = getBoneMatrix( skinIndex.x );",
"mat4 boneMatY = getBoneMatrix( skinIndex.y );",
"#endif"
].join("\n"),
"skinning_vertex": [
"#ifdef USE_SKINNING",
"#ifdef USE_MORPHTARGETS",
"vec4 skinVertex = vec4( morphed, 1.0 );",
"#else",
"vec4 skinVertex = vec4( position, 1.0 );",
"#endif",
"vec4 skinned = boneMatX * skinVertex * skinWeight.x;",
"skinned += boneMatY * skinVertex * skinWeight.y;",
"#endif"
].join("\n"),
// MORPHING
"morphtarget_pars_vertex": [
"#ifdef USE_MORPHTARGETS",
"#ifndef USE_MORPHNORMALS",
"uniform float morphTargetInfluences[ 8 ];",
"#else",
"uniform float morphTargetInfluences[ 4 ];",
"#endif",
"#endif"
].join("\n"),
"morphtarget_vertex": [
"#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"
].join("\n"),
"default_vertex" : [
"vec4 mvPosition;",
"#ifdef USE_SKINNING",
"mvPosition = modelViewMatrix * skinned;",
"#endif",
"#if !defined( USE_SKINNING ) && defined( USE_MORPHTARGETS )",
"mvPosition = modelViewMatrix * vec4( morphed, 1.0 );",
"#endif",
"#if !defined( USE_SKINNING ) && ! defined( USE_MORPHTARGETS )",
"mvPosition = modelViewMatrix * vec4( position, 1.0 );",
"#endif",
"gl_Position = projectionMatrix * mvPosition;"
].join("\n"),
"morphnormal_vertex": [
"#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"
].join("\n"),
"skinnormal_vertex": [
"#ifdef USE_SKINNING",
"mat4 skinMatrix = skinWeight.x * boneMatX;",
"skinMatrix += skinWeight.y * boneMatY;",
"#ifdef USE_MORPHNORMALS",
"vec4 skinnedNormal = skinMatrix * vec4( morphedNormal, 0.0 );",
"#else",
"vec4 skinnedNormal = skinMatrix * vec4( normal, 0.0 );",
"#endif",
"#endif"
].join("\n"),
"defaultnormal_vertex": [
"vec3 objectNormal;",
"#ifdef USE_SKINNING",
"objectNormal = skinnedNormal.xyz;",
"#endif",
"#if !defined( USE_SKINNING ) && defined( USE_MORPHNORMALS )",
"objectNormal = morphedNormal;",
"#endif",
"#if !defined( USE_SKINNING ) && ! defined( USE_MORPHNORMALS )",
"objectNormal = normal;",
"#endif",
"#ifdef FLIP_SIDED",
"objectNormal = -objectNormal;",
"#endif",
"vec3 transformedNormal = normalMatrix * objectNormal;"
].join("\n"),
// SHADOW MAP
// based on SpiderGL shadow map and Fabien Sanglard's GLSL shadow mapping examples
// http://spidergl.org/example.php?id=6
// http://fabiensanglard.net/shadowmapping
"shadowmap_pars_fragment": [
"#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"
].join("\n"),
"shadowmap_fragment": [
"#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 ) ) );",
"if ( depthKernel[0][0] < shadowCoord.z ) shadowKernel[0][0] = 0.25;",
"else shadowKernel[0][0] = 0.0;",
"depthKernel[0][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );",
"if ( depthKernel[0][1] < shadowCoord.z ) shadowKernel[0][1] = 0.25;",
"else shadowKernel[0][1] = 0.0;",
"depthKernel[0][2] = unpackDepth( texture2D( shadowMap[ i], shadowCoord.xy + vec2( dx0, dy1 ) ) );",
"if ( depthKernel[0][2] < shadowCoord.z ) shadowKernel[0][2] = 0.25;",
"else shadowKernel[0][2] = 0.0;",
"depthKernel[1][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );",
"if ( depthKernel[1][0] < shadowCoord.z ) shadowKernel[1][0] = 0.25;",
"else shadowKernel[1][0] = 0.0;",
"depthKernel[1][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );",
"if ( depthKernel[1][1] < shadowCoord.z ) shadowKernel[1][1] = 0.25;",
"else shadowKernel[1][1] = 0.0;",
"depthKernel[1][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );",
"if ( depthKernel[1][2] < shadowCoord.z ) shadowKernel[1][2] = 0.25;",
"else shadowKernel[1][2] = 0.0;",
"depthKernel[2][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );",
"if ( depthKernel[2][0] < shadowCoord.z ) shadowKernel[2][0] = 0.25;",
"else shadowKernel[2][0] = 0.0;",
"depthKernel[2][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );",
"if ( depthKernel[2][1] < shadowCoord.z ) shadowKernel[2][1] = 0.25;",
"else shadowKernel[2][1] = 0.0;",
"depthKernel[2][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );",
"if ( depthKernel[2][2] < shadowCoord.z ) shadowKernel[2][2] = 0.25;",
"else shadowKernel[2][2] = 0.0;",
"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"
].join("\n"),
"shadowmap_pars_vertex": [
"#ifdef USE_SHADOWMAP",
"varying vec4 vShadowCoord[ MAX_SHADOWS ];",
"uniform mat4 shadowMatrix[ MAX_SHADOWS ];",
"#endif"
].join("\n"),
"shadowmap_vertex": [
"#ifdef USE_SHADOWMAP",
"for( int i = 0; i < MAX_SHADOWS; i ++ ) {",
"vShadowCoord[ i ] = shadowMatrix[ i ] * worldPosition;",
"}",
"#endif"
].join("\n"),
// ALPHATEST
"alphatest_fragment": [
"#ifdef ALPHATEST",
"if ( gl_FragColor.a < ALPHATEST ) discard;",
"#endif"
].join("\n"),
// LINEAR SPACE
"linear_to_gamma_fragment": [
"#ifdef GAMMA_OUTPUT",
"gl_FragColor.xyz = sqrt( gl_FragColor.xyz );",
"#endif"
].join("\n")
};
}
return __ShaderChunk;
}
final ShaderLib #
get ShaderLib {
if (__ShaderLib == null) {
__ShaderLib = {
'depth': {
'uniforms': {
"mNear": new Uniform.float(1.0),
"mFar" : new Uniform.float(2000.0),
"opacity" : new Uniform.float(1.0)
},
'vertexShader': [
"void main() {",
"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
"}"
].join("\n"),
'fragmentShader': [
"uniform float mNear;",
"uniform float mFar;",
"uniform float opacity;",
"void main() {",
"float depth = gl_FragCoord.z / gl_FragCoord.w;",
"float color = 1.0 - smoothstep( mNear, mFar, depth );",
"gl_FragColor = vec4( vec3( color ), opacity );",
"}"
].join("\n")
},
'normal': {
'uniforms': {
"opacity" : new Uniform.float(1.0)
},
'vertexShader': [
"varying vec3 vNormal;",
"void main() {",
"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
"vNormal = normalize( normalMatrix * normal );",
"gl_Position = projectionMatrix * mvPosition;",
"}"
].join("\n"),
'fragmentShader': [
"uniform float opacity;",
"varying vec3 vNormal;",
"void main() {",
"gl_FragColor = vec4( 0.5 * normalize( vNormal ) + 0.5, opacity );",
"}"
].join("\n")
},
'basic': {
'uniforms': UniformsUtils.merge( [UniformsLib[ "common" ],
UniformsLib[ "fog" ],
UniformsLib[ "shadowmap" ]] ),
'vertexShader': [
ShaderChunk[ "map_pars_vertex" ],
ShaderChunk[ "lightmap_pars_vertex" ],
ShaderChunk[ "envmap_pars_vertex" ],
ShaderChunk[ "color_pars_vertex" ],
ShaderChunk[ "morphtarget_pars_vertex" ],
ShaderChunk[ "skinning_pars_vertex" ],
ShaderChunk[ "shadowmap_pars_vertex" ],
"void main() {",
ShaderChunk[ "map_vertex" ],
ShaderChunk[ "lightmap_vertex" ],
ShaderChunk[ "color_vertex" ],
ShaderChunk[ "skinbase_vertex" ],
"#ifdef USE_ENVMAP",
ShaderChunk[ "morphnormal_vertex" ],
ShaderChunk[ "skinnormal_vertex" ],
ShaderChunk[ "defaultnormal_vertex" ],
"#endif",
ShaderChunk[ "morphtarget_vertex" ],
ShaderChunk[ "skinning_vertex" ],
ShaderChunk[ "default_vertex" ],
ShaderChunk[ "worldpos_vertex" ],
ShaderChunk[ "envmap_vertex" ],
ShaderChunk[ "shadowmap_vertex" ],
"}"
].join("\n"),
'fragmentShader': [
"uniform vec3 diffuse;",
"uniform float opacity;",
ShaderChunk[ "color_pars_fragment" ],
ShaderChunk[ "map_pars_fragment" ],
ShaderChunk[ "lightmap_pars_fragment" ],
ShaderChunk[ "envmap_pars_fragment" ],
ShaderChunk[ "fog_pars_fragment" ],
ShaderChunk[ "shadowmap_pars_fragment" ],
ShaderChunk[ "specularmap_pars_fragment" ],
"void main() {",
"gl_FragColor = vec4( diffuse, opacity );",
ShaderChunk[ "map_fragment" ],
ShaderChunk[ "alphatest_fragment" ],
ShaderChunk[ "specularmap_fragment" ],
ShaderChunk[ "lightmap_fragment" ],
ShaderChunk[ "color_fragment" ],
ShaderChunk[ "envmap_fragment" ],
ShaderChunk[ "shadowmap_fragment" ],
ShaderChunk[ "linear_to_gamma_fragment" ],
ShaderChunk[ "fog_fragment" ],
"}"
].join("\n")
},
'lambert': {
'uniforms': UniformsUtils.merge( [
UniformsLib[ "common" ],
UniformsLib[ "fog" ],
UniformsLib[ "lights" ],
UniformsLib[ "shadowmap" ],
{
"ambient" : new Uniform.color(0xffffff),
"emissive" : new Uniform.color(0x000000),
"wrapRGB" : new Uniform.vector3(1.0, 1.0, 1.0)
}
] ),
'vertexShader': [
"#define LAMBERT",
"varying vec3 vLightFront;",
"#ifdef DOUBLE_SIDED",
"varying vec3 vLightBack;",
"#endif",
ShaderChunk[ "map_pars_vertex" ],
ShaderChunk[ "lightmap_pars_vertex" ],
ShaderChunk[ "envmap_pars_vertex" ],
ShaderChunk[ "lights_lambert_pars_vertex" ],
ShaderChunk[ "color_pars_vertex" ],
ShaderChunk[ "morphtarget_pars_vertex" ],
ShaderChunk[ "skinning_pars_vertex" ],
ShaderChunk[ "shadowmap_pars_vertex" ],
"void main() {",
ShaderChunk[ "map_vertex" ],
ShaderChunk[ "lightmap_vertex" ],
ShaderChunk[ "color_vertex" ],
ShaderChunk[ "morphnormal_vertex" ],
ShaderChunk[ "skinbase_vertex" ],
ShaderChunk[ "skinnormal_vertex" ],
ShaderChunk[ "defaultnormal_vertex" ],
ShaderChunk[ "morphtarget_vertex" ],
ShaderChunk[ "skinning_vertex" ],
ShaderChunk[ "default_vertex" ],
ShaderChunk[ "worldpos_vertex" ],
ShaderChunk[ "envmap_vertex" ],
ShaderChunk[ "lights_lambert_vertex" ],
ShaderChunk[ "shadowmap_vertex" ],
"}"
].join("\n"),
'fragmentShader': [
"uniform float opacity;",
"varying vec3 vLightFront;",
"#ifdef DOUBLE_SIDED",
"varying vec3 vLightBack;",
"#endif",
ShaderChunk[ "color_pars_fragment" ],
ShaderChunk[ "map_pars_fragment" ],
ShaderChunk[ "lightmap_pars_fragment" ],
ShaderChunk[ "envmap_pars_fragment" ],
ShaderChunk[ "fog_pars_fragment" ],
ShaderChunk[ "shadowmap_pars_fragment" ],
ShaderChunk[ "specularmap_pars_fragment" ],
"void main() {",
"gl_FragColor = vec4( vec3 ( 1.0 ), opacity );",
ShaderChunk[ "map_fragment" ],
ShaderChunk[ "alphatest_fragment" ],
ShaderChunk[ "specularmap_fragment" ],
"#ifdef DOUBLE_SIDED",
//"float isFront = float( gl_FrontFacing );",
//"gl_FragColor.xyz *= isFront * vLightFront + ( 1.0 - isFront ) * vLightBack;",
"if ( gl_FrontFacing )",
"gl_FragColor.xyz *= vLightFront;",
"else",
"gl_FragColor.xyz *= vLightBack;",
"#else",
"gl_FragColor.xyz *= vLightFront;",
"#endif",
ShaderChunk[ "lightmap_fragment" ],
ShaderChunk[ "color_fragment" ],
ShaderChunk[ "envmap_fragment" ],
ShaderChunk[ "shadowmap_fragment" ],
ShaderChunk[ "linear_to_gamma_fragment" ],
ShaderChunk[ "fog_fragment" ],
"}"
].join("\n")
},
'phong': {
'uniforms': UniformsUtils.merge( [
UniformsLib[ "common" ],
UniformsLib[ "bump" ],
UniformsLib[ "normalmap" ],
UniformsLib[ "fog" ],
UniformsLib[ "lights" ],
UniformsLib[ "shadowmap" ],
{
"ambient" : new Uniform.color(0xffffff),
"emissive" : new Uniform.color(0x000000),
"specular" : new Uniform.color(0x111111),
"shininess": new Uniform.float(30.0),
"wrapRGB" : new Uniform.vector3(1.0, 1.0, 1.0)
}
] ),
'vertexShader': [
"#define PHONG",
"varying vec3 vViewPosition;",
"varying vec3 vNormal;",
ShaderChunk[ "map_pars_vertex" ],
ShaderChunk[ "lightmap_pars_vertex" ],
ShaderChunk[ "envmap_pars_vertex" ],
ShaderChunk[ "lights_phong_pars_vertex" ],
ShaderChunk[ "color_pars_vertex" ],
ShaderChunk[ "morphtarget_pars_vertex" ],
ShaderChunk[ "skinning_pars_vertex" ],
ShaderChunk[ "shadowmap_pars_vertex" ],
"void main() {",
ShaderChunk[ "map_vertex" ],
ShaderChunk[ "lightmap_vertex" ],
ShaderChunk[ "color_vertex" ],
ShaderChunk[ "morphnormal_vertex" ],
ShaderChunk[ "skinbase_vertex" ],
ShaderChunk[ "skinnormal_vertex" ],
ShaderChunk[ "defaultnormal_vertex" ],
"vNormal = normalize( transformedNormal );",
ShaderChunk[ "morphtarget_vertex" ],
ShaderChunk[ "skinning_vertex" ],
ShaderChunk[ "default_vertex" ],
"vViewPosition = -mvPosition.xyz;",
ShaderChunk[ "worldpos_vertex" ],
ShaderChunk[ "envmap_vertex" ],
ShaderChunk[ "lights_phong_vertex" ],
ShaderChunk[ "shadowmap_vertex" ],
"}"
].join("\n"),
'fragmentShader': [
"uniform vec3 diffuse;",
"uniform float opacity;",
"uniform vec3 ambient;",
"uniform vec3 emissive;",
"uniform vec3 specular;",
"uniform float shininess;",
ShaderChunk[ "color_pars_fragment" ],
ShaderChunk[ "map_pars_fragment" ],
ShaderChunk[ "lightmap_pars_fragment" ],
ShaderChunk[ "envmap_pars_fragment" ],
ShaderChunk[ "fog_pars_fragment" ],
ShaderChunk[ "lights_phong_pars_fragment" ],
ShaderChunk[ "shadowmap_pars_fragment" ],
ShaderChunk[ "bumpmap_pars_fragment" ],
ShaderChunk[ "normalmap_pars_fragment" ],
ShaderChunk[ "specularmap_pars_fragment" ],
"void main() {",
"gl_FragColor = vec4( vec3 ( 1.0 ), opacity );",
ShaderChunk[ "map_fragment" ],
ShaderChunk[ "alphatest_fragment" ],
ShaderChunk[ "specularmap_fragment" ],
ShaderChunk[ "lights_phong_fragment" ],
ShaderChunk[ "lightmap_fragment" ],
ShaderChunk[ "color_fragment" ],
ShaderChunk[ "envmap_fragment" ],
ShaderChunk[ "shadowmap_fragment" ],
ShaderChunk[ "linear_to_gamma_fragment" ],
ShaderChunk[ "fog_fragment" ],
"}"
].join("\n")
},
'particle_basic': {
'uniforms': UniformsUtils.merge( [
UniformsLib[ "particle" ],
UniformsLib[ "shadowmap" ]
] ),
'vertexShader': [
"uniform float size;",
"uniform float scale;",
ShaderChunk[ "color_pars_vertex" ],
ShaderChunk[ "shadowmap_pars_vertex" ],
"void main() {",
ShaderChunk[ "color_vertex" ],
"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
"#ifdef USE_SIZEATTENUATION",
"gl_PointSize = size * ( scale / length( mvPosition.xyz ) );",
"#else",
"gl_PointSize = size;",
"#endif",
"gl_Position = projectionMatrix * mvPosition;",
ShaderChunk[ "worldpos_vertex" ],
ShaderChunk[ "shadowmap_vertex" ],
"}"
].join("\n"),
'fragmentShader': [
"uniform vec3 psColor;",
"uniform float opacity;",
ShaderChunk[ "color_pars_fragment" ],
ShaderChunk[ "map_particle_pars_fragment" ],
ShaderChunk[ "fog_pars_fragment" ],
ShaderChunk[ "shadowmap_pars_fragment" ],
"void main() {",
"gl_FragColor = vec4( psColor, opacity );",
ShaderChunk[ "map_particle_fragment" ],
ShaderChunk[ "alphatest_fragment" ],
ShaderChunk[ "color_fragment" ],
ShaderChunk[ "shadowmap_fragment" ],
ShaderChunk[ "fog_fragment" ],
"}"
].join("\n")
},
'dashed': {
"uniforms": UniformsUtils.merge( [
UniformsLib[ "common" ],
UniformsLib[ "fog" ],
{
"scale": new Uniform.float(1.0),
"dashSize": new Uniform.float(1.0),
"totalSize": new Uniform.float(2.0)
}
] ),
"vertexShader": [
"uniform float scale;",
"attribute float lineDistance;",
"varying float vLineDistance;",
ShaderChunk[ "color_pars_vertex" ],
"void main() {",
ShaderChunk[ "color_vertex" ],
"vLineDistance = scale * lineDistance;",
"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
"gl_Position = projectionMatrix * mvPosition;",
"}"
].join("\n"),
"fragmentShader": [
"uniform vec3 diffuse;",
"uniform float opacity;",
"uniform float dashSize;",
"uniform float totalSize;",
"varying float vLineDistance;",
ShaderChunk[ "color_pars_fragment" ],
ShaderChunk[ "fog_pars_fragment" ],
"void main() {",
"if ( mod( vLineDistance, totalSize ) > dashSize ) {",
"discard;",
"}",
"gl_FragColor = vec4( diffuse, opacity );",
ShaderChunk[ "color_fragment" ],
ShaderChunk[ "fog_fragment" ],
"}"
].join("\n")
},
// Depth encoding into RGBA texture
// based on SpiderGL shadow map example
// http://spidergl.org/example.php?id=6
// originally from
// http://www.gamedev.net/topic/442138-packing-a-float-into-a-a8r8g8b8-texture-shader/page__whichpage__1%25EF%25BF%25BD
// see also here:
// http://aras-p.info/blog/2009/07/30/encoding-floats-to-rgba-the-final/
'depthRGBA': {
'uniforms': {},
'vertexShader': [
ShaderChunk[ "morphtarget_pars_vertex" ],
ShaderChunk[ "skinning_pars_vertex" ],
"void main() {",
ShaderChunk[ "skinbase_vertex" ],
ShaderChunk[ "morphtarget_vertex" ],
ShaderChunk[ "skinning_vertex" ],
ShaderChunk[ "default_vertex" ],
"}"
].join("\n"),
'fragmentShader': [
"vec4 pack_depth( const in float depth ) {",
"const vec4 bit_shift = vec4( 256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0 );",
"const vec4 bit_mask = vec4( 0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0 );",
"vec4 res = fract( depth * bit_shift );",
"res -= res.xxyz * bit_mask;",
"return res;",
"}",
"void main() {",
"gl_FragData[ 0 ] = pack_depth( gl_FragCoord.z );",
//"gl_FragData[ 0 ] = pack_depth( gl_FragCoord.z / gl_FragCoord.w );",
//"float z = ( ( gl_FragCoord.z / gl_FragCoord.w ) - 3.0 ) / ( 4000.0 - 3.0 );",
//"gl_FragData[ 0 ] = pack_depth( z );",
//"gl_FragData[ 0 ] = vec4( z, z, z, 1.0 );",
"}"
].join("\n")
}
};
}
return __ShaderLib;
}
final UniformsLib #
get UniformsLib {
if (__UniformsLib == null) {
__UniformsLib = {
"common": {
"diffuse" : new Uniform.color(0xeeeeee),
"opacity" : new Uniform.float(1.0),
"map" : new Uniform.texture(),
"offsetRepeat" : new Uniform.vector4(0.0, 0.0, 1.0, 1.0),
"lightMap" : new Uniform.texture(),
"specularMap" : new Uniform.texture(),
"envMap" : new Uniform.texture(),
"flipEnvMap" : new Uniform.float(-1.0),
"useRefract" : new Uniform.int(0),
"reflectivity" : new Uniform.float(1.0),
"refractionRatio" : new Uniform.float(0.98),
"combine" : new Uniform.int(0),
"morphTargetInfluences" : new Uniform.float(0.0)
},
"bump": {
"bumpMap" : new Uniform.texture(),
"bumpScale" : new Uniform.float(1.0)
},
"normalmap": {
"normalMap" : new Uniform.texture(),
"normalScale" : new Uniform.vector2(1.0, 1.0)
},
"fog" : {
"fogDensity" : new Uniform.float(0.00025),
"fogNear" : new Uniform.float(1.0),
"fogFar" : new Uniform.float(2000.0),
"fogColor" : new Uniform.color(0xffffff)
},
"lights": {
"ambientLightColor" : new Uniform.floatv([]),
"directionalLightDirection" : new Uniform.floatv([]),
"directionalLightColor" : new Uniform.floatv([]),
"hemisphereLightDirection" : new Uniform.floatv([]),
"hemisphereLightSkyColor" : new Uniform.floatv([]),
"hemisphereLightGroundColor" : new Uniform.floatv([]),
"pointLightColor" : new Uniform.floatv([]),
"pointLightPosition" : new Uniform.floatv([]),
"pointLightDistance" : new Uniform.floatv1([]),
"spotLightColor" : new Uniform.floatv([]),
"spotLightPosition" : new Uniform.floatv([]),
"spotLightDirection" : new Uniform.floatv([]),
"spotLightDistance" : new Uniform.floatv1([]),
"spotLightAngleCos" : new Uniform.floatv1([]),
"spotLightExponent" : new Uniform.floatv1([])
},
"particle": {
"psColor" : new Uniform.color(0xeeeeee),
"opacity" : new Uniform.float(1.0),
"size" : new Uniform.float(1.0),
"scale" : new Uniform.float(1.0),
"map" : new Uniform.texture(),
"fogDensity" : new Uniform.float(0.00025),
"fogNear" : new Uniform.float(1.0),
"fogFar" : new Uniform.float(2000.0),
"fogColor" : new Uniform.color(0xffffff)
},
"shadowmap": {
"shadowMap": new Uniform.texturev([]),
"shadowMapSize": new Uniform.vector2v([]),
"shadowBias" : new Uniform.floatv1([]),
"shadowDarkness": new Uniform.floatv1([]),
"shadowMatrix" : new Uniform.matrix4v([]),
}
};
}
return __UniformsLib;
}
Functions
dynamic multiplyVector3Array(Matrix4 m, List<double> a) #
multiplyVector3Array(Matrix4 m, List<double> a) {
var v1 = new Vector3.zero();
var il = a.length;
for ( var i = 0; i < il; i += 3 ) {
v1.x = a[ i ];
v1.y = a[ i + 1 ];
v1.z = a[ i + 2 ];
v1.applyProjection( m );
a[ i ] = v1.x;
a[ i + 1 ] = v1.y;
a[ i + 2 ] = v1.z;
}
return a;
}
Matrix4 makeRotationAxis(Matrix4 m, Vector3 axis, num angle) #
Matrix4 makeRotationAxis( Matrix4 m, Vector3 axis, num angle ) {
// Based on http://www.gamedev.net/reference/articles/article1199.asp
num c = Math.cos( angle ),
s = Math.sin( angle ),
t = 1.0 - c,
x = axis.x, y = axis.y, z = axis.z,
tx = t * x, ty = t * y;
m.setValues(
tx * x + c, tx * y - s * z, tx * z + s * y, 0.0,
tx * y + s * z, ty * y + c, ty * z - s * x, 0.0,
tx * z - s * y, ty * z + s * x, t * z * z + c, 0.0,
0.0, 0.0, 0.0, 1.0
);
return m;
}
Matrix4 compose(Matrix4 matrix, Vector3 translation, Quaternion rotation, Vector3 s) #
Matrix4 compose( Matrix4 matrix, Vector3 translation, Quaternion rotation, Vector3 s ) {
var te = matrix.storage;
Matrix4 mRotation = new Matrix4.identity();
setRotationFromQuaternion( mRotation, rotation );
Matrix4 mScale = new Matrix4.diagonal3Values(s.x, s.y, s.z);
mRotation.multiply(mScale);
te[12] = translation.x;
te[13] = translation.y;
te[14] = translation.z;
return matrix;
}
Quaternion setFromRotationMatrix(Quaternion quaternion, Matrix4 m) #
Quaternion setFromRotationMatrix(Quaternion quaternion, Matrix4 m ) {
// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
quaternion = new Quaternion.identity();
var te = m.storage,
m11 = te[0], m12 = te[4], m13 = te[8],
m21 = te[1], m22 = te[5], m23 = te[9],
m31 = te[2], m32 = te[6], m33 = te[10],
trace = m11 + m22 + m33,
s;
if( trace > 0 ) {
s = 0.5 / Math.sqrt( trace + 1.0 );
quaternion.w = 0.25 / s;
quaternion.x = ( m32 - m23 ) * s;
quaternion.y = ( m13 - m31 ) * s;
quaternion.z = ( m21 - m12 ) * s;
} else if ( m11 > m22 && m11 > m33 ) {
s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 );
quaternion.w = (m32 - m23 ) / s;
quaternion.x = 0.25 * s;
quaternion.y = (m12 + m21 ) / s;
quaternion.z = (m13 + m31 ) / s;
} else if (m22 > m33) {
s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 );
quaternion.w = (m13 - m31 ) / s;
quaternion.x = (m12 + m21 ) / s;
quaternion.y = 0.25 * s;
quaternion.z = (m23 + m32 ) / s;
} else {
s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 );
quaternion.w = ( m21 - m12 ) / s;
quaternion.x = ( m13 + m31 ) / s;
quaternion.y = ( m23 + m32 ) / s;
quaternion.z = 0.25 * s;
}
return quaternion;
}
List decompose(Matrix4 m, Vector3 translation, Quaternion rotation, Vector3 scale) #
List decompose(Matrix4 m, Vector3 translation, Quaternion rotation, Vector3 scale ) {
var te = m.storage;
// grab the axis vectors
Vector3 x = new Vector3( te[0], te[1], te[2] );
Vector3 y = new Vector3( te[4], te[5], te[6] );
Vector3 z = new Vector3( te[8], te[9], te[10] );
translation = ( translation is Vector3 ) ? translation : new Vector3.zero();
rotation = ( rotation is Quaternion ) ? rotation : new Quaternion.identity();
scale = ( scale is Vector3 ) ? scale : new Vector3.zero();
scale.x = x.length;
scale.y = y.length;
scale.z = z.length;
translation.x = te[12];
translation.y = te[13];
translation.z = te[14];
// scale the rotation part
Matrix4 matrix = m.clone();
matrix.storage[0] /= scale.x;
matrix.storage[1] /= scale.x;
matrix.storage[2] /= scale.x;
matrix.storage[4] /= scale.y;
matrix.storage[5] /= scale.y;
matrix.storage[6] /= scale.y;
matrix.storage[8] /= scale.z;
matrix.storage[9] /= scale.z;
matrix.storage[10] /= scale.z;
setFromRotationMatrix( rotation, matrix );
return [ translation, rotation, scale ];
}
Vector3 getScaleFromMatrix(Matrix4 m) #
Vector3 getScaleFromMatrix(Matrix4 m) {
double sx = new Vector3(m.storage[0], m.storage[1], m.storage[2]).length;
double sy = new Vector3(m.storage[4], m.storage[5], m.storage[6]).length;
double sz = new Vector3(m.storage[8], m.storage[9], m.storage[10]).length;
return new Vector3(sx, sy, sz);
}
Matrix4 extractRotation(Matrix4 te, Matrix4 m) #
Matrix4 extractRotation( Matrix4 te, Matrix4 m ) {
Vector3 vector = new Vector3.zero();
var scaleX = 1.0 / vector.setValues ( m[0], m[1], m[2] ).length;
var scaleY = 1.0 / vector.setValues( m[4], m[5], m[6] ).length;
var scaleZ = 1.0 / vector.setValues( m[8], m[9], m[10] ).length;
te[0] = m[0] * scaleX;
te[1] = m[1] * scaleX;
te[2] = m[2] * scaleX;
te[4] = m[4] * scaleY;
te[5] = m[5] * scaleY;
te[6] = m[6] * scaleY;
te[8] = m[8] * scaleZ;
te[9] = m[9] * scaleZ;
te[10] = m[10] * scaleZ;
return te;
}
Matrix3 calcInverse(Matrix4 m) #
Matrix3 calcInverse( Matrix4 m ) {
// input: THREE.Matrix4
// ( based on http://code.google.com/p/webgl-mjs/ )
double a11 = m[10] * m[5] - m[6] * m[9];
double a21 = - m[10] * m[1] + m[2] * m[9];
double a31 = m[6] * m[1] - m[2] * m[5];
double a12 = - m[10] * m[4] + m[6] * m[8];
double a22 = m[10] * m[0] - m[2] * m[8];
double a32 = - m[6] * m[0] + m[2] * m[4];
double a13 = m[9] * m[4] - m[5] * m[8];
double a23 = - m[9] * m[0] + m[1] * m[8];
double a33 = m[5] * m[0] - m[1] * m[4];
var det = m[0] * a11 + m[1] * a12 + m[2] * a13;
// no inverse
if ( det == 0 ) {
print( "Matrix3.getInverse(): determinant == 0" );
}
var idet = 1.0 / det;
return new Matrix3(idet * a11, idet * a21, idet * a31,
idet * a12, idet * a22, idet * a32,
idet * a13, idet * a23, idet * a33);
}
double calcMaxScaleOnAxis(Matrix4 te) #
double calcMaxScaleOnAxis(Matrix4 te) {
var scaleXSq = te[0] * te[0] + te[1] * te[1] + te[2] * te[2];
var scaleYSq = te[4] * te[4] + te[5] * te[5] + te[6] * te[6];
var scaleZSq = te[8] * te[8] + te[9] * te[9] + te[10] * te[10];
return Math.sqrt( Math.max( scaleXSq, Math.max( scaleYSq, scaleZSq ) ) );
}
Matrix4 setRotationFromQuaternion(Matrix4 m, Quaternion q) #
Matrix4 setRotationFromQuaternion( Matrix4 m, Quaternion q ) {
num x = q.x, y = q.y, z = q.z, w = q.w,
x2 = x + x, y2 = y + y, z2 = z + z,
xx = x * x2, xy = x * y2, xz = x * z2,
yy = y * y2, yz = y * z2, zz = z * z2,
wx = w * x2, wy = w * y2, wz = w * z2;
m[0] = 1.0 - ( yy + zz );
m[4] = xy - wz;
m[8] = xz + wy;
m[1] = xy + wz;
m[5] = 1.0 - ( xx + zz );
m[9] = yz - wx;
m[2] = xz - wy;
m[6] = yz + wx;
m[10] = 1.0 - ( xx + yy );
return m;
}
Matrix4 setRotationFromEuler(Matrix4 m, Vector3 v, [String order = 'XYZ']) #
Matrix4 setRotationFromEuler( Matrix4 m, Vector3 v, [String order = 'XYZ'] ) {
num x = v.x, y = v.y, z = v.z,
a = Math.cos( x ), b = Math.sin( x ),
c = Math.cos( y ), d = Math.sin( y ),
e = Math.cos( z ), f = Math.sin( z );
switch ( order ) {
case 'YXZ':
num ce = c * e, cf = c * f, de = d * e, df = d * f;
m[0] = ce + df * b;
m[4] = de * b - cf;
m[8] = a * d;
m[1] = a * f;
m[5] = a * e;
m[9] = - b;
m[2] = cf * b - de;
m[6] = df + ce * b;
m[10] = a * c;
break;
case 'ZXY':
num ce = c * e, cf = c * f, de = d * e, df = d * f;
m[0] = ce - df * b;
m[4] = - a * f;
m[8] = de + cf * b;
m[1] = cf + de * b;
m[5] = a * e;
m[9] = df - ce * b;
m[2] = - a * d;
m[6] = b;
m[10] = a * c;
break;
case 'ZYX':
num ae = a * e, af = a * f, be = b * e, bf = b * f;
m[0] = c * e;
m[4] = be * d - af;
m[8] = ae * d + bf;
m[1] = c * f;
m[5] = bf * d + ae;
m[9] = af * d - be;
m[2] = - d;
m[6] = b * c;
m[10] = a * c;
break;
case 'YZX':
num ac = a * c, ad = a * d, bc = b * c, bd = b * d;
m[0] = c * e;
m[4] = bd - ac * f;
m[8] = bc * f + ad;
m[1] = f;
m[5] = a * e;
m[9] = - b * e;
m[2] = - d * e;
m[6] = ad * f + bc;
m[10] = ac - bd * f;
break;
case 'XZY':
num ac = a * c, ad = a * d, bc = b * c, bd = b * d;
m[0] = c * e;
m[4] = - f;
m[8] = d * e;
m[1] = ac * f + bd;
m[5] = a * e;
m[9] = ad * f - bc;
m[2] = bc * f - ad;
m[6] = b * e;
m[10] = bd * f + ac;
break;
default: // 'XYZ'
num ae = a * e, af = a * f, be = b * e, bf = b * f;
m[0] = c * e;
m[4] = - c * f;
m[8] = d;
m[1] = af + be * d;
m[5] = ae - bf * d;
m[9] = - b * c;
m[2] = bf - ae * d;
m[6] = be + af * d;
m[10] = a * c;
break;
}
return m;
}
Matrix4 makeLookAt(Matrix4 m, Vector3 eye, Vector3 center, Vector3 up) #
@author mr.doob / http://mrdoob.com/ @author supereggbert / http://www.paulbrunt.co.uk/ @author philogb / http://blog.thejit.org/ @author jordi_ros / http://plattsoft.com @author D1plo1d / http://github.com/D1plo1d @author alteredq / http://alteredqualia.com/ @author mikael emtinger / http://gomo.se/ @author timknip / http://www.floorplanner.com/
Ported to Dart from JS by: @author rob silverton / http://www.unwrong.com/ @author anders forsell / http://aforsell.blogspot.com/
Matrix4 makeLookAt(Matrix4 m, Vector3 eye, Vector3 center, Vector3 up ) {
Vector3 z = (eye - center ).normalize();
if ( z.length == 0.0 ) {
z.z = 1.0;
}
Vector3 x = up.cross(z).normalize();
if ( x.length == 0.0 ) {
z.x = z.x + 0.0001;
x = up.cross( z ).normalize();
}
Vector3 y = z.cross( x ).normalize();
m.setValues(x.x, x.y, x.z, 0.0,
y.x, y.y, y.z, 0.0,
z.x, z.y, z.z, 0.0,
0.0, 0.0, 0.0, 1.0);
return m;
}
Vector4 lerp4(Vector4 start, Vector4 end, double percent) #
Vector4 lerp4(Vector4 start, Vector4 end, double percent) {
return (start + (end - start).scale(percent));
}
Vector3 calcEulerFromQuaternion(Vector4 q, [String order = 'XYZ']) #
Vector3 calcEulerFromQuaternion(Vector4 q, [String order = 'XYZ'] ) {
double x, y, z;
// q is assumed to be normalized
// clamp, to handle numerical problems
var clamp = ( x ) => Math.min( Math.max( x, -1 ), 1 );
// http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m
var sqx = q.x * q.x;
var sqy = q.y * q.y;
var sqz = q.z * q.z;
var sqw = q.w * q.w;
if ( order == 'XYZ' ) {
x = Math.atan2( 2 * ( q.x * q.w - q.y * q.z ), ( sqw - sqx - sqy + sqz ) );
y = Math.asin( clamp( 2 * ( q.x * q.z + q.y * q.w ) ) );
z = Math.atan2( 2 * ( q.z * q.w - q.x * q.y ), ( sqw + sqx - sqy - sqz ) );
} else if ( order == 'YXZ' ) {
x = Math.asin( clamp( 2 * ( q.x * q.w - q.y * q.z ) ) );
y = Math.atan2( 2 * ( q.x * q.z + q.y * q.w ), ( sqw - sqx - sqy + sqz ) );
z = Math.atan2( 2 * ( q.x * q.y + q.z * q.w ), ( sqw - sqx + sqy - sqz ) );
} else if ( order == 'ZXY' ) {
x = Math.asin( clamp( 2 * ( q.x * q.w + q.y * q.z ) ) );
y = Math.atan2( 2 * ( q.y * q.w - q.z * q.x ), ( sqw - sqx - sqy + sqz ) );
z = Math.atan2( 2 * ( q.z * q.w - q.x * q.y ), ( sqw - sqx + sqy - sqz ) );
} else if ( order == 'ZYX' ) {
x = Math.atan2( 2 * ( q.x * q.w + q.z * q.y ), ( sqw - sqx - sqy + sqz ) );
y = Math.asin( clamp( 2 * ( q.y * q.w - q.x * q.z ) ) );
z = Math.atan2( 2 * ( q.x * q.y + q.z * q.w ), ( sqw + sqx - sqy - sqz ) );
} else if ( order == 'YZX' ) {
x = Math.atan2( 2 * ( q.x * q.w - q.z * q.y ), ( sqw - sqx + sqy - sqz ) );
y = Math.atan2( 2 * ( q.y * q.w - q.x * q.z ), ( sqw + sqx - sqy - sqz ) );
z = Math.asin( clamp( 2 * ( q.x * q.y + q.z * q.w ) ) );
} else if ( order == 'XZY' ) {
x = Math.atan2( 2 * ( q.x * q.w + q.y * q.z ), ( sqw - sqx + sqy - sqz ) );
y = Math.atan2( 2 * ( q.x * q.z + q.y * q.w ), ( sqw + sqx - sqy - sqz ) );
z = Math.asin( clamp( 2 * ( q.z * q.w - q.x * q.y ) ) );
}
return new Vector3(x, y, z);
}
Vector3 calcEulerFromRotationMatrix(Matrix4 m, [String order = 'XYZ']) #
@author mr.doob / http://mrdoob.com/ @author kile / http://kile.stravaganza.org/ @author philogb / http://blog.thejit.org/ @author mikael emtinger / http://gomo.se/ @author egraether / http://egraether.com/
Ported to Dart from JS by: @author rob silverton / http://www.unwrong.com/ @author anders forsell / http://aforsell.blogspot.com
(moved from three.js Vector3 to here since these are missing in vector_math's Vector3)
Vector3 calcEulerFromRotationMatrix( Matrix4 m, [String order = 'XYZ'] ) {
double x, y, z;
// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
// clamp, to handle numerical problems
var clamp = ( x ) => Math.min( Math.max( x, -1 ), 1 );
var m11 = m[0], m12 = m[4], m13 = m[8];
var m21 = m[1], m22 = m[5], m23 = m[9];
var m31 = m[2], m32 = m[6], m33 = m[10];
if ( order == 'XYZ' ) {
y = Math.asin( clamp( m13 ) );
if ( m13.abs() < 0.99999 ) {
x = Math.atan2( - m23, m33 );
z = Math.atan2( - m12, m11 );
} else {
x = Math.atan2( m21, m22 );
z = 0.0;
}
} else if ( order == 'YXZ' ) {
x = Math.asin( - clamp( m23 ) );
if ( m23.abs() < 0.99999 ) {
y = Math.atan2( m13, m33 );
z = Math.atan2( m21, m22 );
} else {
y = Math.atan2( - m31, m11 );
z = 0.0;
}
} else if ( order == 'ZXY' ) {
x = Math.asin( clamp( m32 ) );
if ( m32.abs() < 0.99999 ) {
y = Math.atan2( - m31, m33 );
z = Math.atan2( - m12, m22 );
} else {
y = 0.0;
z = Math.atan2( m13, m11 );
}
} else if ( order == 'ZYX' ) {
y = Math.asin( - clamp( m31 ) );
if (m31.abs() < 0.99999 ) {
x = Math.atan2( m32, m33 );
z = Math.atan2( m21, m11 );
} else {
x = 0.0;
z = Math.atan2( - m12, m22 );
}
} else if ( order == 'YZX' ) {
z = Math.asin( clamp( m21 ) );
if ( m21.abs() < 0.99999 ) {
x = Math.atan2( - m23, m22 );
y = Math.atan2( - m31, m11 );
} else {
x = 0.0;
y = Math.atan2( m31, m33 );
}
} else if ( order == 'XZY' ) {
z = Math.asin( - clamp( m12 ) );
if ( m12.abs() < 0.99999 ) {
x = Math.atan2( m32, m22 );
y = Math.atan2( m13, m11 );
} else {
x = Math.atan2( - m13, m33 );
y = 0.0;
}
}
return new Vector3(x, y, z);
}