475 lines
13 KiB
Plaintext
475 lines
13 KiB
Plaintext
////////////////// Util Functions ///////////////
|
|
|
|
//normal must be normalized.
|
|
//tangetnRef and binormalRef should be similar scale.
|
|
void makeTangentAndBinormal(float3 normal, float3 tangentRef, float3 binormalRef, out float3 tangent, out float3 binormal)
|
|
{
|
|
float3 binormaltemp = cross(normal, tangentRef);
|
|
float binormallen = length(binormaltemp);
|
|
float3 tangenttemp = cross(binormalRef, normal);
|
|
float tangentlen = length(tangenttemp);
|
|
// use the longest result (most accurate)
|
|
// both will never be zero.
|
|
if(binormallen > tangentlen)
|
|
{
|
|
binormal = binormaltemp/binormallen;
|
|
tangent = cross(binormal, normal);
|
|
}
|
|
else
|
|
{
|
|
tangent = tangenttemp/tangentlen;
|
|
binormal = cross(normal, tangent);
|
|
}
|
|
}
|
|
|
|
void makeWorldTangentAndBinormalFromTextureXf(float4x4 TextureXf, float3 objNormal,
|
|
out float3 objTangent, out float3 objBinormal)
|
|
{
|
|
//generate tangent and binormal using 3D texturespace X and Y vector.
|
|
float3 tangentRef = mul(TextureXf, float4(1,0,0,0)).xyz;
|
|
float3 binormalRef = mul(TextureXf, float4(0,1,0,0)).xyz;
|
|
makeTangentAndBinormal(objNormal, tangentRef, binormalRef,
|
|
objTangent, objBinormal);
|
|
|
|
|
|
}
|
|
|
|
|
|
void ps_shared_lighting(
|
|
float3 DiffuseColor,
|
|
float3 WorldNormal,
|
|
float3 WorldView,
|
|
float3 Light0Vec,
|
|
float3 Light1Vec,
|
|
uniform float3 Lamp0Color,
|
|
uniform float3 Lamp1Color,
|
|
uniform float3 AmbiColor,
|
|
uniform float Ks,
|
|
uniform float SpecExpon,
|
|
out float3 DiffuseContrib,
|
|
out float3 SpecularContrib
|
|
)
|
|
{
|
|
float3 Nn = normalize(WorldNormal);
|
|
float3 Vn = normalize(WorldView);
|
|
float3 Ln0 = normalize(Light0Vec);
|
|
float3 Ln1 = normalize(Light1Vec);
|
|
float3 Hn0 = normalize(Vn + Ln0);
|
|
float hdn0 = dot(Hn0,Nn);
|
|
float ldn0 = dot(Ln0,Nn);
|
|
float ldn1 = dot(Ln1,Nn);
|
|
float4 lit0V = lit(ldn0,hdn0,SpecExpon);
|
|
float lit1Vy = saturate(ldn1); // don't do specular calculations for second light.
|
|
DiffuseContrib = DiffuseColor * ( lit0V.y*Lamp0Color + lit1Vy*Lamp1Color + AmbiColor);
|
|
SpecularContrib = Ks * (lit0V.z * Lamp0Color);
|
|
}
|
|
|
|
|
|
|
|
void ps_shared_lighting_env(
|
|
float3 DiffuseColor,
|
|
float3 WorldNormal,
|
|
float3 WorldView,
|
|
float3 Light0Vec,
|
|
float3 Light1Vec,
|
|
uniform float3 Lamp0Color,
|
|
uniform float3 Lamp1Color,
|
|
uniform float3 AmbiColor,
|
|
uniform float Ks,
|
|
uniform float SpecExpon,
|
|
uniform float Kr,
|
|
out float3 DiffuseContrib,
|
|
out float3 SpecularContrib
|
|
,uniform samplerCUBE EnvSampler
|
|
,out float3 ReflectionContrib
|
|
)
|
|
{
|
|
float3 Nn = normalize(WorldNormal);
|
|
float3 Vn = normalize(WorldView);
|
|
float3 Ln0 = normalize(Light0Vec);
|
|
float3 Ln1 = normalize(Light1Vec);
|
|
float3 Hn0 = normalize(Vn + Ln0);
|
|
float hdn0 = dot(Hn0,Nn);
|
|
float ldn0 = dot(Ln0,Nn);
|
|
float ldn1 = dot(Ln1,Nn);
|
|
float4 lit0V = lit(ldn0,hdn0,SpecExpon);
|
|
float lit1Vy = saturate(ldn1); // don't do specular calculations for second light.
|
|
DiffuseContrib = DiffuseColor * ( lit0V.y*Lamp0Color + lit1Vy*Lamp1Color + AmbiColor);
|
|
SpecularContrib = Ks * (lit0V.z * Lamp0Color);
|
|
|
|
#ifdef ENABLE_REFLECTIONS
|
|
float3 reflVect = -reflect(Vn,Nn);
|
|
ReflectionContrib = saturate(Kr * texCUBE(EnvSampler,reflVect).xyz);
|
|
#endif
|
|
}
|
|
|
|
|
|
void ps_shared_lighting_specularonly(
|
|
float3 WorldNormal,
|
|
float3 WorldView,
|
|
float3 Light0Vec,
|
|
uniform float3 Lamp0Specular,
|
|
uniform float Ks,
|
|
uniform float SpecExpon,
|
|
out float3 SpecularContrib
|
|
)
|
|
{
|
|
float3 Nn = normalize(WorldNormal);
|
|
float3 Vn = normalize(WorldView);
|
|
float3 Ln0 = normalize(Light0Vec);
|
|
float3 Hn0 = normalize(Vn + Ln0);
|
|
float hdn0 = dot(Hn0,Nn);
|
|
float ldn0 = dot(Ln0,Nn);
|
|
float4 lit0V = lit(ldn0,hdn0,SpecExpon);
|
|
SpecularContrib = Ks * (lit0V.z * Lamp0Specular);
|
|
}
|
|
|
|
void ps_shared_lighting_env_specularonly(
|
|
float3 WorldNormal,
|
|
float3 WorldView,
|
|
float3 Light0Vec,
|
|
uniform float3 Lamp0Specular,
|
|
uniform float Ks,
|
|
uniform float SpecExpon,
|
|
uniform float Kr,
|
|
out float3 SpecularContrib
|
|
,uniform samplerCUBE EnvSampler
|
|
,out float3 ReflectionContrib
|
|
)
|
|
{
|
|
float3 Nn = normalize(WorldNormal);
|
|
float3 Vn = normalize(WorldView);
|
|
float3 Ln0 = normalize(Light0Vec);
|
|
float3 Hn0 = normalize(Vn + Ln0);
|
|
float hdn0 = dot(Hn0,Nn);
|
|
float ldn0 = dot(Ln0,Nn);
|
|
float4 lit0V = lit(ldn0,hdn0,SpecExpon);
|
|
SpecularContrib = Ks * (lit0V.z * Lamp0Specular);
|
|
|
|
#ifdef ENABLE_REFLECTIONS
|
|
float3 reflVect = -reflect(Vn,Nn);
|
|
ReflectionContrib = saturate(Kr * texCUBE(EnvSampler,reflVect).xyz);
|
|
#endif
|
|
}
|
|
|
|
void vs_shared_lighting(
|
|
float3 Position,
|
|
float3 Normal,
|
|
float3 Tangent,
|
|
uniform float4x4 WorldITXf, // our four standard "untweakable" xforms
|
|
uniform float4x4 WorldXf,
|
|
uniform float4x4 ViewIXf,
|
|
uniform float4x4 WvpXf,
|
|
uniform float4 Lamp0Pos,
|
|
uniform float4 Lamp1Pos,
|
|
out float3 Light0Vec,
|
|
out float3 Light1Vec,
|
|
out float3 WorldView,
|
|
out float4 HPosition,
|
|
out float3 WorldNormal,
|
|
out float3 WorldTangent,
|
|
out float3 WorldBinormal)
|
|
{
|
|
float4 Po = float4(Position.xyz,1);
|
|
float3 Pw = mul(WorldXf, Po).xyz;
|
|
|
|
Light0Vec = Lamp0Pos.xyz - (Pw * Lamp0Pos.w);
|
|
Light1Vec = Lamp1Pos.xyz - (Pw * Lamp1Pos.w);
|
|
WorldView = (float3(ViewIXf[0].w,ViewIXf[1].w,ViewIXf[2].w) - Pw);
|
|
|
|
HPosition = mul(WvpXf,Po);
|
|
WorldNormal = mul(WorldITXf, float4(Normal,0)).xyz;
|
|
WorldTangent = mul(WorldITXf, float4(Tangent,0)).xyz;
|
|
WorldBinormal = cross(WorldNormal, WorldTangent);
|
|
}
|
|
|
|
void vs_shared_lighting_diffuse(
|
|
float3 Position,
|
|
float3 Normal,
|
|
float3 Tangent,
|
|
float3 DiffuseColor,
|
|
uniform float4x4 WorldITXf, // our four standard "untweakable" xforms
|
|
uniform float4x4 WorldXf,
|
|
uniform float4x4 ViewIXf,
|
|
uniform float4x4 WvpXf,
|
|
uniform float4 Lamp0Pos,
|
|
uniform float4 Lamp1Pos,
|
|
uniform float3 Lamp0Color,
|
|
uniform float3 Lamp1Color,
|
|
uniform float3 Ambient,
|
|
out float3 Light0Vec,
|
|
out float3 LightDiffuseContrib, // includes ambient
|
|
out float3 WorldView,
|
|
out float4 HPosition,
|
|
out float3 WorldNormal,
|
|
out float3 WorldTangent,
|
|
out float3 WorldBinormal)
|
|
{
|
|
float4 Po = float4(Position.xyz,1);
|
|
float3 Pw = mul(WorldXf, Po).xyz;
|
|
|
|
Light0Vec = Lamp0Pos.xyz - (Pw * Lamp0Pos.w);
|
|
float3 Light1Vec = Lamp1Pos.xyz - (Pw * Lamp1Pos.w);
|
|
WorldView = (float3(ViewIXf[0].w,ViewIXf[1].w,ViewIXf[2].w) - Pw);
|
|
|
|
HPosition = mul(WvpXf,Po);
|
|
WorldNormal = mul(WorldITXf, float4(Normal,0)).xyz;
|
|
WorldTangent = mul(WorldITXf, float4(Tangent,0)).xyz;
|
|
WorldBinormal = cross(WorldNormal, WorldTangent);
|
|
|
|
float3 IgnoredSpecular;
|
|
// reuse ps_ lighting comp
|
|
ps_shared_lighting(
|
|
DiffuseColor,
|
|
WorldNormal,
|
|
WorldView,
|
|
Light0Vec,
|
|
Light1Vec,
|
|
Lamp0Color,
|
|
Lamp1Color,
|
|
Ambient,
|
|
0,
|
|
0,
|
|
LightDiffuseContrib,
|
|
IgnoredSpecular
|
|
);
|
|
}
|
|
|
|
|
|
struct BasicVertexInput {
|
|
float3 Position : POSITION;
|
|
float4 Color : COLOR;
|
|
float2 StudsUV : TEXCOORD0;
|
|
float3 Normal : NORMAL;
|
|
float3 Tangent : TANGENT0;
|
|
};
|
|
|
|
/* data passed from vertex shader to pixel shader */
|
|
struct BasicVertexOutput {
|
|
float4 HPosition : POSITION;
|
|
float4 Color : COLOR;
|
|
float2 StudsUV : TEXCOORD0;
|
|
float3 Light0Vec : TEXCOORD2;
|
|
float3 Light1Vec : TEXCOORD3;
|
|
float3 WorldNormal : TEXCOORD4;
|
|
float3 WorldTangent : TEXCOORD5;
|
|
float3 WorldView : TEXCOORD7;
|
|
};
|
|
|
|
/*********** vertex shader ******/
|
|
|
|
BasicVertexOutput basicVS(BasicVertexInput IN,
|
|
uniform float4x4 WorldITXf, // our four standard "untweakable" xforms
|
|
uniform float4x4 WorldXf,
|
|
uniform float4x4 ViewIXf,
|
|
uniform float4x4 WvpXf,
|
|
uniform float4 Lamp0Pos,
|
|
uniform float4 Lamp1Pos)
|
|
{
|
|
BasicVertexOutput OUT = (BasicVertexOutput )0;
|
|
|
|
float3 unusedBinormal;
|
|
vs_shared_lighting(
|
|
IN.Position,
|
|
IN.Normal,
|
|
IN.Tangent,
|
|
WorldITXf, // our four standard "untweakable" xforms
|
|
WorldXf,
|
|
ViewIXf,
|
|
WvpXf,
|
|
Lamp0Pos,
|
|
Lamp1Pos,
|
|
OUT.Light0Vec,
|
|
OUT.Light1Vec,
|
|
OUT.WorldView,
|
|
OUT.HPosition,
|
|
OUT.WorldNormal,
|
|
OUT.WorldTangent,
|
|
unusedBinormal);
|
|
OUT.StudsUV = IN.StudsUV; // passthrough model UVs.
|
|
OUT.Color = IN.Color;
|
|
|
|
return OUT;
|
|
}
|
|
|
|
/********* pixel shader ********/
|
|
float4 basicPSStuds(BasicVertexOutput IN, uniform float Ks, uniform float SpecExpon,
|
|
uniform float3 Lamp0Color, uniform float3 Lamp1Color, uniform float3 AmbiColor,
|
|
uniform sampler2D StudsSamp) : COLOR
|
|
{
|
|
float4 studShade = tex2D(StudsSamp, IN.StudsUV.xy);
|
|
|
|
float3 diffContrib;
|
|
float3 specContrib;
|
|
|
|
ps_shared_lighting(IN.Color.xyz, IN.WorldNormal, IN.WorldView, IN.Light0Vec, IN.Light1Vec,
|
|
Lamp0Color, Lamp1Color, AmbiColor, Ks, SpecExpon, diffContrib, specContrib);
|
|
|
|
float3 result = lerp(diffContrib, studShade.xyz, studShade.w) + specContrib;
|
|
return float4(result,1);
|
|
}
|
|
|
|
|
|
/************* DATA STRUCTS **************/
|
|
|
|
/* data from application vertex buffer */
|
|
struct appdataTangent {
|
|
float3 Position : POSITION;
|
|
float4 Color : COLOR;
|
|
float2 StudsUV : TEXCOORD0;
|
|
float4 TexPos3D : TEXCOORD1; // w: secondary color (for rust)
|
|
float2 SurfaceUV: TEXCOORD2;
|
|
float3 Normal : NORMAL;
|
|
float3 Tangent : TANGENT0;
|
|
};
|
|
|
|
struct appdataBump {
|
|
float3 Position : POSITION;
|
|
float4 Color : COLOR;
|
|
float2 StudsUV : TEXCOORD0;
|
|
float2 SurfaceUV: TEXCOORD1;
|
|
float3 Normal : NORMAL;
|
|
float3 Tangent : TANGENT0;
|
|
};
|
|
|
|
/* data passed from vertex shader to pixel shader */
|
|
struct VertexOutput {
|
|
float4 HPosition : POSITION;
|
|
float4 Color : COLOR;
|
|
float4 ModelUV : TEXCOORD0;
|
|
float4 TexPos3D : TEXCOORD1; // grain coordinate system
|
|
// coord w is attenuation 0 = no normal map, 1 = full normal map
|
|
float3 Light0Vec : TEXCOORD2;
|
|
float3 Light1Vec : TEXCOORD3;
|
|
float3 WorldNormal : TEXCOORD4;
|
|
float3 WorldTangent : TEXCOORD5;
|
|
float3 WorldView : TEXCOORD7;
|
|
float4 ObjectNormal : TEXCOORD6;
|
|
};
|
|
|
|
struct BumpVertexOutput {
|
|
float4 HPosition : POSITION;
|
|
float4 Color : COLOR;
|
|
float4 ModelUV : TEXCOORD0;
|
|
float3 Light0Vec : TEXCOORD2;
|
|
float3 Light1Vec : TEXCOORD3;
|
|
float3 WorldNormal : TEXCOORD4;
|
|
float3 WorldTangent : TEXCOORD5;
|
|
float3 WorldView : TEXCOORD7;
|
|
float4 ObjectNormal : TEXCOORD6;// coord w is attenuation 0 = no normal map, 1 = full normal map
|
|
};
|
|
|
|
/*********** vertex shader ******/
|
|
|
|
BumpVertexOutput BumpVS(appdataBump IN,
|
|
uniform float4x4 WorldITXf, // our four standard "untweakable" xforms
|
|
uniform float4x4 WorldXf,
|
|
uniform float4x4 ViewIXf,
|
|
uniform float4x4 WvpXf,
|
|
uniform float4 Lamp0Pos,
|
|
uniform float4 Lamp1Pos,
|
|
uniform float NormMapScale,
|
|
uniform float FadeDistance)
|
|
{
|
|
BumpVertexOutput OUT = (BumpVertexOutput)0;
|
|
|
|
float3 unusedBinormal;
|
|
vs_shared_lighting(
|
|
IN.Position,
|
|
IN.Normal,
|
|
IN.Tangent,
|
|
WorldITXf, // our four standard "untweakable" xforms
|
|
WorldXf,
|
|
ViewIXf,
|
|
WvpXf,
|
|
Lamp0Pos,
|
|
Lamp1Pos,
|
|
OUT.Light0Vec,
|
|
OUT.Light1Vec,
|
|
OUT.WorldView,
|
|
OUT.HPosition,
|
|
OUT.WorldNormal,
|
|
OUT.WorldTangent,
|
|
unusedBinormal);
|
|
|
|
OUT.ModelUV = float4(IN.StudsUV, IN.SurfaceUV* NormMapScale); // passthrough model UVs.
|
|
OUT.Color = IN.Color; //Average color of the grass texture
|
|
OUT.ObjectNormal = float4(IN.Normal,1);
|
|
OUT.ObjectNormal.w = mul(WvpXf,float4(IN.Position,1)).z/FadeDistance;
|
|
OUT.ObjectNormal.xyz = normalize(OUT.ObjectNormal.xyz); // dplate only uses w component. stuff it elsewhere, and get rid of this?
|
|
return OUT;
|
|
}
|
|
|
|
VertexOutput NoiseVS(appdataTangent IN,
|
|
uniform float4x4 WorldITXf, // our four standard "untweakable" xforms
|
|
uniform float4x4 WorldXf,
|
|
uniform float4x4 ViewIXf,
|
|
uniform float4x4 WvpXf,
|
|
uniform float4 Lamp0Pos,
|
|
uniform float4 Lamp1Pos,
|
|
uniform float NormMapScale,
|
|
uniform float Transform3DNoiseCoordinates,
|
|
uniform float FadeDistance)
|
|
{
|
|
VertexOutput OUT = (VertexOutput)0;
|
|
|
|
float3 unusedBinormal;
|
|
vs_shared_lighting(
|
|
IN.Position,
|
|
IN.Normal,
|
|
IN.Tangent,
|
|
WorldITXf, // our four standard "untweakable" xforms
|
|
WorldXf,
|
|
ViewIXf,
|
|
WvpXf,
|
|
Lamp0Pos,
|
|
Lamp1Pos,
|
|
OUT.Light0Vec,
|
|
OUT.Light1Vec,
|
|
OUT.WorldView,
|
|
OUT.HPosition,
|
|
OUT.WorldNormal,
|
|
OUT.WorldTangent,
|
|
unusedBinormal);
|
|
|
|
|
|
// This shader uses the object coordinates to determine the grass-grain
|
|
// coordinate system at shader runtime. Alternatively, you could bake
|
|
// the coordinate system into the model as an alternative texcoord. The
|
|
// current method applies to all possible models, while baking-in lets
|
|
// you try different tricks such as modeling the grain of bent ,
|
|
// say for a bow or for the hull timbers of a ship.
|
|
//
|
|
if(Transform3DNoiseCoordinates)
|
|
{
|
|
float cfactor = 0.980066578; //cos(0.2);
|
|
float sfactor = 0.198669331; //sin(0.2);
|
|
float cfactor2 = 0.955336489; //cos(0.3);
|
|
float sfactor2 = 0.295520207; //sin(0.3);
|
|
float cfactor3 = 0.921060994; //cos(0.4);
|
|
float sfactor3 = 0.389418342; //sin(0.4);
|
|
float3 p = IN.TexPos3D.xyz;
|
|
float3 shiftPos = p;
|
|
|
|
shiftPos.x += p.x * cfactor + p.z * sfactor;
|
|
shiftPos.z += p.x * -sfactor + p.z * cfactor;
|
|
|
|
shiftPos.x += p.x * cfactor2 - p.y * sfactor2;
|
|
shiftPos.y += p.x * sfactor2 + p.y * cfactor2;
|
|
|
|
shiftPos.y += p.y * cfactor3 - p.z * sfactor3;
|
|
shiftPos.z += p.y * sfactor3 + p.z * cfactor3;
|
|
|
|
OUT.TexPos3D = float4(shiftPos,IN.TexPos3D.w);
|
|
}
|
|
else
|
|
OUT.TexPos3D = IN.TexPos3D;
|
|
|
|
OUT.ModelUV = float4(IN.StudsUV, IN.SurfaceUV* NormMapScale); // passthrough model UVs.
|
|
OUT.Color = IN.Color; //Average color of the grass texture
|
|
OUT.ObjectNormal = float4(IN.Normal,1);
|
|
OUT.ObjectNormal.w = mul(WvpXf,float4(IN.Position,1)).z/FadeDistance;
|
|
OUT.ObjectNormal.xyz = normalize(OUT.ObjectNormal.xyz);
|
|
return OUT;
|
|
}
|