//
// Dynamic model, bump+reflection
// In world space (more like the other shaders, and gives a chance to modify reflection vectors)
// RvG, 19-11-2010
//
#include "atmosphere.cg"
#include "lighting.cg"
#include "fresnel.cg"
#include "shadowmapping.cg"
#include "../common/utils.cg"
// Vertex to pixel shader structure
struct v2p
{
float extinction : COLOR;
float2 tc0 : TEXCOORD0;
float3 Direction : TEXCOORD1;
float4 RayleighColor : TEXCOORD2;
float4 MieColor : TEXCOORD3;
float4 Position : TEXCOORD4; // For fragment shader
float3 normal : TEXCOORD5;
// Fresnel in pixel shader
float3 I : TEXCOORD6;
//float fresnel : TEXCOORD6;
//float3 R : TEXCOORD7; // Reflection vector
float4 tangent : TEXCOORD7;
};
void main(
// In
in v2p IN,
// Out
out float4 out0 : COLOR0,
#ifdef CSM_MRT
out float4 out1 : COLOR1,
#endif
// Constants
uniform sampler2D baseMap : TEXUNIT0,
uniform sampler2D normalMap : TEXUNIT1,
uniform samplerCUBE envMap : TEXUNIT2,
uniform float3 lightDirection,
uniform float3 lightColor,
uniform float3 lightAmbient,
uniform float3 ambientSpecular,
uniform float3 eyePosW,
uniform float atmosRayleigh,
uniform float atmosMie,
uniform float3 Ke,
uniform float3 Ka,
uniform float3 Kd,
uniform float3 Ks,
uniform float Kr,
uniform float shininess,
uniform float far,
#ifdef USE_CUBEMAP_MIPMAPS
uniform float mipmap, // Mipmap level of reflection map (blurry if >0)
#endif
uniform float sunny,
uniform float scale,
uniform float exposure,
#ifdef CSM
uniform sampler2D shadowArray : TEXUNIT7,
uniform float4x4 smTexMatArray[SM_MAX_SPLITS],
uniform float smSplits,
#endif
uniform float fresnelBias,
uniform float fresnelScale,
uniform float fresnelPower
)
{
float3 skyColor;
// Get texture map info
float4 baseCol=tex2D(baseMap,IN.tc0);
float4 bumpColor=tex2D(normalMap,IN.Position.zx*scale);
// Texture space axes
float4 tangent=IN.tangent;
float3 N=normalize(IN.normal);
float3 binormal=cross(tangent.xyz,N)*tangent.w;
// Expand normal
bumpColor.xyz=UnpackNormal(bumpColor.xyz);
// Mix to 'flat and shiny' based on the interaction of the two values
bumpColor=normalize(lerp(bumpColor,float4(0f,0f,1.0f,sqrt(bumpColor.a)),saturate(2.0f*baseCol.a+bumpColor.a-1.0f)));
// Calculate new normal in world space
float3 bumpNormal=N+(bumpColor.x*tangent+bumpColor.y*binormal);
N=normalize(bumpNormal);
// Reflection vector
float3 R=reflect(IN.I,N);
#ifdef CSM
// Output shadowing
float lit = GetShadowFactor(IN.Position, IN.normal,shadowArray, smTexMatArray, smSplits, lightDirection)*sunny;
#else
const float lit=sunny;
#endif
//lightAmbient = texCUBElod_soft(envMap,float4(R,12.0f));
// Get sky gradient color
skyColor.rgb=GetSkyColor(lightDirection,IN.Direction,IN.RayleighColor,IN.MieColor,atmosRayleigh,atmosMie,lightColor,lightAmbient);
//baseCol=float4(0.5,0,0,0);
// Specular map
float3 reflectiveNess=1-(baseCol.rgb*0.5);
Ks*=reflectiveNess*((0.25f*baseCol.a+0.75f*bumpColor.a));
float gloss = min(0.0,1.0f*bumpColor.a+2.0f*baseCol.a-2.5f);
shininess=pow(10f,gloss+3.0f);
// only load an envMap if we have soft mipmaps
// note: the 7.5f corresponds to shininess and really should depend on it.
#ifdef USE_CUBEMAP_MIPMAPS
float3 envColor=texCUBElod_soft(envMap,float4(R,7.5f-4.0f*gloss));
#endif
// Lighting
float3 ambient,diffuse,specular;
LightingSun(Ke,Ka,Kd,Ks,shininess,lightDirection,lightColor,lightAmbient,IN.Position,N,eyePosW,
ambient,diffuse,specular);
//FresnelMix2 lets us mix using lerp vs fresnel, so we can go from black to white and vice versa, rather than FresnelMix which just does additive blend vs fresnel
//define fresnel
float fresnel=Fresnel(fresnelBias,fresnelScale,fresnelPower,normalize(IN.I),normalize(N));
// fresnel on specular, yay!
specular=FresnelMix(0,specular,Kr,fresnel);
// ambient specular options
// really the cubemap mipmap is a more accurate representation of the 'ambient' light.
#ifdef USE_CUBEMAP_MIPMAPS
// the higher the gloss, the more it should use the reflective color.
ambient=lerp(ambient,envColor,saturate(gloss+1.0f));
#endif
ambientSpecular=FresnelMix(0,(ambient*(0.25f*baseCol.a+0.75f*bumpColor.a)),Kr,fresnel);
//ambientSpecular=0;
float3 litColor=(baseCol*(0.6f+0.4*bumpColor.a))*(diffuse)+specular*reflectiveNess+(ambientSpecular*0.6817);
//float3 litColor=baseCol*diffuse+specular*reflectiveNess+(ambientSpecular*0.6817);
float3 shadowColor=((baseCol*(0.6f+0.4*bumpColor.a))*(ambient+Ke))+ambientSpecular*0.3183;
#ifdef CSM_MRT
// Mix sky with texture color based on atmospheric influence
out0.rgb=lerp(skyColor,shadowColor,IN.extinction);
//outShadow.rgb=lerp(skyColor,litColor,IN.extinction);
out1.rgb=litColor*IN.extinction;
out1.a=lit;
// Blending
out0.a=baseCol.a;
#else
// Mix sky with texture color based on atmospheric influence
float3 finalColor=lerp(skyColor,shadowColor+litColor*lit,IN.extinction);
// Need to clamp output - my nVidia GTX285 only handles colors upto 255, then makes them +Inf!
finalColor=min(finalColor,255);
//out0.rgb=ao;
//out0.rgb=saturate(bumpColor.a+baseCol.a);
out0.rgb=finalColor;
// Blending
out0.a=baseCol.a;
#endif
}