Added all of the shader chunks

This commit is contained in:
Richard Davey 2020-10-01 16:16:12 +01:00
parent 8c3226dc91
commit 6c1a9282c6
134 changed files with 3482 additions and 0 deletions

View file

@ -0,0 +1,12 @@
module.exports = [
'#ifdef ALPHATEST',
'',
' if ( outColor.a < ALPHATEST ) {',
' discard;',
' } else {',
' // Prevent alpha test edge gradient',
' outColor.a = u_Opacity;',
' }',
'',
'#endif'
].join('\n');

View file

@ -0,0 +1,17 @@
module.exports = [
'#ifdef USE_ALPHA_MAP',
'',
' #ifdef USE_ALPHA_MAP_UV_TRANSFORM',
' outColor.a *= texture2D(alphaMap, vAlphaMapUV).g;',
' #else',
' #if (USE_ALPHA_MAP == 1)',
' outColor.a *= texture2D(alphaMap, v_Uv).g;',
' #elif (USE_ALPHA_MAP == 2)',
' outColor.a *= texture2D(alphaMap, v_Uv2).g;',
' #else',
' outColor.a *= texture2D(alphaMap, v_Uv).g;',
' #endif',
' #endif',
'',
'#endif'
].join('\n');

View file

@ -0,0 +1,7 @@
module.exports = [
'#ifdef USE_ALPHA_MAP',
'',
' uniform sampler2D alphaMap;',
'',
'#endif'
].join('\n');

View file

@ -0,0 +1,3 @@
module.exports = [
'uniform vec3 u_AmbientLightColor;'
].join('\n');

View file

@ -0,0 +1,8 @@
module.exports = [
'#ifdef USE_AOMAP',
'',
' uniform sampler2D aoMap;',
' uniform float aoMapIntensity;',
'',
'#endif'
].join('\n');

View file

@ -0,0 +1,3 @@
module.exports = [
'vec4 outColor = vec4(u_Color, u_Opacity);'
].join('\n');

View file

@ -0,0 +1,7 @@
module.exports = [
'vec3 transformed = vec3(a_Position);',
'vec3 objectNormal = vec3(a_Normal);',
'#ifdef USE_TANGENT',
' vec3 objectTangent = vec3(a_Tangent.xyz);',
'#endif'
].join('\n');

View file

@ -0,0 +1,138 @@
module.exports = [
'// diffuse just use lambert',
'',
'vec4 BRDF_Diffuse_Lambert(vec4 diffuseColor) {',
' return RECIPROCAL_PI * diffuseColor;',
'}',
'',
'// specular use Cook-Torrance microfacet model, http://ruh.li/GraphicsCookTorrance.html',
'// About RECIPROCAL_PI: referenced by http://www.joshbarczak.com/blog/?p=272',
'',
'vec4 F_Schlick( const in vec4 specularColor, const in float dotLH ) {',
' // Original approximation by Christophe Schlick '94',
' float fresnel = pow( 1.0 - dotLH, 5.0 );',
'',
' // Optimized variant (presented by Epic at SIGGRAPH '13)',
' // float fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );',
'',
' return ( 1.0 - specularColor ) * fresnel + specularColor;',
'}',
'',
'// use blinn phong instead of phong',
'float D_BlinnPhong( const in float shininess, const in float dotNH ) {',
' // ( shininess * 0.5 + 1.0 ), three.js do this, but why ???',
' return RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );',
'}',
'',
'float G_BlinnPhong_Implicit( /* const in float dotNL, const in float dotNV */ ) {',
' // geometry term is (n dot l)(n dot v) / 4(n dot l)(n dot v)',
' return 0.25;',
'}',
'',
'vec4 BRDF_Specular_BlinnPhong(vec4 specularColor, vec3 N, vec3 L, vec3 V, float shininess) {',
' vec3 H = normalize(L + V);',
'',
' float dotNH = saturate(dot(N, H));',
' float dotLH = saturate(dot(L, H));',
'',
' vec4 F = F_Schlick(specularColor, dotLH);',
'',
' float G = G_BlinnPhong_Implicit( /* dotNL, dotNV */ );',
'',
' float D = D_BlinnPhong(shininess, dotNH);',
'',
' return F * G * D;',
'}',
'',
'// Microfacet Models for Refraction through Rough Surfaces - equation (33)',
'// http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html',
'// alpha is "roughness squared" in Disneys reparameterization',
'float D_GGX( const in float alpha, const in float dotNH ) {',
'',
' float a2 = pow2( alpha );',
'',
' float denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0; // avoid alpha = 0 with dotNH = 1',
'',
' return RECIPROCAL_PI * a2 / pow2( denom );',
'',
'}',
'',
'// Microfacet Models for Refraction through Rough Surfaces - equation (34)',
'// http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html',
'// alpha is "roughness squared" in Disneys reparameterization',
'float G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {',
'',
' // geometry term = G(l)⋅G(v) / 4(n⋅l)(n⋅v)',
'',
' float a2 = pow2( alpha );',
'',
' float gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );',
' float gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );',
'',
' return 1.0 / ( gl * gv );',
'',
'}',
'',
'// Moving Frostbite to Physically Based Rendering 2.0 - page 12, listing 2',
'// http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr_v2.pdf',
'float G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {',
'',
' float a2 = pow2( alpha );',
'',
' // dotNL and dotNV are explicitly swapped. This is not a mistake.',
' float gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );',
' float gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );',
'',
' return 0.5 / max( gv + gl, EPSILON );',
'}',
'',
'// GGX Distribution, Schlick Fresnel, GGX-Smith Visibility',
'vec4 BRDF_Specular_GGX(vec4 specularColor, vec3 N, vec3 L, vec3 V, float roughness) {',
'',
' float alpha = pow2( roughness ); // UE4's roughness',
'',
' vec3 H = normalize(L + V);',
'',
' float dotNL = saturate( dot(N, L) );',
' float dotNV = saturate( dot(N, V) );',
' float dotNH = saturate( dot(N, H) );',
' float dotLH = saturate( dot(L, H) );',
'',
' vec4 F = F_Schlick( specularColor, dotLH );',
'',
' float G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );',
'',
' float D = D_GGX( alpha, dotNH );',
'',
' return F * G * D;',
'',
'}',
'',
'// ref: https://www.unrealengine.com/blog/physically-based-shading-on-mobile - environmentBRDF for GGX on mobile',
'vec4 BRDF_Specular_GGX_Environment( const in vec3 N, const in vec3 V, const in vec4 specularColor, const in float roughness ) {',
'',
' float dotNV = saturate( dot( N, V ) );',
'',
' const vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );',
'',
' const vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );',
'',
' vec4 r = roughness * c0 + c1;',
'',
' float a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;',
'',
' vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;',
'',
' return specularColor * AB.x + AB.y;',
'',
'}',
'',
'// source: http://simonstechblog.blogspot.ca/2011/12/microfacet-brdf.html',
'float GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {',
' return ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );',
'}',
'',
'float BlinnExponentToGGXRoughness( const in float blinnExponent ) {',
' return sqrt( 2.0 / ( blinnExponent + 2.0 ) );',
'}'
].join('\n');

View file

@ -0,0 +1,45 @@
module.exports = [
'#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 uv) {',
'',
' vec2 dSTdx = dFdx( uv );',
' vec2 dSTdy = dFdy( uv );',
'',
' float Hll = bumpScale * texture2D( bumpMap, uv ).x;',
' float dBx = bumpScale * texture2D( bumpMap, uv + dSTdx ).x - Hll;',
' float dBy = bumpScale * texture2D( bumpMap, uv + dSTdy ).x - Hll;',
'',
' return vec2( dBx, dBy );',
'',
' }',
'',
' vec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy) {',
'',
' vec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );',
' vec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );',
' vec3 vN = surf_norm; // normalized',
'',
' vec3 R1 = cross( vSigmaY, vN );',
' vec3 R2 = cross( vN, vSigmaX );',
'',
' float fDet = dot( vSigmaX, R1 );',
'',
' fDet *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );',
'',
' vec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );',
' return normalize( abs( fDet ) * surf_norm - vGrad );',
'',
' }',
'',
'#endif',
''
].join('\n');

View file

@ -0,0 +1,15 @@
module.exports = [
'#if NUM_CLIPPING_PLANES > 0',
'',
' vec4 plane;',
'',
' #pragma unroll_loop',
' for ( int i = 0; i < NUM_CLIPPING_PLANES; i ++ ) {',
'',
' plane = clippingPlanes[ i ];',
' if ( dot( -v_modelPos, plane.xyz ) > plane.w ) discard;',
'',
' }',
'',
'#endif'
].join('\n');

View file

@ -0,0 +1,5 @@
module.exports = [
'#if NUM_CLIPPING_PLANES > 0',
' uniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];',
'#endif'
].join('\n');

View file

@ -0,0 +1,8 @@
module.exports = [
'#ifdef USE_VCOLOR_RGB',
' outColor.rgb *= v_Color;',
'#endif',
'#ifdef USE_VCOLOR_RGBA',
' outColor *= v_Color;',
'#endif'
].join('\n');

View file

@ -0,0 +1,8 @@
module.exports = [
'#ifdef USE_VCOLOR_RGB',
' varying vec3 v_Color;',
'#endif',
'#ifdef USE_VCOLOR_RGBA',
' varying vec4 v_Color;',
'#endif'
].join('\n');

View file

@ -0,0 +1,10 @@
module.exports = [
'#ifdef USE_VCOLOR_RGB',
' attribute vec3 a_Color;',
' varying vec3 v_Color;',
'#endif',
'#ifdef USE_VCOLOR_RGBA',
' attribute vec4 a_Color;',
' varying vec4 v_Color;',
'#endif'
].join('\n');

View file

@ -0,0 +1,5 @@
module.exports = [
'#if defined(USE_VCOLOR_RGB) || defined(USE_VCOLOR_RGBA)',
' v_Color = a_Color;',
'#endif'
].join('\n');

View file

