// // File: Maya_Lighting.cgh // // Description: // Include file with functions for computing Maya lighting. // // ///////////////////////////////////////////////////////////////////////// // Compute if a position is in shadow or not, based on // a shadow map. // // Arguments: // shadowTex : 2d shadow map // worldToProjLightMatrix[0..3] : world to light space transform // worldPosition : position to test ////////////////////////////////////////////////////////////////////////// float MAYA_SoftShadow(float3 worldPosition, uniform sampler2D shadowTexture, uniform float4 lightMatrix0, uniform float4 lightMatrix1, uniform float4 lightMatrix2, uniform float4 lightMatrix3 ) { // Transform the world space position into proj light space. // This is required for shadow maps or projective light texture // look-ups. // float4 projTexCoords; float4 pos = float4(worldPosition.xyz, 1); projTexCoords.x = dot(pos, lightMatrix0); projTexCoords.y = dot(pos, lightMatrix1); projTexCoords.z = dot(pos, lightMatrix2); projTexCoords.w = dot(pos, lightMatrix3); // Do the shadow distance comparison, to find out if the // current fragment is shadowed or not. // TO DO this is just a sample of what one could do with other sampling methods // float value = tex2Dproj(shadowTexture, projTexCoords + float4(.02, .02, 0,0)); value += tex2Dproj(shadowTexture, projTexCoords + float4(-.02, .02, 0,0)); value += tex2Dproj(shadowTexture, projTexCoords + float4(.02, -.02, 0,0)); value += tex2Dproj(shadowTexture, projTexCoords + float4(-.02, -.02, 0,0)); return 0.25 * value; } ///////////////////////////////////////////////////////////////////////// // Compute if a position is in shadow or not, based on // a shadow map. // // Arguments: // shadowTex : 2d shadow map // worldToProjLightMatrix[0..3] : world to light space transform // worldPosition : position to test ////////////////////////////////////////////////////////////////////////// float MAYA_notInShadow(float3 worldPosition, uniform sampler2D shadowTexture, uniform float4 lightMatrix0, uniform float4 lightMatrix1, uniform float4 lightMatrix2, uniform float4 lightMatrix3 ) { // Transform the world space position into proj light space. // This is required for shadow maps or projective light texture // look-ups. // float4 projTexCoords; float4 pos = float4(worldPosition.xyz, 1); projTexCoords.x = dot(pos, lightMatrix0); projTexCoords.y = dot(pos, lightMatrix1); projTexCoords.z = dot(pos, lightMatrix2); projTexCoords.w = dot(pos, lightMatrix3); // Do the shadow distance comparison, to find out if the // current fragment is shadowed or not. float value = tex2Dproj(shadowTexture, projTexCoords); return value; } #if defined (AMBIENT_SHADE) uniform float ambientShade; // only ambient //////////////////////////////////////////////////////////////////// // Compute ambient only // // Arguments: // diffuseAndAmbientColor: the collected diffuse and ambient color // specularColor // lightDir: incoming light direction // normal: The surface normal ////////////////////////////////////////////////////////////////////////// void MAYA_AmbientShade(inout float3 diffuseAndAmbientColor, inout float3 specularColor, float3 attenuatedLightColor, float3 lightDir, float3 normal) { // Compute (L dot N) : float LDotN = dot(lightDir, normal); // Perform the ambient light's diffuse computation. Note that ambient // lights do not contribute to a specular component. // ambientShade = ambientShade * (LDotN - 1.0); float3 diffuseAndAmbientFactor = float3(attenuatedLightColor * (1.0 + ambientShade).xxx); diffuseAndAmbientColor = diffuseAndAmbientFactor; specularColor = float3(0,0,0); } #endif #if defined (PHONG_SHADE) // Lighting constants uniform float constantDiffuse; uniform float4 constantSpecular; uniform float specularity; void MAYA_PhongShade (inout float3 diffuseAndAmbientColor, inout float3 specularColor, float3 attenuatedLightColor, float3 lightDir, float3 viewDirection, float3 normal) { // Compute (L dot N) : float LDotN = dot(lightDir, normal); if (LDotN > 0.0) { //////////////////////////////////////////////////////////////////// // Compute diffuse //////////////////////////////////////////////////////////////////// // // Compute the diffuse coefficient // float diffuseCoef = constantDiffuse; // // Compute the diffuse component // // Base diffuse factor. float diffuseFactor = diffuseCoef * LDotN; diffuseAndAmbientColor += attenuatedLightColor * diffuseFactor; //////////////////////////////////////////////////////////////////// // Compute specular //////////////////////////////////////////////////////////////////// // Apply the placement specular color/exponent texture matrix, // to the corresponding texture coordinates, then fetch the // appropriate texel. // float4 specValues = float4(constantSpecular.rgb, 1.0); // // Compute Phong specular shading // // - Clamp [R dot V] to the [0.001,1] range. // (Note: we don't clamp to [0,1] because // potential floating-point innaccuracies could // cause the value to become negative. // - R = light's reflection direction (R). // float3 reflectDir = reflect(-lightDir, normal); float RDotV = dot(reflectDir, viewDirection); if ( RDotV > 0.001 ) { // Compute the specular exponent float specularExp = constantSpecular.a; specularColor += attenuatedLightColor * specValues.rgb * pow(RDotV, specularExp); } } } #endif // PHONG_SHADE #if defined (BLINN_PHONG_SHADE) // Lighting constants uniform float constantDiffuse; uniform float4 constantSpecular; uniform float specularity; uniform float eccentricity; uniform float specularRollOff; void MAYA_BlinnShade (inout float3 diffuseAndAmbientColor, inout float3 specularColor, float3 attenuatedLightColor, float3 lightDir, float3 viewDir, float3 normal) // Compute a simple Blinn-Phong specular shading // { // Compute (L dot N) : float LDotN = dot(lightDir, normal); if (LDotN > 0.0f) { //////////////////////////////////////////////////////////////////// // Compute diffuse //////////////////////////////////////////////////////////////////// // // Compute the diffuse coefficient // float diffuseCoef = constantDiffuse; // // Compute the diffuse component // // Base diffuse factor. float diffuseFactor = diffuseCoef * LDotN; diffuseAndAmbientColor = attenuatedLightColor * diffuseFactor; //////////////////////////////////////////////////////////////////////// // Compute the Blinn specular component //////////////////////////////////////////////////////////////////////// float4 specValues = float4(constantSpecular.rgb, 1.0); float3 halfVector = normalize(lightDir + viewDir); float NdotHV = dot(halfVector, normal); if ( NdotHV > 0.001 ) { // Compute the specular exponent float specularExp = constantSpecular.a; specularColor += attenuatedLightColor * specValues.rgb * pow(NdotHV, specularExp); } } } #endif // BLINN_PHONG_SHADE #if defined (BLINN_SHADE) // Lighting constants uniform float constantDiffuse; uniform float4 constantSpecular; uniform float specularity; uniform float eccentricity; uniform float specularRollOff; void MAYA_BlinnShade (inout float3 diffuseAndAmbientColor, inout float3 specularColor, float3 attenuatedLightColor, float3 lightDir, float3 viewDir, float3 normal) // Compute Blinn specular shading // { // Compute (L dot N) : // [mashworth] might move this before the shadow code. We could skip the expensive shadow lookup // float LDotN = dot(lightDir, normal); if (LDotN > 0.0f) { //////////////////////////////////////////////////////////////////// // Compute diffuse //////////////////////////////////////////////////////////////////// // // Compute the diffuse coefficient // float diffuseCoef = constantDiffuse; // // Compute the diffuse component // // Base diffuse factor. float diffuseFactor = diffuseCoef * LDotN; diffuseAndAmbientColor += attenuatedLightColor * diffuseFactor; //////////////////////////////////////////////////////////////////////// // Compute the Blinn specular component //////////////////////////////////////////////////////////////////////// float3 halfAngleDir = normalize(lightDir + viewDir); // [mashworth] this chould be a uniform float cosne = dot(viewDir, normal); float coseh = dot(halfAngleDir, viewDir); // [mashworth] this is a really complicated blinn shader ??? float cosnh = dot(halfAngleDir, normal); float eccSM1 = eccentricity * eccentricity - 1.0; // Protection against division by zero cosne = max(cosne, 0.0001); // [mashworth] shader code are suppose to protect against this might not be needed. coseh = max(coseh, 0.0001); cosnh = max(cosnh, 0.0001); float4 specValues = float4(constantSpecular.rgb, 1.0); #if defined(REFLECTED_SPECULAR) if( (eccSM1 > -0.0001) && (eccSM1 < 0.0001) ) eccSM1 = 0.0001; // eccSM1 = 1.0 / eccSM1; float Dd = (eccSM1 + 1.0f) / ( eccSM1 + cosnh * cosnh ); #else float Dd = (eccSM1 + 1.0f) / ( 1.0 + eccSM1 * cosnh * cosnh ); #endif Dd = Dd * Dd; cosnh = 2 * cosnh; float Gg; if (cosne < LDotN) Gg = (cosne*cosnh < coseh) ? (cosnh / coseh) : (1.0f / cosne); else Gg = (LDotN*cosnh < coseh) ? ((LDotN * cosnh) / (coseh * cosne)) : (1.0f / cosne); float Ff = 0.0f; #if defined(REFLECTED_SPECULAR) Ff = specularity; #else // Fresnel calculation. coseh = 1.0f - coseh; coseh = coseh * coseh * coseh; Ff = coseh + (1.0f - coseh) * specularRollOff; #endif // Ensure the specularCoefficient to be always positive. // float specularCoefficient = max(Dd * Gg * Ff, 0); specularColor += specularCoefficient * attenuatedLightColor * specValues.rgb; } } #endif // BLINN_SHADE /////////////////////////////////////////////////////////////////// // Point light attenutation // /////////////////////////////////////////////////////////////////// #if defined (POINT_LIGHT) uniform float4 lightDecayCoeff; float3 MAYA_PointLight (float3 attenuatedLightColor, float3 lightVector) // { // Compute the distance-from-light-source attenuation. // float lightDistance = length(lightVector); // The following line could be optimized. float attenuation = lightDecayCoeff.x + lightDecayCoeff.y * lightDistance + lightDecayCoeff.z * lightDistance * lightDistance + lightDecayCoeff.w * lightDistance * lightDistance * lightDistance; // Do not allow the light to have an attenuation factor smaller than // 1, since this would make the light source appear too bright. // attenuation = max(attenuation, 1.0); return attenuatedLightColor / attenuation; } #endif // (POINT_LIGHT) /////////////////////////////////////////////////////////////////// // Spot light attenutation // /////////////////////////////////////////////////////////////////// #if defined (SPOT_LIGHT) uniform float3 wSpotDir; uniform float cosPenumbra; uniform float cosUmbra; uniform float radialDropOff; uniform float4 lightDecayCoeff; float3 MAYA_SpotLight (float3 attenuatedLightColor, float3 lightDir, float3 lightVector ) { float lightDistance = length(lightVector); // The following line could be optimized. float attenuation = lightDecayCoeff.x + lightDecayCoeff.y * lightDistance + lightDecayCoeff.z * lightDistance * lightDistance + lightDecayCoeff.w * lightDistance * lightDistance * lightDistance; // Do not allow the light to have an attenuation factor smaller than // 1, since this would make the light source appear too bright. // attenuation = max(attenuation, 1.0); float spotRadialIntensity = 1.0; // Compute the spot light's radial attenuation. // The spot cone of influence is divided into // two regions: the penumbra (outer region) and // umbra (inner region). // NOTE: at this point the penumbra angle is assumed // to be positive, and both the umbra and penumbra angle // are assumed to be greater than 0. // float SdotL = dot(lightDir, wSpotDir); if (SdotL < cosPenumbra) { // The angle is larger than the total angle, // therefore it's outside of the cone. // spotRadialIntensity = 0.0; } else { // Make an exponential decay over the inner region. // spotRadialIntensity = pow(SdotL, radialDropOff); if (SdotL < cosUmbra) { // Linearly interpolate between // the penumbra and umbra angle. // spotRadialIntensity = spotRadialIntensity * (SdotL - cosPenumbra) / (cosUmbra - cosPenumbra); } } // // Compute attenuated light colour // return attenuatedLightColor * spotRadialIntensity / attenuation; } #endif