vertex.glsl
precision highp float
precision highp int
uniform mat4 modelMatrix
uniform mat4 modelViewMatrix
uniform mat4 projectionMatrix
uniform mat4 viewMatrix
uniform mat3 normalMatrix
uniform vec3 cameraPosition
uniform bool isOrthographic
attribute mat4 instanceMatrix
attribute vec3 position
attribute vec3 normal
attribute vec2 uv
attribute vec4 tangent
attribute vec3 color
attribute vec3 morphTarget0
attribute vec3 morphTarget1
attribute vec3 morphTarget2
attribute vec3 morphTarget3
attribute vec3 morphNormal0
attribute vec3 morphNormal1
attribute vec3 morphNormal2
attribute vec3 morphNormal3
attribute vec3 morphTarget4
attribute vec3 morphTarget5
attribute vec3 morphTarget6
attribute vec3 morphTarget7
attribute vec4 skinIndex
attribute vec4 skinWeight
// <tonemapping_pars_fragment> may have defined saturate() already
float pow2( const in float x ) { return x*x
float pow3( const in float x ) { return x*x*x
float pow4( const in float x ) { float x2 = x*x
float average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) )
// expects values in the range of [0,1]x[0,1], returns values in the [0,1] range.
// do not collapse into a single function per: http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/
highp float rand( const in vec2 uv ) {
const highp float a = 12.9898, b = 78.233, c = 43758.5453
highp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI )
return fract(sin(sn) * c)
}
float precisionSafeLength( vec3 v ) { return length( v )
float max3( vec3 v ) { return max( max( v.x, v.y ), v.z )
float precisionSafeLength( vec3 v ) {
float maxComponent = max3( abs( v ) )
return length( v / maxComponent ) * maxComponent
}
struct IncidentLight {
vec3 color
vec3 direction
bool visible
}
struct ReflectedLight {
vec3 directDiffuse
vec3 directSpecular
vec3 indirectDiffuse
vec3 indirectSpecular
}
struct GeometricContext {
vec3 position
vec3 normal
vec3 viewDir
vec3 clearcoatNormal
}
vec3 transformDirection( in vec3 dir, in mat4 matrix ) {
return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz )
}
vec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {
// dir can be either a direction vector or a normal vector
// upper-left 3x3 of matrix is assumed to be orthogonal
return normalize( ( vec4( dir, 0.0 ) * matrix ).xyz )
}
vec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {
float distance = dot( planeNormal, point - pointOnPlane )
return - distance * planeNormal + point
}
float sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {
return sign( dot( point - pointOnPlane, planeNormal ) )
}
vec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {
return lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine
}
mat3 transposeMat3( const in mat3 m ) {
mat3 tmp
tmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x )
tmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y )
tmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z )
return tmp
}
// https://en.wikipedia.org/wiki/Relative_luminance
float linearToRelativeLuminance( const in vec3 color ) {
vec3 weights = vec3( 0.2126, 0.7152, 0.0722 )
return dot( weights, color.rgb )
}
bool isPerspectiveMatrix( mat4 m ) {
return m[ 2 ][ 3 ] == - 1.0
}
vec2 equirectUv( in vec3 dir ) {
// dir is assumed to be unit length
float u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5
float v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5
return vec2( u, v )
}
vec2 vUv
varying vec2 vUv
uniform mat3 uvTransform
attribute vec2 uv2
varying vec2 vUv2
uniform mat3 uv2Transform
varying vec3 vWorldPosition
varying vec3 vReflect
uniform float refractionRatio
varying vec3 vColor
varying float fogDepth
uniform float morphTargetBaseInfluence
uniform float morphTargetInfluences[ 8 ]
uniform float morphTargetInfluences[ 4 ]
uniform mat4 bindMatrix
uniform mat4 bindMatrixInverse
uniform highp sampler2D boneTexture
uniform int boneTextureSize
mat4 getBoneMatrix( const in float i ) {
float j = i * 4.0
float x = mod( j, float( boneTextureSize ) )
float y = floor( j / float( boneTextureSize ) )
float dx = 1.0 / float( boneTextureSize )
float dy = 1.0 / float( boneTextureSize )
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
}
uniform mat4 boneMatrices[ MAX_BONES ]
mat4 getBoneMatrix( const in float i ) {
mat4 bone = boneMatrices[ int(i) ]
return bone
}
varying float vFragDepth
varying float vIsPerspective
uniform float logDepthBufFC
varying vec3 vClipPosition
void main() {
vUv = ( uvTransform * vec3( uv, 1 ) ).xy
vUv2 = ( uv2Transform * vec3( uv2, 1 ) ).xy
vColor.xyz = color.xyz
mat4 boneMatX = getBoneMatrix( skinIndex.x )
mat4 boneMatY = getBoneMatrix( skinIndex.y )
mat4 boneMatZ = getBoneMatrix( skinIndex.z )
mat4 boneMatW = getBoneMatrix( skinIndex.w )
vec3 objectNormal = vec3( normal )
vec3 objectTangent = vec3( tangent.xyz )
// morphTargetBaseInfluence is set based on BufferGeometry.morphTargetsRelative value:
// When morphTargetsRelative is false, this is set to 1 - sum(influences)
// When morphTargetsRelative is true, this is set to 1
objectNormal *= morphTargetBaseInfluence
objectNormal += morphNormal0 * morphTargetInfluences[ 0 ]
objectNormal += morphNormal1 * morphTargetInfluences[ 1 ]
objectNormal += morphNormal2 * morphTargetInfluences[ 2 ]
objectNormal += morphNormal3 * morphTargetInfluences[ 3 ]
mat4 skinMatrix = mat4( 0.0 )
skinMatrix += skinWeight.x * boneMatX
skinMatrix += skinWeight.y * boneMatY
skinMatrix += skinWeight.z * boneMatZ
skinMatrix += skinWeight.w * boneMatW
skinMatrix = bindMatrixInverse * skinMatrix * bindMatrix
objectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz
objectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz
vec3 transformedNormal = objectNormal
// this is in lieu of a per-instance normal-matrix
// shear transforms in the instance matrix are not supported
mat3 m = mat3( instanceMatrix )
transformedNormal /= vec3( dot( m[ 0 ], m[ 0 ] ), dot( m[ 1 ], m[ 1 ] ), dot( m[ 2 ], m[ 2 ] ) )
transformedNormal = m * transformedNormal
transformedNormal = normalMatrix * transformedNormal
transformedNormal = - transformedNormal
vec3 transformedTangent = ( modelViewMatrix * vec4( objectTangent, 0.0 ) ).xyz
transformedTangent = - transformedTangent
vec3 transformed = vec3( position )
// morphTargetBaseInfluence is set based on BufferGeometry.morphTargetsRelative value:
// When morphTargetsRelative is false, this is set to 1 - sum(influences)
// When morphTargetsRelative is true, this is set to 1
transformed *= morphTargetBaseInfluence
transformed += morphTarget0 * morphTargetInfluences[ 0 ]
transformed += morphTarget1 * morphTargetInfluences[ 1 ]
transformed += morphTarget2 * morphTargetInfluences[ 2 ]
transformed += morphTarget3 * morphTargetInfluences[ 3 ]
transformed += morphTarget4 * morphTargetInfluences[ 4 ]
transformed += morphTarget5 * morphTargetInfluences[ 5 ]
transformed += morphTarget6 * morphTargetInfluences[ 6 ]
transformed += morphTarget7 * morphTargetInfluences[ 7 ]
vec4 skinVertex = bindMatrix * vec4( transformed, 1.0 )
vec4 skinned = vec4( 0.0 )
skinned += boneMatX * skinVertex * skinWeight.x
skinned += boneMatY * skinVertex * skinWeight.y
skinned += boneMatZ * skinVertex * skinWeight.z
skinned += boneMatW * skinVertex * skinWeight.w
transformed = ( bindMatrixInverse * skinned ).xyz
vec4 mvPosition = vec4( transformed, 1.0 )
mvPosition = instanceMatrix * mvPosition
mvPosition = modelViewMatrix * mvPosition
gl_Position = projectionMatrix * mvPosition
vFragDepth = 1.0 + gl_Position.w
vIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) )
if ( isPerspectiveMatrix( projectionMatrix ) ) {
gl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0
gl_Position.z *= gl_Position.w
}
vec4 worldPosition = vec4( transformed, 1.0 )
worldPosition = instanceMatrix * worldPosition
worldPosition = modelMatrix * worldPosition
vClipPosition = - mvPosition.xyz
vWorldPosition = worldPosition.xyz
vec3 cameraToVertex
if ( isOrthographic ) {
cameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) )
} else {
cameraToVertex = normalize( worldPosition.xyz - cameraPosition )
}
vec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix )
vReflect = reflect( cameraToVertex, worldNormal )
vReflect = refract( cameraToVertex, worldNormal, refractionRatio )
fogDepth = -mvPosition.z
}
fragment.glsl
out highp vec4 pc_fragColor
precision highp float
precision highp int
uniform mat4 viewMatrix
uniform vec3 cameraPosition
uniform bool isOrthographic
// For a discussion of what this is, please read this: http://lousodrome.net/blog/light/2013/05/26/gamma-correct-and-hdr-rendering-in-a-32-bits-buffer/
vec4 LinearToLinear( in vec4 value ) {
return value
}
vec4 GammaToLinear( in vec4 value, in float gammaFactor ) {
return vec4( pow( value.rgb, vec3( gammaFactor ) ), value.a )
}
vec4 LinearToGamma( in vec4 value, in float gammaFactor ) {
return vec4( pow( value.rgb, vec3( 1.0 / gammaFactor ) ), value.a )
}
vec4 sRGBToLinear( in vec4 value ) {
return vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.a )
}
vec4 LinearTosRGB( in vec4 value ) {
return vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a )
}
vec4 RGBEToLinear( in vec4 value ) {
return vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 )
}
vec4 LinearToRGBE( in vec4 value ) {
float maxComponent = max( max( value.r, value.g ), value.b )
float fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 )
return vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 )
// return vec4( value.brg, ( 3.0 + 128.0 ) / 256.0 )
}
// reference: http://iwasbeingirony.blogspot.ca/2010/06/difference-between-rgbm-and-rgbd.html
vec4 RGBMToLinear( in vec4 value, in float maxRange ) {
return vec4( value.rgb * value.a * maxRange, 1.0 )
}
vec4 LinearToRGBM( in vec4 value, in float maxRange ) {
float maxRGB = max( value.r, max( value.g, value.b ) )
float M = clamp( maxRGB / maxRange, 0.0, 1.0 )
M = ceil( M * 255.0 ) / 255.0
return vec4( value.rgb / ( M * maxRange ), M )
}
// reference: http://iwasbeingirony.blogspot.ca/2010/06/difference-between-rgbm-and-rgbd.html
vec4 RGBDToLinear( in vec4 value, in float maxRange ) {
return vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 )
}
vec4 LinearToRGBD( in vec4 value, in float maxRange ) {
float maxRGB = max( value.r, max( value.g, value.b ) )
float D = max( maxRange / maxRGB, 1.0 )
// NOTE: The implementation with min causes the shader to not compile on
// a common Alcatel A502DL in Chrome 78/Android 8.1. Some research suggests
// that the chipset is Mediatek MT6739 w/ IMG PowerVR GE8100 GPU.
// D = min( floor( D ) / 255.0, 1.0 )
D = clamp( floor( D ) / 255.0, 0.0, 1.0 )
return vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D )
}
// LogLuv reference: http://graphicrants.blogspot.ca/2009/04/rgbm-color-encoding.html
// M matrix, for encoding
const mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 )
vec4 LinearToLogLuv( in vec4 value ) {
vec3 Xp_Y_XYZp = cLogLuvM * value.rgb
Xp_Y_XYZp = max( Xp_Y_XYZp, vec3( 1e-6, 1e-6, 1e-6 ) )
vec4 vResult
vResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z
float Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0
vResult.w = fract( Le )
vResult.z = ( Le - ( floor( vResult.w * 255.0 ) ) / 255.0 ) / 255.0
return vResult
}
// Inverse M matrix, for decoding
const mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 )
vec4 LogLuvToLinear( in vec4 value ) {
float Le = value.z * 255.0 + value.w
vec3 Xp_Y_XYZp
Xp_Y_XYZp.y = exp2( ( Le - 127.0 ) / 2.0 )
Xp_Y_XYZp.z = Xp_Y_XYZp.y / value.y
Xp_Y_XYZp.x = value.x * Xp_Y_XYZp.z
vec3 vRGB = cLogLuvInverseM * Xp_Y_XYZp.rgb
return vec4( max( vRGB, 0.0 ), 1.0 )
}
vec4 linearToOutputTexel( vec4 value ) { return LinearTosRGB( value )
uniform vec3 diffuse
uniform float opacity
varying vec3 vNormal
// <tonemapping_pars_fragment> may have defined saturate() already
float pow2( const in float x ) { return x*x
float pow3( const in float x ) { return x*x*x
float pow4( const in float x ) { float x2 = x*x
float average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) )
// expects values in the range of [0,1]x[0,1], returns values in the [0,1] range.
// do not collapse into a single function per: http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/
highp float rand( const in vec2 uv ) {
const highp float a = 12.9898, b = 78.233, c = 43758.5453
highp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI )
return fract(sin(sn) * c)
}
float precisionSafeLength( vec3 v ) { return length( v )
float max3( vec3 v ) { return max( max( v.x, v.y ), v.z )
float precisionSafeLength( vec3 v ) {
float maxComponent = max3( abs( v ) )
return length( v / maxComponent ) * maxComponent
}
struct IncidentLight {
vec3 color
vec3 direction
bool visible
}
struct ReflectedLight {
vec3 directDiffuse
vec3 directSpecular
vec3 indirectDiffuse
vec3 indirectSpecular
}
struct GeometricContext {
vec3 position
vec3 normal
vec3 viewDir
vec3 clearcoatNormal
}
vec3 transformDirection( in vec3 dir, in mat4 matrix ) {
return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz )
}
vec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {
// dir can be either a direction vector or a normal vector
// upper-left 3x3 of matrix is assumed to be orthogonal
return normalize( ( vec4( dir, 0.0 ) * matrix ).xyz )
}
vec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {
float distance = dot( planeNormal, point - pointOnPlane )
return - distance * planeNormal + point
}
float sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {
return sign( dot( point - pointOnPlane, planeNormal ) )
}
vec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {
return lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine
}
mat3 transposeMat3( const in mat3 m ) {
mat3 tmp
tmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x )
tmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y )
tmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z )
return tmp
}
// https://en.wikipedia.org/wiki/Relative_luminance
float linearToRelativeLuminance( const in vec3 color ) {
vec3 weights = vec3( 0.2126, 0.7152, 0.0722 )
return dot( weights, color.rgb )
}
bool isPerspectiveMatrix( mat4 m ) {
return m[ 2 ][ 3 ] == - 1.0
}
vec2 equirectUv( in vec3 dir ) {
// dir is assumed to be unit length
float u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5
float v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5
return vec2( u, v )
}
// based on https://www.shadertoy.com/view/MslGR8
vec3 dithering( vec3 color ) {
//Calculate grid position
float grid_position = rand( gl_FragCoord.xy )
//Shift the individual colors differently, thus making it even harder to see the dithering pattern
vec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 )
//modify shift acording to grid position.
dither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position )
//shift the color by dither_shift
return color + dither_shift_RGB
}
varying vec3 vColor
varying vec2 vUv
varying vec2 vUv2
uniform sampler2D map
uniform sampler2D alphaMap
uniform sampler2D aoMap
uniform float aoMapIntensity
uniform sampler2D lightMap
uniform float lightMapIntensity
uniform float envMapIntensity
uniform float flipEnvMap
uniform int maxMipLevel
uniform samplerCube envMap
uniform sampler2D envMap
uniform float reflectivity
varying vec3 vWorldPosition
uniform float refractionRatio
varying vec3 vReflect
// These shader functions convert between the UV coordinates of a single face of
// a cubemap, the 0-5 integer index of a cube face, and the direction vector for
// sampling a textureCube (not generally normalized).
float getFace(vec3 direction) {
vec3 absDirection = abs(direction)
float face = -1.0
if (absDirection.x > absDirection.z) {
if (absDirection.x > absDirection.y)
face = direction.x > 0.0 ? 0.0 : 3.0
else
face = direction.y > 0.0 ? 1.0 : 4.0
} else {
if (absDirection.z > absDirection.y)
face = direction.z > 0.0 ? 2.0 : 5.0
else
face = direction.y > 0.0 ? 1.0 : 4.0
}
return face
}
// RH coordinate system
vec2 getUV(vec3 direction, float face) {
vec2 uv
if (face == 0.0) {
uv = vec2(direction.z, direction.y) / abs(direction.x)
} else if (face == 1.0) {
uv = vec2(-direction.x, -direction.z) / abs(direction.y)
} else if (face == 2.0) {
uv = vec2(-direction.x, direction.y) / abs(direction.z)
} else if (face == 3.0) {
uv = vec2(-direction.z, direction.y) / abs(direction.x)
} else if (face == 4.0) {
uv = vec2(-direction.x, direction.z) / abs(direction.y)
} else {
uv = vec2(direction.x, direction.y) / abs(direction.z)
}
return 0.5 * (uv + 1.0)
}
vec3 bilinearCubeUV(sampler2D envMap, vec3 direction, float mipInt) {
float face = getFace(direction)
float filterInt = max(cubeUV_minMipLevel - mipInt, 0.0)
mipInt = max(mipInt, cubeUV_minMipLevel)
float faceSize = exp2(mipInt)
float texelSize = 1.0 / (3.0 * cubeUV_maxTileSize)
vec2 uv = getUV(direction, face) * (faceSize - 1.0)
vec2 f = fract(uv)
uv += 0.5 - f
if (face > 2.0) {
uv.y += faceSize
face -= 3.0
}
uv.x += face * faceSize
if(mipInt < cubeUV_maxMipLevel){
uv.y += 2.0 * cubeUV_maxTileSize
}
uv.y += filterInt * 2.0 * cubeUV_minTileSize
uv.x += 3.0 * max(0.0, cubeUV_maxTileSize - 2.0 * faceSize)
uv *= texelSize
vec3 tl = envMapTexelToLinear(texture2D(envMap, uv)).rgb
uv.x += texelSize
vec3 tr = envMapTexelToLinear(texture2D(envMap, uv)).rgb
uv.y += texelSize
vec3 br = envMapTexelToLinear(texture2D(envMap, uv)).rgb
uv.x -= texelSize
vec3 bl = envMapTexelToLinear(texture2D(envMap, uv)).rgb
vec3 tm = mix(tl, tr, f.x)
vec3 bm = mix(bl, br, f.x)
return mix(tm, bm, f.y)
}
// These defines must match with PMREMGenerator
float roughnessToMip(float roughness) {
float mip = 0.0
if (roughness >= r1) {
mip = (r0 - roughness) * (m1 - m0) / (r0 - r1) + m0
} else if (roughness >= r4) {
mip = (r1 - roughness) * (m4 - m1) / (r1 - r4) + m1
} else if (roughness >= r5) {
mip = (r4 - roughness) * (m5 - m4) / (r4 - r5) + m4
} else if (roughness >= r6) {
mip = (r5 - roughness) * (m6 - m5) / (r5 - r6) + m5
} else {
mip = -2.0 * log2(1.16 * roughness)
}
return mip
}
vec4 textureCubeUV(sampler2D envMap, vec3 sampleDir, float roughness) {
float mip = clamp(roughnessToMip(roughness), m0, cubeUV_maxMipLevel)
float mipF = fract(mip)
float mipInt = floor(mip)
vec3 color0 = bilinearCubeUV(envMap, sampleDir, mipInt)
if (mipF == 0.0) {
return vec4(color0, 1.0)
} else {
vec3 color1 = bilinearCubeUV(envMap, sampleDir, mipInt + 1.0)
return vec4(mix(color0, color1, mipF), 1.0)
}
}
uniform vec3 fogColor
varying float fogDepth
uniform float fogDensity
uniform float fogNear
uniform float fogFar
uniform sampler2D specularMap
uniform float logDepthBufFC
varying float vFragDepth
varying float vIsPerspective
varying vec3 vClipPosition
uniform vec4 clippingPlanes[ 0 ]
void main() {
vec4 plane
bool clipped = true
if ( clipped ) discard
vec4 diffuseColor = vec4( diffuse, opacity )
// Doing a strict comparison with == 1.0 can cause noise artifacts
// on some platforms. See issue
gl_FragDepthEXT = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5
vec4 texelColor = texture2D( map, vUv )
texelColor = mapTexelToLinear( texelColor )
diffuseColor *= texelColor
diffuseColor.rgb *= vColor
diffuseColor.a *= texture2D( alphaMap, vUv ).g
if ( diffuseColor.a < ALPHATEST ) discard
float specularStrength
vec4 texelSpecular = texture2D( specularMap, vUv )
specularStrength = texelSpecular.r
specularStrength = 1.0
ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) )
// accumulation (baked indirect lighting only)
vec4 lightMapTexel= texture2D( lightMap, vUv2 )
reflectedLight.indirectDiffuse += lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity
reflectedLight.indirectDiffuse += vec3( 1.0 )
// modulation
// reads channel R, compatible with a combined OcclusionRoughnessMetallic (RGB) texture
float ambientOcclusion = ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0
reflectedLight.indirectDiffuse *= ambientOcclusion
float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) )
reflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.specularRoughness )
reflectedLight.indirectDiffuse *= diffuseColor.rgb
vec3 outgoingLight = reflectedLight.indirectDiffuse
vec3 cameraToFrag
if ( isOrthographic ) {
cameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) )
} else {
cameraToFrag = normalize( vWorldPosition - cameraPosition )
}
// Transforming Normal Vectors with the Inverse Transformation
vec3 worldNormal = inverseTransformDirection( normal, viewMatrix )
vec3 reflectVec = reflect( cameraToFrag, worldNormal )
vec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio )
vec3 reflectVec = vReflect
vec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) )
vec4 envColor = textureCubeUV( envMap, reflectVec, 0.0 )
reflectVec = normalize( reflectVec )
vec2 sampleUV = equirectUv( reflectVec )
vec4 envColor = texture2D( envMap, sampleUV )
vec4 envColor = vec4( 0.0 )
envColor = envMapTexelToLinear( envColor )
outgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity )
outgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity )
outgoingLight += envColor.xyz * specularStrength * reflectivity
gl_FragColor = vec4( outgoingLight, diffuseColor.a )
gl_FragColor.rgb = toneMapping( gl_FragColor.rgb )
gl_FragColor = linearToOutputTexel( gl_FragColor )
float fogFactor = 1.0 - exp( - fogDensity * fogDensity * fogDepth * fogDepth )
float fogFactor = smoothstep( fogNear, fogFar, fogDepth )
gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor )
// Get get normal blending with premultipled, use with CustomBlending, OneFactor, OneMinusSrcAlphaFactor, AddEquation.
gl_FragColor.rgb *= gl_FragColor.a
gl_FragColor.rgb = dithering( gl_FragColor.rgb )
}