@ -0,0 +1,8 @@
module.exports = [
'uniform mat4 u_View;',
'',
'uniform float u_Opacity;',
'uniform vec3 u_Color;',
'',
'uniform vec3 u_CameraPosition;'
].join('\n');

View file

@ -0,0 +1,41 @@
module.exports = [
'attribute vec3 a_Position;',
'attribute vec3 a_Normal;',
'#ifdef USE_TANGENT',
' attribute vec4 a_Tangent;',
'#endif',
'',
'#include <transpose>',
'#include <inverse>',
'',
'uniform mat4 u_Projection;',
'uniform mat4 u_View;',
'uniform mat4 u_Model;',
'',
'uniform vec3 u_CameraPosition;',
'',
'#ifdef USE_MORPHTARGETS',
'',
' attribute vec3 morphTarget0;',
' attribute vec3 morphTarget1;',
' attribute vec3 morphTarget2;',
' attribute vec3 morphTarget3;',
'',
' #ifdef USE_MORPHNORMALS',
'',
' attribute vec3 morphNormal0;',
' attribute vec3 morphNormal1;',
' attribute vec3 morphNormal2;',
' attribute vec3 morphNormal3;',
'',
' #else',
'',
' attribute vec3 morphTarget4;',
' attribute vec3 morphTarget5;',
' attribute vec3 morphTarget6;',
' attribute vec3 morphTarget7;',
'',
' #endif',
'',
'#endif'
].join('\n');

View file

@ -0,0 +1,15 @@
module.exports = [
'#ifdef USE_DIFFUSE_MAP',
' #if (USE_DIFFUSE_MAP == 1)',
' vec4 texelColor = texture2D( diffuseMap, v_Uv );',
' #elif (USE_DIFFUSE_MAP == 2)',
' vec4 texelColor = texture2D( diffuseMap, v_Uv2 );',
' #else',
' vec4 texelColor = texture2D( diffuseMap, v_Uv );',
' #endif',
'',
' texelColor = mapTexelToLinear( texelColor );',
'',
' outColor *= texelColor;',
'#endif'
].join('\n');

View file

@ -0,0 +1,5 @@
module.exports = [
'#ifdef USE_DIFFUSE_MAP',
' uniform sampler2D diffuseMap;',
'#endif'
].join('\n');

View file

@ -0,0 +1,13 @@
module.exports = [
'struct DirectLight',
'{',
' vec3 direction;',
' vec4 color;',
'',
' int shadow;',
' float shadowBias;',
' float shadowRadius;',
' vec2 shadowMapSize;',
'};',
'uniform DirectLight u_Directional[NUM_DIR_LIGHTS];'
].join('\n');

View file

@ -0,0 +1,7 @@
module.exports = [
'#if defined( DITHERING )',
'',
' gl_FragColor.rgb = dithering( gl_FragColor.rgb );',
'',
'#endif'
].join('\n');

View file

@ -0,0 +1,20 @@
module.exports = [
'#if defined( DITHERING )',
'',
' // based on http://loopit.dk/banding_in_games.pdf',
' 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;',
' }',
'',
'#endif'
].join('\n');

View file

@ -0,0 +1,17 @@
module.exports = [
'#ifdef USE_EMISSIVEMAP',
'',
' #if (USE_EMISSIVEMAP == 1)',
' vec4 emissiveColor = texture2D(emissiveMap, v_Uv);',
' #elif (USE_EMISSIVEMAP == 2)',
' vec4 emissiveColor = texture2D(emissiveMap, v_Uv2);',
' #else',
' vec4 emissiveColor = texture2D(emissiveMap, v_Uv);',
' #endif',
'',
' emissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;',
'',
' totalEmissiveRadiance *= emissiveColor.rgb;',
'',
'#endif'
].join('\n');

View file

@ -0,0 +1,7 @@
module.exports = [
'#ifdef USE_EMISSIVEMAP',
'',
' uniform sampler2D emissiveMap;',
'',
'#endif'
].join('\n');

View file

@ -0,0 +1,3 @@
module.exports = [
'gl_FragColor = linearToOutputTexel( gl_FragColor );'
].join('\n');

View file

@ -0,0 +1,81 @@
module.exports = [
'// 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.xyz, vec3( gammaFactor ) ), value.w );',
'}',
'vec4 LinearToGamma( in vec4 value, in float gammaFactor ) {',
' return vec4( pow( value.xyz, vec3( 1.0 / gammaFactor ) ), value.w );',
'}',
'',
'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.w );',
'}',
'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.w );',
'}',
'',
'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.xyz * value.w * maxRange, 1.0 );',
'}',
'vec4 LinearToRGBM( in vec4 value, in float maxRange ) {',
' float maxRGB = max( value.x, 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.x, max( value.g, value.b ) );',
' float D = max( maxRange / maxRGB, 1.0 );',
' D = min( floor( D ) / 255.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 = value.rgb * cLogLuvM;',
' 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 = Xp_Y_XYZp.rgb * cLogLuvInverseM;',
' return vec4( max(vRGB, 0.0), 1.0 );',
'}',
''
].join('\n');

View file

@ -0,0 +1,3 @@
module.exports = [
'gl_FragColor = outColor;'
].join('\n');

View file

@ -0,0 +1,23 @@
module.exports = [
'#ifdef USE_ENV_MAP',
'',
' vec3 envDir;',
' #if defined(USE_NORMAL_MAP) || defined(USE_BUMPMAP)',
' envDir = reflect(normalize(v_worldPos - u_CameraPosition), N);',
' #else',
' envDir = v_EnvPos;',
' #endif',
'',
' vec4 envColor = textureCube(envMap, envDir);',
'',
' envColor = envMapTexelToLinear( envColor );',
'',
' #ifdef ENVMAP_BLENDING_MULTIPLY',
' outColor = mix(outColor, envColor * outColor, u_EnvMap_Intensity);',
' #elif defined( ENVMAP_BLENDING_MIX )',
' outColor = mix(outColor, envColor, u_EnvMap_Intensity);',
' #elif defined( ENVMAP_BLENDING_ADD )',
' outColor += envColor * u_EnvMap_Intensity;',
' #endif',
'#endif'
].join('\n');

View file

@ -0,0 +1,12 @@
module.exports = [
'#ifdef USE_ENV_MAP',
' #if defined(USE_NORMAL_MAP) || defined(USE_BUMPMAP)',
' varying vec3 v_worldPos;',
' #else',
' varying vec3 v_EnvPos;',
' #endif',
' uniform samplerCube envMap;',
' uniform float u_EnvMap_Intensity;',
' uniform int maxMipLevel;',
'#endif'
].join('\n');

View file

@ -0,0 +1,9 @@
module.exports = [
'#ifdef USE_ENV_MAP',
' #if defined(USE_NORMAL_MAP) || defined(USE_BUMPMAP)',
' varying vec3 v_worldPos;',
' #else',
' varying vec3 v_EnvPos;',
' #endif',
'#endif'
].join('\n');

View file

@ -0,0 +1,9 @@
module.exports = [
'#ifdef USE_ENV_MAP',
' #if defined(USE_NORMAL_MAP) || defined(USE_BUMPMAP)',
' v_worldPos = (u_Model * vec4(transformed, 1.0)).xyz;',
' #else',
' v_EnvPos = reflect(normalize((u_Model * vec4(transformed, 1.0)).xyz - u_CameraPosition), (transposeMat4(inverseMat4(u_Model)) * vec4(objectNormal, 1.0)).xyz);',
' #endif',
'#endif'
].join('\n');

View file

@ -0,0 +1,19 @@
module.exports = [
'#ifdef USE_FOG',
'',
' float depth = gl_FragCoord.z / gl_FragCoord.w;',
'',
' #ifdef USE_EXP2_FOG',
'',
' float fogFactor = whiteCompliment( exp2( - u_FogDensity * u_FogDensity * depth * depth * LOG2 ) );',
'',
' #else',
'',
' float fogFactor = smoothstep( u_FogNear, u_FogFar, depth );',
'',
' #endif',
'',
' gl_FragColor.rgb = mix( gl_FragColor.rgb, u_FogColor, fogFactor );',
'',
'#endif'
].join('\n');

View file

@ -0,0 +1,17 @@
module.exports = [
'#ifdef USE_FOG',
'',
' uniform vec3 u_FogColor;',
'',
' #ifdef USE_EXP2_FOG',
'',
' uniform float u_FogDensity;',
'',
' #else',
'',
' uniform float u_FogNear;',
' uniform float u_FogFar;',
' #endif',
'',
'#endif'
].join('\n');

View file

@ -0,0 +1,10 @@
#ifdef ALPHATEST
if ( outColor.a < ALPHATEST ) {
discard;
} else {
// Prevent alpha test edge gradient
outColor.a = u_Opacity;
}
#endif

View file

@ -0,0 +1,15 @@
#ifdef USE_ALPHA_MAP
#ifdef USE_ALPHA_MAP_UV_TRANSFORM
outColor.a *= texture2D(alphaMap, vAlphaMapUV).g;
#else
#if (USE_ALPHA_MAP == 1)
outColor.a *= texture2D(alphaMap, v_Uv).g;
#elif (USE_ALPHA_MAP == 2)
outColor.a *= texture2D(alphaMap, v_Uv2).g;
#else
outColor.a *= texture2D(alphaMap, v_Uv).g;
#endif
#endif
#endif

View file

@ -0,0 +1,5 @@
#ifdef USE_ALPHA_MAP
uniform sampler2D alphaMap;
#endif

View file

@ -0,0 +1 @@
uniform vec3 u_AmbientLightColor;

View file

@ -0,0 +1,6 @@
#ifdef USE_AOMAP
uniform sampler2D aoMap;
uniform float aoMapIntensity;
#endif

View file

@ -0,0 +1 @@
vec4 outColor = vec4(u_Color, u_Opacity);

View file

@ -0,0 +1,5 @@
vec3 transformed = vec3(a_Position);
vec3 objectNormal = vec3(a_Normal);
#ifdef USE_TANGENT
vec3 objectTangent = vec3(a_Tangent.xyz);
#endif

