提交 2d856c96 编写于 作者: R Ricardo Cabello

Merge pull request #6347 from benaadams/glsl-improvements

Glsl improvements
......@@ -4,57 +4,116 @@
#define LOG2 1.442695
#define EPSILON 1e-6
float square( in float a ) { return a*a; }
vec2 square( in vec2 a ) { return vec2( a.x*a.x, a.y*a.y ); }
vec3 square( in vec3 a ) { return vec3( a.x*a.x, a.y*a.y, a.z*a.z ); }
vec4 square( in vec4 a ) { return vec4( a.x*a.x, a.y*a.y, a.z*a.z, a.w*a.w ); }
float saturate( in float a ) { return clamp( a, 0.0, 1.0 ); }
vec2 saturate( in vec2 a ) { return clamp( a, 0.0, 1.0 ); }
vec3 saturate( in vec3 a ) { return clamp( a, 0.0, 1.0 ); }
vec4 saturate( in vec4 a ) { return clamp( a, 0.0, 1.0 ); }
float average( in float a ) { return a; }
float average( in vec2 a ) { return ( a.x + a.y) * 0.5; }
float average( in vec3 a ) { return ( a.x + a.y + a.z) / 3.0; }
float average( in vec4 a ) { return ( a.x + a.y + a.z + a.w) * 0.25; }
float whiteCompliment( in float a ) { return saturate( 1.0 - a ); }
vec2 whiteCompliment( in vec2 a ) { return saturate( vec2(1.0) - a ); }
vec3 whiteCompliment( in vec3 a ) { return saturate( vec3(1.0) - a ); }
vec4 whiteCompliment( in vec4 a ) { return saturate( vec4(1.0) - a ); }
vec3 transformDirection( in vec3 normal, in mat4 matrix ) {
return normalize( ( matrix * vec4( normal, 0.0 ) ).xyz );
}
// http://en.wikibooks.org/wiki/GLSL_Programming/Applying_Matrix_Transformations
vec3 inverseTransformDirection( in vec3 normal, in mat4 matrix ) {
return normalize( ( vec4( normal, 0.0 ) * matrix ).xyz );
}
vec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal) {
float distance = dot( planeNormal, point-pointOnPlane );
return point - distance * planeNormal;
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 pointOnLine + lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) );
return lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;
}
float calcLightAttenuation( float lightDistance, float cutoffDistance, float decayExponent ) {
if ( decayExponent > 0.0 ) {
return pow( saturate( 1.0 - lightDistance / cutoffDistance ), decayExponent );
return pow( clamp( -lightDistance / cutoffDistance + 1.0, 0.0, 1.0 ), decayExponent );
}
return 1.0;
}
vec3 F_Schlick( in vec3 specularColor, in float dotLH ) {
return ( 1.0 - specularColor ) * pow( 1.0 - dotLH, 5.0 ) + specularColor;
}
float G_BlinnPhong_Implicit( /* in float dotNL, in float dotNV */ ) {
// geometry term is (n⋅l)(n⋅v) / 4(n⋅l)(n⋅v)
return 0.25;
}
float D_BlinnPhong( in float shininess, in float dotNH ) {
// factor of 1/PI in distribution term omitted
return ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );
}
vec3 BRDF_BlinnPhong( in vec3 specularColor, in float shininess, in vec3 normal, in vec3 lightDir, in vec3 viewDir ) {
vec3 halfDir = normalize( lightDir + viewDir );
//float dotNL = clamp( dot( normal, lightDir ), 0.0, 1.0 );
//float dotNV = clamp( dot( normal, viewDir ), 0.0, 1.0 );
float dotNH = clamp( dot( normal, halfDir ), 0.0, 1.0 );
float dotLH = clamp( dot( lightDir, halfDir ), 0.0, 1.0 );
vec3 F = F_Schlick( specularColor, dotLH );
float G = G_BlinnPhong_Implicit( /* dotNL, dotNV */ );
float D = D_BlinnPhong( shininess, dotNH );
return F * G * D;
}
vec3 inputToLinear( in vec3 a ) {
#ifdef GAMMA_INPUT
return pow( a, vec3( float( GAMMA_FACTOR ) ) );
#else
return a;
#endif
#ifdef GAMMA_INPUT
return pow( a, vec3( float( GAMMA_FACTOR ) ) );
#else
return a;
#endif
}
vec3 linearToOutput( in vec3 a ) {
#ifdef GAMMA_OUTPUT
return pow( a, vec3( 1.0 / float( GAMMA_FACTOR ) ) );
#else
return a;
#endif
#ifdef GAMMA_OUTPUT
return pow( a, vec3( 1.0 / float( GAMMA_FACTOR ) ) );
#else
return a;
#endif
}
......@@ -24,7 +24,7 @@
#endif
#ifdef DOUBLE_SIDED
float flipNormal = ( -1.0 + 2.0 * float( gl_FrontFacing ) );
float flipNormal = ( float( gl_FrontFacing ) * 2.0 - 1.0 );
#else
float flipNormal = 1.0;
#endif
......@@ -34,7 +34,7 @@
#elif defined( ENVMAP_TYPE_EQUIREC )
vec2 sampleUV;
sampleUV.y = saturate( flipNormal * reflectVec.y * 0.5 + 0.5 );
sampleUV.y = clamp( flipNormal * reflectVec.y * 0.5 + 0.5, 0.0, 1.0 );
sampleUV.x = atan( flipNormal * reflectVec.z, flipNormal * reflectVec.x ) * RECIPROCAL_PI2 + 0.5;
vec4 envColor = texture2D( envMap, sampleUV );
......
......@@ -12,8 +12,7 @@
#ifdef FOG_EXP2
float fogFactor = exp2( - square( fogDensity ) * square( depth ) * LOG2 );
fogFactor = whiteCompliment( fogFactor );
float fogFactor = 1.0 - clamp( exp2( - fogDensity * fogDensity * depth * depth * LOG2 ), 0.0, 1.0 );
#else
......
float square( in float a ) { return a * a; }
vec2 square( in vec2 a ) { return a * a; }
vec3 square( in vec3 a ) { return a * a; }
vec4 square( in vec4 a ) { return a * a; }
float saturate( in float a ) { return clamp( a, 0.0, 1.0 ); }
vec2 saturate( in vec2 a ) { return clamp( a, 0.0, 1.0 ); }
vec3 saturate( in vec3 a ) { return clamp( a, 0.0, 1.0 ); }
vec4 saturate( in vec4 a ) { return clamp( a, 0.0, 1.0 ); }
float average( in float a ) { return a; }
float average( in vec2 a ) { return ( a.x + a.y) * 0.5; }
float average( in vec3 a ) { return ( a.x + a.y + a.z) / 3.0; }
float average( in vec4 a ) { return ( a.x + a.y + a.z + a.w) * 0.25; }
float whiteCompliment( in float a ) { return saturate( 1.0 - a ); }
vec2 whiteCompliment( in vec2 a ) { return saturate( 1.0 - a ); }
vec3 whiteCompliment( in vec3 a ) { return saturate( 1.0 - a ); }
vec4 whiteCompliment( in vec4 a ) { return saturate( 1.0 - a ); }
\ No newline at end of file
......@@ -16,8 +16,6 @@
#endif
vec3 viewPosition = normalize( vViewPosition );
#ifdef USE_NORMALMAP
normal = perturbNormal2Arb( -vViewPosition, normal );
......@@ -28,6 +26,8 @@ vec3 viewPosition = normalize( vViewPosition );
#endif
vec3 viewDir = normalize( vViewPosition );
vec3 totalDiffuseLight = vec3( 0.0 );
vec3 totalSpecularLight = vec3( 0.0 );
......@@ -35,42 +35,29 @@ vec3 totalSpecularLight = vec3( 0.0 );
for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {
vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );
vec3 lightColor = pointLightColor[ i ];
vec3 lightPosition = pointLightPosition[ i ];
vec4 lPosition = viewMatrix * vec4( lightPosition, 1.0 );
vec3 lVector = lPosition.xyz + vViewPosition.xyz;
vec3 lightDir = normalize( lVector );
float attenuation = calcLightAttenuation( length( lVector ), pointLightDistance[ i ], pointLightDecay[ i ] );
// attenuation
lVector = normalize( lVector );
float attenuation = calcLightAttenuation( length( lVector ), pointLightDistance[ i ], pointLightDecay[ i ] );
// 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
vec3 cosineTerm = calcCosineTerm( normal, lightDir );
totalDiffuseLight += pointLightColor[ i ] * pointDiffuseWeight * attenuation;
totalDiffuseLight += lightColor * attenuation * cosineTerm;
// specular
// specular
vec3 pointHalfVector = normalize( lVector + viewPosition );
float pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );
float pointSpecularWeight = specularStrength * max( pow( pointDotNormalHalf, shininess ), 0.0 );
vec3 brdf = BRDF_BlinnPhong( specular, shininess, normal, lightDir, viewDir );
float specularNormalization = ( shininess + 2.0 ) / 8.0;
totalSpecularLight += brdf * specularStrength * lightColor * attenuation * cosineTerm;
vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, pointHalfVector ), 0.0 ), 5.0 );
totalSpecularLight += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * attenuation * specularNormalization;
}
......@@ -80,48 +67,36 @@ vec3 totalSpecularLight = vec3( 0.0 );
for ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {
vec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );
vec3 lVector = lPosition.xyz + vViewPosition.xyz;
float attenuation = calcLightAttenuation( length( lVector ), spotLightDistance[ i ], spotLightDecay[ i ] );
vec3 lightColor = spotLightColor[ i ];
lVector = normalize( lVector );
vec3 lightPosition = spotLightPosition[ i ];
vec4 lPosition = viewMatrix * vec4( lightPosition, 1.0 );
vec3 lVector = lPosition.xyz + vViewPosition.xyz;
vec3 lightDir = normalize( lVector );
float spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) );
float spotEffect = dot( spotLightDirection[ i ], normalize( lightPosition - vWorldPosition ) );
if ( spotEffect > spotLightAngleCos[ i ] ) {
spotEffect = max( pow( max( spotEffect, 0.0 ), spotLightExponent[ i ] ), 0.0 );
// diffuse
float dotProduct = dot( normal, lVector );
#ifdef WRAP_AROUND
spotEffect = clamp( pow( clamp( spotEffect, 0.0, 1.0 ), spotLightExponent[ i ] ), 0.0, 1.0 );
float spotDiffuseWeightFull = max( dotProduct, 0.0 );
float spotDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );
// attenuation
vec3 spotDiffuseWeight = mix( vec3( spotDiffuseWeightFull ), vec3( spotDiffuseWeightHalf ), wrapRGB );
float attenuation = calcLightAttenuation( length( lVector ), spotLightDistance[ i ], spotLightDecay[ i ] );
#else
attenuation *= spotEffect;
float spotDiffuseWeight = max( dotProduct, 0.0 );
// diffuse
#endif
vec3 cosineTerm = calcCosineTerm( normal, lightDir );
totalDiffuseLight += spotLightColor[ i ] * spotDiffuseWeight * attenuation * spotEffect;
totalDiffuseLight += lightColor * attenuation * cosineTerm;
// specular
vec3 spotHalfVector = normalize( lVector + viewPosition );
float spotDotNormalHalf = max( dot( normal, spotHalfVector ), 0.0 );
float spotSpecularWeight = specularStrength * max( pow( spotDotNormalHalf, shininess ), 0.0 );
float specularNormalization = ( shininess + 2.0 ) / 8.0;
vec3 brdf = BRDF_BlinnPhong( specular, shininess, normal, lightDir, viewDir );
vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, spotHalfVector ), 0.0 ), 5.0 );
totalSpecularLight += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * attenuation * specularNormalization * spotEffect;
totalSpecularLight += brdf * specularStrength * lightColor * attenuation * cosineTerm;
}
......@@ -133,59 +108,21 @@ vec3 totalSpecularLight = vec3( 0.0 );
for( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {
vec3 dirVector = transformDirection( directionalLightDirection[ i ], viewMatrix );
vec3 lightColor = directionalLightColor[ i ];
// 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
vec3 lightDir = transformDirection( directionalLightDirection[ i ], viewMatrix );
float dirDiffuseWeight = max( dotProduct, 0.0 );
// diffuse
#endif
vec3 cosineTerm = calcCosineTerm( normal, lightDir );
totalDiffuseLight += directionalLightColor[ i ] * dirDiffuseWeight;
totalDiffuseLight += lightColor * cosineTerm;
// specular
vec3 dirHalfVector = normalize( dirVector + viewPosition );
float dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );
float dirSpecularWeight = specularStrength * max( pow( dirDotNormalHalf, shininess ), 0.0 );
/*
// fresnel term from skin shader
const float F0 = 0.128;
float base = 1.0 - dot( viewPosition, dirHalfVector );
float exponential = pow( base, 5.0 );
float fresnel = exponential + F0 * ( 1.0 - exponential );
*/
/*
// fresnel term from fresnel shader
const float mFresnelBias = 0.08;
const float mFresnelScale = 0.3;
const float mFresnelPower = 5.0;
float fresnel = mFresnelBias + mFresnelScale * pow( 1.0 + dot( normalize( -viewPosition ), normal ), mFresnelPower );
*/
float specularNormalization = ( shininess + 2.0 ) / 8.0;
// dirSpecular += specular * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization * fresnel;
vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( dirVector, dirHalfVector ), 0.0 ), 5.0 );
totalSpecularLight += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;
vec3 brdf = BRDF_BlinnPhong( specular, shininess, normal, lightDir, viewDir );
totalSpecularLight += brdf * specularStrength * lightColor * cosineTerm;
}
......@@ -195,38 +132,23 @@ vec3 totalSpecularLight = vec3( 0.0 );
for( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {
vec3 lVector = transformDirection( hemisphereLightDirection[ i ], viewMatrix );
vec3 lightDir = transformDirection( hemisphereLightDirection[ i ], viewMatrix );
// diffuse
float dotProduct = dot( normal, lVector );
float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;
vec3 hemiColor = mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );
totalDiffuseLight += hemiColor;
// specular (sky light)
float dotProduct = dot( normal, lightDir );
vec3 hemiHalfVectorSky = normalize( lVector + viewPosition );
float hemiDotNormalHalfSky = 0.5 * dot( normal, hemiHalfVectorSky ) + 0.5;
float hemiSpecularWeightSky = specularStrength * max( pow( max( hemiDotNormalHalfSky, 0.0 ), shininess ), 0.0 );
// specular (ground light)
float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;
vec3 lVectorGround = -lVector;
vec3 lightColor = mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );
vec3 hemiHalfVectorGround = normalize( lVectorGround + viewPosition );
float hemiDotNormalHalfGround = 0.5 * dot( normal, hemiHalfVectorGround ) + 0.5;
float hemiSpecularWeightGround = specularStrength * max( pow( max( hemiDotNormalHalfGround, 0.0 ), shininess ), 0.0 );
totalDiffuseLight += lightColor;
float dotProductGround = dot( normal, lVectorGround );
// specular (sky term only)
float specularNormalization = ( shininess + 2.0 ) / 8.0;
vec3 brdf = BRDF_BlinnPhong( specular, shininess, normal, lightDir, viewDir );
vec3 schlickSky = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, hemiHalfVectorSky ), 0.0 ), 5.0 );
vec3 schlickGround = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVectorGround, hemiHalfVectorGround ), 0.0 ), 5.0 );
totalSpecularLight += hemiColor * specularNormalization * ( schlickSky * hemiSpecularWeightSky * max( dotProduct, 0.0 ) + schlickGround * hemiSpecularWeightGround * max( dotProductGround, 0.0 ) );
totalSpecularLight += brdf * specularStrength * lightColor * max( dotProduct, 0.0 );
}
......
......@@ -56,3 +56,21 @@ varying vec3 vViewPosition;
varying vec3 vNormal;
#endif
vec3 calcCosineTerm( in vec3 normal, in vec3 lightDir ) {
float dotProduct = dot( normal, lightDir );
vec3 cosineTerm = vec3( clamp( dotProduct, 0.0, 1.0 ) );
#ifdef WRAP_AROUND
vec3 cosineTermHalf = vec3( saturate( 0.5 * dotProduct + 0.5 ) );
cosineTerm = mix( cosineTerm, cosineTermHalf, wrapRGB );
#endif
return cosineTerm;
}
......@@ -737,7 +737,7 @@ THREE.ShaderLib = {
// " gl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );",
"vec3 direction = normalize( vWorldPosition );",
"vec2 sampleUV;",
"sampleUV.y = saturate( tFlip * direction.y * -0.5 + 0.5 );",
"sampleUV.y = clamp( tFlip * direction.y * -0.5 + 0.5, 0.0, 1.0 );",
"sampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;",
"gl_FragColor = texture2D( tEquirect, sampleUV );",
......
......@@ -49,6 +49,17 @@ THREE.WebGLProgram = ( function () {
return attributes;
}
function programArrayToString ( previousValue, currentValue, index, array ) {
if ( currentValue !== '' && currentValue !== undefined && currentValue !== null ) {
return previousValue + currentValue + '\n';
}
return previousValue;
}
return function ( renderer, code, material, parameters ) {
......@@ -261,7 +272,7 @@ THREE.WebGLProgram = ( function () {
''
].join( '\n' );
].reduce( programArrayToString, '' );
prefix_fragment = [
......@@ -320,7 +331,7 @@ THREE.WebGLProgram = ( function () {
'uniform vec3 cameraPosition;',
''
].join( '\n' );
].reduce( programArrayToString, '' );
}
......
......@@ -108,6 +108,7 @@
"src/renderers/shaders/ShaderChunk/envmap_vertex.glsl",
"src/renderers/shaders/ShaderChunk/fog_fragment.glsl",
"src/renderers/shaders/ShaderChunk/fog_pars_fragment.glsl",
"src/renderers/shaders/ShaderChunk/helper_funcs.glsl",
"src/renderers/shaders/ShaderChunk/lightmap_fragment.glsl",
"src/renderers/shaders/ShaderChunk/lightmap_pars_fragment.glsl",
"src/renderers/shaders/ShaderChunk/lights_lambert_pars_vertex.glsl",
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册