source: GTP/trunk/App/Demos/Illum/Envmap/EnvMap.fx @ 843

Revision 843, 24.1 KB checked in by szirmay, 18 years ago (diff)
Line 
1//--------------------------------------------------------------------------------------
2// File: EnvMap.fx
3//
4// The effect file for the OptimizedMesh sample. 
5//
6// Copyright (c) Microsoft Corporation. All rights reserved.
7//--------------------------------------------------------------------------------------
8
9/// size of the cube map taken from the reference point of the object
10#define CUBEMAP_SIZE    128
11/// size of the cube map for diffuse/glossy reflections
12#define LR_CUBEMAP_SIZE 4
13/// cube map downsampling rate for diffuse/glossy reflections
14#define RATE (CUBEMAP_SIZE/LR_CUBEMAP_SIZE)
15#define PI 3.14159f
16
17//--------------------------------------------------------------------------------------
18// Global variables
19//--------------------------------------------------------------------------------------
20
21float4x4 World;                                 ///< World matrix for the current object
22float4x4 WorldIT;                               ///< World matrix IT (inverse transposed) to transform surface normals of the current object
23float4x4 WorldView;                             ///< World * View matrix
24//float4x4 WorldViewIT;                 ///< World * View IT (inverse transposed) to transform surface normals of the current object
25float4x4 WorldViewProjection;   ///< World * View * Projection matrix
26
27float texel_size;                               ///< upload this constant every time the viewport changes
28
29float4 eyePos;                                  ///< current eye (camera) position
30float4 reference_pos;                   ///< Reference point for the last cube map generation.
31
32int nFace;                                              ///<
33int iShowCubeMap;                               ///<
34float4 objColor;
35
36float3 nMetal;                                  ///< real part of the refraction coefficient for metals
37float3 kMetal;                                  ///< imaginary part of the refraction coefficient for metals
38float sFresnel;                                 ///< Fresnel refraction param.
39float refractionIndex;
40float intensity;
41
42float shininess;
43float brightness;
44
45texture EnvironmentMap;
46texture SmallEnvironmentMap;
47texture PreconvolvedEnvironmentMap;
48texture Decoration;
49
50sampler EnvironmentMapSampler = sampler_state
51{
52    /*MinFilter = LINEAR;
53    MagFilter = LINEAR;
54    MipFilter = LINEAR;*/
55    Texture   = <EnvironmentMap>;
56    AddressU  = WRAP;
57    AddressV  = WRAP;
58};
59
60sampler PreconvolvedEnvironmentMapSampler = sampler_state
61{
62    MinFilter = LINEAR;
63    MagFilter = LINEAR;
64    //MipFilter = LINEAR;
65    Texture   = <PreconvolvedEnvironmentMap>;
66    AddressU  = WRAP;
67    AddressV  = WRAP;
68};
69
70sampler SmallEnvironmentMapSampler = sampler_state
71{
72    MinFilter = Point;
73    MagFilter = Point;
74    //MipFilter = Point;
75    Texture   = <SmallEnvironmentMap>;
76    AddressU  = WRAP;
77    AddressV  = WRAP;
78};
79
80sampler DecorationSampler = sampler_state
81{
82    Texture   = <Decoration>;
83    MinFilter = LINEAR;
84    MagFilter = LINEAR;
85    //MipFilter = LINEAR;
86    AddressU  = CLAMP; //WRAP;
87    AddressV  = CLAMP; //WRAP;
88};
89
90// ---------------------------------------------------------------------------------------------------
91
92struct ReduceTextureVS_input {           ///< vertex shader input
93    float4 Position : POSITION;
94};
95
96struct ReduceTextureVS_output {          ///< vertex shader output, pixel shader input
97    float4 hPosition : POSITION;
98    float2 Position  : TEXCOORD0;
99};
100
101/// See the pixel program.
102ReduceTextureVS_output ReduceTextureVS(ReduceTextureVS_input IN) {
103        ReduceTextureVS_output OUT;
104    OUT.hPosition = IN.Position;
105    OUT.Position = IN.Position.xy;
106    return OUT;
107}
108
109/// \brief Downsamples a face of a cube map.
110///
111/// Downsamples the nFace-th face of a cube map from resolution #CUBEMAP_SIZE to #LR_CUBEMAP_SIZE
112/// by averaging the corresponding texel values. The #EnvironmentMap is sampled via #EnvironmentMapSampler.
113/// \param nFace uniform parameter identifies the current face (0...5)
114float4 ReduceTexturePS(ReduceTextureVS_output IN) : COLOR
115{
116    float4 color = 0;
117    float3 dir;
118   
119    for (int i = 0; i < RATE; i++)
120     for (int j = 0; j < RATE; j++)
121    {
122                // generate a position
123                float2 pos;
124                pos.x = IN.Position.x + (2*i + 1)/(float)CUBEMAP_SIZE;
125                pos.y = IN.Position.y - (2*j + 1)/(float)CUBEMAP_SIZE;  // y=-u
126
127                // "scrambling"
128                // ( put the generated position on the nFace-th face )
129                if (nFace == 0) dir = float3(1, pos.y, -pos.x);
130                if (nFace == 1) dir = float3(-1, pos.y, pos.x);
131                if (nFace == 2) dir = float3(pos.x, 1, -pos.y);
132                if (nFace == 3) dir = float3(pos.x, -1, pos.y);
133                if (nFace == 4) dir = float3(pos.xy, 1);
134                if (nFace == 5) dir = float3(-pos.x, pos.y,-1);
135
136                color += texCUBE( EnvironmentMapSampler, dir);
137    }
138        return color / (RATE*RATE);     
139}
140
141/// \brief Returns the precalculated contribution of a texel with regard to the specified query direction.
142///
143/// \param q <b>query direction</b> (i.e. surface normal in diffuse case, ideal reflection direction in specular case).
144/// \param L vector pointing to the texel center
145float4 GetContibution(float3 q, float3 L)
146// Lin * a * ( dw )
147// -- actually, dw is calculated by the caller --
148{
149        //float shininess = 1;
150        float fcos = max(dot(L, q), 0);
151        // diffuse
152        if (shininess <= 0)     
153                return 0.2 * fcos * texCUBE( SmallEnvironmentMapSampler, L);
154        else
155                // some ad-hoc formula that maintains more even intensity for different shininess values
156                // in case of HDRI environment
157                return (pow(shininess,0.8)*0.2) * pow(fcos, shininess) * texCUBE( SmallEnvironmentMapSampler, L);
158
159                // return (shininess+2)/8 * pow(fcos, shininess) * texCUBE( SmallEnvironmentMapSampler, L);
160}
161
162/*float4 GetContibution_Metal(float3 q, float3 L)
163// Lin * a * ( dw )
164// -- actually, dw is calculated by the caller --
165{
166        float fcos = max(dot(L, q), 0);
167        float4 Lin = texCUBE( SmallEnvironmentMapSampler, L);
168        return Lin * (pow(shininess,0.8)*0.2) * pow(fcos, shininess);
169}*/
170
171struct ConvolutionVS_input {
172    float4 Position : POSITION;
173};
174
175struct ConvolutionVS_output {
176    float4 hPosition : POSITION;
177    float3 Position  : TEXCOORD0;
178};
179
180/// See the pixel program.
181ConvolutionVS_output ConvolutionVS(ConvolutionVS_input IN) {
182    ConvolutionVS_output OUT;
183    OUT.hPosition = IN.Position;
184   
185        float2 pos = IN.Position.xy;    // -1..1
186        pos.x += 1.0f / LR_CUBEMAP_SIZE;
187        pos.y -= 1.0f / LR_CUBEMAP_SIZE;       
188   
189        if (nFace == 0) OUT.Position = float3(1, pos.y, -pos.x);
190        if (nFace == 1) OUT.Position = float3(-1, pos.y, pos.x);
191        if (nFace == 2) OUT.Position = float3(pos.x, 1, -pos.y);
192        if (nFace == 3) OUT.Position = float3(pos.x,-1, pos.y);
193        if (nFace == 4) OUT.Position = float3(pos.xy, 1);
194        if (nFace == 5) OUT.Position = float3(-pos.x, pos.y,-1);
195       
196    return OUT;
197}
198
199/// \brief Convolves the values of a cube map.
200///
201/// Calculates the diffuse/specular irradiance map of resolution #LR_CUBEMAP_SIZE by summing up the contributions of all cube map texels
202/// with regard to the current query direction.
203/// \param SmallEnvironmentMap is bound to EnvMap::pCubeTextureSmall (cube map of resolution #LR_CUBEMAP_SIZE)
204
205float4 ConvolutionPS(ConvolutionVS_output IN) : COLOR
206{
207        // input position = query direction for the result
208    float3 q = normalize( IN.Position );
209    float4 color = 0;
210   
211    //
212    for (int i = 0; i < LR_CUBEMAP_SIZE; i++)
213     for (int j = 0; j < LR_CUBEMAP_SIZE; j++)
214    {
215        float u = (i+0.5) / (float)LR_CUBEMAP_SIZE;
216        float v = (j+0.5) / (float)LR_CUBEMAP_SIZE;
217        float3 pos = float3( 2*u-1, 1-2*v, 1 );
218
219                float r = length(pos); 
220                pos /= r;
221               
222                float4 dcolor = 0;     
223            float3 L;
224                L = float3(pos.z, pos.y, -pos.x);       dcolor += GetContibution( q, L );
225                L = float3(-pos.z, pos.y, pos.x);       dcolor += GetContibution( q, L );
226                L = float3(pos.x, pos.z, -pos.y);       dcolor += GetContibution( q, L );
227                L = float3(pos.x, -pos.z, pos.y);       dcolor += GetContibution( q, L );
228                L = float3(pos.x, pos.y, pos.z);        dcolor += GetContibution( q, L );
229                L = float3(-pos.x, pos.y, -pos.z);      dcolor += GetContibution( q, L );
230
231                float dw = 4 / (r*r*r); // using accurate solid angles
232                //float dw = 4;                 // assuming equal solid angles
233
234                color += dcolor*dw;     
235    }
236
237        return 1.5 * color / (LR_CUBEMAP_SIZE * LR_CUBEMAP_SIZE);   
238}
239
240// ---------------------------------------------------------------------------------------------------
241
242/// \brief This function approximately traces a ray from point x towards direction R.
243/// Depth information is obtained from the alpha channel of mp.
244/// \return the approximate hit point.
245
246float3 Hit(float3 x, float3 R, sampler mp)
247{
248        float rl = texCUBE(mp, R).a; // |r|
249        float dp = rl - dot(x, R);              // parallax
250
251        float3 p = x + R * dp;
252        return p;
253}
254
255/// \brief Simple Fresnel term approximation for metals.
256///
257/// The metal is described by its (complex) refraction coefficient (#nMetal,#kMetal).
258float4 metal_reflectivity(float3 L, float3 N, float3 V)
259{
260        float3 n = nMetal;
261        float3 k = kMetal;
262
263        float ctheta_in = dot(N,L);
264        float ctheta_out = dot(N,V);
265
266        float4 intens = 0;
267        float3 F = 0;
268       
269        // calculating terms F, P, G for Cook-Torrance
270        if ( ctheta_in > 0 && ctheta_out > 0 )
271        {
272                float3 H = normalize(L + V);    // halfway vector
273                float calpha = dot(N,H);
274                float cbeta  = dot(H,L);
275               
276                F = ( (n-1)*(n-1) + pow(1-cbeta,5) * 4*n + k*k) / ( (n+1)*(n+1) + k*k );
277        }
278       
279        return float4(F, 1);
280}
281// --------------------------------------------------------
282// technique EnvMappedScene
283// --------------------------------------------------------
284
285struct EnvMapVS_input
286{
287    float4 Position                     : POSITION;
288    float3 Normal                       : NORMAL;
289    float2 TexCoord                     : TEXCOORD0;
290};
291
292struct EnvMapVS_output
293{
294    float4 hPosition            : POSITION;
295    float2 TexCoord                     : TEXCOORD0;
296    float3 Normal                       : TEXCOORD1;
297    float3 View                         : TEXCOORD2;
298    float3 Position                     : TEXCOORD3;
299};
300
301
302EnvMapVS_output EnvMapVS( EnvMapVS_input IN )
303{
304        EnvMapVS_output OUT;
305 
306    OUT.Position = mul( IN.Position, World ).xyz;               // scale & offset
307    OUT.View = normalize( OUT.Position - eyePos );
308        //OUT.Normal = IN.Normal;                                                               
309    OUT.Normal = mul( IN.Normal, WorldIT ).xyz;                 // allow distortion/rotation
310           
311    OUT.TexCoord = IN.TexCoord;
312   
313    OUT.hPosition = mul( IN.Position, WorldViewProjection );
314    return OUT;
315}
316
317/// \brief Environment mapping with distance impostors.
318///
319/// Determines the ideal reflection/refraction direction and approximately traces a ray toward that direction using the Hit() function.
320/// \param EnvironmentMap is bound to EnvMap::pCubeTexture (cube map of resolution #CUBEMAP_SIZE)
321float4 EnvMapImpostorPS( EnvMapVS_output IN ) : COLOR
322{
323        IN.View = normalize( IN.View );
324        IN.Normal = normalize( IN.Normal );
325
326        float3 R = reflect(IN.View, IN.Normal);                         // reflection direction
327        float3 T = refract(IN.View, IN.Normal, refractionIndex);
328
329        // translate reference point to the origin     
330        float3 p0 = IN.Position - reference_pos.xyz;
331       
332        float3 RR = 0, TT = 0;
333
334        // -------------------------- approximate raytracing --------------------------
335       
336        // using depth impostors + interpolation
337        RR = Hit(p0, R, EnvironmentMapSampler);
338       
339        // single refraction           
340        TT = Hit(p0, T, EnvironmentMapSampler);
341       
342        // reading from the cubemap
343        float4 reflectcolor = texCUBE(EnvironmentMapSampler, RR);       
344        float4 refractcolor = texCUBE(EnvironmentMapSampler, TT);       
345
346        float cos_theta = -dot( IN.View, IN.Normal );           // Fresnel approximation
347        float F = (sFresnel + pow(1-cos_theta, 5.0f) * (1-sFresnel));
348       
349    return intensity * (F * reflectcolor + (1-F) * refractcolor);       
350    //return reflectcolor;
351}
352
353float4 EnvMapImpostorMetalPS( EnvMapVS_output IN ) : COLOR
354{
355        IN.View = normalize( IN.View );
356        IN.Normal = normalize( IN.Normal );
357
358        float3 R = reflect(IN.View, IN.Normal);                         // reflection direction
359        // translate reference point to the origin
360        float3 p0 = IN.Position - reference_pos.xyz;           
361       
362        // -------------------------- approximate raytracing --------------------------
363
364        // using depth impostors + interpolation
365        float3 RR = Hit(p0, R, EnvironmentMapSampler);
366       
367        // reading from the cubemap
368        float4 reflectcolor = texCUBE(EnvironmentMapSampler, RR);       
369
370        float3 L = R;
371        return intensity * reflectcolor * metal_reflectivity(L, IN.Normal, -IN.View);
372    //return reflectcolor;
373}
374
375/// \brief Classic environment mapping technique.
376///
377/// Simply determines the ideal reflection/refraction direction and performs a cube map lookup into that direction
378/// \param EnvironmentMap is bound to EnvMap::pCubeTexture (cube map of resolution #CUBEMAP_SIZE)
379
380float4 EnvMapClassicPS( EnvMapVS_output IN ) : COLOR
381{
382        IN.View = normalize( IN.View );
383        IN.Normal = normalize( IN.Normal );
384
385        float3 R = reflect(IN.View, IN.Normal);
386        float3 T = refract(IN.View, IN.Normal, refractionIndex);
387        float3 p0 = IN.Position;
388       
389        // -------------------------- return value --------------------------
390       
391        // reading from the cubemap
392        float4 reflectcolor = texCUBE(EnvironmentMapSampler, R);       
393        float4 refractcolor = texCUBE(EnvironmentMapSampler, T);       
394
395        float cos_theta = -dot( IN.View, IN.Normal );   // Fresnel approximation
396        float F = (sFresnel + pow(1-cos_theta, 5.0f) * (1-sFresnel));
397       
398        return intensity * (F * reflectcolor + (1-F) * refractcolor);   
399    //return reflectcolor;
400}
401
402/// Classic environment mapping technique with a simple Fresnel term approximation (metal_reflectivity()).
403float4 EnvMapClassicMetalPS( EnvMapVS_output IN ) : COLOR
404{
405        IN.View = normalize( IN.View );
406        IN.Normal = normalize( IN.Normal );
407
408        float3 R = reflect(IN.View, IN.Normal);
409        float3 p0 = IN.Position;
410       
411        float4 reflectcolor = texCUBE(EnvironmentMapSampler, R);       
412
413        float3 L = R;
414        return intensity * reflectcolor * metal_reflectivity(L, IN.Normal, -IN.View);   
415    //return reflectcolor;
416}
417
418/// \brief Determines diffuse or specular illumination with a single lookup into #PreconvolvedEnvironmentMap.
419/// \param PreconvolvedEnvironmentMap is bound to EnvMap::pCubeTexturePreConvolved (cube map of resolution #LR_CUBEMAP_SIZE)
420float4 EnvMapDiffusePS( EnvMapVS_output IN ) : COLOR
421{
422        IN.View = normalize( IN.View );
423        IN.Normal = normalize( IN.Normal );
424       
425        float3 R = reflect(IN.View, IN.Normal);
426
427        if (shininess <= 0)     // diffuse
428                return intensity * texCUBE(PreconvolvedEnvironmentMapSampler, IN.Normal);               
429        else                            // specular
430                return intensity * texCUBE(PreconvolvedEnvironmentMapSampler, R);       
431}
432
433/// \brief Calculates the contribution of a single texel of #SmallEnvironmentMap to the illumination of the shaded point.
434///
435/// \param L vector pointing to the center of the texel under examination. We assume that the largest coordinate component
436/// of L is equal to one, i.e. L points to the face of a cube of edge length of 2.
437/// \param pos is the position of the shaded point
438/// \param N is the surface normal at the shaded point
439/// \param V is the viewing direction at the shaded point
440
441float4 GetContibution(float3 L, float3 pos, float3 N, float3 V) // Phong-Blinn
442// L: a hossza lényeges (az egységkocka faláig ér)
443{
444        float kd = 0.4; // 0.3
445        float ks = 0.5; // 0.5
446       
447        float l = length(L);
448        L = normalize(L);
449
450        //Lin
451        float4 Lin = texCUBE(SmallEnvironmentMapSampler, L);
452        //dw
453        float dw = 4 / (LR_CUBEMAP_SIZE*LR_CUBEMAP_SIZE*l*l*l + 4/2/3.1416f);
454       
455        float dws = dw;
456
457//#ifdef LOCALIZE
458
459        //r
460        float doy = texCUBE(SmallEnvironmentMapSampler, L).a;
461        float dxy = length(pos - L * doy);
462
463        //dws
464        dws = (doy*doy * dw) / (dxy*dxy*(1 - dw/2/3.1416f) + doy*doy*dw/2/3.1416f);     // localization
465
466        L = L * doy - pos;      // L should start from the object (and not from the reference point)
467        L = normalize(L);
468
469//#endif
470
471        float3 H = normalize(L + V);    // felezõvektor
472        float3 R = reflect(-V, N);              // reflection vector
473
474        // a: from texture
475
476        float4 color = 0;
477       
478        float a = 0;
479        if ( shininess <= 0 )
480                a = kd * max(dot(N,L),0);                                       // diffuse
481        else
482                a = ks * pow(max(dot(N,H),0), shininess) * (shininess+2)/(2*PI);        // specular
483                // note: using dot(N,H) looks better than dot(R,L)
484                       
485        return Lin * a * dws;
486}
487
488/// \brief Calculates diffuse or specular contributions of all texels in #SmallEnvironmentMap to the current point.
489/// For each texel of #SmallEnvironmentMap, function GetContibution(float3,float3,float3,float3) is called.
490/// \param SmallEnvironmentMap is bound to EnvMap::pCubeTextureSmall (cube map of resolution #LR_CUBEMAP_SIZE)
491
492float4 EnvMapDiffuseLocalizedPS( EnvMapVS_output IN ) : COLOR
493{
494        IN.View = -normalize( IN.View );
495        IN.Normal = normalize( IN.Normal );
496        // translate reference point to the origin
497        IN.Position -= reference_pos.xyz;               
498       
499        float3 R = -reflect( IN.View, IN.Normal );              // reflection direction
500       
501    float4 I = 0;
502   
503        for (int x = 0; x < LR_CUBEMAP_SIZE; x++)                       // foreach texel
504         for (int y = 0; y < LR_CUBEMAP_SIZE; y++)
505         {
506                // compute intensity for 6 texels with equal solid angles
507               
508                float2 tpos;
509            tpos.x = x/(float)LR_CUBEMAP_SIZE;          // 0..1
510            tpos.y = y/(float)LR_CUBEMAP_SIZE;          // 0..1
511            tpos.xy += float2(0.5/LR_CUBEMAP_SIZE, 0.5/LR_CUBEMAP_SIZE);        // offset to texel center
512           
513            float2 p = float2(tpos.x, 1-tpos.y);        // reverse y
514            p.xy = 2*p.xy - 1;                                          // -1..1
515           
516            float3 L;
517           
518                L = float3(p.x, p.y, 1);
519                I += GetContibution( L, IN.Position, IN.Normal, IN.View );
520               
521                L = float3(p.x, p.y, -1);
522                I += GetContibution( L, IN.Position, IN.Normal, IN.View );
523               
524                L = float3(p.x, 1, p.y);
525                I += GetContibution( L, IN.Position, IN.Normal, IN.View );
526               
527                L = float3(p.x, -1, p.y);
528                I += GetContibution( L, IN.Position, IN.Normal, IN.View );
529               
530                L = float3(1, p.x, p.y);
531                I += GetContibution( L, IN.Position, IN.Normal, IN.View );
532               
533                L = float3(-1, p.x, p.y);
534                I += GetContibution( L, IN.Position, IN.Normal, IN.View );
535        }
536
537        return intensity * I;
538}
539
540/// \brief Calculates the contribution of a single texel of #SmallEnvironmentMap to the illumination of the shaded point.
541///
542/// The only difference from GetContibution(float3,float3,float3,float3) is that
543/// now we use precalculated integral values to compute reflectivity (instead of using only one sample).
544
545float4 GetContibutionWithCosLookup(float3 L, float3 pos, float3 N, float3 V)    // Phong-Blinn
546// L: a hossza lényeges (az egységkocka faláig ér)
547{
548        float ks = 0.5; // 0.5
549        float l = length(L);
550        L = normalize(L);
551
552        //Lin
553        float4 Lin = texCUBE(SmallEnvironmentMapSampler, L);
554
555        //dw
556        //float dw = 4 / (LIGHT_TEXTURE_SIZE*LIGHT_TEXTURE_SIZE*l*l*l + 4/3.1416f);
557        float dw = 4 / (LR_CUBEMAP_SIZE*LR_CUBEMAP_SIZE*l*l*l + 4/2/3.1416f);
558       
559        float dws = dw;
560
561//#ifdef LOCALIZE
562
563//if (localize > 0)
564{
565        //r
566        float doy = texCUBE(SmallEnvironmentMapSampler, L).a;
567        float dxy = length(pos - L * doy);
568
569        //dws
570        //dws = (doy*doy * dw) / (dxy*dxy*(1 - dw/3.1416f) + doy*doy*dw/3.1416f);       // localization:
571        dws = (doy*doy * dw) / (dxy*dxy*(1 - dw/2/3.1416f) + doy*doy*dw/2/3.1416f);     // localization:
572
573        // az illum.képletben használt L kiszámítása
574        L = L * doy - pos;      // bugfix: L az objektumtól induljon, ne a középpontból (x->y)
575        L = normalize(L);
576}
577
578//#endif
579
580        float3 H = normalize(L + V);    // felezõvektor
581        float3 R = reflect(-V, N);              // reflection vector
582
583        // from texture
584
585        float4 color = 0;
586        float cos_value;
587
588        if (shininess <= 0)
589                cos_value = dot(N,L);   // diffuse
590        else
591                cos_value = dot(R,L);   // specular
592       
593        float2 tex;
594        tex.x = (cos_value + 1)/2;
595        tex.y = dws/2/PI;
596        cos_value = tex2D(DecorationSampler, tex).g * 3;
597        //color = Lin * kd * cos_value * 2;     // bugfix: kd
598        color = Lin * ks * cos_value * 1.2;     // ks
599        //return Lin * cos_value;       
600
601        return color;
602}
603
604/// \brief Calculates diffuse or specular contributions of all texels in #SmallEnvironmentMap to the current point.
605/// For each texel of #SmallEnvironmentMap, function GetContibutionWithCosLookup() is called.
606/// \param SmallEnvironmentMap is bound to EnvMap::pCubeTextureSmall (cube map of resolution #LR_CUBEMAP_SIZE)
607
608float4 EnvMapDiffuseLocalizedWithCosLookupPS( EnvMapVS_output IN ) : COLOR
609{
610        IN.View = -normalize( IN.View );
611        IN.Normal = normalize( IN.Normal );
612        IN.Position -= reference_pos.xyz;               
613       
614        float3 R = -reflect( IN.View, IN.Normal );              // reflection direction
615       
616    float4 I = 0;
617   
618        for (int x = 0; x < LR_CUBEMAP_SIZE; x++)                       // foreach texel
619         for (int y = 0; y < LR_CUBEMAP_SIZE; y++)
620         {
621                // compute intensity for 6 texels with equal solid angles
622               
623                float2 tpos;
624            tpos.x = x/(float)LR_CUBEMAP_SIZE;          // 0..1
625            tpos.y = y/(float)LR_CUBEMAP_SIZE;          // 0..1
626            tpos.xy += float2(0.5/LR_CUBEMAP_SIZE, 0.5/LR_CUBEMAP_SIZE);        // offset to texel center
627           
628            float2 p = float2(tpos.x, 1-tpos.y);        // reverse y
629            p.xy = 2*p.xy - 1;                                          // -1..1
630           
631            float3 L;
632           
633                L = float3(p.x, p.y, 1);
634                I += GetContibutionWithCosLookup( L, IN.Position, IN.Normal, IN.View );
635               
636                L = float3(p.x, p.y, -1);
637                I += GetContibutionWithCosLookup( L, IN.Position, IN.Normal, IN.View );
638               
639                L = float3(p.x, 1, p.y);
640                I += GetContibutionWithCosLookup( L, IN.Position, IN.Normal, IN.View );
641               
642                L = float3(p.x, -1, p.y);
643                I += GetContibutionWithCosLookup( L, IN.Position, IN.Normal, IN.View );
644               
645                L = float3(1, p.x, p.y);
646                I += GetContibutionWithCosLookup( L, IN.Position, IN.Normal, IN.View );
647               
648                L = float3(-1, p.x, p.y);
649                I += GetContibutionWithCosLookup( L, IN.Position, IN.Normal, IN.View );
650        }
651
652        return intensity * I;
653}
654
655// --------------------------------------------------------
656// technique IlluminatedScene
657// --------------------------------------------------------
658
659struct IlluminatedSceneVS_input {
660    float4 Position : POSITION;
661    float3 Normal : NORMAL;
662    float2 TexCoord : TEXCOORD0;
663};
664
665struct IlluminatedSceneVS_output {
666    float4 hPosition : POSITION;
667    float2 TexCoord : TEXCOORD0;
668    float3 Position : TEXCOORD1;
669};
670
671IlluminatedSceneVS_output IlluminatedSceneVS( IlluminatedSceneVS_input IN )
672{
673        IlluminatedSceneVS_output OUT;
674    OUT.hPosition = mul( IN.Position, WorldViewProjection );
675   
676    // texel_size as uniform parameter
677        OUT.hPosition.x -= texel_size * OUT.hPosition.w;
678        OUT.hPosition.y += texel_size * OUT.hPosition.w;
679
680    if (iShowCubeMap > 0)
681    {
682                // if one of the cube maps is displayed on the walls,
683                // position is simply forwarded
684                OUT.Position = IN.Position;
685        }
686        else
687        {
688                // also consider camera orientation
689                OUT.Position = mul( IN.Position, WorldView );
690        }
691   
692    OUT.TexCoord = IN.TexCoord;
693    return OUT;
694}
695
696/// Displays the environment with a simple shading
697float4 IlluminatedScenePS( IlluminatedSceneVS_output IN ) : COLOR0
698{
699    float3 color = objColor * tex2D(DecorationSampler, IN.TexCoord);
700   
701    if (iShowCubeMap > 0)
702    {
703                // if one of the cube maps should be displayed on the walls,
704                // display it
705            color = texCUBE(EnvironmentMapSampler, IN.Position) * intensity;
706    }
707    else
708    {
709                // create an exponential falloff for each face of the room
710                float3 L = float3(2*IN.TexCoord.x-1, 2*IN.TexCoord.y-1, -1);
711                L = normalize(L);
712                float3 N = float3(0,0,1);
713                color *= abs(pow(dot(L,N), 3)) * brightness;
714        }
715               
716        float dist = length( IN.Position );
717
718    return float4(color, dist);
719}
720
721
722//--------------------------------------------------------------------------------------
723// Techniques
724//--------------------------------------------------------------------------------------
725
726/// a helpful macro to define techniques with a common vertex program
727#define TechniqueUsingCommonVS(name);                                   \
728        technique name                                                                          \
729        {                                                                                                       \
730            pass p0                                                                                     \
731            {                                                                                           \
732                    VertexShader = compile vs_3_0 EnvMapVS();   \
733                    PixelShader  = compile ps_3_0 name##PS();   \
734                }                                                                                               \
735        }
736       
737TechniqueUsingCommonVS( EnvMapClassic );
738TechniqueUsingCommonVS( EnvMapClassicMetal );
739TechniqueUsingCommonVS( EnvMapImpostor );
740TechniqueUsingCommonVS( EnvMapImpostorMetal );
741TechniqueUsingCommonVS( EnvMapDiffuse );
742TechniqueUsingCommonVS( EnvMapDiffuseLocalized );
743TechniqueUsingCommonVS( EnvMapDiffuseLocalizedWithCosLookup );
744
745/// a helpful macro to define techniques
746#define Technique(name);                                                                \
747        technique name                                                                          \
748        {                                                                                                       \
749            pass p0                                                                                     \
750            {                                                                                           \
751                    VertexShader = compile vs_3_0 name##VS();   \
752                    PixelShader  = compile ps_3_0 name##PS();   \
753                }                                                                                               \
754        }
755
756// defining techniques
757// where the name of EnvMapVS program is <TechniqueName>EnvMapVS
758// and the name of PS program is <TechniqueName>PS
759Technique( IlluminatedScene );
760Technique( ReduceTexture );
761Technique( Convolution );
Note: See TracBrowser for help on using the repository browser.