View file

@ -0,0 +1,136 @@
// diffuse just use lambert
vec4 BRDF_Diffuse_Lambert(vec4 diffuseColor) {
return RECIPROCAL_PI * diffuseColor;
}
// specular use Cook-Torrance microfacet model, http://ruh.li/GraphicsCookTorrance.html
// About RECIPROCAL_PI: referenced by http://www.joshbarczak.com/blog/?p=272
vec4 F_Schlick( const in vec4 specularColor, const in float dotLH ) {
// Original approximation by Christophe Schlick '94
float fresnel = pow( 1.0 - dotLH, 5.0 );
// Optimized variant (presented by Epic at SIGGRAPH '13)
// float fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );
return ( 1.0 - specularColor ) * fresnel + specularColor;
}
// use blinn phong instead of phong
float D_BlinnPhong( const in float shininess, const in float dotNH ) {
// ( shininess * 0.5 + 1.0 ), three.js do this, but why ???
return RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );
}
float G_BlinnPhong_Implicit( /* const in float dotNL, const in float dotNV */ ) {
// geometry term is (n dot l)(n dot v) / 4(n dot l)(n dot v)
return 0.25;
}
vec4 BRDF_Specular_BlinnPhong(vec4 specularColor, vec3 N, vec3 L, vec3 V, float shininess) {
vec3 H = normalize(L + V);
float dotNH = saturate(dot(N, H));
float dotLH = saturate(dot(L, H));
vec4 F = F_Schlick(specularColor, dotLH);
float G = G_BlinnPhong_Implicit( /* dotNL, dotNV */ );
float D = D_BlinnPhong(shininess, dotNH);
return F * G * D;
}
// Microfacet Models for Refraction through Rough Surfaces - equation (33)
// http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html
// alpha is "roughness squared" in Disneys reparameterization
float D_GGX( const in float alpha, const in float dotNH ) {
float a2 = pow2( alpha );
float denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0; // avoid alpha = 0 with dotNH = 1
return RECIPROCAL_PI * a2 / pow2( denom );
}
// Microfacet Models for Refraction through Rough Surfaces - equation (34)
// http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html
// alpha is "roughness squared" in Disneys reparameterization
float G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {
// geometry term = G(l)⋅G(v) / 4(n⋅l)(n⋅v)
float a2 = pow2( alpha );
float gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );
float gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );
return 1.0 / ( gl * gv );
}
// Moving Frostbite to Physically Based Rendering 2.0 - page 12, listing 2
// http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr_v2.pdf
float G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {
float a2 = pow2( alpha );
// dotNL and dotNV are explicitly swapped. This is not a mistake.
float gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );
float gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );
return 0.5 / max( gv + gl, EPSILON );
}
// GGX Distribution, Schlick Fresnel, GGX-Smith Visibility
vec4 BRDF_Specular_GGX(vec4 specularColor, vec3 N, vec3 L, vec3 V, float roughness) {
float alpha = pow2( roughness ); // UE4's roughness
vec3 H = normalize(L + V);
float dotNL = saturate( dot(N, L) );
float dotNV = saturate( dot(N, V) );
float dotNH = saturate( dot(N, H) );
float dotLH = saturate( dot(L, H) );
vec4 F = F_Schlick( specularColor, dotLH );
float G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );
float D = D_GGX( alpha, dotNH );
return F * G * D;
}
// ref: https://www.unrealengine.com/blog/physically-based-shading-on-mobile - environmentBRDF for GGX on mobile
vec4 BRDF_Specular_GGX_Environment( const in vec3 N, const in vec3 V, const in vec4 specularColor, const in float roughness ) {
float dotNV = saturate( dot( N, V ) );
const vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );
const vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );
vec4 r = roughness * c0 + c1;
float a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;
vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;
return specularColor * AB.x + AB.y;
}
// source: http://simonstechblog.blogspot.ca/2011/12/microfacet-brdf.html
float GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {
return ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );
}
float BlinnExponentToGGXRoughness( const in float blinnExponent ) {
return sqrt( 2.0 / ( blinnExponent + 2.0 ) );
}

View file

@ -0,0 +1,42 @@
#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 uv) {
vec2 dSTdx = dFdx( uv );
vec2 dSTdy = dFdy( uv );
float Hll = bumpScale * texture2D( bumpMap, uv ).x;
float dBx = bumpScale * texture2D( bumpMap, uv + dSTdx ).x - Hll;
float dBy = bumpScale * texture2D( bumpMap, uv + dSTdy ).x - Hll;
return vec2( dBx, dBy );
}
vec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy) {
vec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );
vec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );
vec3 vN = surf_norm; // normalized
vec3 R1 = cross( vSigmaY, vN );
vec3 R2 = cross( vN, vSigmaX );
float fDet = dot( vSigmaX, R1 );
fDet *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );
vec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );
return normalize( abs( fDet ) * surf_norm - vGrad );
}
#endif

View file

@ -0,0 +1,13 @@
#if NUM_CLIPPING_PLANES > 0
vec4 plane;
#pragma unroll_loop
for ( int i = 0; i < NUM_CLIPPING_PLANES; i ++ ) {
plane = clippingPlanes[ i ];
if ( dot( -v_modelPos, plane.xyz ) > plane.w ) discard;
}
#endif

View file

@ -0,0 +1,3 @@
#if NUM_CLIPPING_PLANES > 0
uniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];
#endif

View file

@ -0,0 +1,6 @@
#ifdef USE_VCOLOR_RGB
outColor.rgb *= v_Color;
#endif
#ifdef USE_VCOLOR_RGBA
outColor *= v_Color;
#endif

View file

@ -0,0 +1,6 @@
#ifdef USE_VCOLOR_RGB
varying vec3 v_Color;
#endif
#ifdef USE_VCOLOR_RGBA
varying vec4 v_Color;
#endif

View file

@ -0,0 +1,8 @@
#ifdef USE_VCOLOR_RGB
attribute vec3 a_Color;
varying vec3 v_Color;
#endif
#ifdef USE_VCOLOR_RGBA
attribute vec4 a_Color;
varying vec4 v_Color;
#endif

View file

@ -0,0 +1,3 @@
#if defined(USE_VCOLOR_RGB) || defined(USE_VCOLOR_RGBA)
v_Color = a_Color;
#endif

View file

@ -0,0 +1,6 @@
uniform mat4 u_View;
uniform float u_Opacity;
uniform vec3 u_Color;
uniform vec3 u_CameraPosition;

View file

@ -0,0 +1,39 @@
attribute vec3 a_Position;
attribute vec3 a_Normal;
#ifdef USE_TANGENT
attribute vec4 a_Tangent;
#endif
#include <transpose>
#include <inverse>
uniform mat4 u_Projection;
uniform mat4 u_View;
uniform mat4 u_Model;
uniform vec3 u_CameraPosition;
#ifdef USE_MORPHTARGETS
attribute vec3 morphTarget0;
attribute vec3 morphTarget1;
attribute vec3 morphTarget2;
attribute vec3 morphTarget3;
#ifdef USE_MORPHNORMALS
attribute vec3 morphNormal0;
attribute vec3 morphNormal1;
attribute vec3 morphNormal2;
attribute vec3 morphNormal3;
#else
attribute vec3 morphTarget4;
attribute vec3 morphTarget5;
attribute vec3 morphTarget6;
attribute vec3 morphTarget7;
#endif
#endif

View file

@ -0,0 +1,13 @@
#ifdef USE_DIFFUSE_MAP
#if (USE_DIFFUSE_MAP == 1)
vec4 texelColor = texture2D( diffuseMap, v_Uv );
#elif (USE_DIFFUSE_MAP == 2)
vec4 texelColor = texture2D( diffuseMap, v_Uv2 );
#else
vec4 texelColor = texture2D( diffuseMap, v_Uv );
#endif
texelColor = mapTexelToLinear( texelColor );
outColor *= texelColor;
#endif

View file

@ -0,0 +1,3 @@
#ifdef USE_DIFFUSE_MAP
uniform sampler2D diffuseMap;
#endif

View file

@ -0,0 +1,11 @@
struct DirectLight
{
vec3 direction;
vec4 color;
int shadow;
float shadowBias;
float shadowRadius;
vec2 shadowMapSize;
};
uniform DirectLight u_Directional[NUM_DIR_LIGHTS];

View file

@ -0,0 +1,5 @@
#if defined( DITHERING )
gl_FragColor.rgb = dithering( gl_FragColor.rgb );
#endif

View file

@ -0,0 +1,18 @@
#if defined( DITHERING )
// based on http://loopit.dk/banding_in_games.pdf
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;
}
#endif

View file

@ -0,0 +1,15 @@
#ifdef USE_EMISSIVEMAP
#if (USE_EMISSIVEMAP == 1)
vec4 emissiveColor = texture2D(emissiveMap, v_Uv);
#elif (USE_EMISSIVEMAP == 2)
vec4 emissiveColor = texture2D(emissiveMap, v_Uv2);
#else
vec4 emissiveColor = texture2D(emissiveMap, v_Uv);
#endif
emissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;
totalEmissiveRadiance *= emissiveColor.rgb;
#endif

View file

@ -0,0 +1,5 @@
#ifdef USE_EMISSIVEMAP
uniform sampler2D emissiveMap;
#endif

View file

@ -0,0 +1 @@
gl_FragColor = linearToOutputTexel( gl_FragColor );

View file

