提交 f9a58ee5 编写于 作者: B Ben Adams

Merge pull request #7 from WestLangley/dev-phong

Clean up phong shader
......@@ -4,57 +4,136 @@
#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 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 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 ); }
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) {
vec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {
float distance = dot( planeNormal, point-pointOnPlane );
return point - distance * planeNormal;
}
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 ) );
}
float calcLightAttenuation( float lightDistance, float cutoffDistance, float decayExponent ) {
if ( decayExponent > 0.0 ) {
return pow( saturate( 1.0 - lightDistance / cutoffDistance ), decayExponent );
}
return 1.0;
}
vec3 F_Schlick( in vec3 specularColor, in float dotLH ) {
return specularColor + ( 1.0 - specularColor ) * pow( 1.0 - dotLH, 5.0 );
}
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 = saturate( dot( normal, lightDir ) );
//float dotNV = saturate( dot( normal, viewDir ) );
float dotNH = saturate( dot( normal, halfDir ) );
float dotLH = saturate( dot( lightDir, halfDir ) );
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
}
......@@ -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 = saturate( pow( saturate( spotEffect ), spotLightExponent[ i ] ) );
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( saturate( dotProduct ) );
#ifdef WRAP_AROUND
vec3 cosineTermHalf = vec3( saturate( 0.5 * dotProduct + 0.5 ) );
cosineTerm = mix( cosineTerm, cosineTermHalf, wrapRGB );
#endif
return cosineTerm;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册