| 1 | // General functions | 
|---|
| 2 |  | 
|---|
| 3 | // Expand a range-compressed vector | 
|---|
| 4 | float3 expand(float3 v) | 
|---|
| 5 | { | 
|---|
| 6 |         return (v - 0.5) * 2; | 
|---|
| 7 | } | 
|---|
| 8 |  | 
|---|
| 9 |  | 
|---|
| 10 | /* Bump mapping vertex program | 
|---|
| 11 |    In this program, we want to calculate the tangent space light vector | 
|---|
| 12 |    on a per-vertex level which will get passed to the fragment program, | 
|---|
| 13 |    or to the fixed function dot3 operation, to produce the per-pixel | 
|---|
| 14 |    lighting effect. | 
|---|
| 15 | */ | 
|---|
| 16 | void main_vp(float4 position    : POSITION, | 
|---|
| 17 |                          float3 normal          : NORMAL, | 
|---|
| 18 |                          float2 uv                      : TEXCOORD0, | 
|---|
| 19 |                          float3 tangent     : TANGENT0, | 
|---|
| 20 |                          // outputs | 
|---|
| 21 |                          out float4 oPosition    : POSITION, | 
|---|
| 22 |                          out float2 oUv                  : TEXCOORD0, | 
|---|
| 23 |                          out float3 oTSLightDir  : TEXCOORD1, | 
|---|
| 24 |                          // parameters | 
|---|
| 25 |                          uniform float4 lightPosition, // object space | 
|---|
| 26 |                          uniform float4x4 worldViewProj) | 
|---|
| 27 | { | 
|---|
| 28 |         // calculate output position | 
|---|
| 29 |         oPosition = mul(worldViewProj, position); | 
|---|
| 30 |  | 
|---|
| 31 |         // pass the main uvs straight through unchanged | 
|---|
| 32 |         oUv = uv; | 
|---|
| 33 |  | 
|---|
| 34 |         // calculate tangent space light vector | 
|---|
| 35 |         // Get object space light direction | 
|---|
| 36 |         // Non-normalised since we'll do that in the fragment program anyway | 
|---|
| 37 |         float3 lightDir = lightPosition.xyz -  (position * lightPosition.w); | 
|---|
| 38 |  | 
|---|
| 39 |         // Calculate the binormal (NB we assume both normal and tangent are | 
|---|
| 40 |         // already normalised) | 
|---|
| 41 |         // NB looks like nvidia cross params are BACKWARDS to what you'd expect | 
|---|
| 42 |         // this equates to NxT, not TxN | 
|---|
| 43 |         float3 binormal = cross(tangent, normal); | 
|---|
| 44 |  | 
|---|
| 45 |         // Form a rotation matrix out of the vectors | 
|---|
| 46 |         float3x3 rotation = float3x3(tangent, binormal, normal); | 
|---|
| 47 |  | 
|---|
| 48 |         // Transform the light vector according to this matrix | 
|---|
| 49 |         oTSLightDir = mul(rotation, lightDir); | 
|---|
| 50 |  | 
|---|
| 51 |  | 
|---|
| 52 | } | 
|---|
| 53 |  | 
|---|
| 54 | void main_fp( float2 uv                 : TEXCOORD0, | 
|---|
| 55 |                           float3 TSlightDir : TEXCOORD1, | 
|---|
| 56 |  | 
|---|
| 57 |                           out float4 colour     : COLOR, | 
|---|
| 58 |  | 
|---|
| 59 |                           uniform float4 lightDiffuse, | 
|---|
| 60 |                           uniform sampler2D   normalMap : register(s0), | 
|---|
| 61 |                           uniform samplerCUBE normalCubeMap : register(s1) ) | 
|---|
| 62 | { | 
|---|
| 63 |         // retrieve normalised light vector, expand from range-compressed | 
|---|
| 64 |         float3 lightVec = expand(texCUBE(normalCubeMap, TSlightDir).xyz); | 
|---|
| 65 |  | 
|---|
| 66 |         // get bump map vector, again expand from range-compressed | 
|---|
| 67 |         float3 bumpVec = expand(tex2D(normalMap, uv).xyz); | 
|---|
| 68 |  | 
|---|
| 69 |         // Calculate dot product | 
|---|
| 70 |         colour = lightDiffuse * dot(bumpVec, lightVec); | 
|---|
| 71 |  | 
|---|
| 72 | } | 
|---|
| 73 |  | 
|---|
| 74 | /* Vertex program which includes specular component */ | 
|---|
| 75 | void specular_vp(float4 position        : POSITION, | 
|---|
| 76 |                                  float3 normal          : NORMAL, | 
|---|
| 77 |                                  float2 uv                      : TEXCOORD0, | 
|---|
| 78 |                                  float3 tangent     : TANGENT0, | 
|---|
| 79 |                                  // outputs | 
|---|
| 80 |                                  out float4 oPosition    : POSITION, | 
|---|
| 81 |                                  out float2 oUv                  : TEXCOORD0, | 
|---|
| 82 |                                  out float3 oTSLightDir  : TEXCOORD1, | 
|---|
| 83 |                                  out float3 oTSHalfAngle : TEXCOORD2, | 
|---|
| 84 |                                  // parameters | 
|---|
| 85 |                                  uniform float4 lightPosition, // object space | 
|---|
| 86 |                                  uniform float3 eyePosition,   // object space | 
|---|
| 87 |                                  uniform float4x4 worldViewProj) | 
|---|
| 88 | { | 
|---|
| 89 |         // calculate output position | 
|---|
| 90 |         oPosition = mul(worldViewProj, position); | 
|---|
| 91 |  | 
|---|
| 92 |         // pass the main uvs straight through unchanged | 
|---|
| 93 |         oUv = uv; | 
|---|
| 94 |  | 
|---|
| 95 |         // calculate tangent space light vector | 
|---|
| 96 |         // Get object space light direction | 
|---|
| 97 |         float3 lightDir = normalize(lightPosition.xyz -  (position * lightPosition.w)); | 
|---|
| 98 |  | 
|---|
| 99 |         // Calculate the binormal (NB we assume both normal and tangent are | 
|---|
| 100 |         // already normalised) | 
|---|
| 101 |         // NB looks like nvidia cross params are BACKWARDS to what you'd expect | 
|---|
| 102 |         // this equates to NxT, not TxN | 
|---|
| 103 |         float3 binormal = cross(tangent, normal); | 
|---|
| 104 |  | 
|---|
| 105 |         // Form a rotation matrix out of the vectors | 
|---|
| 106 |         float3x3 rotation = float3x3(tangent, binormal, normal); | 
|---|
| 107 |  | 
|---|
| 108 |         // Transform the light vector according to this matrix | 
|---|
| 109 |         oTSLightDir = mul(rotation, lightDir); | 
|---|
| 110 |  | 
|---|
| 111 |         // Calculate half-angle in tangent space | 
|---|
| 112 |         float3 eyeDir = normalize(eyePosition - position.xyz); | 
|---|
| 113 |         float3 halfAngle = normalize(eyeDir + lightDir); | 
|---|
| 114 |         oTSHalfAngle = mul(rotation, halfAngle); | 
|---|
| 115 |  | 
|---|
| 116 |  | 
|---|
| 117 | } | 
|---|
| 118 |  | 
|---|
| 119 | /* Fragment program which supports specular component */ | 
|---|
| 120 | void specular_fp( float2 uv                     : TEXCOORD0, | 
|---|
| 121 |                           float3 TSlightDir : TEXCOORD1, | 
|---|
| 122 |                           float3 TShalfAngle: TEXCOORD2, | 
|---|
| 123 |  | 
|---|
| 124 |                           out float4 colour     : COLOR, | 
|---|
| 125 |  | 
|---|
| 126 |                           uniform float4 lightDiffuse, | 
|---|
| 127 |                           uniform float4 lightSpecular, | 
|---|
| 128 |                           uniform float shine, | 
|---|
| 129 |                           uniform sampler2D   normalMap : register(s0), | 
|---|
| 130 |                           uniform samplerCUBE normalCubeMap : register(s1), | 
|---|
| 131 |                           uniform samplerCUBE normalCubeMap2 : register(s2)) // we need this second binding to be compatible with ps_1_1, ps_2_0 could reuse the other | 
|---|
| 132 | { | 
|---|
| 133 |         // retrieve normalised light vector, expand from range-compressed | 
|---|
| 134 |         float3 lightVec = expand(texCUBE(normalCubeMap, TSlightDir).xyz); | 
|---|
| 135 |  | 
|---|
| 136 |         // retrieve half angle and normalise through cube map | 
|---|
| 137 |         float3 halfAngle = expand(texCUBE(normalCubeMap2, TShalfAngle).xyz); | 
|---|
| 138 |  | 
|---|
| 139 |         // get bump map vector, again expand from range-compressed | 
|---|
| 140 |         float3 bumpVec = expand(tex2D(normalMap, uv).xyz); | 
|---|
| 141 |  | 
|---|
| 142 |  | 
|---|
| 143 |         float specFactor = pow(dot(bumpVec, halfAngle),shine); | 
|---|
| 144 |  | 
|---|
| 145 |  | 
|---|
| 146 |  | 
|---|
| 147 |         // Calculate dot product for diffuse | 
|---|
| 148 |         colour = (lightDiffuse * saturate(dot(bumpVec, lightVec))) + | 
|---|
| 149 |                         (lightSpecular * specFactor); | 
|---|
| 150 |  | 
|---|
| 151 | } | 
|---|
| 152 |  | 
|---|