@ -0,0 +1,78 @@
// 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.xyz, vec3( gammaFactor ) ), value.w );
}
vec4 LinearToGamma( in vec4 value, in float gammaFactor ) {
return vec4( pow( value.xyz, vec3( 1.0 / gammaFactor ) ), value.w );
}
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.w );
}
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.w );
}
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.xyz * value.w * maxRange, 1.0 );
}
vec4 LinearToRGBM( in vec4 value, in float maxRange ) {
float maxRGB = max( value.x, 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.x, max( value.g, value.b ) );
float D = max( maxRange / maxRGB, 1.0 );
D = min( floor( D ) / 255.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 = value.rgb * cLogLuvM;
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 = Xp_Y_XYZp.rgb * cLogLuvInverseM;
return vec4( max(vRGB, 0.0), 1.0 );
}

View file

@ -0,0 +1 @@
gl_FragColor = outColor;

View file

@ -0,0 +1,21 @@
#ifdef USE_ENV_MAP
vec3 envDir;
#if defined(USE_NORMAL_MAP) || defined(USE_BUMPMAP)
envDir = reflect(normalize(v_worldPos - u_CameraPosition), N);
#else
envDir = v_EnvPos;
#endif
vec4 envColor = textureCube(envMap, envDir);
envColor = envMapTexelToLinear( envColor );
#ifdef ENVMAP_BLENDING_MULTIPLY
outColor = mix(outColor, envColor * outColor, u_EnvMap_Intensity);
#elif defined( ENVMAP_BLENDING_MIX )
outColor = mix(outColor, envColor, u_EnvMap_Intensity);
#elif defined( ENVMAP_BLENDING_ADD )
outColor += envColor * u_EnvMap_Intensity;
#endif
#endif

View file

@ -0,0 +1,10 @@
#ifdef USE_ENV_MAP
#if defined(USE_NORMAL_MAP) || defined(USE_BUMPMAP)
varying vec3 v_worldPos;
#else
varying vec3 v_EnvPos;
#endif
uniform samplerCube envMap;
uniform float u_EnvMap_Intensity;
uniform int maxMipLevel;
#endif

View file

@ -0,0 +1,7 @@
#ifdef USE_ENV_MAP
#if defined(USE_NORMAL_MAP) || defined(USE_BUMPMAP)
varying vec3 v_worldPos;
#else
varying vec3 v_EnvPos;
#endif
#endif

View file

@ -0,0 +1,7 @@
#ifdef USE_ENV_MAP
#if defined(USE_NORMAL_MAP) || defined(USE_BUMPMAP)
v_worldPos = (u_Model * vec4(transformed, 1.0)).xyz;
#else
v_EnvPos = reflect(normalize((u_Model * vec4(transformed, 1.0)).xyz - u_CameraPosition), (transposeMat4(inverseMat4(u_Model)) * vec4(objectNormal, 1.0)).xyz);
#endif
#endif

View file

@ -0,0 +1,17 @@
#ifdef USE_FOG
float depth = gl_FragCoord.z / gl_FragCoord.w;
#ifdef USE_EXP2_FOG
float fogFactor = whiteCompliment( exp2( - u_FogDensity * u_FogDensity * depth * depth * LOG2 ) );
#else
float fogFactor = smoothstep( u_FogNear, u_FogFar, depth );
#endif
gl_FragColor.rgb = mix( gl_FragColor.rgb, u_FogColor, fogFactor );
#endif

View file

@ -0,0 +1,15 @@
#ifdef USE_FOG
uniform vec3 u_FogColor;
#ifdef USE_EXP2_FOG
uniform float u_FogDensity;
#else
uniform float u_FogNear;
uniform float u_FogFar;
#endif
#endif

View file

@ -0,0 +1,37 @@
mat4 inverseMat4(mat4 m) {
float
a00 = m[0][0], a01 = m[0][1], a02 = m[0][2], a03 = m[0][3],
a10 = m[1][0], a11 = m[1][1], a12 = m[1][2], a13 = m[1][3],
a20 = m[2][0], a21 = m[2][1], a22 = m[2][2], a23 = m[2][3],
a30 = m[3][0], a31 = m[3][1], a32 = m[3][2], a33 = m[3][3],
b00 = a00 * a11 - a01 * a10,
b01 = a00 * a12 - a02 * a10,
b02 = a00 * a13 - a03 * a10,
b03 = a01 * a12 - a02 * a11,
b04 = a01 * a13 - a03 * a11,
b05 = a02 * a13 - a03 * a12,
b06 = a20 * a31 - a21 * a30,
b07 = a20 * a32 - a22 * a30,
b08 = a20 * a33 - a23 * a30,
b09 = a21 * a32 - a22 * a31,
b10 = a21 * a33 - a23 * a31,
b11 = a22 * a33 - a23 * a32,
det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
return mat4(
a11 * b11 - a12 * b10 + a13 * b09,
a02 * b10 - a01 * b11 - a03 * b09,
a31 * b05 - a32 * b04 + a33 * b03,
a22 * b04 - a21 * b05 - a23 * b03,
a12 * b08 - a10 * b11 - a13 * b07,
a00 * b11 - a02 * b08 + a03 * b07,
a32 * b02 - a30 * b05 - a33 * b01,
a20 * b05 - a22 * b02 + a23 * b01,
a10 * b10 - a11 * b08 + a13 * b06,
a01 * b08 - a00 * b10 - a03 * b06,
a30 * b04 - a31 * b02 + a33 * b00,
a21 * b02 - a20 * b04 - a23 * b00,
a11 * b07 - a10 * b09 - a12 * b06,
a00 * b09 - a01 * b07 + a02 * b06,
a31 * b01 - a30 * b03 - a32 * b00,
a20 * b03 - a21 * b01 + a22 * b00) / det;
}

View file

@ -0,0 +1,213 @@
#ifdef USE_LIGHT
vec4 light;
vec3 L;
vec4 totalReflect = vec4(0., 0., 0., 0.); // direct light
// https://computergraphics.stackexchange.com/questions/7503/what-is-the-difference-between-radiance-and-irradiance-in-brdf
vec3 indirectIrradiance = vec3(0., 0., 0.); // for indirect diffuse
vec3 indirectRadiance = vec3(0., 0., 0.); // for indirect specular
#ifdef USE_PBR
#ifdef USE_PBR2
vec4 diffuseColor = outColor.xyzw;
vec4 specularColor = vec4(specularFactor.rgb, 1.);
float roughness = clamp(1.0 - glossinessFactor, 0.04, 1.0);
#else
vec4 diffuseColor = outColor.xyzw * (1.0 - metalnessFactor);
vec4 specularColor = mix(vec4(0.04), outColor.xyzw, metalnessFactor);
float roughness = clamp(roughnessFactor, 0.04, 1.0);
#endif
#else
vec4 diffuseColor = outColor.xyzw;
#ifdef USE_PHONG
vec4 specularColor = vec4(u_SpecularColor, 1.);
float shininess = u_Specular;
#endif
#endif
#ifdef USE_AMBIENT_LIGHT
indirectIrradiance += u_AmbientLightColor;
#endif
// TODO light map
#ifdef USE_PBR
#ifdef USE_ENV_MAP
vec3 envDir;
#if defined(USE_NORMAL_MAP) || defined(USE_BUMPMAP)
envDir = reflect(normalize(v_worldPos - u_CameraPosition), N);
#else
envDir = v_EnvPos;
#endif
indirectIrradiance += getLightProbeIndirectIrradiance(maxMipLevel, envDir);
indirectRadiance += getLightProbeIndirectRadiance(GGXRoughnessToBlinnExponent(roughness), maxMipLevel, envDir);
#endif
#endif
#if (defined(USE_PHONG) || defined(USE_PBR))
vec3 V = normalize( u_CameraPosition - v_modelPos );
#endif
float dotNL;
vec4 irradiance;
vec4 reflectLight;
float dist;
#if NUM_DIR_LIGHTS > 0
#pragma unroll_loop
for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {
L = -u_Directional[ i ].direction;
light = u_Directional[ i ].color;
L = normalize(L);
dotNL = saturate( dot(N, L) );
irradiance = light * dotNL;
#if NUM_DIR_SHADOWS > 0
#ifdef USE_PCSS_SOFT_SHADOW
irradiance *= bool( u_Directional[ i ].shadow ) ? getShadowWithPCSS( directionalDepthMap[ i ], directionalShadowMap[ i ], vDirectionalShadowCoord[ i ], u_Directional[ i ].shadowBias, u_Directional[ i ].shadowRadius, u_Directional[ i ].shadowMapSize ) : 1.0;
#else
irradiance *= bool( u_Directional[ i ].shadow ) ? getShadow( directionalShadowMap[ i ], vDirectionalShadowCoord[ i ], u_Directional[ i ].shadowBias, u_Directional[ i ].shadowRadius, u_Directional[ i ].shadowMapSize ) : 1.0;
#endif
#endif
// #ifndef USE_PBR
// irradiance *= PI;
// #endif
reflectLight = irradiance * BRDF_Diffuse_Lambert(diffuseColor);
#ifdef USE_PHONG
reflectLight += irradiance * BRDF_Specular_BlinnPhong(specularColor, N, L, V, shininess) * specularStrength;
#endif
#ifdef USE_PBR
reflectLight += irradiance * BRDF_Specular_GGX(specularColor, N, L, V, roughness);
#endif
totalReflect += reflectLight;
}
#endif
#if NUM_POINT_LIGHTS > 0
vec3 worldV;
#pragma unroll_loop
for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {
L = u_Point[ i ].position - v_modelPos;
dist = pow(clamp(1. - length(L) / u_Point[ i ].distance, 0.0, 1.0), u_Point[ i ].decay);
light = u_Point[ i ].color * dist;
L = normalize(L);
dotNL = saturate( dot(N, L) );
irradiance = light * dotNL;
// #ifndef USE_PBR
// irradiance *= PI;
// #endif
#if NUM_POINT_SHADOWS > 0
worldV = v_modelPos - u_Point[ i ].position;
irradiance *= bool( u_Point[ i ].shadow ) ? getPointShadow( pointShadowMap[ i ], worldV, u_Point[ i ].shadowBias, u_Point[ i ].shadowRadius, u_Point[ i ].shadowMapSize, u_Point[ i ].shadowCameraNear, u_Point[ i ].shadowCameraFar ) : 1.0;
#endif
reflectLight = irradiance * BRDF_Diffuse_Lambert(diffuseColor);
#ifdef USE_PHONG
reflectLight += irradiance * BRDF_Specular_BlinnPhong(specularColor, N, L, V, shininess) * specularStrength;
#endif
#ifdef USE_PBR
reflectLight += irradiance * BRDF_Specular_GGX(specularColor, N, L, V, roughness);
#endif
totalReflect += reflectLight;
}
#endif
#if NUM_SPOT_LIGHTS > 0
float lightDistance;
float angleCos;
float spotEffect;
#pragma unroll_loop
for ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {
L = u_Spot[ i ].position - v_modelPos;
lightDistance = length(L);
L = normalize(L);
angleCos = dot( L, -normalize(u_Spot[ i ].direction) );
if( all( bvec2(angleCos > u_Spot[ i ].coneCos, lightDistance < u_Spot[ i ].distance) ) ) {
spotEffect = smoothstep( u_Spot[ i ].coneCos, u_Spot[ i ].penumbraCos, angleCos );
dist = pow(clamp(1. - lightDistance / u_Spot[ i ].distance, 0.0, 1.0), u_Spot[ i ].decay);
light = u_Spot[ i ].color * dist * spotEffect;
dotNL = saturate( dot(N, L) );
irradiance = light * dotNL;
// #ifndef USE_PBR
// irradiance *= PI;
// #endif
#if NUM_SPOT_SHADOWS > 0
#ifdef USE_PCSS_SOFT_SHADOW
irradiance *= bool( u_Spot[ i ].shadow ) ? getShadowWithPCSS( spotDepthMap[ i ], spotShadowMap[ i ], vSpotShadowCoord[ i ], u_Spot[ i ].shadowBias, u_Spot[ i ].shadowRadius, u_Spot[ i ].shadowMapSize ) : 1.0;
#else
irradiance *= bool( u_Spot[ i ].shadow ) ? getShadow( spotShadowMap[ i ], vSpotShadowCoord[ i ], u_Spot[ i ].shadowBias, u_Spot[ i ].shadowRadius, u_Spot[ i ].shadowMapSize ) : 1.0;
#endif
#endif
reflectLight = irradiance * BRDF_Diffuse_Lambert(diffuseColor);
#ifdef USE_PHONG
reflectLight += irradiance * BRDF_Specular_BlinnPhong(specularColor, N, L, V, shininess) * specularStrength;
#endif
#ifdef USE_PBR
reflectLight += irradiance * BRDF_Specular_GGX(specularColor, N, L, V, roughness);
#endif
totalReflect += reflectLight;
}
}
#endif
vec3 indirectDiffuse = indirectIrradiance * BRDF_Diffuse_Lambert(diffuseColor).rgb;
vec3 indirectSpecular = vec3(0., 0., 0.);
#if defined( USE_ENV_MAP ) && defined( USE_PBR )
indirectSpecular += indirectRadiance * BRDF_Specular_GGX_Environment(N, V, specularColor, roughness).rgb;
#endif
#ifdef USE_AOMAP
// reads channel R, compatible with a combined OcclusionRoughnessMetallic (RGB) texture
#if (USE_AOMAP == 1)
float ambientOcclusion = ( texture2D( aoMap, v_Uv ).r - 1.0 ) * aoMapIntensity + 1.0;
#elif (USE_AOMAP == 2)
float ambientOcclusion = ( texture2D( aoMap, v_Uv2 ).r - 1.0 ) * aoMapIntensity + 1.0;
#else
float ambientOcclusion = ( texture2D( aoMap, v_Uv ).r - 1.0 ) * aoMapIntensity + 1.0;
#endif
indirectDiffuse *= ambientOcclusion;
#if defined( USE_ENV_MAP ) && defined( USE_PBR )
float dotNV = saturate( dot( N, V ) );
indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, GGXRoughnessToBlinnExponent(roughness) );
#endif
#endif
outColor.xyz = totalReflect.xyz + indirectDiffuse + indirectSpecular;
#endif

