98 lines
3.2 KiB
Plaintext
98 lines
3.2 KiB
Plaintext
/* Bump mapping with Parallax offset vertex program
|
|
In this program, we want to calculate the tangent space light end eye vectors
|
|
which will get passed to the fragment program to produce the per-pixel bump map
|
|
with parallax offset effect.
|
|
*/
|
|
|
|
/* Vertex program that moves light and eye vectors into texture tangent space at vertex */
|
|
|
|
void main_vp(float4 position : POSITION,
|
|
float3 normal : NORMAL,
|
|
float2 uv : TEXCOORD0,
|
|
float3 tangent : TANGENT0,
|
|
// outputs
|
|
out float4 oPosition : POSITION,
|
|
out float2 oUv : TEXCOORD0,
|
|
out float3 oLightDir : TEXCOORD1, // tangent space
|
|
out float3 oEyeDir : TEXCOORD2, // tangent space
|
|
out float3 oHalfAngle : TEXCOORD3, //
|
|
// parameters
|
|
uniform float4 lightPosition, // object space
|
|
uniform float3 eyePosition, // object space
|
|
uniform float4x4 worldViewProj)
|
|
{
|
|
// calculate output position
|
|
oPosition = mul(worldViewProj, position);
|
|
|
|
// pass the main uvs straight through unchanged
|
|
oUv = uv;
|
|
|
|
// calculate tangent space light vector
|
|
// Get object space light direction
|
|
float3 lightDir = normalize(lightPosition.xyz - (position * lightPosition.w));
|
|
float3 eyeDir = eyePosition - position.xyz;
|
|
|
|
// Calculate the binormal (NB we assume both normal and tangent are
|
|
// already normalised)
|
|
// NB looks like nvidia cross params are BACKWARDS to what you'd expect
|
|
// this equates to NxT, not TxN
|
|
float3 binormal = cross(tangent, normal);
|
|
|
|
// Form a rotation matrix out of the vectors
|
|
float3x3 rotation = float3x3(tangent, binormal, normal);
|
|
|
|
// Transform the light vector according to this matrix
|
|
lightDir = normalize(mul(rotation, lightDir));
|
|
eyeDir = normalize(mul(rotation, eyeDir));
|
|
|
|
oLightDir = lightDir;
|
|
oEyeDir = eyeDir;
|
|
oHalfAngle = normalize(eyeDir + lightDir);
|
|
}
|
|
|
|
// General functions
|
|
|
|
// Expand a range-compressed vector
|
|
float3 expand(float3 v)
|
|
{
|
|
return (v - 0.5) * 2;
|
|
}
|
|
|
|
void main_fp(float2 uv : TEXCOORD0,
|
|
float3 lightDir : TEXCOORD1,
|
|
float3 eyeDir : TEXCOORD2,
|
|
float3 halfAngle : TEXCOORD3,
|
|
uniform float3 lightDiffuse,
|
|
uniform float3 lightSpecular,
|
|
uniform float4 scaleBias,
|
|
uniform sampler2D normalHeightMap,
|
|
uniform sampler2D diffuseMap,
|
|
out float4 oColor : COLOR)
|
|
{
|
|
// get the height using the tex coords
|
|
float height = tex2D(normalHeightMap, uv).a;
|
|
|
|
// scale and bias factors
|
|
float scale = scaleBias.x;
|
|
float bias = scaleBias.y;
|
|
|
|
// calculate displacement
|
|
float displacement = (height * scale) + bias;
|
|
|
|
float3 uv2 = float3(uv, 1);
|
|
|
|
// calculate the new tex coord to use for normal and diffuse
|
|
float2 newTexCoord = ((eyeDir * displacement) + uv2).xy;
|
|
|
|
// get the new normal and diffuse values
|
|
float3 normal = expand(tex2D(normalHeightMap, newTexCoord).xyz);
|
|
float3 diffuse = tex2D(diffuseMap, newTexCoord).xyz;
|
|
|
|
float3 specular = pow(saturate(dot(normal, halfAngle)), 32) * lightSpecular;
|
|
float3 col = diffuse * saturate(dot(normal, lightDir)) * lightDiffuse + specular;
|
|
|
|
oColor = float4(col, 1);
|
|
}
|
|
|
|
|