// Maya_phong_fragment.cg // // This file cannot be directly compiled through CG... it first must be // parsed to insert channel-specific instructions. // #include "Maya_Blends.cgh" #include "Maya_EnvironmentMap.cgh" #include "Maya_phong_connecters.cgh" #if !defined (BLEND_MODE1) // The blend function between layers 0 and 1: Default add #define BLEND_MODE1 kBlendAdd #endif #if !defined (ALPHA_LUMIANANCE) // Use the alpha channel as luminance : Default off #define ALPHA_LUMIANANCE 0 #endif // Explicit matrix to transform object space normal vector to world space #if defined(OBJECT_NORMAL) uniform float4x4 objToWorldMatrix; #endif // already defined in the connecters header //#if defined (LAYER_TWO) // #define PASS_TEX1_UV 1 //#endif /////////////////////////////////////////////////////////////////////////////////// struct MAYA_NormalInfoInput { float3 wNormal; // World space normal float faceMultiplier; // Normal inversion (double-sided lighting, neg-determinants #if defined(BUMP_MAP) float4 wTangent; // World space tangent #endif #if defined(BUMP_MAP) || defined(OBJECT_NORMAL) float4 bumpTexUv; // Normal map texcoords uniform float4 bumpTexMatrix0; uniform float4 bumpTexMatrix1; sampler bumpTex; // Normal map #endif }; /////////////////////////////////////////////////////////////////////////////////// // // Procedure: MAYA_computeWorldSpaceNormal // Description: // Compute the world space normal. // float3 MAYA_computeWorldSpaceNormal(MAYA_NormalInfoInput IN) { float3 wBumpedNormal; #if defined(BUMP_MAP) // Compute an orthonormal basis to transform from tangent space // to world space, and vice-versa. // float3 wTangent = normalize(IN.wTangent.xyz); float3 wNormal = normalize(IN.wNormal); #if defined (BINORMAL_SIGN) float3 wBinormal = cross(wNormal, wTangent) * IN.wTangent.w; #else float3 wBinormal = cross(wNormal, wTangent); #endif // Translate and scale bump texture coordinates, by multiplying // the uvs by the bump texture matrix. // float2 placedBumpTexUv; float4 bumpTexUv = float4(IN.bumpTexUv.xy, 0.0, 1.0); placedBumpTexUv.x = dot(IN.bumpTexMatrix0, bumpTexUv); placedBumpTexUv.y = dot(IN.bumpTexMatrix1, bumpTexUv); // Fetch the bumped normal (in tangent space) from the bump texture. // The (... * 2 - 1) at the end is used to unpack the normal components, // from the [0,1] to [-1, 1] range. // float3 tBumpedNormal = normalize(tex2D(IN.bumpTex, placedBumpTexUv).xyz * 2.0 - 1.0); // Compute the world-space bumped normal by multiplying the tangent // space normal by the tangent space basis vectors. // #if defined(INVERT_TANGENT_SPACE_BASIS) wTangent = -wTangent; tBumpedNormal = -tBumpedNormal; wNormal = -wNormal; #if !defined(TWO_SIDED_LIGHTING) // Is transparent float flipBump = -IN.faceMultiplier; #else // Is opaque float flipBump = IN.faceMultiplier; #endif wBumpedNormal = tBumpedNormal.x * wTangent + tBumpedNormal.y * wBinormal + tBumpedNormal.z * wNormal * flipBump; #else wBumpedNormal = IN.faceMultiplier * tBumpedNormal.x * wTangent + IN.faceMultiplier * tBumpedNormal.y * wBinormal + tBumpedNormal.z * wNormal; #endif wBumpedNormal = normalize(wBumpedNormal); #elif defined (OBJECT_NORMAL) // Translate and scale bump texture coordinates, by multiplying // the uvs by the bump texture matrix. // // [Should be moved to vertex program for efficiency] float4 bumpTexUv = float4(IN.bumpTexUv.xy, 0.0, 1.0); float2 placedBumpTexUv; placedBumpTexUv.x = dot(IN.bumpTexMatrix0, bumpTexUv); placedBumpTexUv.y = dot(IN.bumpTexMatrix1, bumpTexUv); // Fetch the bumped normal (in object space) from the bump texture. // The (... * 2 - 1) at the end is used to unpack the normal components, // from the [0,1] to [-1, 1] range. // float3 oBumpedNormal = tex2D(IN.bumpTex, placedBumpTexUv).xyz * 2.0 - 1.0; // tranform the normal to world space. wBumpedNormal = normalize(mul(objToWorldMatrix, float4(oBumpedNormal, 0.0)).xyz); #else // No bump map. Just pass through the normal as is wBumpedNormal = normalize(IN.wNormal); #endif // BUMP_MAP // Handle double sided lighting within the // program, as opposed to using the "normalMultiplier". // which is set externally. // // To support transparency and back-face lighting, // allow normal inversion. #if !defined(INVERT_TANGENT_SPACE_BASIS) wBumpedNormal = IN.faceMultiplier * wBumpedNormal; #endif return wBumpedNormal; } /////////////////////////////////////////////////////////////////////////////////// struct MAYA_ColorTxInfoInput { #if defined(LIGHTANGLE_COLOR_UVS) || defined(CAMERA_ANGLE_COLOR_UVS) #if defined(LIGHTANGLE_COLOR_UVS) float LDotNsigned; // Lookup is based on angle of light w.r.t normal #endif #if defined(CAMERA_ANGLE_COLOR_UVS) float3 wViewDir; // Lookup is based on angle of camera w.r.t. normal float3 wBumpedNormal; // Also sometimes mentioned as "facing ratio". #endif #else float4 colorTexUv; // Basic 2D texture lookup, with 2d transform applied float4 colorTexMatrix0; float4 colorTexMatrix1; #endif }; // // Procedure: MAYA_computeColorTextureLookup // Description: // Compute the coordinates for color texture lookups. // Currently only 2D lookups are supported. // float2 MAYA_computeColorTextureLookup(MAYA_ColorTxInfoInput IN) { // Apply the appropriate color texture lookup // then fetch the appropriate color texel. // float2 placedColorTexUv; // Use 0.5 for y to avoid filtering problems at the edges // of the texture. MUST use signed value so // that areas facing away from the light are also mapped // properly ! // #if defined(LIGHTANGLE_COLOR_UVS) || defined(CAMERA_ANGLE_COLOR_UVS) #if defined(LIGHTANGLE_COLOR_UVS) placedColorTexUv.x = 0.5 * (IN.LDotNsigned+1.0); // This is from Maya's ramp shader placedColorTexUv.x = min( placedColorTexUv.x, 1.0 ); placedColorTexUv.x = max( placedColorTexUv.x, 0.0 ); placedColorTexUv.y = 0.5; #endif #if defined(CAMERA_ANGLE_COLOR_UVS) float EDotN = dot(IN.wViewDir, IN.wBumpedNormal); EDotN = max(EDotN, 0.001); placedColorTexUv.x = EDotN; placedColorTexUv.y = 0.5; #endif #else float4 colorTexUv = float4(IN.colorTexUv.xy, 0.0, 1.0); placedColorTexUv.x = dot(IN.colorTexMatrix0, IN.colorTexUv); placedColorTexUv.y = dot(IN.colorTexMatrix1, IN.colorTexUv); #endif return placedColorTexUv; } /////////////////////////////////////////////////////////////////////////////////// struct MAYA_BaseInfoInput { #if defined(INTENSITY_ANGLE_COLOR_UVS) float4 intensityAngleColor; #else #if defined(CONSTANT_COLOR) // Constant colour float4 constantColor; #else // Sampler lookup sampler colorTex; float3 lookupVector; //float2 placedColorTexUv; #if defined(PASS_TEX1_UV) // Sampler lookup sampler colorTex2; float3 lookupVector2; //float2 placedColorTexUv2; #endif #if defined(PASS_TEX1_ALPHA_UV) sampler alphaTex2; float2 placedAlphaTexUv2; #else float passAlpha2; #endif #endif #if defined(COLOR_PER_VERTEX) float4 colorPerVertex; #if defined(COLOR_PER_VERTEX_MASK) float colorPerVertexMask; #endif #endif #endif }; // // Procedure: MAYA_computeBaseColor // Description: // Compute the base color. Value may be computed externally based on // lighting; a constant colour or texture lookup; and may be // affected by colour per vertex. // /////////////////////////////////////////////////////////////////////////////////// float4 MAYA_computeBaseColor(MAYA_BaseInfoInput IN, out float4 previousColor) { float4 baseColor = float4(0,0,0,1); #if defined(INTENSITY_ANGLE_COLOR_UVS) // Color is based on light intensity. Skip color computation. baseColor = IN.intensityAngleColor; // float4(1, 1, 1, 1); #else #if defined(CONSTANT_COLOR) baseColor = IN.constantColor; #else // Switch on whether to lookup using environment mapping or not. // Crap. Must do switching in compiler, since you can't do run time seting of a sampler // to the correct type. Sigh. // #if (defined(PASS_TEX0_ENV_SPHERE) || defined(PASS_TEX0_ENV_CUBE)) #if defined(PASS_TEX0_ENV_SPHERE) baseColor = MAYA_environmentLookup(IN.lookupVector, IN.colorTex, kEnvironmentSphere); #else baseColor = MAYA_environmentLookup(IN.lookupVector, IN.colorTex, kEnvironmentCube); #endif #else //baseColor = tex2D(IN.colorTex, IN.placedColorTexUv); baseColor = tex2D(IN.colorTex, IN.lookupVector.xy); #endif #if defined(PASS_TEX1_UV) float4 color2; // Note that we are forced to do things this way since the compiler complains that // we are changing the interpretation of a sampler otherwise. So can't do a // conditional if-else. #if (defined(PASS_TEX1_ENV_SPHERE) || defined(PASS_TEX1_ENV_CUBE)) #if defined(PASS_TEX1_ENV_SPHERE) color2 = MAYA_environmentLookup(IN.lookupVector2, IN.colorTex2, kEnvironmentSphere ); #else color2 = MAYA_environmentLookup(IN.lookupVector2, IN.colorTex2, kEnvironmentCube ); #endif #else //color2 = tex2D(IN.colorTex2, IN.placedColorTexUv2); color2 = tex2D(IN.colorTex2, IN.lookupVector2.xy); #endif #if defined(PASS_TEX1_ALPHA_UV) float4 layerAlphaColor = float4( tex2D(IN.alphaTex2, IN.placedAlphaTexUv2).xyz, 1.0); float layerAlpha = MAYA_computeLuminance( layerAlphaColor.xyz ); color2.a *= layerAlpha; #else // Pre-multiply by pass alpha. color2.a *= IN.passAlpha2; #endif // Need to switch on blending factor. // Note that CPV blending occurs after layered blending MAYA_computeLayeredBlend( baseColor, color2, BLEND_MODE1, ALPHA_LUMIANANCE); #endif #endif #if defined(COLOR_PER_VERTEX) #if defined(OPACITY_IN_COLOR_ALPHA) previousColor = baseColor; #endif // Using mapped / unmapped mask #if defined(COLOR_PER_VERTEX_MASK) float4 mask = IN.colorPerVertexMask.rrrr; float4 invMask = float4(1.0, 1.0, 1.0, 1.0) - mask; #if defined(COLOR_PER_VERTEX_OPERATOR_replace) baseColor = (IN.colorPerVertex * mask) + (baseColor * invMask); #elif defined(COLOR_PER_VERTEX_OPERATOR_add) baseColor = baseColor + (IN.colorPerVertex * mask); #elif defined(COLOR_PER_VERTEX_OPERATOR_subtract) baseColor = baseColor - (IN.colorPerVertex * mask); #elif defined(COLOR_PER_VERTEX_OPERATOR_modulate) baseColor = baseColor * (IN.colorPerVertex * mask); #elif defined(COLOR_PER_VERTEX_OPERATOR_divide) baseColor = baseColor / (IN.colorPerVertex * mask); #elif defined(COLOR_PER_VERTEX_OPERATOR_average) baseColor = 0.5 * (baseColor + (IN.colorPerVertex * mask)); #elif defined(COLOR_PER_VERTEX_OPERATOR_modulate2x) baseColor = (baseColor * (IN.colorPerVertex * mask)) * 2.0; #endif #else #if defined(COLOR_PER_VERTEX_OPERATOR_replace) baseColor = IN.colorPerVertex; #elif defined(COLOR_PER_VERTEX_OPERATOR_add) baseColor = baseColor + IN.colorPerVertex; #elif defined(COLOR_PER_VERTEX_OPERATOR_subtract) baseColor = baseColor - IN.colorPerVertex; #elif defined(COLOR_PER_VERTEX_OPERATOR_modulate) baseColor = baseColor * IN.colorPerVertex; #elif defined(COLOR_PER_VERTEX_OPERATOR_divide) baseColor = baseColor / IN.colorPerVertex; #elif defined(COLOR_PER_VERTEX_OPERATOR_average) baseColor = 0.5 * (baseColor + IN.colorPerVertex); #elif defined(COLOR_PER_VERTEX_OPERATOR_modulate2x) baseColor = (baseColor * IN.colorPerVertex) * 2.0; #endif #endif // COLOR_PER_VERTEX_MASK #endif #endif return baseColor; } /////////////////////////////////////////////////////////////////////////////////// struct MAYA_DiffuseInfoInput { #if defined(CONSTANT_DIFFUSE) float constantDiffuse; #else float4 diffuseTexUv; float4 diffuseTexMatrix0; float4 diffuseTexMatrix1; sampler diffuseTex; #endif }; // // Procedure: MAYA_computeDiffuseCoef // Description: // Compute Maya's diffuse coefficient // float MAYA_computeDiffuseCoef(MAYA_DiffuseInfoInput IN) { float diffuseCoef; #if defined(CONSTANT_DIFFUSE) diffuseCoef = IN.constantDiffuse; #else // Apply placement texture matrix and fetch from diffuse texture. // Note that only the alpha is taken in consideration. // float2 placedDiffuseTexUv; float4 diffuseTexUv = float4(IN.diffuseTexUv.xy, 0.0, 1.0); placedDiffuseTexUv.x = dot(IN.diffuseTexMatrix0, diffuseTexUv); placedDiffuseTexUv.y = dot(IN.diffuseTexMatrix1, diffuseTexUv); diffuseCoef = tex2D(IN.diffuseTex, placedDiffuseTexUv).a; #endif return diffuseCoef; } /////////////////////////////////////////////////////////////////////////////////// // struct MAYA_SpecularInfoInput1 { float3 attenuatedLightColor; float RDotV; float specularExp; float4 specValues; #if defined(COLOR_PER_VERTEX_SPECULAR) float4 colorPerVertex; #if defined(COLOR_PER_VERTEX_MASK) float colorPerVertexMask; #endif #endif }; // // Procedure: MAYA_computePhongSpecular // Description: // Compute Maya's Phong specular colour component // float3 MAYA_computePhongSpecular(MAYA_SpecularInfoInput1 IN) { float3 specularColor; // Regular non-colour per vertex case #if !defined(COLOR_PER_VERTEX_SPECULAR) specularColor = IN.attenuatedLightColor * IN.specValues.rgb * pow(IN.RDotV, IN.specularExp); // Specular CPV case #else float specPower = pow(IN.RDotV, IN.specularExp); #if defined(COLOR_PER_VERTEX_MASK) float4 mask = IN.colorPerVertexMask.rrrr; float4 invMask = float4(1.0, 1.0, 1.0, 1.0) - mask; #if defined(COLOR_PER_VERTEX_OPERATOR_replace) specularColor = (IN.colorPerVertex.rgb * mask.rgb * IN.attenuatedLightColor.rgb) * (specPower * invMask); #elif defined(COLOR_PER_VERTEX_OPERATOR_add) specularColor = (IN.specValues.rgb + IN.colorPerVertex.rgb * mask.rgb) * IN.attenuatedLightColor.rgb * specPower; #elif defined(COLOR_PER_VERTEX_OPERATOR_subtract) specularColor = (IN.specValues.rgb - IN.colorPerVertex.rgb * mask.rgb) * IN.attenuatedLightColor.rgb * specPower; #elif defined(COLOR_PER_VERTEX_OPERATOR_modulate) specularColor = (IN.specValues.rgb * IN.colorPerVertex.rgb * mask.rgb) * IN.attenuatedLightColor.rgb * specPower; #elif defined(COLOR_PER_VERTEX_OPERATOR_divide) specularColor = (IN.specValues.rgb / (IN.colorPerVertex.rgb * mask.rgb)) * IN.attenuatedLightColor.rgb * specPower; #elif defined(COLOR_PER_VERTEX_OPERATOR_average) specularColor = (0.5 * (IN.specValues.rgb + (IN.colorPerVertex.rgb * mask.rgb))) * IN.attenuatedLightColor.rgb * specPower; #elif defined(COLOR_PER_VERTEX_OPERATOR_modulate2x) specularColor = (IN.specValues.rgb * IN.colorPerVertex.rgb * mask.rgb) * IN.attenuatedLightColor.rgb * specPower * 2.0; #endif #else #if defined(COLOR_PER_VERTEX_OPERATOR_replace) specularColor = IN.colorPerVertex.rgb * IN.attenuatedLightColor.rgb * specPower; #elif defined(COLOR_PER_VERTEX_OPERATOR_add) specularColor = (IN.specValues.rgb + IN.colorPerVertex.rgb) * IN.attenuatedLightColor.rgb * specPower; #elif defined(COLOR_PER_VERTEX_OPERATOR_subtract) specularColor = (IN.specValues.rgb - IN.colorPerVertex.rgb) * IN.attenuatedLightColor.rgb * specPower; #elif defined(COLOR_PER_VERTEX_OPERATOR_modulate) specularColor = (IN.specValues.rgb * IN.colorPerVertex.rgb) * IN.attenuatedLightColor.rgb * specPower; #elif defined(COLOR_PER_VERTEX_OPERATOR_divide) specularColor = (IN.specValues.rgb / IN.colorPerVertex.rgb) * IN.attenuatedLightColor.rgb * specPower; #elif defined(COLOR_PER_VERTEX_OPERATOR_average) specularColor = (0.5 * (IN.specValues.rgb + IN.colorPerVertex.rgb)) * IN.attenuatedLightColor.rgb * specPower; #elif defined(COLOR_PER_VERTEX_OPERATOR_modulate2x) specularColor = (IN.specValues.rgb * IN.colorPerVertex.rgb) * IN.attenuatedLightColor.rgb * specPower * 2.0; #endif #endif #endif // Specular CPV return specularColor; } /////////////////////////////////////////////////////////////////////////////////// // // Procedure: MAYA_computeBlinnSpecular // Description: // Compute Maya's Blinn specular colour component // struct MAYA_SpecularInfoInput // Input data to compute specular { float3 wBumpedNormal; float3 wLightDir; float3 attenuatedLightColor; float3 wViewDir; float eccentricity; #if defined(REFLECTED_SPECULAR) float specularity; #else float specularRollOff; #endif float4 specValues; float LDotN; float cosne; }; float3 MAYA_computeBlinnSpecular(MAYA_SpecularInfoInput IN) { float3 specularColor = float3(0,0,0); // Compute the Blinn specular component // float3 wHalfAngleDir = normalize(IN.wLightDir + IN.wViewDir); float coseh = dot(wHalfAngleDir, IN.wViewDir); float cosnh = dot(wHalfAngleDir, IN.wBumpedNormal); float eccSM1 = IN.eccentricity * IN.eccentricity - 1.0; // Protection against division by zero float cosne = max( IN.cosne, 0.0001 ); coseh = max( coseh, 0.0001 ); cosnh = max( cosnh, 0.0001 ); #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 < IN.LDotN) Gg = (cosne*cosnh < coseh) ? (cosnh / coseh) : (1.0f / cosne); else Gg = (IN.LDotN*cosnh < coseh) ? ((IN.LDotN * cosnh) / (coseh * cosne)) : (1.0f / cosne); float Ff = 0.0f; #if defined(REFLECTED_SPECULAR) Ff = IN.specularity; #else // Fresnel calculation. coseh = 1.0f - coseh; coseh = coseh * coseh * coseh; Ff = coseh + (1.0f - coseh) * IN.specularRollOff; #endif // Ensure the specularCoefficient to be always positive. // float specularCoefficient = max(Dd * Gg * Ff, 0); specularColor = specularCoefficient * IN.attenuatedLightColor * IN.specValues.rgb; return specularColor; } /////////////////////////////////////////////////////////////////////////////////// // // Procedure: MAYA_computeTranslucence // Description: // Compute translucence // struct MAYA_translucenceInfo { float3 wLightDir; float3 wViewDir; float LDotNsigned; float LDotN; uniform float translucence; uniform float translucenceFocus; uniform float translucenceDepth; }; float MAYA_computeTranslucence(MAYA_translucenceInfo IN) { float tlBright = 0.0; // Forward scatter is not considered yet. // float translFade = 0.15; float translMinAngle = -1.0 * (1.0+translFade) * IN.translucenceDepth * 10.0; if (IN.LDotNsigned > translMinAngle) { translFade = translFade - translMinAngle; translFade = max(translFade, 1.0 ); tlBright = IN.translucence; if (IN.translucenceFocus > 0.0) { float LDotE = -dot(IN.wLightDir, IN.wViewDir); LDotE = (LDotE + 1.0) * 0.5; LDotE = min(LDotE, 1.0); LDotE = max(LDotE, 0.0); // subtract from 1.00001 so there is still a light at 1.0 float tFocus = IN.translucenceFocus /(1.00001-IN.translucenceFocus); tlBright = IN.translucence * pow( LDotE, tFocus ); } if( IN.LDotNsigned < (translMinAngle + translFade) ) tlBright *= (IN.LDotN - translMinAngle) / translFade; } return tlBright; } /////////////////////////////////////////////////////////////////////////////////// // // Procedure: MAYA_lookupTexturedTransparency // Description: // Compute textured transparency // struct MAYA_TranspLookupInfo // Structure to pass over generalized data. To convert to interface. { uniform sampler transpTex; #if defined(CAMERA_ANGLE_TRANSP_UVS) float EDotN; #else float4 transpTexUv; uniform float4 transpTexMatrix0; uniform float4 transpTexMatrix1; #endif }; float3 MAYA_lookupTexturedTransparency(MAYA_TranspLookupInfo IN) { // Apply the placement transparency/opacity texture lookup, // then fetch the appropriate texel. // float2 placedTranspTexUv; #if defined(CAMERA_ANGLE_TRANSP_UVS) placedTranspTexUv.x = IN.EDotN; placedTranspTexUv.y = 0.5; #else float4 transpTexUv = float4(IN.transpTexUv.xy, 0.0, 1.0); placedTranspTexUv.x = dot(IN.transpTexMatrix0, transpTexUv); placedTranspTexUv.y = dot(IN.transpTexMatrix1, transpTexUv); #endif // The transparency color is encoded in the transparency texture's RGB, // and the opacity is stored in the transparency texture's alpha. // This mode allows colored transparency. // float4 transpColor = tex2D(IN.transpTex, placedTranspTexUv); return (1.0 - transpColor.rgb); } /////////////////////////////////////////////////////////////////////////////////// // // Procedure: MAYA_computePerVertexAlpha // Description: // Compute fragment opacity based per vertex alpha input. // As alpha may not exist, a mask 'bit' must also be sent over // to test with. // float3 MAYA_computePerVertexAlpha(float alphaValue, float alphaBit, float3 opacityColorIn) { float3 colorPerVertexAlpha = float3(alphaValue, alphaValue, alphaValue); float3 opacityColor = float3(1,1,1); #if defined(COLOR_PER_VERTEX_MASK) float aInvMask = 1.0 - alphaBit; #if defined(COLOR_PER_VERTEX_OPERATOR_replace) opacityColor = (colorPerVertexAlpha * alphaBit) + (opacityColorIn.rgb * aInvMask); #elif defined(COLOR_PER_VERTEX_OPERATOR_add) opacityColor = (opacityColorIn.rgb + colorPerVertexAlpha * alphaBit); #elif defined(COLOR_PER_VERTEX_OPERATOR_subtract) opacityColor = (opacityColorIn.rgb - colorPerVertexAlpha * alphaBit) ; #elif defined(COLOR_PER_VERTEX_OPERATOR_modulate) opacityColor = (opacityColorIn.rgb * colorPerVertexAlpha * alphaBit) ; #elif defined(COLOR_PER_VERTEX_OPERATOR_divide) opacityColor = (opacityColorIn.rgb / (colorPerVertexAlpha * alphaBit)) ; #elif defined(COLOR_PER_VERTEX_OPERATOR_average) opacityColor = (0.5 * (opacityColorIn.rgb + (colorPerVertexAlpha * alphaBit))) ; #elif defined(COLOR_PER_VERTEX_OPERATOR_modulate2x) opacityColor = (opacityColorIn.rgb * colorPerVertexAlpha * alphaBit) * 2.0; #endif #else #if defined(COLOR_PER_VERTEX_OPERATOR_replace) opacityColor = colorPerVertexAlpha; #elif defined(COLOR_PER_VERTEX_OPERATOR_add) opacityColor = (opacityColorIn.rgb + colorPerVertexAlpha) ; #elif defined(COLOR_PER_VERTEX_OPERATOR_subtract) opacityColor = (opacityColorIn.rgb - colorPerVertexAlpha) ; #elif defined(COLOR_PER_VERTEX_OPERATOR_modulate) opacityColor = (opacityColorIn.rgb * colorPerVertexAlpha) ; #elif defined(COLOR_PER_VERTEX_OPERATOR_divide) opacityColor = (opacityColorIn.rgb / colorPerVertexAlpha) ; #elif defined(COLOR_PER_VERTEX_OPERATOR_average) opacityColor = (0.5 * (opacityColorIn.rgb + colorPerVertexAlpha)) ; #elif defined(COLOR_PER_VERTEX_OPERATOR_modulate2x) opacityColor = (opacityColorIn.rgb * colorPerVertexAlpha) * 2.0; #endif #endif return opacityColor; } /////////////////////////////////////////////////////////////////////////////////// // // Description: Compute the final output color // float4 MAYA_computeFinalColor(float3 diffuseAndAmbientValue, float3 specularValue, float3 opacityValue) { // To match standard hardware fixed-function pipeline specular, allow the option of modulating // speculary by opacity. #if defined(SPECULAR_IS_AFFECTED_BY_OPACITY) float4 finalColor = float4(opacityValue * (diffuseAndAmbientValue + specularValue), 1); #else float4 finalColor = float4(opacityValue * diffuseAndAmbientValue + specularValue, 1); #endif return finalColor; } /////////////////////// // Uniforms common to projective light textures or shadow maps. // #if defined(PROJ_LIGHT_TEXTURE) || defined(SHADOW_MAP) #define UNIFORM_WORLD_TO_PROJECTIVE_LIGHT_MATRIX \ , uniform float4 worldToProjLightMatrix0, \ uniform float4 worldToProjLightMatrix1, \ uniform float4 worldToProjLightMatrix2, \ uniform float4 worldToProjLightMatrix3 #else // (! (defined(PROJ_LIGHT_TEXTURE) || defined(SHADOW_MAP)) #define UNIFORM_WORLD_TO_PROJECTIVE_LIGHT_MATRIX #endif // PROJ_LIGHT_TEXTURE || SHADOW_MAP // Uniforms specific to shadow map. // #if defined(SHADOW_MAP) #define UNIFORM_SHADOW_MAP_TEXTURE \ , uniform sampler shadowTex \ , uniform float3 shadowColor #else // !defined(SHADOW_MAP) #define UNIFORM_SHADOW_MAP_TEXTURE #endif // SHADOW_MAP // Uniforms specific to projective light texture. // #if defined(PROJ_LIGHT_TEXTURE) #define UNIFORM_PROJ_LIGHT_TEXTURE \ , uniform sampler lightColorTex, \ uniform float lightIntensity, \ uniform float lightScale #else // !defined(PROJ_LIGHT_TEXTURE) #define UNIFORM_PROJ_LIGHT_TEXTURE #endif // PROJ_LIGHT_TEXTURE #if defined(BOUNDED_LIGHT) #define UNIFORM_LIGHT_BOUNDS \ , uniform float3 wCorner1, \ uniform float3 wCorner2, \ uniform float3 wCorner3, \ uniform float3 wCorner4, \ uniform float3 wSpotDir \ UNIFORM_WORLD_TO_PROJECTIVE_LIGHT_MATRIX \ UNIFORM_SHADOW_MAP_TEXTURE #else #define UNIFORM_LIGHT_BOUNDS #endif // Uniforms specific to a given light type. Only one of these // (POINT_LIGHT, SPOT_LIGHT, DIR_LIGHT, AMBIENT_LIGHT) should // be enabled within a compile. // #if defined(POINT_LIGHT) #define LIGHT_SPECIFIC_UNIFORMS \ , uniform float3 wLightPos \ UNIFORM_LIGHT_BOUNDS \ , uniform float4 lightDecayCoeff #elif defined(SPOT_LIGHT) #define LIGHT_SPECIFIC_UNIFORMS \ , uniform float3 wLightPos, \ uniform float4 lightDecayCoeff, \ uniform float3 wSpotDir, \ uniform float cosPenumbra, \ uniform float cosUmbra, \ uniform float radialDropOff \ UNIFORM_WORLD_TO_PROJECTIVE_LIGHT_MATRIX \ UNIFORM_SHADOW_MAP_TEXTURE \ UNIFORM_PROJ_LIGHT_TEXTURE #elif defined(DIR_LIGHT) #define LIGHT_SPECIFIC_UNIFORMS \ , uniform float3 wLightDir \ UNIFORM_WORLD_TO_PROJECTIVE_LIGHT_MATRIX \ UNIFORM_SHADOW_MAP_TEXTURE #elif defined(AMBIENT_LIGHT) #define LIGHT_SPECIFIC_UNIFORMS \ , \ uniform float3 wLightPos, \ uniform float ambientShade #endif // Light-specific uniforms // // Main fragment program // float4 main(MAYA_phong_vert2frag IN, uniform float4 gWorldEyePos, #if !defined(TWO_SIDED_LIGHTING) uniform float normalMultiplier, // -1 if normal needs to be inverted, 1 otherwise. #endif uniform float3 lightColor // pre-multiplied by intensity. LIGHT_SPECIFIC_UNIFORMS #if defined(CONSTANT_COLOR) , uniform float4 constantColor #else , uniform sampler colorTex , uniform float4 colorTexMatrix0 , uniform float4 colorTexMatrix1 // Need to add these in for cube mapping. //uniform float3 worldToCubeRotationMatrix0, //uniform float3 worldToCubeRotationMatrix1, //uniform float3 worldToCubeRotationMatrix2, #if defined (PASS_TEX1_UV) , uniform sampler pass2Tex , uniform float4 pass2TexMatrix0 , uniform float4 pass2TexMatrix1 #endif #if defined (PASS_TEX1_ALPHA_UV) , uniform sampler2D pass2AlphaTex , uniform float4 pass2AlphaTexMatrix0 , uniform float4 pass2AlphaTexMatrix1 #else , uniform float pass2TexAlpha #endif #endif #if defined(CONSTANT_DIFFUSE) , uniform float constantDiffuse #else , uniform sampler diffuseTex , uniform float4 diffuseTexMatrix0 , uniform float4 diffuseTexMatrix1 #endif #if defined(CONSTANT_SPECULAR) , uniform float4 constantSpecular #else , uniform sampler specTex , uniform float4 specTexMatrix0 , uniform float4 specTexMatrix1 #endif #if defined(BUMP_MAP) || defined (OBJECT_NORMAL) , uniform sampler bumpTex , uniform float4 bumpTexMatrix0, uniform float4 bumpTexMatrix1 #endif // BUMP_MAP || OBJECT_NORMAL #if defined(CONSTANT_TRANSPARENCY) , uniform float3 constantTransparency // Allow for colored transparency #else , uniform sampler transpTex , uniform float4 transpTexMatrix0 , uniform float4 transpTexMatrix1 #endif #if defined(COMPUTE_TRANSLUCENCE) , uniform float translucence , uniform float translucenceFocus , uniform float translucenceDepth #endif #if defined(BLINN_SHADING_MODEL) , uniform float eccentricity , uniform float specularRollOff #if defined(REFLECTED_SPECULAR) , uniform float specularity #endif #endif ) : COLOR { // Compute the unnormalized light direction vector, expressed // in world space. // #if defined(POINT_LIGHT) || defined(SPOT_LIGHT) || defined(AMBIENT_LIGHT) float3 wLightVector = (wLightPos - IN.wPosition.xyz).xyz; float3 wLightDir = normalize(wLightVector); #if defined(BOUNDED_LIGHT) float3 wLightVector1 = (wCorner1 - IN.wPosition.xyz).xyz; float3 wLightVector2 = (wCorner2 - IN.wPosition.xyz).xyz; float3 wLightVector3 = (wCorner3 - IN.wPosition.xyz).xyz; float3 wLightVector4 = (wCorner4 - IN.wPosition.xyz).xyz; float3 wLightDir1 = normalize(wLightVector1); float3 wLightDir2 = normalize(wLightVector2); float3 wLightDir3 = normalize(wLightVector3); float3 wLightDir4 = normalize(wLightVector4); // Analytic computation for a polygon float3 light_vector1 = acos( dot( wLightDir1, wLightDir2 )) * cross(wLightDir1, wLightDir2); float3 light_vector2 = acos( dot( wLightDir2, wLightDir3 )) * cross(wLightDir2, wLightDir3); float3 light_vector3 = acos( dot( wLightDir3, wLightDir4 )) * cross(wLightDir3, wLightDir4); float3 light_vector4 = acos( dot( wLightDir4, wLightDir1 )) * cross(wLightDir4, wLightDir1); #endif #elif defined(DIR_LIGHT) // do nothing. wLightDir is read from the uniform. #endif // (POINT_LIGHT || SPOT_LIGHT || AMBIENT_LIGHT) // Calculate view direction in world space, // from point to eye. // float3 wViewDir = normalize(gWorldEyePos.xyz - IN.wPosition.xyz); #if defined(TWO_SIDED_LIGHTING) float faceMultiplier = IN.frontColor.x > 0.3 ? 1.0 : -1.0; #else float faceMultiplier = normalMultiplier; #endif /////////////////////////////////////////////////////////// // Compute proper world space normal /////////////////////////////////////////////////////////// MAYA_NormalInfoInput normin; #if !defined(OBJECT_NORMAL) normin.wNormal = IN.wNormal; #endif normin.faceMultiplier = faceMultiplier; #if defined(BUMP_MAP) normin.wTangent = IN.wTangent; #endif #if defined(BUMP_MAP) || defined(OBJECT_NORMAL) normin.bumpTexUv = IN.bumpTexUv; normin.bumpTexMatrix0 = bumpTexMatrix0; normin.bumpTexMatrix1 = bumpTexMatrix1; normin.bumpTex = bumpTex; #endif float3 wBumpedNormal = MAYA_computeWorldSpaceNormal( normin ); // Compute (L dot N) : float LDotN = dot(wLightDir, wBumpedNormal); float LDotNsigned = LDotN; #if defined(POINT_LIGHT) #if defined(BOUNDED_LIGHT) float LDotN1 = dot(wLightDir1, wBumpedNormal); float LDotNsigned1 = LDotN1; LDotN1 = max(LDotN1, 0); float LDotN2 = dot(wLightDir2, wBumpedNormal); float LDotNsigned2 = LDotN2; LDotN2 = max(LDotN2, 0); float LDotN3 = dot(wLightDir3, wBumpedNormal); float LDotNsigned3 = LDotN3; LDotN3 = max(LDotN3, 0); float LDotN4 = dot(wLightDir4, wBumpedNormal); float LDotNsigned4 = LDotN4; LDotN4 = max(LDotN4, 0); #endif #endif #if !defined(AMBIENT_LIGHT) LDotN = max(LDotN, 0); #endif // not ambient light #if defined(SHADOW_MAP) || defined(PROJ_LIGHT_TEXTURE) // 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(IN.wPosition.xyz, 1); projTexCoords.x = dot(pos, worldToProjLightMatrix0); projTexCoords.y = dot(pos, worldToProjLightMatrix1); projTexCoords.z = dot(pos, worldToProjLightMatrix2); projTexCoords.w = dot(pos, worldToProjLightMatrix3); #endif // (SHADOW_MAP || PROJ_LIGHT_TEXTURE) #if defined(PROJ_LIGHT_TEXTURE) // This is a spot light, where the light color comes from a // projective texture. Fetch the color from that texture. // float2 projLightTexCoords = projTexCoords.xy / projTexCoords.w; projLightTexCoords = (projLightTexCoords - 0.5) * lightScale + 0.5; float3 attenuatedLightColor = lightIntensity * tex2D(lightColorTex, projLightTexCoords).xyz ; #else float3 attenuatedLightColor = lightColor; #endif // PROJ_LIGHT_TEXTURE #if defined(SHADOW_MAP) // Do the shadow distance comparison, to find out if the // current fragment is shadowed or not. float inShadow = tex2Dproj(shadowTex, projTexCoords); // Test code for multi-sampling a shadow map. Results are very poor. //float value = tex2Dproj(shadowTex, projTexCoords + float4(0.02, 0.02, 0 ,0)); //value += tex2Dproj(shadowTex, projTexCoords + float4(-0.02, 0.02, 0 ,0)); //value += tex2Dproj(shadowTex, projTexCoords + float4(0.02, -0.02, 0 ,0)); //value += tex2Dproj(shadowTex, projTexCoords + float4(-0.02, -0.02, 0,0)); //float inShadow = 0.25 * value; // Color the shadowed areas if (inShadow < 0.001) attenuatedLightColor.rgb = attenuatedLightColor * shadowColor; else attenuatedLightColor.rgb = attenuatedLightColor; #endif // SHADOW_MAP // The attenuation is a dividing factor used to attenuate // the light source contribution. // float attenuation = 1; #if defined(POINT_LIGHT) || defined(SPOT_LIGHT) // Compute the distance-from-light-source attenuation. // float wLightDistance = length(wLightVector); // The following line could be optimized. attenuation = lightDecayCoeff.x + lightDecayCoeff.y * wLightDistance + lightDecayCoeff.z * wLightDistance * wLightDistance + lightDecayCoeff.w * wLightDistance * wLightDistance * wLightDistance; // Add special attenuation code for bounded lights ? [***] // Do not allow the light to have an attenuation factor greater than // 1, since this would make the light source appear too bright. // attenuation = max(attenuation, 1); #endif // (POINT_LIGHT || SPOT_LIGHT) distance-based attenuation. float spotRadialIntensity = 1; #if defined(SPOT_LIGHT) // 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(wLightDir, wSpotDir); if (SdotL < cosPenumbra) { // The angle is larger than the total angle, // therefore it's outside of the cone. // spotRadialIntensity = 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); } } #endif // SPOT_LIGHT #if defined (BOUNDED_LIGHT) #if defined(LIGHT_SHAPE_RECTANGLE) // Use this to clip the light against a hard plane. If we had volumes, // we could do volume level clipping as well with multiple planes. float SdotL = dot(wLightDir, wSpotDir); if (SdotL < 0) spotRadialIntensity = 0; #endif #endif // // Compute attenuated light colour // attenuatedLightColor = attenuatedLightColor * spotRadialIntensity / attenuation; // Compute the base colour // MAYA_BaseInfoInput baseinput; float4 previousColor; #if defined(INTENSITY_ANGLE_COLOR_UVS) baseinput.intensityAngleColor = float4(1,1,1,1); #else #if defined(CONSTANT_COLOR) // Constant colour baseinput.constantColor = constantColor; #else // // Apply the appropriate color texture lookup // then fetch the appropriate color texel. // MAYA_ColorTxInfoInput ctinput; #if defined(LIGHTANGLE_COLOR_UVS) || defined(CAMERA_ANGLE_COLOR_UVS) #if defined(LIGHTANGLE_COLOR_UVS) ctinput.LDotNsigned = LDotNsigned; #endif #if defined(CAMERA_ANGLE_COLOR_UVS) ctinput.wViewDir = wViewDir; ctinput.wBumpedNormal = wBumpedNormal; #endif #else ctinput.colorTexUv = IN.colorTexUv; ctinput.colorTexMatrix0 = colorTexMatrix0; ctinput.colorTexMatrix1 = colorTexMatrix1; #endif // Compute first texture lookup // #if defined(PASS_TEX0_ENV_SPHERE) baseinput.lookupVector = reflect(-wViewDir, wBumpedNormal); //baseinput.lookupVector = wBumpedNormal * dot(wBumpedNormal, wViewDir) * 2.0 - wViewDir; #elif defined(PASS_TEX0_ENV_CUBE) float3 lookupVector; #if defined(PASS_NORMAL0_LOOKUP) baseinput.lookupVector = wBumpedNormal; #else // #if defined(PASS_REFLECTION0_LOOKUP) baseinput.lookupVector = reflect(-wViewDir, wBumpedNormal); #endif #else baseinput.lookupVector = float3( MAYA_computeColorTextureLookup( ctinput ), 0.0 ); #endif // Send first texture baseinput.colorTex = colorTex; // Compute second texture lookup // #if defined(PASS_TEX1_UV) #if defined(PASS_TEX1_ENV_SPHERE) baseinput.lookupVector2 = reflect(-wViewDir, wBumpedNormal); #elif defined(PASS_TEX1_ENV_CUBE) #if defined(PASS_NORMAL1_LOOKUP) baseinput.lookupVector2 = wBumpedNormal; #else // #if defined(PASS_REFLECTION1_LOOKUP) baseinput.lookupVector2 = reflect(-wViewDir, wBumpedNormal); #endif #else // Extract uvs from packed float4. float2 placedColorTexUv; float4 tempUV = float4(IN.pass2TexUv.xy, 0.0, 1.0); placedColorTexUv.x = dot(pass2TexMatrix0, tempUV); placedColorTexUv.y = dot(pass2TexMatrix1, tempUV); baseinput.lookupVector2 = float3( placedColorTexUv, 0.0 ); #endif // Send second texture baseinput.colorTex2 = pass2Tex; #endif // Compute alpha blend texture lookup // #if defined(PASS_TEX1_ALPHA_UV) // Extract uvs from packed float4. float4 tempUV2 = float4(IN.pass2TexUv.zw, 0.0, 1.0); placedColorTexUv.x = dot(pass2AlphaTexMatrix0, tempUV2); placedColorTexUv.y = dot(pass2AlphaTexMatrix1, tempUV2); baseinput.alphaTex2 = pass2AlphaTex; baseinput.placedAlphaTexUv2 = placedColorTexUv; #else baseinput.passAlpha2 = pass2TexAlpha; #endif #endif #if defined(COLOR_PER_VERTEX) baseinput.colorPerVertex = IN.colorPerVertex; #if defined(COLOR_PER_VERTEX_MASK) baseinput.colorPerVertexMask = IN.colorPerVertexMask; #endif #endif #endif float4 baseColor = MAYA_computeBaseColor( baseinput, previousColor ); float3 diffuseAndAmbientColor; //*** AMBIENT #if defined(AMBIENT_LIGHT) //////////////////////////////////////////////////////////////////// // Compute ambient only //////////////////////////////////////////////////////////////////// #if defined( COLOR_PER_VERTEX_AMBIENT ) // Ambient color has been calculated in a separate ambient pass // which takes into account colour per vertex data. // diffuseAndAmbientColor = float3(0,0,0); #else // 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(lightColor * (1.0 + ambientShade).xxx); #if defined(INTENSITY_ANGLE_COLOR_UVS) float2 intensityLookup; intensityLookup.x = (diffuseAndAmbientFactor.x + diffuseAndAmbientFactor.y + diffuseAndAmbientFactor.z) / 3.0; intensityLookup.x = min(1.0, intensityLookup.x); intensityLookup.y = 0.5; diffuseAndAmbientColor = tex2D(colorTex, intensityLookup).xyz; #else diffuseAndAmbientColor = baseColor.rgb * diffuseAndAmbientFactor; #endif #endif float3 specularColor = float3(0,0,0); //*** NON AMBIENT #else //////////////////////////////////////////////////////////////////// // Compute diffuse //////////////////////////////////////////////////////////////////// // // Compute the diffuse coefficient // MAYA_DiffuseInfoInput dinput; #if defined(CONSTANT_DIFFUSE) dinput.constantDiffuse = constantDiffuse; #else dinput.diffuseTexUv = IN.diffuseTexUv; dinput.diffuseTexMatrix0 = diffuseTexMatrix0; dinput.diffuseTexMatrix1 = diffuseTexMatrix1; dinput.diffuseTex = diffuseTex; #endif float diffuseCoef = MAYA_computeDiffuseCoef(dinput); // // Compute the diffuse component // // Base diffuse factor. #if defined(POINT_LIGHT) #if defined (BOUNDED_LIGHT) #if defined(LIGHT_SHAPE_RECTANGLE) float diffuseFactor; // Note that spot direction doesn't really play any part in the direction of // the hilite, so is basically ignored here. It's the lights position, and // dimensions which play the main factor. // // Point lights to get the spread. float NdotS = dot( wBumpedNormal, wSpotDir ); diffuseFactor = (LDotN + LDotN1 + LDotN2 + LDotN3 + LDotN4) /5.0 * diffuseCoef; // Integration to handle dimensions. Fills in the center float light_val = dot( wBumpedNormal, light_vector1) + dot( wBumpedNormal, light_vector2 ) + dot( wBumpedNormal, light_vector3) + dot( wBumpedNormal, light_vector4 ); diffuseFactor += light_val / (2.0 * 3.14159) * diffuseCoef; #else // Use this if not using the shape. float diffuseFactor = 2.0 * LDotN * max( dot(wLightDir, wSpotDir), 0.0); diffuseFactor += LDotN1 * max( dot(wLightDir1, wSpotDir), 0.0); diffuseFactor += LDotN2 * max( dot(wLightDir2, wSpotDir), 0.0); diffuseFactor += LDotN3 * max( dot(wLightDir3, wSpotDir), 0.0); diffuseFactor += LDotN4 * max( dot(wLightDir4, wSpotDir), 0.0); diffuseFactor *= diffuseCoef / 4.0; #endif #else float diffuseFactor = diffuseCoef * LDotN; #endif #else float diffuseFactor = diffuseCoef * LDotN; #endif // Compute translucency if required. // #if defined(COMPUTE_TRANSLUCENCE) if (translucence > 0.0) { MAYA_translucenceInfo translinput; translinput.LDotNsigned = LDotNsigned; translinput.LDotN = LDotN; translinput.wViewDir = wViewDir; translinput.wLightDir = wLightDir; translinput.translucence = translucence; translinput.translucenceFocus = translucenceFocus; translinput.translucenceDepth = translucenceDepth; float tlBright = MAYA_computeTranslucence( translinput ); diffuseFactor += tlBright; } #endif #if defined(INTENSITY_ANGLE_COLOR_UVS) // Brightness float2 intensityLookup; attenuatedLightColor *= diffuseFactor; intensityLookup.x = (attenuatedLightColor.x + attenuatedLightColor.y + attenuatedLightColor.z) / 3.0; intensityLookup.x = min(1.0, intensityLookup.x); intensityLookup.y = 0.5; diffuseAndAmbientColor = tex2D(colorTex, intensityLookup).xyz; #else diffuseAndAmbientColor = attenuatedLightColor * baseColor.rgb * diffuseFactor; #endif //////////////////////////////////////////////////////////////////// // Compute specular //////////////////////////////////////////////////////////////////// // Apply the placement specular color/exponent texture matrix, // to the corresponding texture coordinates, then fetch the // appropriate texel. // float cosne = dot(wViewDir, wBumpedNormal); float3 specularColor = float3(0,0,0); #if defined(CONSTANT_SPECULAR) float4 specValues = float4(constantSpecular.rgb, 1.0); #else float2 placedSpecTexUv; #if defined(REFLECTED_SPECULAR) float3 refVector = (cosne + cosne) * wBumpedNormal - wViewDir; float LDotR = dot(wLightDir, refVector); float specTexUv = 0.5f * (LDotR + 1.0); placedSpecTexUv.x = specTexUv * specTexUv * specTexUv; placedSpecTexUv.y = 0.5f; #else float4 specTexUv = float4(IN.specTexUv.xy, 0.0, 1.0); placedSpecTexUv.x = dot(specTexMatrix0, specTexUv); placedSpecTexUv.y = dot(specTexMatrix1, specTexUv); #endif float4 specValues = tex2D(specTex, placedSpecTexUv); #endif #if defined(BLINN_SHADING_MODEL) // // Compute Blinn specular shading // #if defined(POINT_LIGHT) #if defined (BOUNDED_LIGHT) float3 specularColor2 = float3(0,0,0); float count = 0; MAYA_SpecularInfoInput specin; specin.wBumpedNormal = wBumpedNormal; specin.attenuatedLightColor = attenuatedLightColor; specin.wViewDir = wViewDir; specin.eccentricity = eccentricity; #if defined(REFLECTED_SPECULAR) specin.specularity = specularity; #else specin.specularRollOff = specularRollOff; #endif specin.specValues = specValues; specin.cosne = cosne; specin.LDotN = max( LDotN, 0.001 ); specin.wLightDir = wLightDir; specularColor2 += MAYA_computeBlinnSpecular( specin ); count +=1 ; specin.LDotN = max( LDotN1, 0.001 ); specin.wLightDir = wLightDir1; specularColor2 += MAYA_computeBlinnSpecular( specin ); count +=1 ; specin.LDotN = max( LDotN2, 0.001 ); specin.wLightDir = wLightDir2; specularColor2 += MAYA_computeBlinnSpecular( specin ); count +=1 ; specin.LDotN = max( LDotN3, 0.001 ); specin.wLightDir = wLightDir3; specularColor2 += MAYA_computeBlinnSpecular( specin ); count +=1 ; specin.LDotN = max( LDotN4, 0.001 ); specin.wLightDir = wLightDir4; specularColor2 += MAYA_computeBlinnSpecular( specin ); count +=1 ; if (count > 0) specularColor2 = specularColor2 / count; specularColor = specularColor2; #else MAYA_SpecularInfoInput specin; specin.wBumpedNormal = wBumpedNormal; specin.wLightDir = wLightDir; specin.attenuatedLightColor = attenuatedLightColor; specin.wViewDir = wViewDir; specin.eccentricity = eccentricity; #if defined(REFLECTED_SPECULAR) specin.specularity = specularity; #else specin.specularRollOff = specularRollOff; #endif specin.specValues = specValues; specin.LDotN = max( LDotN, 0.001 ); specin.cosne = cosne; specularColor = MAYA_computeBlinnSpecular( specin ); #endif #else MAYA_SpecularInfoInput specin; specin.wBumpedNormal = wBumpedNormal; specin.wLightDir = wLightDir; specin.attenuatedLightColor = attenuatedLightColor; specin.wViewDir = wViewDir; specin.eccentricity = eccentricity; #if defined(REFLECTED_SPECULAR) specin.specularity = specularity; #else specin.specularRollOff = specularRollOff; #endif specin.specValues = specValues; specin.LDotN = max( LDotN, 0.001 ); specin.cosne = cosne; specularColor = MAYA_computeBlinnSpecular( specin ); #endif #else // // 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 wReflectDir = reflect(-wLightDir, wBumpedNormal); float RDotV = dot(wReflectDir, wViewDir); RDotV = max(RDotV, 0.001); //if ( RDotV > 0.001 ) -- Doing this creates a clear circular band artifact. { // Compute the specular exponent #if defined(CONSTANT_SPECULAR) // The specular exponent is encoded in the alpha // of the specular color. float specularExp = constantSpecular.a; #else // The specular exponent (encoded in the alpha of the spec texture) // needs to be converted from the [0,1] to the [0,128] range. // float specularExp = specValues.a * 128; #endif MAYA_SpecularInfoInput1 specin; specin.attenuatedLightColor = attenuatedLightColor; specin.RDotV = RDotV; specin.specularExp = specularExp; specin.specValues = specValues ; #if defined(COLOR_PER_VERTEX_SPECULAR) specin.colorPerVertex = IN.colorPerVertex; #if defined(COLOR_PER_VERTEX_MASK) specin.colorPerVertexMask = IN.colorPerVertexMask; #endif #endif #if defined(POINT_LIGHT) #if defined (BOUNDED_LIGHT) specularColor = float3(0.0, 0.0, 0.0); float3 specularColor2; float factor1 = dot( wBumpedNormal, wLightDir ); // cos(N,L) float factor2 = dot ( wLightDir, wSpotDir ); // cos(L,LD) float specFactor = factor1*factor2; float count = 1.0; //specin.specularExp = specularExp * 2.2; specularColor2 = MAYA_computePhongSpecular(specin); specularColor = specularColor2 ; specin.specularExp = specularExp; wReflectDir = reflect(-wLightDir1, wBumpedNormal); specin.RDotV = max( dot(wReflectDir, wViewDir), 0.001); specularColor2 = MAYA_computePhongSpecular(specin); specularColor += specularColor2; count += 1.0; wReflectDir = reflect(normalize(-wLightDir1 + -wLightDir2), wBumpedNormal); specin.RDotV = max( dot( wReflectDir , wViewDir), 0.001); specularColor2 = MAYA_computePhongSpecular(specin); specularColor += specularColor2; count += 1.0; wReflectDir = reflect(-wLightDir2, wBumpedNormal); specin.RDotV = max( dot( wReflectDir , wViewDir), 0.001); specularColor2 = MAYA_computePhongSpecular(specin); specularColor += specularColor2; count += 1.0; wReflectDir = reflect(normalize(-wLightDir2 + -wLightDir3), wBumpedNormal); specin.RDotV = max( dot( wReflectDir , wViewDir), 0.001); specularColor2 = MAYA_computePhongSpecular(specin); specularColor += specularColor2; count += 1.0; wReflectDir = reflect(-wLightDir3, wBumpedNormal); specin.RDotV = max( dot( wReflectDir, wViewDir), 0.001); specularColor2 = MAYA_computePhongSpecular(specin); specularColor += specularColor2; count += 1.0; wReflectDir = reflect(normalize(-wLightDir3 + -wLightDir4), wBumpedNormal); specin.RDotV = max( dot( wReflectDir , wViewDir), 0.001); specularColor2 = MAYA_computePhongSpecular(specin); specularColor += specularColor2; count += 1.0; wReflectDir = reflect(-wLightDir4, wBumpedNormal); specin.RDotV = max( dot( wReflectDir, wViewDir), 0.001); specularColor2 = MAYA_computePhongSpecular(specin); specularColor += specularColor2; count += 1.0; wReflectDir = reflect(normalize(-wLightDir1 + -wLightDir4), wBumpedNormal); specin.RDotV = max( dot( wReflectDir , wViewDir), 0.001); specularColor2 = MAYA_computePhongSpecular(specin); specularColor += specularColor2; count += 1.0; #if defined(MORE_LIGHT_SAMPLES) wReflectDir = reflect(normalize(-wLightDir1 + -wLightDir), wBumpedNormal); specin.RDotV = max( dot(wReflectDir, wViewDir), 0.001); specularColor2 = MAYA_computePhongSpecular(specin); specularColor += specularColor2; count += 1.0; wReflectDir = reflect(normalize(-wLightDir2 + -wLightDir), wBumpedNormal); specin.RDotV = max( dot(wReflectDir, wViewDir), 0.001); specularColor2 = MAYA_computePhongSpecular(specin); specularColor += specularColor2; count += 1.0; wReflectDir = reflect(normalize(-wLightDir3 + -wLightDir), wBumpedNormal); specin.RDotV = max( dot(wReflectDir, wViewDir), 0.001); specularColor2 = MAYA_computePhongSpecular(specin); specularColor += specularColor2; count += 1.0; wReflectDir = reflect(normalize(-wLightDir4 + -wLightDir), wBumpedNormal); specin.RDotV = max( dot(wReflectDir, wViewDir), 0.001); specularColor2 = MAYA_computePhongSpecular(specin); specularColor += specularColor2; count += 1.0; #endif specularColor = specularColor / count; //specularColor = specularColor * specFactor; #else specularColor = MAYA_computePhongSpecular(specin); #endif #else specularColor = MAYA_computePhongSpecular(specin); #endif } #endif // BLINN_SHADING_MODEL #endif // AMBIENT_LIGHT //////////////////////////////////////////////////////////////////// // Compute transparency //////////////////////////////////////////////////////////////////// float3 opacityColor; // The transparency texel can be interpreted in two different ways: #if defined(OPACITY_IN_COLOR_ALPHA) // The opacity is encoded in the base color texture's alpha. // This mode is frequently used to combine the base color and // transparency in one texture. // #if defined(COLOR_PER_VERTEX) opacityColor = previousColor.aaa; #else opacityColor = baseColor.aaa; #endif #else // TRANSP_IN_TRANSP_RGB #if defined(CONSTANT_TRANSPARENCY) // Passthrough constant transparency information // opacityColor = constantTransparency; #else MAYA_TranspLookupInfo input2; #if defined(CAMERA_ANGLE_TRANSP_UVS) float EDotN = dot(wViewDir, wBumpedNormal); EDotN = max(EDotN, 0.001); input2.EDotN = EDotN; #else input2.transpTexUv = IN.transpTexUv; input2.transpTexMatrix0 = transpTexMatrix0; input2.transpTexMatrix1 = transpTexMatrix1; #endif input2.transpTex = transpTex; opacityColor = MAYA_lookupTexturedTransparency( input2 ); #endif #endif // OPACITY_IN_COLOR_ALPHA #if defined(COLOR_PER_VERTEX) // Get opacity based in incoming per-vertex alpha. float alphaValue = IN.colorPerVertex.a; #if defined(COLOR_PER_VERTEX_MASK) float alphaBit= IN.colorPerVertexMask.r; #else float alphaBit = 1.0; #endif opacityColor = MAYA_computePerVertexAlpha(alphaValue, alphaBit, opacityColor); #endif // Collect everything together to get the final colour. // float4 finalColor = MAYA_computeFinalColor(diffuseAndAmbientColor, specularColor, opacityColor); return finalColor; }