View file

@ -0,0 +1,75 @@
#ifdef USE_AMBIENT_LIGHT
#include <ambientlight_pars_frag>
#endif
#if NUM_DIR_LIGHTS > 0
#include <directlight_pars_frag>
#endif
#if NUM_POINT_LIGHTS > 0
#include <pointlight_pars_frag>
#endif
#if NUM_SPOT_LIGHTS > 0
#include <spotlight_pars_frag>
#endif
#if defined(USE_PBR) && defined(USE_ENV_MAP)
vec3 getLightProbeIndirectIrradiance(const in int maxMIPLevel, const in vec3 envDir) {
// TODO: replace with properly filtered cubemaps and access the irradiance LOD level, be it the last LOD level
// of a specular cubemap, or just the default level of a specially created irradiance cubemap.
#ifdef TEXTURE_LOD_EXT
vec4 envMapColor = textureCubeLodEXT( envMap, envDir, float( maxMIPLevel ) );
#else
// force the bias high to get the last LOD level as it is the most blurred.
vec4 envMapColor = textureCube( envMap, envDir, float( maxMIPLevel ) );
#endif
envMapColor = envMapTexelToLinear( envMapColor );
return PI * envMapColor.rgb * u_EnvMap_Intensity;
}
// taken from here: http://casual-effects.blogspot.ca/2011/08/plausible-environment-lighting-in-two.html
float getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {
//float envMapWidth = pow( 2.0, maxMIPLevelScalar );
//float desiredMIPLevel = log2( envMapWidth * sqrt( 3.0 ) ) - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );
float maxMIPLevelScalar = float( maxMIPLevel );
float desiredMIPLevel = maxMIPLevelScalar - 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );
// clamp to allowable LOD ranges.
return clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );
}
vec3 getLightProbeIndirectRadiance(const in float blinnShininessExponent, const in int maxMIPLevel, const in vec3 envDir) {
float specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );
#ifdef TEXTURE_LOD_EXT
vec4 envMapColor = textureCubeLodEXT( envMap, envDir, specularMIPLevel );
#else
vec4 envMapColor = textureCube( envMap, envDir, specularMIPLevel );
#endif
envMapColor = envMapTexelToLinear( envMapColor );
return envMapColor.rgb * u_EnvMap_Intensity;
}
// ref: https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
float computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {
return saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );
}
#endif

View file

@ -0,0 +1,8 @@
#ifdef USE_MORPHNORMALS
objectNormal += morphNormal0 * morphTargetInfluences[ 0 ];
objectNormal += morphNormal1 * morphTargetInfluences[ 1 ];
objectNormal += morphNormal2 * morphTargetInfluences[ 2 ];
objectNormal += morphNormal3 * morphTargetInfluences[ 3 ];
#endif

View file

@ -0,0 +1,13 @@
#ifdef USE_MORPHTARGETS
#ifndef USE_MORPHNORMALS
uniform float morphTargetInfluences[ 8 ];
#else
uniform float morphTargetInfluences[ 4 ];
#endif
#endif

View file

@ -0,0 +1,17 @@
#ifdef USE_MORPHTARGETS
transformed += morphTarget0 * morphTargetInfluences[ 0 ];
transformed += morphTarget1 * morphTargetInfluences[ 1 ];
transformed += morphTarget2 * morphTargetInfluences[ 2 ];
transformed += morphTarget3 * morphTargetInfluences[ 3 ];
#ifndef USE_MORPHNORMALS
transformed += morphTarget4 * morphTargetInfluences[ 4 ];
transformed += morphTarget5 * morphTargetInfluences[ 5 ];
transformed += morphTarget6 * morphTargetInfluences[ 6 ];
transformed += morphTarget7 * morphTargetInfluences[ 7 ];
#endif
#endif

View file

@ -0,0 +1,30 @@
#ifdef FLAT_SHADED
// Workaround for Adreno/Nexus5 not able able to do dFdx( Vec3 ) ...
vec3 fdx = vec3( dFdx( v_modelPos.x ), dFdx( v_modelPos.y ), dFdx( v_modelPos.z ) );
vec3 fdy = vec3( dFdy( v_modelPos.x ), dFdy( v_modelPos.y ), dFdy( v_modelPos.z ) );
vec3 N = normalize( cross( fdx, fdy ) );
#else
vec3 N = normalize(v_Normal);
#ifdef DOUBLE_SIDED
N = N * ( float( gl_FrontFacing ) * 2.0 - 1.0 );
#endif
#endif
#ifdef USE_NORMAL_MAP
vec3 mapN = texture2D(normalMap, v_Uv).rgb * 2.0 - 1.0;
#if defined(USE_TANGENT) && !defined(FLAT_SHADED)
vec3 tangent = normalize(v_Tangent);
vec3 bitangent = normalize(v_Bitangent);
#ifdef DOUBLE_SIDED
tangent = tangent * ( float( gl_FrontFacing ) * 2.0 - 1.0 );
bitangent = bitangent * ( float( gl_FrontFacing ) * 2.0 - 1.0 );
#endif
mat3 tspace = mat3(tangent, bitangent, N);
#else
// for now, uv coord is flip Y
mat3 tspace = tsn(N, v_modelPos, vec2(v_Uv.x, 1.0 - v_Uv.y));
mapN.xy *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );
#endif
N = normalize(tspace * mapN);
#elif defined(USE_BUMPMAP)
N = perturbNormalArb(v_modelPos, N, dHdxy_fwd(v_Uv));
#endif

View file

@ -0,0 +1,4 @@
#if !defined(USE_TANGENT) || defined(FLAT_SHADED)
#include <tsn>
#endif
uniform sampler2D normalMap;

View file

@ -0,0 +1,7 @@
#ifndef FLAT_SHADED
varying vec3 v_Normal;
#ifdef USE_TANGENT
varying vec3 v_Tangent;
varying vec3 v_Bitangent;
#endif
#endif

View file

@ -0,0 +1,7 @@
#ifndef FLAT_SHADED
varying vec3 v_Normal;
#ifdef USE_TANGENT
varying vec3 v_Tangent;
varying vec3 v_Bitangent;
#endif
#endif

View file

