| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2012 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #include "./torque.hlsl"
- #ifndef TORQUE_SHADERGEN
- // These are the uniforms used by most lighting shaders.
- uniform float4 inLightPos[3];
- uniform float4 inLightInvRadiusSq;
- uniform float4 inLightColor[4];
- #ifndef TORQUE_BL_NOSPOTLIGHT
- uniform float4 inLightSpotDir[3];
- uniform float4 inLightSpotAngle;
- uniform float4 inLightSpotFalloff;
- #endif
- uniform float4 ambient;
- #define ambientCameraFactor 0.3
- uniform float specularPower;
- uniform float4 specularColor;
- #endif // !TORQUE_SHADERGEN
- void compute4Lights( float3 wsView,
- float3 wsPosition,
- float3 wsNormal,
- float4 shadowMask,
- #ifdef TORQUE_SHADERGEN
-
- float4 inLightPos[3],
- float4 inLightInvRadiusSq,
- float4 inLightColor[4],
- float4 inLightSpotDir[3],
- float4 inLightSpotAngle,
- float4 inLightSpotFalloff,
- float specularPower,
- float4 specularColor,
- #endif // TORQUE_SHADERGEN
-
- out float4 outDiffuse,
- out float4 outSpecular )
- {
- // NOTE: The light positions and spotlight directions
- // are stored in SoA order, so inLightPos[0] is the
- // x coord for all 4 lights... inLightPos[1] is y... etc.
- //
- // This is the key to fully utilizing the vector units and
- // saving a huge amount of instructions.
- //
- // For example this change saved more than 10 instructions
- // over a simple for loop for each light.
-
- int i;
- float4 lightVectors[3];
- for ( i = 0; i < 3; i++ )
- lightVectors[i] = wsPosition[i] - inLightPos[i];
- float4 squareDists = 0;
- for ( i = 0; i < 3; i++ )
- squareDists += lightVectors[i] * lightVectors[i];
- // Accumulate the dot product between the light
- // vector and the normal.
- //
- // The normal is negated because it faces away from
- // the surface and the light faces towards the
- // surface... this keeps us from needing to flip
- // the light vector direction which complicates
- // the spot light calculations.
- //
- // We normalize the result a little later.
- //
- float4 nDotL = 0;
- for ( i = 0; i < 3; i++ )
- nDotL += lightVectors[i] * -wsNormal[i];
- float4 rDotL = 0;
- #ifndef TORQUE_BL_NOSPECULAR
- // We're using the Phong specular reflection model
- // here where traditionally Torque has used Blinn-Phong
- // which has proven to be more accurate to real materials.
- //
- // We do so because its cheaper as do not need to
- // calculate the half angle for all 4 lights.
- //
- // Advanced Lighting still uses Blinn-Phong, but the
- // specular reconstruction it does looks fairly similar
- // to this.
- //
- float3 R = reflect( wsView, -wsNormal );
- for ( i = 0; i < 3; i++ )
- rDotL += lightVectors[i] * R[i];
- #endif
-
- // Normalize the dots.
- //
- // Notice we're using the half type here to get a
- // much faster sqrt via the rsq_pp instruction at
- // the loss of some precision.
- //
- // Unless we have some extremely large point lights
- // i don't believe the precision loss will matter.
- //
- half4 correction = (half4)rsqrt( squareDists );
- nDotL = saturate( nDotL * correction );
- rDotL = clamp( rDotL * correction, 0.00001, 1.0 );
- // First calculate a simple point light linear
- // attenuation factor.
- //
- // If this is a directional light the inverse
- // radius should be greater than the distance
- // causing the attenuation to have no affect.
- //
- float4 atten = saturate( 1.0 - ( squareDists * inLightInvRadiusSq ) );
- #ifndef TORQUE_BL_NOSPOTLIGHT
- // The spotlight attenuation factor. This is really
- // fast for what it does... 6 instructions for 4 spots.
- float4 spotAtten = 0;
- for ( i = 0; i < 3; i++ )
- spotAtten += lightVectors[i] * inLightSpotDir[i];
- float4 cosAngle = ( spotAtten * correction ) - inLightSpotAngle;
- atten *= saturate( cosAngle * inLightSpotFalloff );
- #endif
- // Finally apply the shadow masking on the attenuation.
- atten *= shadowMask;
- // Get the final light intensity.
- float4 intensity = nDotL * atten;
- // Combine the light colors for output.
- outDiffuse = 0;
- for ( i = 0; i < 4; i++ )
- outDiffuse += intensity[i] * inLightColor[i];
- // Output the specular power.
- float4 specularIntensity = pow( rDotL, specularPower.xxxx ) * atten;
-
- // Apply the per-light specular attenuation.
- float4 specular = float4(0,0,0,1);
- for ( i = 0; i < 4; i++ )
- specular += float4( inLightColor[i].rgb * inLightColor[i].a * specularIntensity[i], 1 );
- // Add the final specular intensity values together
- // using a single dot product operation then get the
- // final specular lighting color.
- outSpecular = specularColor * specular;
- }
- // This value is used in AL as a constant power to raise specular values
- // to, before storing them into the light info buffer. The per-material
- // specular value is then computer by using the integer identity of
- // exponentiation:
- //
- // (a^m)^n = a^(m*n)
- //
- // or
- //
- // (specular^constSpecular)^(matSpecular/constSpecular) = specular^(matSpecular*constSpecular)
- //
- #define AL_ConstantSpecularPower 12.0f
- /// The specular calculation used in Advanced Lighting.
- ///
- /// @param toLight Normalized vector representing direction from the pixel
- /// being lit, to the light source, in world space.
- ///
- /// @param normal Normalized surface normal.
- ///
- /// @param toEye The normalized vector representing direction from the pixel
- /// being lit to the camera.
- ///
- float AL_CalcSpecular( float3 toLight, float3 normal, float3 toEye )
- {
- // (R.V)^c
- float specVal = dot( normalize( -reflect( toLight, normal ) ), toEye );
- // Return the specular factor.
- return pow( max( specVal, 0.00001f ), AL_ConstantSpecularPower );
- }
- /// The output for Deferred Lighting
- ///
- /// @param toLight Normalized vector representing direction from the pixel
- /// being lit, to the light source, in world space.
- ///
- /// @param normal Normalized surface normal.
- ///
- /// @param toEye The normalized vector representing direction from the pixel
- /// being lit to the camera.
- ///
- float4 AL_DeferredOutput(
- float3 lightColor,
- float3 diffuseColor,
- float4 matInfo,
- float4 ambient,
- float specular,
- float shadowAttenuation)
- {
- float3 specularColor = float3(specular, specular, specular);
- bool metalness = getFlag(matInfo.r, 3);
- if ( metalness )
- {
- specularColor = 0.04 * (1 - specular) + diffuseColor * specular;
- }
-
- //specular = color * map * spec^gloss
- float specularOut = (specularColor * matInfo.b * min(pow(abs(specular), max(( matInfo.a/ AL_ConstantSpecularPower),1.0f)),matInfo.a)).r;
-
- lightColor *= shadowAttenuation;
- lightColor += ambient.rgb;
- return float4(lightColor.rgb, specularOut);
- }
|