source: GTP/trunk/App/Demos/Illum/MultipleReflections/Media/Shaders/MultipleReflection.fx @ 2242

Revision 2242, 7.8 KB checked in by szirmay, 18 years ago (diff)
Line 
1float4x4 World;                                 ///< World matrix for the current object
2float4x4 WorldIT;                               ///< World matrix IT (inverse transposed) to transform surface normals of the current object
3float4x4 WorldView;
4float4x4 WorldViewIT;
5float4x4 WorldViewProj;
6float3 referencePos;
7float3 eyePos;
8float3 F0; // Freshnel factor
9float N0; // Refraction coefficient
10
11int MAX_LIN_ITERATIONCOUNT;
12int MIN_LIN_ITERATIONCOUNT;
13int SECANT_ITERATIONCOUNT;
14int MAX_RAY_DEPTH;
15
16texture envCube1;
17sampler envCubeSampler1 = sampler_state
18{
19    MinFilter = POINT;
20    MagFilter = POINT;
21    MipFilter = POINT;   
22    Texture   = <envCube1>;
23    AddressU  = WRAP;
24    AddressV  = WRAP;
25};
26
27texture envCube2;
28sampler envCubeSampler2 = sampler_state
29{
30    MinFilter = POINT;
31    MagFilter = POINT;
32    MipFilter = POINT;   
33    Texture   = <envCube2>;
34    AddressU  = WRAP;
35    AddressV  = WRAP;
36};
37
38texture envCube3;
39sampler envCubeSampler3 = sampler_state
40{
41    MinFilter = LINEAR;
42    MagFilter = LINEAR;
43    MipFilter = POINT;   
44    Texture   = <envCube3>;
45    AddressU  = WRAP;
46    AddressV  = WRAP;
47};
48
49void linearSearch(  float3 x, float3 R, samplerCUBE mp,
50                    out float3 p,
51                    out float dl,
52                    out float dp,
53                    out float llp,
54                    out float ppp)
55{       
56 p = 1;
57       
58        float3 Ra = abs(R), xa = abs(x);
59        float  a = max(max(xa.x, xa.y), xa.z) / max(max(Ra.x, Ra.y), Ra.z);
60        bool   undershoot = false, overshoot = false;   
61       
62        float dt =  length(x / max(max(xa.x, xa.y), xa.z) - R / max(max(Ra.x, Ra.y), Ra.z)) * MAX_LIN_ITERATIONCOUNT;
63    dt = max(dt, MIN_LIN_ITERATIONCOUNT);
64    dt = 1.0 / dt;
65 
66        float t = 0.01;
67        while( t < 1 && !(overshoot && undershoot) ) {  // iteration
68                float dr = a * t / (1 - t);     // ray parameter corresponding to t
69                float3 r = x + R * dr;          // point on the ray
70                float ra =  texCUBElod(mp, float4(r, 0)).a;     // |p'|: distance direction of p
71               
72               
73                if (ra > 0) {           // valid texel, i.e. anything is visible
74                float rrp = length(r)/ra; //|r|/|r'|
75                        if (rrp < 1) {          // undershooting
76                        dl = dr;        // store last undershooting as l
77                        llp = rrp;
78                        undershoot = true;
79                } else {
80                        dp = dr;        // store last overshooting as p
81                        ppp = rrp;
82                        overshoot = true;}
83                } else {                        // nothing is visible: restart search
84                undershoot = false;     
85                overshoot = false;
86                }       
87                t += dt;                        // next texel
88        }
89
90        if(!(overshoot && undershoot))
91          p = float3(0,0,0);
92
93}
94
95void secantSearch(float3 x, float3 R, samplerCUBE mp,
96                       float dl,
97                       float dp,
98                       float llp,
99                       float ppp,
100                       out float3 p)
101{
102  p = x + R * dp; // if no secant iteration
103  for(int i= 0; i < SECANT_ITERATIONCOUNT; i++)
104  {
105   float dnew;
106   dnew = dl + (dp - dl) * (1 - llp) / (ppp - llp);
107   p = x + R * dnew;
108   half pppnew = length(p) / texCUBElod(mp, float4(p, 0)).a;
109   if(pppnew == 1.0)
110        i = SECANT_ITERATIONCOUNT;
111   else if(pppnew < 1.0f)
112   {
113    llp = pppnew;
114    dl = dnew;
115   }
116   else
117   {
118    ppp = pppnew;
119    dp = dnew;
120   }
121  }
122}
123
124float3 Hit(float3 x, float3 R, out float4 Il, out float3 Nl)
125{
126 float dl1 = 0, dp1, llp1, ppp1;
127 float3 p1;
128 linearSearch(x, R, envCubeSampler1, p1, dl1, dp1, llp1, ppp1);
129 float dl2 = 0, dp2, llp2, ppp2;
130 float3 p2;
131 linearSearch(x, R, envCubeSampler2, p2, dl2, dp2, llp2, ppp2);
132 
133 bool valid1 = dot(p1,p1) != 0;
134 bool valid2 = dot(p2,p2) != 0;
135               
136 float dl, dp, llp, ppp;
137 float3 p;
138 
139 if(!valid1 && ! valid2)
140 {
141    linearSearch(x, R, envCubeSampler3, p, dl, dp, llp, ppp);
142    Il.a = 1;
143    secantSearch(x, R, envCubeSampler3, dl, dp, llp, ppp, p);
144    Il.rgb =  Nl.rgb = texCUBElod(envCubeSampler3, float4(p, 0)).rgb; 
145 }
146 else
147 {
148    if( !valid2 || (valid1 && dp1 < dp2))
149    {
150     secantSearch(x, R, envCubeSampler1, dl1, dp1, llp1, ppp1, p1);
151     Il.rgb =  Nl.rgb = texCUBElod(envCubeSampler1, float4(p1, 0)).rgb;
152     p = p1;
153    }
154    else
155    {
156     secantSearch(x, R, envCubeSampler2, dl2, dp2, llp2, ppp2, p2);
157     Il.rgb =  Nl.rgb = texCUBElod(envCubeSampler2, float4(p2, 0)).rgb;
158     p = p2;
159    }
160    Il.a = 0;   
161 }
162 
163 return p;
164}
165
166
167struct SpecularReflection_VS_OUT
168{
169        float4 hPos : POSITION;         // clipping space
170        float3 x    : TEXCOORD1;        // cube map space
171        float3 N    : TEXCOORD2;        // normal
172        float3 V    : TEXCOORD3;        // view
173};
174
175SpecularReflection_VS_OUT SpecularReflectionVS(         
176        float4 Pos  : POSITION,
177        float4 Norm : NORMAL)
178{
179        SpecularReflection_VS_OUT OUT;
180        OUT.hPos = mul(Pos, WorldViewProj);
181        OUT.x    = mul(Pos, World).xyz;
182        OUT.N    = mul(Norm, WorldIT).xyz;
183        OUT.V    = OUT.x - eyePos;
184        OUT.x   -= referencePos;
185        return OUT;
186}
187
188float4 SingleReflectionPS( SpecularReflection_VS_OUT IN) : COLOR
189{
190        float3 V = normalize(IN.V); float3 N = normalize(IN.N);
191        float3 R;               // reflection dir.
192        float3 Nl;                      // normal vector at the hit point
193        float4 Il;                      // radiance at the hit point
194        float3 I = 1;
195       
196        float3 F = F0 + pow(1-dot(N, -V), 5) * (1 - F0);
197        if (N0 <= 0) // reflective material
198        {
199        R = reflect(V, N);
200        I *= F; // Fresnel reflection
201    }
202    else //refractive material
203    {
204        R = refract(V, N, N0);
205        if (dot(R, R) == 0)     // no refraction direction exits
206                R = reflect(V, N); // total reflection                         
207                else
208                I *= (1 - F);      // Fresnel refraction
209    }
210    // ray hit l, radiance Il, normal Nl
211    float3 l = Hit(IN.x, R, Il, Nl);
212    if(Il.a == 0)//not a valid hit
213                Il = texCUBE(envCubeSampler3, R); //read the distance environment map from the last direction
214               
215        return Il * float4(I,1);
216}
217
218
219technique SingleReflection
220{                                                                                                                               
221                        pass p0                                                                                                         
222                        {                                                                                                                       
223                                VertexShader = compile vs_2_0 SpecularReflectionVS();           
224                                PixelShader  = compile ps_3_0 SingleReflectionPS();     
225                        }                                                                                                                       
226}
227
228float4 MultipleReflectionPS( SpecularReflection_VS_OUT IN ) : COLOR
229{
230        float3 V = normalize(IN.V); float3 N = normalize(IN.N);
231        float3 x = IN.x;
232       
233        float4 I = float4(1,1,1,0);// radiance of the path
234        float3 Fp = F0;           // Fresnel at 90 degrees at first hit
235        float  n = N0;             // index of refraction of the first hit
236        int depth = 0;          // length of the path
237        while (depth < MAX_RAY_DEPTH) {
238        float3 R;       // reflection or refraction dir
239        float3 F = Fp + pow(1-abs(dot(N, -V)), 5) * (1-Fp);  // Fresnel
240        if (n <= 0) {
241                R = reflect(V, N);  // reflection
242                I.rgb *= F;             // Fresnel reflection
243        }
244        else{                   // refraction
245                if (dot(V,N) > 0) { // coming from inside
246                                n = 1.0 / n;
247                                N = -N;
248                }
249                R = refract(V, N, n);
250                if (dot(R, R) == 0)     // no refraction direction exits
251                        R = reflect(V, N); // total reflection                         
252                        else
253                        I.rgb *= (1-F);        // Fresnel refraction
254        }
255       
256        float4 Il;              // radiance at the hit point
257                float3 Nl;              // normal vector at the hit point
258        // Trace ray x+R*d and obtain hit l, radiance Il, normal Nl
259            float3 l = Hit(x, R, Il, Nl);
260            if (Il.a == 0)// hit point is on specular surface
261            {           
262                depth += 1;
263        }
264        else
265        {               // hit point is on diffuse surface
266                I.rgb *= Il.rgb;        // multiply with the radiance
267                I.a = 1;
268                        depth = MAX_RAY_DEPTH;   // terminate
269        }
270        N = Nl; V = R; x = l; // hit point is the next shaded point
271        }
272        return I * I.a;
273}
274
275technique MultipleReflection
276{                                                                                                                               
277                        pass p0                                                                                                         
278                        {                                                                                                                       
279                                VertexShader = compile vs_2_0 SpecularReflectionVS();           
280                                PixelShader  = compile ps_3_0 MultipleReflectionPS();   
281                        }                                                                                                                       
282}
Note: See TracBrowser for help on using the repository browser.