第一个texture unit 里是凹凸贴图,第二个texutre unit里是漫反射贴图
vertex shader和pixex shader如下:
offsetmapping.program:
- // Bump map with Parallax offset vertex program, support for this is required
- vertex_program my/OffsetMappingVP cg
- {
- source OffsetMapping.cg
- default_params
- {
- param_named scale float 1.0
- param_named_auto lightPosition light_position_object_space 0
- param_named_auto eyePosition camera_position_object_space
- param_named_auto worldViewProj worldviewproj_matrix
- }
- entry_point main_vp
- profiles vs_1_1 arbvp1
- }
- // Bump map with parallax fragment program
- fragment_program my/OffsetMappingFP cg
- {
- source OffsetMapping.cg
- default_params
- {
- param_named_auto lightDiffuse light_diffuse_colour 0
- param_named_auto lightSpecular light_specular_colour 0
- // Parallax Height scale and bias
- param_named scaleBias float4 0.04 -0.02 1 0
- }
- entry_point main_fp
- profiles ps_2_0 arbfp1
- }
OffsetMapping.cg:
- /* 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.
- */
- struct outPixel
- {
- float4 colour : COLOR0;
- };
- // General functions
- // Expand a range-compressed vector
- half4 expand(half4 v)
- {
- return v * 2 - 1;
- }
- half3 expand(half3 v)
- {
- return v * 2 - 1;
- }
- half2 expand(half2 v)
- {
- return v * 2 - 1;
- }
- half1 expand(half1 v)
- {
- return v * 2 - 1;
- }
- // Returns light direction from light position and vertex position
- half3 getLightDirection(float4 lightPosition, float4 position)
- {
- // calculate tangent space light vector
- // Get object space light direction
- // Non-normalised since we'll do that in the fragment program anyway
- return lightPosition.xyz - (position.xyz * lightPosition.w);
- }
- // Returns eye direction from eye position and vertex position
- half3 getEyeDirection(float3 eyePosition, float4 position)
- {
- return eyePosition - position.xyz;
- }
- // Returns a Tangent Binormal Normal matrix
- half3x3 getTBNMatrix(float3 tangent, float3 normal)
- {
- // 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
- return half3x3(tangent, binormal, normal);
- }
- // Returns expanded normal vector from texture map
- half3 getNormalMapVector(sampler2D normalMap, float2 uv)
- {
- // get bump map vector, again expand from range-compressed
- return expand(tex2D(normalMap, uv).xyz);
- }
- // Returns displacement vector from normalmaps alpha channel
- half getDisplacement(sampler2D normalMap, float2 uv, half scale, half bias)
- {
- // get the height using the tex coords
- half height = tex2D(normalMap, uv).a;
- // calculate displacement
- return (height * scale) + bias;
- }
- // Returns a specular component from normal vector, specular colour and specular power
- half3 getSpecularComponent(float3 normal, float3 halfAngle, float3 specularcolour, float specularPower)
- {
- return pow(saturate(dot(normal, halfAngle)), specularPower) * specularcolour;
- }
- // Returns a per-pixel lighted component from normal vector, lightdir and colour
- half3 getLightingComponent(float3 normal, float3 lightDir, float3 colour)
- {
- return saturate(dot(normal, lightDir)) * colour;
- }
- float4 lightPosition;
- float3 eyePosition;
- float4x4 worldViewProj;
- float3 lightDiffuse;
- float3 lightSpecular;
- float4 scaleBias;
- sampler2D normalHeightMap;
- sampler2D diffuseMap;
- struct app2vertOffsetMapping
- {
- float4 position : POSITION;
- float3 normal : NORMAL;
- float2 uv : TEXCOORD0;
- float3 tangent : TANGENT0;
- };
- struct vert2fragOffsetMapping
- {
- float4 position : POSITION;
- float2 uv : TEXCOORD0;
- float3 lightDir : TEXCOORD1;
- float3 eyeDir : TEXCOORD2;
- float3 halfAngle : TEXCOORD3;
- };
- /* Vertex program that moves light and eye vectors into texture tangent space at vertex */
- vert2fragOffsetMapping main_vp(uniform float scale,app2vertOffsetMapping IN)
- {
- vert2fragOffsetMapping OUT;
- // calculate output position
- OUT.position = mul(worldViewProj, IN.position);
- // pass the main uvs straight through unchanged
- OUT.uv = IN.uv*scale;
- half3 lightDir = getLightDirection(lightPosition, IN.position);
- half3 eyeDir = getEyeDirection(eyePosition, IN.position);
- // Form a rotation matrix out of the vectors
- half3x3 TBN = getTBNMatrix(IN.tangent, IN.normal);
- // Transform the light vector according to this matrix
- OUT.lightDir = normalize(mul(TBN, lightDir));
- OUT.eyeDir = normalize(mul(TBN, eyeDir));
- OUT.halfAngle = normalize(OUT.eyeDir + OUT.lightDir);
- return OUT;
- }
- outPixel main_fp(vert2fragOffsetMapping IN)
- {
- outPixel OUT;
- half displacement = getDisplacement(normalHeightMap, IN.uv, scaleBias.x, scaleBias.y);
- float3 uv2 = float3(IN.uv, 1);
- // calculate the new tex coord to use for normal and diffuse
- float2 newTexCoord = ((IN.eyeDir * displacement) + uv2).xy;
- // get the new normal and diffuse values
- half3 normal = getNormalMapVector(normalHeightMap, newTexCoord);
- half3 diffuse = tex2D(diffuseMap, newTexCoord).xyz;
- half3 specular = getSpecularComponent(normal, IN.halfAngle, lightSpecular, 32);
- half3 col = diffuse * getLightingComponent(normal, IN.lightDir, lightDiffuse) + specular;
- OUT.colour = float4(col, 1);
- return OUT;
- }