@ -0,0 +1,17 @@
#ifndef FLAT_SHADED
v_Normal = (transposeMat4(inverseMat4(u_Model)) * vec4(objectNormal, 0.0)).xyz;
#ifdef FLIP_SIDED
v_Normal = - v_Normal;
#endif
#ifdef USE_TANGENT
v_Tangent = (transposeMat4(inverseMat4(u_Model)) * vec4(objectTangent, 0.0)).xyz;
#ifdef FLIP_SIDED
v_Tangent = - v_Tangent;
#endif
v_Bitangent = normalize(cross(v_Normal, v_Tangent) * a_Tangent.w);
#endif
#endif

View file

@ -0,0 +1,21 @@
const float PackUpscale = 256. / 255.; // fraction -> 0..1 (including 1)
const float UnpackDownscale = 255. / 256.; // 0..1 -> fraction (excluding 1)
const vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );
const vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );
const float ShiftRight8 = 1. / 256.;
vec4 packDepthToRGBA( const in float v ) {
vec4 r = vec4( fract( v * PackFactors ), v );
r.yzw -= r.xyz * ShiftRight8; // tidy overflow
return r * PackUpscale;
}
float unpackRGBAToDepth( const in vec4 v ) {
return dot( v, UnpackFactors );
}

View file

@ -0,0 +1,16 @@
struct PointLight
{
vec3 position;
vec4 color;
float distance;
float decay;
int shadow;
float shadowBias;
float shadowRadius;
vec2 shadowMapSize;
float shadowCameraNear;
float shadowCameraFar;
};
uniform PointLight u_Point[NUM_POINT_LIGHTS];

View file

@ -0,0 +1,3 @@
#ifdef USE_PREMULTIPLIED_ALPHA
gl_FragColor.rgb = gl_FragColor.rgb * gl_FragColor.a;
#endif

View file

@ -0,0 +1 @@
gl_Position = u_Projection * u_View * u_Model * vec4(transformed, 1.0);

View file

