Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/tutorial/Tutorial/Media/materials/programs/Example_BumpMapping.cg @ 25

Last change on this file since 25 was 25, checked in by nicolasc, 17 years ago

added Media and Config

File size: 7.3 KB
Line 
1// General functions
2
3// Expand a range-compressed vector
4float3 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*/
16void 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/* Bump mapping vertex program for shadow receiving
55   In this program, we want to calculate the tangent space light vector
56   on a per-vertex level which will get passed to the fragment program,
57   or to the fixed function dot3 operation, to produce the per-pixel
58   lighting effect.
59*/
60void main_shadowreceiver_vp(float4 position     : POSITION,
61                         float3 normal          : NORMAL,
62                         float2 uv                      : TEXCOORD0,
63                         float3 tangent     : TANGENT0,
64                         
65                         // outputs
66                         out float4 oPosition    : POSITION,
67                         out float4 uvproj               : TEXCOORD0,
68                         out float2 oUv                  : TEXCOORD1,
69                         out float3 oTSLightDir  : TEXCOORD2,
70                         
71                         // parameters
72                         uniform float4 lightPosition, // object space
73                         uniform float4x4 worldViewProj,
74                         uniform float4x4 worldMatrix,
75                         uniform float4x4 texViewProj)
76{
77        // calculate output position
78        oPosition = mul(worldViewProj, position);
79
80        // pass the main uvs straight through unchanged
81        oUv = uv;
82
83        // calculate tangent space light vector
84        // Get object space light direction
85        // Non-normalised since we'll do that in the fragment program anyway
86        float3 lightDir = lightPosition.xyz -  (position * lightPosition.w);
87
88        // Calculate the binormal (NB we assume both normal and tangent are
89        // already normalised)
90        // NB looks like nvidia cross params are BACKWARDS to what you'd expect
91        // this equates to NxT, not TxN
92        float3 binormal = cross(tangent, normal);
93       
94        // Form a rotation matrix out of the vectors
95        float3x3 rotation = float3x3(tangent, binormal, normal);
96       
97        // Transform the light vector according to this matrix
98        oTSLightDir = mul(rotation, lightDir);
99
100        // Projection
101    uvproj = mul(worldMatrix, position);
102        uvproj = mul(texViewProj, uvproj);
103       
104}
105
106
107void main_fp( float2 uv                 : TEXCOORD0,
108                          float3 TSlightDir : TEXCOORD1,
109
110                          out float4 colour     : COLOR,
111
112                          uniform float4 lightDiffuse,
113                          uniform sampler2D   normalMap : register(s0),
114                          uniform samplerCUBE normalCubeMap : register(s1) )
115{
116        // retrieve normalised light vector, expand from range-compressed
117        float3 lightVec = expand(texCUBE(normalCubeMap, TSlightDir).xyz);
118
119        // get bump map vector, again expand from range-compressed
120        float3 bumpVec = expand(tex2D(normalMap, uv).xyz);
121
122        // Calculate dot product
123        colour = lightDiffuse * dot(bumpVec, lightVec);
124       
125}
126
127void main_shadowreceiver_fp(
128                          float4 uvproj         : TEXCOORD0,
129                          float2 uv                     : TEXCOORD1,
130                          float3 TSlightDir : TEXCOORD2,
131
132                          out float4 colour     : COLOR,
133
134                          uniform float4 lightDiffuse,
135                          uniform sampler2D   shadowMap : register(s0),
136                          uniform sampler2D   normalMap : register(s1),
137                          uniform samplerCUBE normalCubeMap : register(s2))
138{
139
140
141        // retrieve normalised light vector, expand from range-compressed
142        float3 lightVec = expand(texCUBE(normalCubeMap, TSlightDir).xyz);
143
144        // get bump map vector, again expand from range-compressed
145        float3 bumpVec = expand(tex2D(normalMap, uv).xyz);
146
147        // get shadow value
148        float3 shadow = tex2Dproj(shadowMap, uvproj).xyz;
149
150        // Calculate dot product
151        colour = float4(shadow * lightDiffuse * dot(bumpVec, lightVec), 1.0f);
152       
153}
154
155/* Vertex program which includes specular component */
156void specular_vp(float4 position        : POSITION,
157                                 float3 normal          : NORMAL,
158                                 float2 uv                      : TEXCOORD0,
159                                 float3 tangent     : TANGENT0,
160                                 // outputs
161                                 out float4 oPosition    : POSITION,
162                                 out float2 oUv                  : TEXCOORD0,
163                                 out float3 oTSLightDir  : TEXCOORD1,
164                                 out float3 oTSHalfAngle : TEXCOORD2,
165                                 // parameters
166                                 uniform float4 lightPosition, // object space
167                                 uniform float3 eyePosition,   // object space
168                                 uniform float4x4 worldViewProj)
169{
170        // calculate output position
171        oPosition = mul(worldViewProj, position);
172
173        // pass the main uvs straight through unchanged
174        oUv = uv;
175
176        // calculate tangent space light vector
177        // Get object space light direction
178        float3 lightDir = normalize(lightPosition.xyz -  (position * lightPosition.w));
179
180        // Calculate the binormal (NB we assume both normal and tangent are
181        // already normalised)
182        // NB looks like nvidia cross params are BACKWARDS to what you'd expect
183        // this equates to NxT, not TxN
184        float3 binormal = cross(tangent, normal);
185       
186        // Form a rotation matrix out of the vectors
187        float3x3 rotation = float3x3(tangent, binormal, normal);
188       
189        // Transform the light vector according to this matrix
190        oTSLightDir = mul(rotation, lightDir);
191
192        // Calculate half-angle in tangent space
193        float3 eyeDir = normalize(eyePosition - position.xyz);
194        float3 halfAngle = normalize(eyeDir + lightDir);
195        oTSHalfAngle = mul(rotation, halfAngle);
196       
197       
198}
199
200/* Fragment program which supports specular component */
201void specular_fp( float2 uv                     : TEXCOORD0,
202                          float3 TSlightDir : TEXCOORD1,
203                          float3 TShalfAngle: TEXCOORD2,
204
205                          out float4 colour     : COLOR,
206
207                          uniform float4 lightDiffuse,
208                          uniform float4 lightSpecular,
209                          uniform sampler2D   normalMap : register(s0),
210                          uniform samplerCUBE normalCubeMap : register(s1),
211                          uniform samplerCUBE normalCubeMap2 : register(s2)) // we need this second binding to be compatible with ps_1_1, ps_2_0 could reuse the other
212{
213        // retrieve normalised light vector, expand from range-compressed
214        float3 lightVec = expand(texCUBE(normalCubeMap, TSlightDir).xyz);
215
216        // retrieve half angle and normalise through cube map
217        float3 halfAngle = expand(texCUBE(normalCubeMap2, TShalfAngle).xyz);
218
219        // get bump map vector, again expand from range-compressed
220        float3 bumpVec = expand(tex2D(normalMap, uv).xyz);
221
222        // Pre-raise the specular exponent to the eight power
223        // Note we have no 'pow' function in basic fragment programs, if we were willing to accept compatibility
224        // with ps_2_0 / arbfp1 and above, we could have a variable shininess parameter
225        // This is equivalent to
226        float specFactor = dot(bumpVec, halfAngle);
227        for (int i = 0; i < 3; ++i)
228                specFactor *= specFactor;
229       
230
231        // Calculate dot product for diffuse
232        colour = (lightDiffuse * saturate(dot(bumpVec, lightVec))) +
233                        (lightSpecular * specFactor);
234       
235}
236                         
Note: See TracBrowser for help on using the repository browser.