@ -0,0 +1,380 @@
#ifdef WEBGL2
float computeShadow(sampler2DShadow shadowMap, vec3 shadowCoord) {
return texture2D( shadowMap, shadowCoord );
}
#else
float computeShadow(sampler2D shadowMap, vec3 shadowCoord) {
return step( shadowCoord.z, unpackRGBAToDepth( texture2D( shadowMap, shadowCoord.xy ) ) );
}
#endif
float computeShadowWithPoissonSampling( sampler2DShadow shadowMap, vec3 shadowCoord, float texelSize ) {
vec3 poissonDisk[4];
poissonDisk[0] = vec3(-0.94201624, -0.39906216, 0);
poissonDisk[1] = vec3(0.94558609, -0.76890725, 0);
poissonDisk[2] = vec3(-0.094184101, -0.92938870, 0);
poissonDisk[3] = vec3(0.34495938, 0.29387760, 0);
return computeShadow( shadowMap, shadowCoord + poissonDisk[0] * texelSize ) * 0.25 +
computeShadow( shadowMap, shadowCoord + poissonDisk[1] * texelSize ) * 0.25 +
computeShadow( shadowMap, shadowCoord + poissonDisk[2] * texelSize ) * 0.25 +
computeShadow( shadowMap, shadowCoord + poissonDisk[3] * texelSize ) * 0.25;
}
// Shadow PCF kernel size 1 with a single tap (lowest quality)
float computeShadowWithPCF1(sampler2DShadow shadowSampler, vec3 shadowCoord) {
return computeShadow(shadowSampler, shadowCoord);
}
// Shadow PCF kernel 3*3 in only 4 taps (medium quality)
// This uses a well distributed taps to allow a gaussian distribution covering a 3*3 kernel
// https://mynameismjp.wordpress.com/2013/09/10/shadow-maps/
float computeShadowWithPCF3(sampler2DShadow shadowSampler, vec3 shadowCoord, vec2 shadowMapSizeAndInverse) {
vec2 uv = shadowCoord.xy * shadowMapSizeAndInverse.x; // uv in texel units
uv += 0.5; // offset of half to be in the center of the texel
vec2 st = fract(uv); // how far from the center
vec2 base_uv = floor(uv) - 0.5; // texel coord
base_uv *= shadowMapSizeAndInverse.y; // move back to uv coords
// Equation resolved to fit in a 3*3 distribution like
// 1 2 1
// 2 4 2
// 1 2 1
vec2 uvw0 = 3. - 2. * st;
vec2 uvw1 = 1. + 2. * st;
vec2 u = vec2((2. - st.x) / uvw0.x - 1., st.x / uvw1.x + 1.) * shadowMapSizeAndInverse.y;
vec2 v = vec2((2. - st.y) / uvw0.y - 1., st.y / uvw1.y + 1.) * shadowMapSizeAndInverse.y;
float shadow = 0.;
shadow += uvw0.x * uvw0.y * computeShadow(shadowSampler, vec3(base_uv.xy + vec2(u[0], v[0]), shadowCoord.z));
shadow += uvw1.x * uvw0.y * computeShadow(shadowSampler, vec3(base_uv.xy + vec2(u[1], v[0]), shadowCoord.z));
shadow += uvw0.x * uvw1.y * computeShadow(shadowSampler, vec3(base_uv.xy + vec2(u[0], v[1]), shadowCoord.z));
shadow += uvw1.x * uvw1.y * computeShadow(shadowSampler, vec3(base_uv.xy + vec2(u[1], v[1]), shadowCoord.z));
shadow = shadow / 16.;
return shadow;
}
// Shadow PCF kernel 5*5 in only 9 taps (high quality)
// This uses a well distributed taps to allow a gaussian distribution covering a 5*5 kernel
// https://mynameismjp.wordpress.com/2013/09/10/shadow-maps/
float computeShadowWithPCF5(sampler2DShadow shadowSampler, vec3 shadowCoord, vec2 shadowMapSizeAndInverse) {
vec2 uv = shadowCoord.xy * shadowMapSizeAndInverse.x; // uv in texel units
uv += 0.5; // offset of half to be in the center of the texel
vec2 st = fract(uv); // how far from the center
vec2 base_uv = floor(uv) - 0.5; // texel coord
base_uv *= shadowMapSizeAndInverse.y; // move back to uv coords
// Equation resolved to fit in a 5*5 distribution like
// 1 2 4 2 1
vec2 uvw0 = 4. - 3. * st;
vec2 uvw1 = vec2(7.);
vec2 uvw2 = 1. + 3. * st;
vec3 u = vec3((3. - 2. * st.x) / uvw0.x - 2., (3. + st.x) / uvw1.x, st.x / uvw2.x + 2.) * shadowMapSizeAndInverse.y;
vec3 v = vec3((3. - 2. * st.y) / uvw0.y - 2., (3. + st.y) / uvw1.y, st.y / uvw2.y + 2.) * shadowMapSizeAndInverse.y;
float shadow = 0.;
shadow += uvw0.x * uvw0.y * computeShadow(shadowSampler, vec3(base_uv.xy + vec2(u[0], v[0]), shadowCoord.z));
shadow += uvw1.x * uvw0.y * computeShadow(shadowSampler, vec3(base_uv.xy + vec2(u[1], v[0]), shadowCoord.z));
shadow += uvw2.x * uvw0.y * computeShadow(shadowSampler, vec3(base_uv.xy + vec2(u[2], v[0]), shadowCoord.z));
shadow += uvw0.x * uvw1.y * computeShadow(shadowSampler, vec3(base_uv.xy + vec2(u[0], v[1]), shadowCoord.z));
shadow += uvw1.x * uvw1.y * computeShadow(shadowSampler, vec3(base_uv.xy + vec2(u[1], v[1]), shadowCoord.z));
shadow += uvw2.x * uvw1.y * computeShadow(shadowSampler, vec3(base_uv.xy + vec2(u[2], v[1]), shadowCoord.z));
shadow += uvw0.x * uvw2.y * computeShadow(shadowSampler, vec3(base_uv.xy + vec2(u[0], v[2]), shadowCoord.z));
shadow += uvw1.x * uvw2.y * computeShadow(shadowSampler, vec3(base_uv.xy + vec2(u[1], v[2]), shadowCoord.z));
shadow += uvw2.x * uvw2.y * computeShadow(shadowSampler, vec3(base_uv.xy + vec2(u[2], v[2]), shadowCoord.z));
shadow = shadow / 144.;
return shadow;
}
float getShadow( sampler2DShadow shadowMap, vec4 shadowCoord, float shadowBias, float shadowRadius, vec2 shadowMapSize ) {
shadowCoord.xyz /= shadowCoord.w;
shadowCoord.z += shadowBias;
bvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );
bool inFrustum = all( inFrustumVec );
bvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );
bool frustumTest = all( frustumTestVec );
if ( frustumTest ) {
#ifdef USE_HARD_SHADOW
return computeShadow(shadowMap, shadowCoord.xyz);
#else
#ifdef USE_PCF3_SOFT_SHADOW
vec2 shadowMapSizeAndInverse = vec2(shadowMapSize.x, 1. / shadowMapSize.x);
return computeShadowWithPCF3(shadowMap, shadowCoord.xyz, shadowMapSizeAndInverse);
#else
#ifdef USE_PCF5_SOFT_SHADOW
vec2 shadowMapSizeAndInverse = vec2(shadowMapSize.x, 1. / shadowMapSize.x);
return computeShadowWithPCF5(shadowMap, shadowCoord.xyz, shadowMapSizeAndInverse);
#else
float texelSize = shadowRadius / shadowMapSize.x;
return computeShadowWithPoissonSampling(shadowMap, shadowCoord.xyz, texelSize);
#endif
#endif
#endif
}
return 1.0;
}
float textureCubeCompare( samplerCube depths, vec3 uv, float compare ) {
return step( compare, unpackRGBAToDepth( textureCube( depths, uv ) ) );
}
float getPointShadow( samplerCube shadowMap, vec3 V, float shadowBias, float shadowRadius, vec2 shadowMapSize, float shadowCameraNear, float shadowCameraFar ) {
// depth = normalized distance from light to fragment position
float depth = ( length( V ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear ); // need to clamp?
depth += shadowBias;
#ifdef USE_HARD_SHADOW
return textureCubeCompare( shadowMap, normalize(V), depth);
#else
float texelSize = shadowRadius / shadowMapSize.x;
vec3 poissonDisk[4];
poissonDisk[0] = vec3(-1.0, 1.0, -1.0);
poissonDisk[1] = vec3(1.0, -1.0, -1.0);
poissonDisk[2] = vec3(-1.0, -1.0, -1.0);
poissonDisk[3] = vec3(1.0, -1.0, 1.0);
return textureCubeCompare( shadowMap, normalize(V) + poissonDisk[0] * texelSize, depth ) * 0.25 +
textureCubeCompare( shadowMap, normalize(V) + poissonDisk[1] * texelSize, depth ) * 0.25 +
textureCubeCompare( shadowMap, normalize(V) + poissonDisk[2] * texelSize, depth ) * 0.25 +
textureCubeCompare( shadowMap, normalize(V) + poissonDisk[3] * texelSize, depth ) * 0.25;
#endif
}
#ifdef USE_PCSS_SOFT_SHADOW
const vec3 PoissonSamplers32[64] = vec3[64](
vec3(0.06407013, 0.05409927, 0.),
vec3(0.7366577, 0.5789394, 0.),
vec3(-0.6270542, -0.5320278, 0.),
vec3(-0.4096107, 0.8411095, 0.),
vec3(0.6849564, -0.4990818, 0.),
vec3(-0.874181, -0.04579735, 0.),
vec3(0.9989998, 0.0009880066, 0.),
vec3(-0.004920578, -0.9151649, 0.),
vec3(0.1805763, 0.9747483, 0.),
vec3(-0.2138451, 0.2635818, 0.),
vec3(0.109845, 0.3884785, 0.),
vec3(0.06876755, -0.3581074, 0.),
vec3(0.374073, -0.7661266, 0.),
vec3(0.3079132, -0.1216763, 0.),
vec3(-0.3794335, -0.8271583, 0.),
vec3(-0.203878, -0.07715034, 0.),
vec3(0.5912697, 0.1469799, 0.),
vec3(-0.88069, 0.3031784, 0.),
vec3(0.5040108, 0.8283722, 0.),
vec3(-0.5844124, 0.5494877, 0.),
vec3(0.6017799, -0.1726654, 0.),
vec3(-0.5554981, 0.1559997, 0.),
vec3(-0.3016369, -0.3900928, 0.),
vec3(-0.5550632, -0.1723762, 0.),
vec3(0.925029, 0.2995041, 0.),
vec3(-0.2473137, 0.5538505, 0.),
vec3(0.9183037, -0.2862392, 0.),
vec3(0.2469421, 0.6718712, 0.),
vec3(0.3916397, -0.4328209, 0.),
vec3(-0.03576927, -0.6220032, 0.),
vec3(-0.04661255, 0.7995201, 0.),
vec3(0.4402924, 0.3640312, 0.),
vec3(0., 0., 0.),
vec3(0., 0., 0.),
vec3(0., 0., 0.),
vec3(0., 0., 0.),
vec3(0., 0., 0.),
vec3(0., 0., 0.),
vec3(0., 0., 0.),
vec3(0., 0., 0.),
vec3(0., 0., 0.),
vec3(0., 0., 0.),
vec3(0., 0., 0.),
vec3(0., 0., 0.),
vec3(0., 0., 0.),
vec3(0., 0., 0.),
vec3(0., 0., 0.),
vec3(0., 0., 0.),
vec3(0., 0., 0.),
vec3(0., 0., 0.),
vec3(0., 0., 0.),
vec3(0., 0., 0.),
vec3(0., 0., 0.),
vec3(0., 0., 0.),
vec3(0., 0., 0.),
vec3(0., 0., 0.),
vec3(0., 0., 0.),
vec3(0., 0., 0.),
vec3(0., 0., 0.),
vec3(0., 0., 0.),
vec3(0., 0., 0.),
vec3(0., 0., 0.),
vec3(0., 0., 0.),
vec3(0., 0., 0.)
);
const vec3 PoissonSamplers64[64] = vec3[64](
vec3(-0.613392, 0.617481, 0.),
vec3(0.170019, -0.040254, 0.),
vec3(-0.299417, 0.791925, 0.),
vec3(0.645680, 0.493210, 0.),
vec3(-0.651784, 0.717887, 0.),
vec3(0.421003, 0.027070, 0.),
vec3(-0.817194, -0.271096, 0.),
vec3(-0.705374, -0.668203, 0.),
vec3(0.977050, -0.108615, 0.),
vec3(0.063326, 0.142369, 0.),
vec3(0.203528, 0.214331, 0.),
vec3(-0.667531, 0.326090, 0.),
vec3(-0.098422, -0.295755, 0.),
vec3(-0.885922, 0.215369, 0.),
vec3(0.566637, 0.605213, 0.),
vec3(0.039766, -0.396100, 0.),
vec3(0.751946, 0.453352, 0.),
vec3(0.078707, -0.715323, 0.),
vec3(-0.075838, -0.529344, 0.),
vec3(0.724479, -0.580798, 0.),
vec3(0.222999, -0.215125, 0.),
vec3(-0.467574, -0.405438, 0.),
vec3(-0.248268, -0.814753, 0.),
vec3(0.354411, -0.887570, 0.),
vec3(0.175817, 0.382366, 0.),
vec3(0.487472, -0.063082, 0.),
vec3(-0.084078, 0.898312, 0.),
vec3(0.488876, -0.783441, 0.),
vec3(0.470016, 0.217933, 0.),
vec3(-0.696890, -0.549791, 0.),
vec3(-0.149693, 0.605762, 0.),
vec3(0.034211, 0.979980, 0.),
vec3(0.503098, -0.308878, 0.),
vec3(-0.016205, -0.872921, 0.),
vec3(0.385784, -0.393902, 0.),
vec3(-0.146886, -0.859249, 0.),
vec3(0.643361, 0.164098, 0.),
vec3(0.634388, -0.049471, 0.),
vec3(-0.688894, 0.007843, 0.),
vec3(0.464034, -0.188818, 0.),
vec3(-0.440840, 0.137486, 0.),
vec3(0.364483, 0.511704, 0.),
vec3(0.034028, 0.325968, 0.),
vec3(0.099094, -0.308023, 0.),
vec3(0.693960, -0.366253, 0.),
vec3(0.678884, -0.204688, 0.),
vec3(0.001801, 0.780328, 0.),
vec3(0.145177, -0.898984, 0.),
vec3(0.062655, -0.611866, 0.),
vec3(0.315226, -0.604297, 0.),
vec3(-0.780145, 0.486251, 0.),
vec3(-0.371868, 0.882138, 0.),
vec3(0.200476, 0.494430, 0.),
vec3(-0.494552, -0.711051, 0.),
vec3(0.612476, 0.705252, 0.),
vec3(-0.578845, -0.768792, 0.),
vec3(-0.772454, -0.090976, 0.),
vec3(0.504440, 0.372295, 0.),
vec3(0.155736, 0.065157, 0.),
vec3(0.391522, 0.849605, 0.),
vec3(-0.620106, -0.328104, 0.),
vec3(0.789239, -0.419965, 0.),
vec3(-0.545396, 0.538133, 0.),
vec3(-0.178564, -0.596057, 0.)
);
// https://stackoverflow.com/questions/4200224/random-noise-functions-for-glsl
float getRand(vec2 seed) {
return fract(sin(dot(seed.xy ,vec2(12.9898,78.233))) * 43758.5453);
}
// PCSS
// This helps to achieve a contact hardening effect on the shadow
// It uses 16 Taps for search and a 32 PCF taps in a randomly rotating poisson sampling disc.
// This is heavily inspired from http://developer.download.nvidia.com/shaderlibrary/docs/shadow_PCSS.pdf
// and http://developer.download.nvidia.com/whitepapers/2008/PCSS_Integration.pdf
float computeShadowWithPCSS(sampler2D depthSampler, sampler2DShadow shadowSampler, vec3 shadowCoord, float shadowMapSizeInverse, float lightSizeUV, int searchTapCount, int pcfTapCount, vec3[64] poissonSamplers) {
float depthMetric = shadowCoord.z;
float blockerDepth = 0.0;
float sumBlockerDepth = 0.0;
float numBlocker = 0.0;
for (int i = 0; i < searchTapCount; i ++) {
blockerDepth = unpackRGBAToDepth( texture( depthSampler, shadowCoord.xy + (lightSizeUV * shadowMapSizeInverse * PoissonSamplers32[i].xy) ) );
if (blockerDepth < depthMetric) {
sumBlockerDepth += blockerDepth;
numBlocker++;
}
}
if (numBlocker < 1.0) {
return 1.0;
}
float avgBlockerDepth = sumBlockerDepth / numBlocker;
// Offset preventing aliasing on contact.
float AAOffset = shadowMapSizeInverse * 10.;
// Do not dividing by z despite being physically incorrect looks better due to the limited kernel size.
// float penumbraRatio = (depthMetric - avgBlockerDepth) / avgBlockerDepth;
float penumbraRatio = ((depthMetric - avgBlockerDepth) + AAOffset);
float filterRadius = penumbraRatio * lightSizeUV * shadowMapSizeInverse;
float random = getRand(shadowCoord.xy);//getRand(vPositionFromLight.xy);
float rotationAngle = random * 3.1415926;
vec2 rotationVector = vec2(cos(rotationAngle), sin(rotationAngle));
float shadow = 0.;
for (int i = 0; i < pcfTapCount; i++) {
vec3 offset = poissonSamplers[i];
// Rotated offset.
offset = vec3(offset.x * rotationVector.x - offset.y * rotationVector.y, offset.y * rotationVector.x + offset.x * rotationVector.y, 0.);
shadow += texture(shadowSampler, shadowCoord + offset * filterRadius);
}
shadow /= float(pcfTapCount);
// Blocker distance falloff
shadow = mix(shadow, 1., depthMetric - avgBlockerDepth);
return shadow;
}
float getShadowWithPCSS( sampler2D depthSampler, sampler2DShadow shadowMap, vec4 shadowCoord, float shadowBias, float shadowRadius, vec2 shadowMapSize ) {
shadowCoord.xyz /= shadowCoord.w;
shadowCoord.z += shadowBias;
bvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );
bool inFrustum = all( inFrustumVec );
bvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );
bool frustumTest = all( frustumTestVec );
if ( frustumTest ) {
#ifdef USE_PCSS16_SOFT_SHADOW
return computeShadowWithPCSS(depthSampler, shadowMap, shadowCoord.xyz, 1. / shadowMapSize.x, 0.1 * shadowMapSize.x, 16, 16, PoissonSamplers32);
#else
#ifdef USE_PCSS32_SOFT_SHADOW
return computeShadowWithPCSS(depthSampler, shadowMap, shadowCoord.xyz, 1. / shadowMapSize.x, 0.1 * shadowMapSize.x, 16, 32, PoissonSamplers32);
#else
return computeShadowWithPCSS(depthSampler, shadowMap, shadowCoord.xyz, 1. / shadowMapSize.x, 0.1 * shadowMapSize.x, 32, 64, PoissonSamplers64);
#endif
#endif
}
return 1.0;
}
#endif

View file

@ -0,0 +1,3 @@
#ifdef USE_SHADOW
// outColor *= getShadowMask();
#endif

View file

@ -0,0 +1,38 @@
#ifdef USE_SHADOW
#if NUM_DIR_SHADOWS > 0
uniform sampler2DShadow directionalShadowMap[ NUM_DIR_LIGHTS ];
varying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];
#ifdef USE_PCSS_SOFT_SHADOW
uniform sampler2D directionalDepthMap[ NUM_DIR_LIGHTS ];
#endif
#endif
#if NUM_POINT_SHADOWS > 0
uniform samplerCube pointShadowMap[ NUM_POINT_LIGHTS ];
#endif
#if NUM_SPOT_SHADOWS > 0
uniform sampler2DShadow spotShadowMap[ NUM_SPOT_LIGHTS ];
varying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];
#ifdef USE_PCSS_SOFT_SHADOW
uniform sampler2D spotDepthMap[ NUM_SPOT_LIGHTS ];
#endif
#endif
#include <packing>
#include <shadow>
#endif

View file

@ -0,0 +1,23 @@
#ifdef USE_SHADOW
#if NUM_DIR_SHADOWS > 0
uniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHTS ];
varying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];
#endif
#if NUM_POINT_SHADOWS > 0
// nothing
#endif
#if NUM_SPOT_SHADOWS > 0
uniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHTS ];
varying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];
#endif
#endif

View file

@ -0,0 +1,33 @@
#ifdef USE_SHADOW
vec4 worldPosition = u_Model * vec4(transformed, 1.0);
#if NUM_DIR_SHADOWS > 0
#pragma unroll_loop
for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {
vDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;
}
#endif
#if NUM_POINT_SHADOWS > 0
// nothing
#endif
#if NUM_SPOT_SHADOWS > 0
#pragma unroll_loop
for ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {
vSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;
}
#endif
#endif

View file

@ -0,0 +1,41 @@
#ifdef USE_SKINNING
attribute vec4 skinIndex;
attribute vec4 skinWeight;
uniform mat4 bindMatrix;
uniform mat4 bindMatrixInverse;
#ifdef BONE_TEXTURE
uniform 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;
}
#else
uniform mat4 boneMatrices[MAX_BONES];
mat4 getBoneMatrix(const in float i) {
mat4 bone = boneMatrices[int(i)];
return bone;
}
#endif
#endif

View file

@ -0,0 +1,19 @@
#ifdef USE_SKINNING
mat4 boneMatX = getBoneMatrix( skinIndex.x );
mat4 boneMatY = getBoneMatrix( skinIndex.y );
mat4 boneMatZ = getBoneMatrix( skinIndex.z );
mat4 boneMatW = getBoneMatrix( skinIndex.w );
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;
skinned = bindMatrixInverse * skinned;
transformed = skinned.xyz / skinned.w;
#endif

View file

@ -0,0 +1,18 @@
#ifdef USE_SKINNING
mat4 skinMatrix = mat4( 0.0 );
skinMatrix += skinWeight.x * boneMatX;
skinMatrix += skinWeight.y * boneMatY;
skinMatrix += skinWeight.z * boneMatZ;
skinMatrix += skinWeight.w * boneMatW;
skinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;
objectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;
#ifdef USE_TANGENT
objectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;
#endif
#endif

View file

@ -0,0 +1,12 @@
float specularStrength;
#ifdef USE_SPECULARMAP
vec4 texelSpecular = texture2D( specularMap, v_Uv );
specularStrength = texelSpecular.r;
#else
specularStrength = 1.0;
#endif

View file

@ -0,0 +1,5 @@
#ifdef USE_SPECULARMAP
uniform sampler2D specularMap;
#endif

View file

@ -0,0 +1,16 @@
struct SpotLight
{
vec3 position;
vec4 color;
float distance;
float decay;
float coneCos;
float penumbraCos;
vec3 direction;
int shadow;
float shadowBias;
float shadowRadius;
vec2 shadowMapSize;
};
uniform SpotLight u_Spot[NUM_SPOT_LIGHTS];

View file

@ -0,0 +1,13 @@
mat4 transposeMat4(mat4 inMatrix) {
vec4 i0 = inMatrix[0];
vec4 i1 = inMatrix[1];
vec4 i2 = inMatrix[2];
vec4 i3 = inMatrix[3];
mat4 outMatrix = mat4(
vec4(i0.x, i1.x, i2.x, i3.x),
vec4(i0.y, i1.y, i2.y, i3.y),
vec4(i0.z, i1.z, i2.z, i3.z),
vec4(i0.w, i1.w, i2.w, i3.w)
);
return outMatrix;
}

View file

@ -0,0 +1,18 @@
// Per-Pixel Tangent Space Normal Mapping
// http://hacksoflife.blogspot.ch/2009/11/per-pixel-tangent-space-normal-mapping.html
mat3 tsn(vec3 N, vec3 V, vec2 uv) {
// Workaround for Adreno/Nexus5 not able able to do dFdx( Vec3 ) ...
vec3 q0 = vec3(dFdx(V.x), dFdx(V.y), dFdx(V.z));
vec3 q1 = vec3(dFdy(V.x), dFdy(V.y), dFdy(V.z));
vec2 st0 = dFdx( uv.st );
vec2 st1 = dFdy( uv.st );
float scale = sign( st1.t * st0.s - st0.t * st1.s );
vec3 S = normalize( ( q0 * st1.t - q1 * st0.t ) * scale );
vec3 T = normalize( ( -q0 * st1.s + q1 * st0.s ) * scale );
// vec3 N = normalize( N );
mat3 tsn = mat3( S, T, N );
return tsn;
}

View file

@ -0,0 +1,11 @@
#ifdef USE_UV
varying vec2 v_Uv;
#endif
#ifdef USE_UV2
varying vec2 v_Uv2;
#endif
#ifdef USE_ALPHA_MAP_UV_TRANSFORM
varying vec2 vAlphaMapUV;
#endif

View file

@ -0,0 +1,15 @@
#ifdef USE_UV
attribute vec2 a_Uv;
varying vec2 v_Uv;
uniform mat3 uvTransform;
#endif
#ifdef USE_UV2
attribute vec2 a_Uv2;
varying vec2 v_Uv2;
#endif
#ifdef USE_ALPHA_MAP_UV_TRANSFORM
varying vec2 vAlphaMapUV;
uniform mat3 alphaMapUVTransform;
#endif

View file

@ -0,0 +1,17 @@
#ifdef USE_UV
v_Uv = (uvTransform * vec3(a_Uv, 1.)).xy;
#endif
#ifdef USE_UV2
v_Uv2 = a_Uv2;
#endif
#ifdef USE_ALPHA_MAP_UV_TRANSFORM
#if (USE_ALPHA_MAP == 1)
vAlphaMapUV = (alphaMapUVTransform * vec3(a_Uv, 1.)).xy;
#elif (USE_ALPHA_MAP == 2)
vAlphaMapUV = (alphaMapUVTransform * vec3(a_Uv2, 1.)).xy;
#else
vAlphaMapUV = (alphaMapUVTransform * vec3(a_Uv, 1.)).xy;
#endif
#endif

View file

@ -0,0 +1,3 @@
#if (NUM_POINT_LIGHTS > 0) || (NUM_SPOT_LIGHTS > 0) || defined(USE_NORMAL_MAP) || defined(USE_BUMPMAP) || defined(FLAT_SHADED) || defined(USE_PHONG) || defined(USE_PBR) || (NUM_CLIPPING_PLANES > 0)
varying vec3 v_modelPos;
#endif

View file

@ -0,0 +1,3 @@
#if (NUM_POINT_LIGHTS > 0) || (NUM_SPOT_LIGHTS > 0) || defined(USE_NORMAL_MAP) || defined(USE_BUMPMAP) || defined(FLAT_SHADED) || defined(USE_PHONG) || defined(USE_PBR)|| (NUM_CLIPPING_PLANES > 0)
varying vec3 v_modelPos;
#endif

View file

@ -0,0 +1,3 @@
#if (NUM_POINT_LIGHTS > 0) || (NUM_SPOT_LIGHTS > 0) || defined(USE_NORMAL_MAP) || defined(USE_BUMPMAP) || defined(FLAT_SHADED) || defined(USE_PHONG) || defined(USE_PBR) || (NUM_CLIPPING_PLANES > 0)
v_modelPos = (u_Model * vec4(transformed, 1.0)).xyz;
#endif

Some files were not shown because too many files have changed in this diff Show more