source: GTP/trunk/App/Demos/Illum/EnvMap/EnvMap.cpp @ 1556

Revision 1556, 29.5 KB checked in by szirmay, 18 years ago (diff)
Line 
1#include "dxstdafx.h"
2#include "resource.h"
3#include <time.h>
4
5#include "Cube.h"
6#include "Mesh.h"
7#include "Parameters.h"
8#include "EnvMap.h"
9 
10//--------------------------------------------------------------------------------------
11// Media
12//--------------------------------------------------------------------------------------
13
14#define MESH0   L"Media\\Objects\\room.x"
15#define MESH1   L"Media\\Objects\\sphere.x"             // src: DirectX Samples
16#define MESH2   L"Media\\Objects\\column.x"
17#define MESH3   L"Media\\Objects\\teapot.x"             // src: DirectX Samples
18#define MESH4   L"Media\\Objects\\ring.x"               // src: DirectX Samples
19#define MESH5   L"Media\\Objects\\lamp01.x"             // src: 3dcafe
20#define MESH6   L"Media\\Objects\\happy.x"              // src: Stanford Repository
21#define MESH7   L"Media\\Objects\\dragon.x"             // src: Stanford Repository
22#define MESH8   L"Media\\Objects\\bunny.x"              // src: Stanford Repository
23#define MESH9   L"Media\\Objects\\skullocc.x"   // src: DirectX Samples
24
25#define TEX0    L"Media\\Maps\\white.png"
26#define TEX1    L"Media\\Maps\\pixel-grid-gy.png"
27#define TEX2    L"Media\\Maps\\fire.jpg"                // src: astronomy.swin.edu.au/~pbourke/texture/fire
28#define ROOM_TEXTURE  L"Media\\Maps\\pixel-grid-b.png"
29
30//--------------------------------------------------------------------------------------
31// Constants
32//--------------------------------------------------------------------------------------
33
34/// size of the cube map taken from the reference point of the object
35#define CUBEMAP_SIZE    128 // 256
36/// size of the cube map for diffuse/glossy reflections
37int LR_CUBEMAP_SIZE     = 2;
38
39/// Number of samples when precomputing geometric factors.
40//#define M 25                          // for production
41#define M 10                    // for runtime
42
43extern Parameters pp;
44bool bPreproc = false;
45
46float eval( float cos_theta, float dw );
47float evaluate( float dx, float dy )
48{
49        return eval( 2*dx-1, dy*2*3.14159f ) / 3;
50}
51
52/// Called by ::OnCreateDevice() (Main.cpp) to perform app-specific tasks.
53void EnvMap::OnCreateDevice( IDirect3DDevice9* pd3dDevice, ID3DXEffect* g_pEffect )
54{
55        this->pd3dDevice = pd3dDevice;
56        this->g_pEffect = g_pEffect;
57
58        // init centralMesh array
59        meshCount = 0;
60        // room
61        meshes[meshCount++] = new Mesh(MESH0, TEX0, 0, D3DXVECTOR3(0,0,0));                     // room
62
63//      meshes[meshCount++] = new Mesh(MESH1, TEX2, 0.6, D3DXVECTOR3(0,-1.7,0));        // 1 fireball
64
65        meshes[meshCount++] = new Mesh(MESH1, TEX2, 0.6, D3DXVECTOR3(1.5,0,1.5));       // fireballs
66        meshes[meshCount++] = new Mesh(MESH1, TEX2, 0.6, D3DXVECTOR3(1.5,0,-1.5));
67        meshes[meshCount++] = new Mesh(MESH1, TEX2, 0.6, D3DXVECTOR3(-1.5,0,1.5));
68        meshes[meshCount++] = new Mesh(MESH1, TEX2, 0.6, D3DXVECTOR3(-1.5,0,-1.5));
69
70        // central centralMesh
71        centralMesh = new Mesh(MESH0, TEX0, pp.Get( fMeshScale )*2, D3DXVECTOR3(0,0,0));
72        centralMesh->SetContainerSize( D3DXVECTOR3(roomSize,roomSize,roomSize) );
73        centralMesh->SetMeshPosition( D3DXVECTOR3(-roomSize*2/3,0,0) );
74       
75        ChooseMesh( pp.GetInt( iWhichMesh ));
76       
77        bCubeMapIsValid = false;
78}
79
80/// Called by ::OnDestroyDevice() (Main.cpp) to perform app-specific tasks.
81void EnvMap::OnDestroyDevice()
82{
83        // central centralMesh
84        delete centralMesh;
85
86        // destroy centralMesh array
87        for (int i=0; i<meshCount; i++)
88                delete meshes[i];
89        meshCount = 0;
90
91        SAFE_RELEASE( pCosValuesTexture );
92}
93
94/// Called by ::OnResetDevice() (Main.cpp) to perform app-specific tasks.
95void EnvMap::OnResetDevice()
96{
97        // 1: mipmapping disabled, (1 level only)
98        // D3DX_DEFAULT: mipmapping enabled
99        V( D3DXCreateTextureFromFileExW( pd3dDevice, ROOM_TEXTURE,
100                D3DX_DEFAULT, D3DX_DEFAULT, 1/*1 or D3DX_DEFAULT=all*/, 0, D3DFMT_A16B16G16R16F, D3DPOOL_MANAGED,
101                D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL,
102                &pRoomTexture ) );
103
104        int exp = pp.GetInt( iResolution ) + 1; // 1..4
105        LR_CUBEMAP_SIZE = pow( 2, exp );
106
107        pCubeTexture             = CreateCubeTexture( CUBEMAP_SIZE,             D3DFMT_A16B16G16R16F );
108        pCubeTextureSmall        = CreateCubeTexture( LR_CUBEMAP_SIZE,  D3DFMT_A16B16G16R16F );
109        pCubeTexturePreConvolved = CreateCubeTexture( LR_CUBEMAP_SIZE,  D3DFMT_A16B16G16R16F );
110
111        InitFullScreenQuad();
112        cube = new Cube(pd3dDevice);
113}
114
115/// Called by ::OnLostDevice() (Main.cpp) to perform app-specific tasks.
116void EnvMap::OnLostDevice()
117{
118        SAFE_RELEASE( pRoomTexture );
119        //SAFE_RELEASE( pBoxTexture );
120        SAFE_RELEASE( pCubeTexture );
121        SAFE_RELEASE( pCubeTextureSmall );
122        SAFE_RELEASE( pCubeTexturePreConvolved );
123//      SAFE_RELEASE( pCosValuesTexture );
124        SAFE_RELEASE( pVertexBuffer );  // fullscreen quad
125        cube->Destroy();
126        delete cube;
127
128        bCubeMapIsValid = false;
129}
130
131/// Called when the resolution of the cube maps is to change.
132/// To re-generate all resources, the DirectX device is simply reseted.
133void EnvMap::InvalidateResolution()
134{
135        if (!bCubeMapIsValid) return;   // don't do anything during GUI initialization
136
137        // rebuild textures
138        OnLostDevice();         // !!!!!
139        OnResetDevice();        // !!!!!
140}
141
142
143/// Loads the specified mesh.
144void EnvMap::ChooseMesh(int whichMesh)
145{
146        if (centralMesh == NULL) return;
147
148        // redirect call from keyboard to parameter class
149        if ( pp.GetInt( iWhichMesh ) != whichMesh)
150        {
151                pp.SetInt( iWhichMesh, whichMesh );
152                return;
153        }
154
155        switch (whichMesh)
156        {
157                case 0: centralMesh->Load(MESH0);  break;
158                case 1: centralMesh->Load(MESH1);  break;
159                case 2: centralMesh->Load(MESH2);  break;
160                case 3: centralMesh->Load(MESH3);  break;
161                case 4: centralMesh->Load(MESH4);  break;
162                case 5: centralMesh->Load(MESH5);  break;
163                case 6: centralMesh->Load(MESH6);  break;
164                case 7: centralMesh->Load(MESH7);  break;
165                case 8: centralMesh->Load(MESH8);  break;
166                case 9: centralMesh->Load(MESH9);  break;
167        }
168
169        bCubeMapIsValid = false;        // ask for cubemap redraw
170}
171
172/// Handles keystroke messages.
173void EnvMap::KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown )
174{
175    if( bKeyDown )
176    {
177                bool b = pp.Get( bConfineToRoom );
178                float step = 0.1f;
179                //float max = roomSize-1.02f;
180
181                if ( nChar >= '0' && nChar <= '9' ) {
182                        int whichMesh = nChar-'0';
183                        ChooseMesh(whichMesh);          // load centralMesh
184
185                }
186                else switch( nChar )
187        {
188                        case VK_RIGHT: centralMesh->Move( D3DXVECTOR3( step,0,0), b ); break;
189                        case VK_LEFT:  centralMesh->Move( D3DXVECTOR3(-step,0,0), b ); break;
190                        case VK_UP:        centralMesh->Move( D3DXVECTOR3(0, step,0), b ); break;
191                        case VK_DOWN:  centralMesh->Move( D3DXVECTOR3(0,-step,0), b ); break;
192                        case VK_PRIOR: centralMesh->Move( D3DXVECTOR3(0,0, step), b ); break;
193                        case VK_NEXT:  centralMesh->Move( D3DXVECTOR3(0,0,-step), b ); break;
194                        case 32:           bCubeMapIsValid = false; break;
195
196       } // switch
197    }
198}
199
200/// Performs prepocessing steps if necessary and then renders the scene.
201void EnvMap::OnFrameRender( IDirect3DDevice9* pd3dDevice, D3DXMATRIXA16& mView, D3DXMATRIXA16& mProj )
202{
203        /*if (pp.Get( bAutoGenCubeMap ))                // calculate cube maps for each frame
204                bCubeMapIsValid = false;*/
205
206        // regenerate cube maps if necessary
207        // regenerate if:
208        // - centralMesh changes
209        // - resolution changes
210        if ( !bCubeMapIsValid )
211        {
212                long clock1 = clock();
213
214                // (to avoid warnings)
215                V( g_pEffect->SetTexture( "EnvironmentMap", NULL ) );
216
217                D3DXVECTOR3 p = centralMesh->GetMeshPosition();
218                centralMesh->SetMeshPosition( D3DXVECTOR3(0,0,0) );
219               
220                // to be precise: offsetting to the center of the (DirectX) texel
221                V( g_pEffect->SetFloat( "texel_size",  1 / (float)CUBEMAP_SIZE ) );
222                // I had to call it 2 times to render the environment completely
223                RenderCubeMap( pCubeTexture );
224                RenderCubeMap( pCubeTexture );  // don't ask why
225
226                centralMesh->SetMeshPosition( p );
227                V( g_pEffect->SetFloat( "texel_size",  0 ) );
228
229                ReduceCubeMapSize( pCubeTexture, pCubeTextureSmall);
230                bShininessIsValid = false;
231                bCubeMapIsValid = true;
232        }
233
234        if ( !bShininessIsValid )       
235        // refresh cos texture
236        {
237                if ( pp.GetInt( iWhichMethod ) == DIFFUSE_SPECULAR_CLASSIC )
238                {
239                        // prepare preconvolved cubemap
240                        PreConvolve(pCubeTextureSmall, pCubeTexturePreConvolved);
241                }
242                else
243                {
244                        // load precomputed reflectivity integral values
245                        // or generate them if not found
246                        GenerateCosTextureIfNotFound( L"cos\\cos_s", &evaluate );
247                }
248
249                bShininessIsValid = true;
250        }
251
252        // Render the scene
253        DoRendering(mView, mProj);
254}
255
256/// Render the scene.
257void EnvMap::DoRendering(D3DXMATRIXA16& mView, D3DXMATRIXA16& mProj)
258{
259        UINT uPasses;
260
261        D3DCOLOR backgroundColor = D3DCOLOR_ARGB(0, 66, 75, 121);
262        V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, backgroundColor, 1.0f, 0) );
263
264        D3DXVECTOR3 eye = *camera->GetEyePt();
265        D3DXVECTOR4 eyePos(eye.x, eye.y, eye.z, 1);
266        D3DXVECTOR4 refPos(reference_pos.x, reference_pos.y, reference_pos.z, 1);
267
268        V( g_pEffect->SetTexture( "EnvironmentMap", pCubeTexture ) );
269        V( g_pEffect->SetTexture( "SmallEnvironmentMap", pCubeTextureSmall ) );
270        V( g_pEffect->SetTexture( "Decoration", pCosValuesTexture ) );
271
272        V( g_pEffect->SetVector ( "eyePos", &eyePos ) );
273        V( g_pEffect->SetVector ( "reference_pos", &refPos ) );
274        V( g_pEffect->SetFloat  ( "intensity", pp.Get( fIntensity ) ));
275        V( g_pEffect->SetFloat  ( "shininess", (float)pp.GetInt( iShininess )));
276        V( g_pEffect->SetInt    ( "LR_CUBEMAP_SIZE", LR_CUBEMAP_SIZE ));
277
278        // ------------------------- choose technique -------------------------
279       
280        switch (pp.GetInt( iWhichMethod )) {
281                case DIFFUSE_SPECULAR_CLASSIC:
282                        V( g_pEffect->SetTechnique( "EnvMapDiffuseClassic" ) ); 
283                        V( g_pEffect->SetTexture( "PreconvolvedEnvironmentMap", pCubeTexturePreConvolved ) );
284                        break;
285                case DIFFUSE_SPECULAR_LOCALIZED:
286                        //V( g_pEffect->SetTechnique( "EnvMapDiffuseLocalized" ) );
287                        char techniqueName[100];
288                        sprintf(techniqueName, "EnvMapDiffuseLocalized%i", LR_CUBEMAP_SIZE );
289                        V( g_pEffect->SetTechnique( techniqueName ) );
290                        break;
291                case DIFFUSE_SPECULAR_LOCALIZED_NEW:
292                        sprintf(techniqueName, "EnvMapDiffuseLocalizedNew%i", LR_CUBEMAP_SIZE );
293                        V( g_pEffect->SetTechnique( "EnvMapDiffuseLocalizedNew" ) );
294                        break;
295                case DIFFUSE_SPECULAR_LOCALIZED_5TEX:
296                        V( g_pEffect->SetTechnique( "EnvMapDiffuseLocalized5Tex" ) );
297                        break;
298        }
299
300        // ------------------------ end choose technique ------------------------
301       
302
303        V( g_pEffect->Begin( &uPasses, 0 ) );
304        V( g_pEffect->BeginPass( 0 ) ); // csak 1 db PASS wan
305
306                DrawCenterObjects( mView, mProj );
307
308                if (pp.Get( bMultipleObjects ))
309                // draw two more object instances
310                {
311                        double offset=1.3;
312
313                        D3DXVECTOR3 pos = centralMesh->GetMeshPosition();
314                        centralMesh->SetMeshPosition( pos + D3DXVECTOR3(0,offset,0));
315                        DrawCenterObjects( mView, mProj );
316
317                        centralMesh->SetMeshPosition( pos + D3DXVECTOR3(0,-offset,0));
318                        DrawCenterObjects( mView, mProj );
319
320                        centralMesh->SetMeshPosition( pos );
321                }
322
323        V( g_pEffect->EndPass() );
324        V( g_pEffect->End() );
325
326        if (pp.GetInt( iShowCubeMap ) == 3 && pp.GetInt( iWhichMethod ) != DIFFUSE_SPECULAR_CLASSIC )
327                pp.SetInt( iShowCubeMap, 0 );
328
329        switch (pp.GetInt( iShowCubeMap ))
330        {
331                case 0: break;
332                case 1: V( g_pEffect->SetTexture( "EnvironmentMap", pCubeTexture ) );  break;
333                case 2: V( g_pEffect->SetTexture( "EnvironmentMap", pCubeTextureSmall   ) ); break;
334                case 3: V( g_pEffect->SetTexture( "EnvironmentMap", pCubeTexturePreConvolved) ); break;
335        }
336
337        // draw environment objects (room)
338        V( g_pEffect->SetTechnique( "IlluminatedScene" ) );
339        V( g_pEffect->Begin( &uPasses, 0 ) );
340        V( g_pEffect->BeginPass( 0 ) );
341
342                DrawEnvObjects( mView, mProj );
343
344        V( g_pEffect->EndPass() );
345        V( g_pEffect->End() );
346
347        V( g_pEffect->SetInt ( "iShowCubeMap", 0 ));
348}
349
350/// Draw the central diffuse/glossy object.
351void EnvMap::DrawCenterObjects( D3DXMATRIXA16& mView, D3DXMATRIXA16& mProj )
352{
353        D3DXVECTOR4 objColor(1,1,0,1);
354
355        objColor = D3DXVECTOR4(1,1,1,1);
356        V( g_pEffect->SetVector( "objColor",  &objColor ) );
357
358        float scale = centralMesh->GetMeshScale();
359        D3DXVECTOR3 offset = centralMesh->GetMeshPosition();
360
361        D3DXMATRIXA16 w, rot;
362        D3DXMatrixRotationY( &rot, - 3.14159f  /  2);
363
364        if ( pp.GetInt( iWhichMesh ) == 8)      // rotate the bunny for better look
365        {
366                D3DXMatrixRotationY( &rot, - 3.14159f);
367                w = rot * ScaleAndOffset( scale, offset );
368        }
369        else if ( pp.GetInt( iWhichMesh ) == 9) // rotate the skull for better look
370        {
371                D3DXMatrixRotationY( &rot, - 3.14159f  /  2);
372                w = rot * ScaleAndOffset( scale, offset );
373        }
374        else
375                w = ScaleAndOffset( scale, offset );
376
377        SetWorldViewProj( w, mView, mProj );
378
379        centralMesh->Draw();
380}
381
382/// Draw environment objects.
383void EnvMap::DrawEnvObjects( D3DXMATRIXA16& mView, D3DXMATRIXA16& mProj )
384{
385        D3DXVECTOR4 objColor(3,3,3,1);
386        if (bPreproc)
387                objColor *= 5;
388        g_pEffect->SetVector( "objColor", &objColor );
389        V( g_pEffect->SetFloat( "brightness", 0.0f ));
390        g_pEffect->CommitChanges();
391
392        // meshes of the environment
393        if (pp.Get( bShowFireballs ))
394        {
395                for (int i=1; i<meshCount; i++)
396                {
397                        V( g_pEffect->SetTexture( "Decoration", meshes[i]->GetTexture() ) );
398
399                        float scale = meshes[i]->GetMeshScale();
400                        D3DXVECTOR3 offset = meshes[i]->GetMeshPosition();
401                        SetWorldViewProj( ScaleAndOffset( scale, offset ), mView, mProj );
402
403                        meshes[i]->Draw();
404                }
405        }
406
407        V( g_pEffect->SetTexture( "Decoration", pRoomTexture ) );
408
409        // ----------------------------------------
410        // draw a room of size [-roomSize..roomSize]
411        // ----------------------------------------
412
413        cube->PrepareDrawing();
414        D3DXVECTOR3 scale = D3DXVECTOR3(roomSize,roomSize,roomSize);
415        SetWorldViewProj( ScaleAndOffset( scale, D3DXVECTOR3(0,0,0) ), mView, mProj );
416
417        // flip normals so that the room is visible from its inside
418        V( pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW) );
419        V( g_pEffect->SetTexture( "Decoration", pRoomTexture ) );
420        V( g_pEffect->SetFloat( "brightness", 2.8f ));
421        V( g_pEffect->SetInt ( "iShowCubeMap", 0 ));
422
423        // decide if the room should visualize one of the cube maps
424        if ( bCubeMapIsValid && pp.GetInt( iShowCubeMap ) > 0)
425                V( g_pEffect->SetInt ( "iShowCubeMap", pp.GetInt( iShowCubeMap ) ));
426
427        D3DXVECTOR4 facecolors[]={D3DXVECTOR4(1,0,0,1),
428                                                        D3DXVECTOR4(1,0,1,1),
429                                                        D3DXVECTOR4(1,1,0,1),
430                                                        D3DXVECTOR4(0,0,1,1),
431                                                        D3DXVECTOR4(0,1,0,1),
432                                                        D3DXVECTOR4(0,1,1,1)};
433        for( int i=0; i<6; i++ )
434        {
435        /*      objColor = D3DXVECTOR4(0.4f-i*0.1f, i*0.1f, (i%2)*0.4f, 1);             // a colorful room
436                if (i==3) objColor += D3DXVECTOR4(0.05, 0.05, 0, 1);*/         
437
438                objColor = facecolors[i];               
439
440                g_pEffect->SetVector( "objColor", &objColor );
441                g_pEffect->CommitChanges();
442               
443                cube->DrawFace(i);
444        }
445
446        pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
447        V( g_pEffect->SetInt ( "iShowCubeMap", 0 ));
448        //V( g_pEffect->SetInt( "shininess", 2));
449        V( g_pEffect->SetFloat( "brightness", 1.0f ));
450
451        //V( g_pEffect->SetTexture( "Decoration", pBoxTexture ) );
452
453        /*// térelválasztó fal rajzolása
454        SetWorldViewProj( ScaleAndOffset( D3DXVECTOR3(0.01,roomSizeCurr*2/3,roomSizeCurr*0.3),
455                D3DXVECTOR3(1,-roomSizeCurr/3,0) ), mView, mProj );
456
457        objColor = D3DXVECTOR4(1.3,0,0.8, 1);
458        g_pEffect->SetVector( "objColor", &objColor );
459
460        for( int i=0; i<6; i++ )
461        {
462                cube->DrawFace(i);
463        }*/
464
465        g_pEffect->CommitChanges();
466}
467
468/**
469        Sets the given scaling and offset.
470        @return The resulting world transformation matrix.
471*/
472D3DXMATRIXA16 EnvMap::ScaleAndOffset(D3DXVECTOR3 vScale, D3DXVECTOR3 vOffset)
473{
474        D3DXMATRIXA16 mScale, mOffset;
475        D3DXMatrixIdentity(&mScale);
476        D3DXMatrixIdentity(&mOffset);
477
478        D3DXMatrixTranslation( &mOffset, vOffset.x, vOffset.y, vOffset.z );
479        D3DXMatrixScaling( &mScale, vScale.x, vScale.y, vScale.z );
480
481        return mScale * mOffset;
482}
483
484/**
485        Sets the given uniform scaling and an offset.
486        @return The resulting world transformation matrix.
487*/
488D3DXMATRIXA16 EnvMap::ScaleAndOffset(float fScale, D3DXVECTOR3 vOffset)
489{
490        return ScaleAndOffset( D3DXVECTOR3(fScale,fScale,fScale), vOffset );
491}
492
493/**
494        \brief Uploads the specified world/view/projection transformation matrices to the GPU.
495*/
496void EnvMap::SetWorldViewProj(D3DXMATRIXA16& mWorld, D3DXMATRIXA16& mView, D3DXMATRIXA16& mProj )
497{
498        D3DXMATRIXA16 mWorldView = mWorld * mView;
499        D3DXMATRIXA16 mWorldViewProjection = mWorldView * mProj;
500
501        D3DXMATRIXA16 mWorldViewI, mWorldViewIT, mWorldI, mWorldIT;
502        D3DXMatrixInverse(&mWorldViewI, NULL, &mWorldView);
503        D3DXMatrixTranspose(&mWorldViewIT, &mWorldViewI);
504
505        D3DXMatrixInverse(&mWorldI, NULL, &mWorld);
506        D3DXMatrixTranspose(&mWorldIT, &mWorldI);
507
508        V( g_pEffect->SetMatrix( "World", &mWorld ) );
509        V( g_pEffect->SetMatrix( "WorldIT", &mWorldIT ) );
510        V( g_pEffect->SetMatrix( "WorldView", &mWorldView ) );
511        //V( g_pEffect->SetMatrix( "WorldViewIT", &mWorldViewIT ) );
512
513        V( g_pEffect->SetMatrix( "WorldViewProjection", &mWorldViewProjection ) );
514        V( g_pEffect->CommitChanges() );
515}
516
517/// \brief Renders the environment into the specified cubemap.
518///
519/// The camera is placed into #reference_pos. Uses technique IlluminatedScenePS() for rendering.
520void EnvMap::RenderCubeMap(IDirect3DCubeTexture9* pCubeTexture)
521{
522        IDirect3DSurface9*      oldRenderTarget;
523        IDirect3DSurface9*      oldDepthStencil;
524        IDirect3DSurface9*  newDepthStencil;
525
526        // create a CUBEMAP_SIZE x CUBEMAP_SIZE size depth buffer
527        pd3dDevice->CreateDepthStencilSurface(CUBEMAP_SIZE, CUBEMAP_SIZE, D3DFMT_D16,
528                D3DMULTISAMPLE_NONE, 0, true, &newDepthStencil, NULL);
529
530        // replace old depth buffer
531        pd3dDevice->GetDepthStencilSurface(&oldDepthStencil);
532        pd3dDevice->SetDepthStencilSurface(newDepthStencil);
533
534        pd3dDevice->GetRenderTarget(0,&oldRenderTarget);
535
536        UINT uPasses;
537        for (int i = 0; i < 6; i++)
538        {
539                IDirect3DSurface9* pFace;
540                V( pCubeTexture->GetCubeMapSurface((D3DCUBEMAP_FACES)i, 0, &pFace) );
541                V( pd3dDevice->SetRenderTarget(0, pFace) );
542
543                V( g_pEffect->SetTechnique( "IlluminatedScene" ) );
544                V( g_pEffect->SetTexture( "Decoration", pRoomTexture ) );
545
546                V( g_pEffect->Begin( &uPasses, 0 ) );
547                V( g_pEffect->BeginPass( 0 ) );
548               
549                V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
550                        D3DCOLOR_ARGB(0,/*i==0 ? 255 : */0,0,0), 1.0f, 0) );
551
552                // mView
553                D3DXMATRIXA16 mView, mProj;
554
555                // looking toward the cube map faces _from the origin_
556                // mView = DXUTGetCubeMapViewMatrix( i );                       
557
558                //float scale = centralMesh->GetMeshScale();
559                //D3DXVECTOR3 offset = centralMesh->GetMeshPosition();
560
561                D3DXVECTOR3 vecEye(0,0,0);
562            D3DXVECTOR3 vecAt(0.0f, 0.0f, 0.0f);
563            D3DXVECTOR3 vecUp(0.0f, 0.0f, 0.0f);
564
565                switch( i )
566                {
567            case D3DCUBEMAP_FACE_POSITIVE_X:
568                vecAt = D3DXVECTOR3( 1, 0, 0 );
569                vecUp = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
570                break;
571            case D3DCUBEMAP_FACE_NEGATIVE_X:
572                vecAt = D3DXVECTOR3(-1.0f, 0.0f, 0.0f );
573                vecUp = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
574                break;
575            case D3DCUBEMAP_FACE_POSITIVE_Y:
576                vecAt = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
577                vecUp = D3DXVECTOR3( 0.0f, 0.0f,-1.0f );
578                break;
579            case D3DCUBEMAP_FACE_NEGATIVE_Y:
580                vecAt = D3DXVECTOR3( 0.0f,-1.0f, 0.0f );
581                vecUp = D3DXVECTOR3( 0.0f, 0.0f, 1.0f );
582                break;
583            case D3DCUBEMAP_FACE_POSITIVE_Z:
584                vecAt = D3DXVECTOR3( 0.0f, 0.0f, 1.0f );
585                vecUp = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
586                break;
587            case D3DCUBEMAP_FACE_NEGATIVE_Z:
588                vecAt = D3DXVECTOR3( 0.0f, 0.0f,-1.0f );       
589                vecUp = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
590                break;
591        }
592
593                // reference point is the current object position
594                reference_pos = centralMesh->GetMeshPosition();
595                vecEye += reference_pos;
596                vecAt += reference_pos;
597
598                D3DXMatrixLookAtLH(&mView, &vecEye, &vecAt, &vecUp);
599                D3DXMatrixPerspectiveFovLH( &mProj, D3DX_PI/2, 1, 0.1, 100 );
600
601                bPreproc = true;
602                DrawEnvObjects(mView, mProj);   // boost lightness of the environment
603                bPreproc = false;
604
605                V( g_pEffect->EndPass() );
606                V( g_pEffect->End() );
607
608                SAFE_RELEASE( pFace );
609        }
610
611        // restore old rendertarget & depth buffer
612        pd3dDevice->SetRenderTarget(0, oldRenderTarget);
613        pd3dDevice->SetDepthStencilSurface(oldDepthStencil);
614        SAFE_RELEASE( oldDepthStencil );
615        SAFE_RELEASE( oldRenderTarget );
616        SAFE_RELEASE( newDepthStencil );
617}
618
619/// Downsample a cube map to resolution LR_CUBEMAP_SIZE
620void EnvMap::ReduceCubeMapSize(IDirect3DCubeTexture9* pSourceCube, IDirect3DCubeTexture9* pDestCube)
621{
622        // get the descriptor of the source cubemap
623        IDirect3DSurface9* pSourceFace;
624        pSourceCube->GetCubeMapSurface((D3DCUBEMAP_FACES)0, 0, &pSourceFace);
625        D3DSURFACE_DESC sourceDesc;
626        pSourceFace->GetDesc( &sourceDesc );
627        SAFE_RELEASE( pSourceFace );
628
629        // pTexture : copy of the source cubemap's face
630        IDirect3DTexture9* pTexture = NULL;
631        V( D3DXCreateTexture( pd3dDevice, sourceDesc.Width, sourceDesc.Height, 1,
632                                                D3DUSAGE_RENDERTARGET, D3DFMT_A16B16G16R16F, D3DPOOL_DEFAULT, &pTexture ) );
633
634        IDirect3DSurface9* m_backBuffer=NULL;
635        pd3dDevice->GetRenderTarget(0, &m_backBuffer);
636
637        for(int i=0; i<6; i++)
638        {
639                IDirect3DSurface9* pFace;
640                IDirect3DSurface9* pSurface;
641
642                // a forrás cubemap akt. lapjának átmásolása pTexture-be
643                V( pSourceCube->GetCubeMapSurface((D3DCUBEMAP_FACES)i, 0, &pFace) );
644                V( pTexture->GetSurfaceLevel( 0, &pSurface ) );
645                V( pd3dDevice->StretchRect(pFace, NULL, pSurface, NULL, D3DTEXF_NONE) );
646
647                // pTexture átadása a shadernek
648                V( g_pEffect->SetTexture( "Decoration", pTexture ) );
649       
650                // rendertarget: a cél lap
651                IDirect3DSurface9* pDestCubeFace;
652                V( pDestCube->GetCubeMapSurface((D3DCUBEMAP_FACES)i, 0, &pDestCubeFace) );
653                V( pd3dDevice->SetRenderTarget(0, pDestCubeFace) );
654
655                // begin drawing
656                //V( g_pEffect->SetTechnique( "ReduceTexture" ) );
657
658                char techniqueName[100];
659                sprintf(techniqueName, "ReduceTexture%i", LR_CUBEMAP_SIZE );
660                V( g_pEffect->SetTechnique( techniqueName ) );
661
662
663                UINT uPasses;
664                V( g_pEffect->Begin( &uPasses, 0 ) );
665                V( g_pEffect->BeginPass( 0 ) );
666
667                        V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
668                                        D3DCOLOR_ARGB(0,255,255,0), 1.0f, 0) );
669
670                        // draw a square
671                        DrawFullScreenQuad();
672               
673                V( g_pEffect->EndPass() );
674                V( g_pEffect->End() );
675
676                SAFE_RELEASE( pSurface );
677                SAFE_RELEASE( pFace );
678                SAFE_RELEASE( pDestCubeFace );
679        }
680
681        pd3dDevice->SetRenderTarget(0,m_backBuffer);
682
683        SAFE_RELEASE( pTexture );
684        SAFE_RELEASE( m_backBuffer );
685}
686
687/// \brief Calculates the irradiance map by convolution.
688///
689/// Convolves data from the source cubemap and stores the result in the target cubemap. Uses ConvolutionPS().
690void EnvMap::PreConvolve(IDirect3DCubeTexture9* pSourceCube, IDirect3DCubeTexture9* pDestCube)
691{
692        IDirect3DSurface9*      oldRenderTarget;
693        IDirect3DSurface9*      oldDepthStencil;
694        IDirect3DSurface9*  newDepthStencil;
695
696        // create a LR_CUBEMAP_SIZE x LR_CUBEMAP_SIZE size depth buffer
697        pd3dDevice->CreateDepthStencilSurface(LR_CUBEMAP_SIZE, LR_CUBEMAP_SIZE, D3DFMT_D16,
698                D3DMULTISAMPLE_NONE, 0, true, &newDepthStencil, NULL);
699
700        // replace old depth buffer
701        pd3dDevice->GetDepthStencilSurface(&oldDepthStencil);
702        pd3dDevice->SetDepthStencilSurface(newDepthStencil);
703        pd3dDevice->GetRenderTarget(0, &oldRenderTarget);
704
705        V( g_pEffect->SetTexture( "SmallEnvironmentMap", pSourceCube ) );
706
707        float s = (float)pp.GetInt( iShininess );
708        V( g_pEffect->SetFloat  ( "shininess", s));
709
710        for(int i=0; i<6; i++)
711        {
712                V( g_pEffect->SetInt( "nFace", i ) );
713       
714                // set a face of 'pDestCube' as rendertarget
715                IDirect3DSurface9* pDestCubeFace;
716                V( pDestCube->GetCubeMapSurface((D3DCUBEMAP_FACES)i, 0, &pDestCubeFace) );
717                V( pd3dDevice->SetRenderTarget(0, pDestCubeFace) );
718
719                // begin drawing
720                //V( g_pEffect->SetTechnique( "Convolution" ) );
721                char techniqueName[100];
722                sprintf(techniqueName, "Convolution%i", LR_CUBEMAP_SIZE );
723                V( g_pEffect->SetTechnique( techniqueName ) );
724
725
726                UINT uPasses;
727                V( g_pEffect->Begin( &uPasses, 0 ) );
728                V( g_pEffect->BeginPass( 0 ) );
729
730                        V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
731                                        D3DCOLOR_ARGB(0,255,255,255), 1.0f, 0) );
732
733                        // draw a square
734                        DrawFullScreenQuad();
735               
736                V( g_pEffect->EndPass() );
737                V( g_pEffect->End() );
738                SAFE_RELEASE( pDestCubeFace );
739        }
740
741        //SaveCubeMap( pDestCube, "ha", "");
742
743        // restore old rendertarget & depth buffer
744        pd3dDevice->SetRenderTarget(0, oldRenderTarget);
745        pd3dDevice->SetDepthStencilSurface(oldDepthStencil);
746        SAFE_RELEASE( oldDepthStencil );
747        SAFE_RELEASE( oldRenderTarget );
748        SAFE_RELEASE( newDepthStencil );
749}
750
751void EnvMap::SaveCubeMap(IDirect3DCubeTexture9* pCubeTexture, char* FileNamePrefix, char* FileNameSuffix)
752{
753        char buf[100];
754        wchar_t wbuf[100];
755
756        for(int i=0;i<6;i++)
757        {
758                sprintf(buf, "%s%i%s.png", FileNamePrefix, i, FileNameSuffix);
759                mbstowcs( wbuf, buf, 100 );
760
761                IDirect3DSurface9* pFace;
762                V( pCubeTexture->GetCubeMapSurface((D3DCUBEMAP_FACES)i, 0, &pFace) );
763                D3DXSaveSurfaceToFile(wbuf, D3DXIFF_PNG, pFace, NULL,NULL);
764        }
765}
766
767/// \brief Calls GenerateCosTexture() if the specified texture is not yet calculated
768/// and stored as a texture in the <b>cos</b> subdirectory.
769
770void EnvMap::GenerateCosTextureIfNotFound( wchar_t* fileName, eval_fn evaluator )
771// precomputing geometric factors
772{
773        wchar_t wCosTextureName[100];
774        swprintf( wCosTextureName, L"%s%02i.png", fileName, pp.GetInt( iShininess ) );
775
776        // try to open
777        hr = D3DXCreateTextureFromFile( pd3dDevice, wCosTextureName, &pCosValuesTexture);
778        if ( FAILED( hr ) )
779        {
780                wchar_t buf[ 400 ];
781                swprintf( buf, L"Preprocessed texture not found!\n"
782                        L"The program will generate the following texture:\n"
783                        L"Texture name: %s\n"
784                        L"Shininess: %i\n"
785                        L"Iterations: %i (%i%% of the original texture quality).",
786                        wCosTextureName, pp.GetInt( iShininess ), M*M, 100 * M*M/25/25 );
787                MessageBox( NULL, buf, L"Texture not found!", MB_ICONINFORMATION );                     // show message
788
789                // generate
790                pCosValuesTexture = GenerateCosTexture( evaluator );
791
792                // save
793                IDirect3DSurface9* pSurface = NULL;
794                V( pCosValuesTexture->GetSurfaceLevel( 0, &pSurface ) );
795                hr = D3DXSaveSurfaceToFile( wCosTextureName, D3DXIFF_PNG, pSurface, NULL,NULL);
796                if ( FAILED( hr ) )
797                {
798                        swprintf( buf, L"Failed to save texture %s!", wCosTextureName );
799                        MessageBox( NULL, buf, L"Texture saving failed!", MB_ICONERROR );
800                }
801                SAFE_RELEASE( pSurface );
802        }
803}
804
805/// Generates precomputed texture to store values for the reflectivity integral. Uses the eval() function.
806IDirect3DTexture9* EnvMap::GenerateCosTexture( eval_fn evaluator )
807{
808        const int X = 128;
809        const int Y = 128;
810
811    IDirect3DDevice9* pd3dDevice = DXUTGetD3DDevice();
812   
813        // Create a temporary texture
814    LPDIRECT3DTEXTURE9 texTemp;
815    V( pd3dDevice->CreateTexture( X, Y, 1,
816                                         D3DUSAGE_DYNAMIC, D3DFMT_A32B32G32R32F,
817                                         D3DPOOL_DEFAULT, &texTemp, NULL ) );
818
819    D3DLOCKED_RECT Rect;
820    V( texTemp->LockRect(0, &Rect, 0, 0) );
821   
822    int u, v;
823    float dx, dy, I;
824    float* pBits; 
825
826        FILE* f = fopen( ".progress_bar", "wt");               
827        fprintf(f, "");
828        fclose( f );
829
830        long clock1 = clock();
831
832    for( v=0; v < Y; ++v )
833    {
834        pBits = (float*)((char*)(Rect.pBits)+v*Rect.Pitch);
835       
836        for( u=0; u < X; ++u )
837        {
838            dx = u/(float)X;    // 0..1
839            dy = v/(float)Y;    // 0..1
840
841                        //*(pBits++) = eval( 2*dx-1, dy*2*3.14159f ) / 3;  // old: intensity
842                        //*(pBits++) = values[ v*X + u ] / 50; // intensity
843
844                        float result = evaluator( dx, dy );
845                *(pBits++) = result;  // intensity
846                        *(pBits++) = result;  // intensity
847                        *(pBits++) = result;  // intensity
848                        *(pBits++) = 0;  // intensity
849        }
850
851                if ( v > 0 && v % (Y/10) == 0)
852                {
853                        FILE* f = fopen( ".progress_bar", "at");                // some silly progress bar:
854                        fprintf(f, "#");                                                        // write a # for each 10% done
855                        fclose( f );
856                }
857    }
858
859/*      long clock2 = clock();
860        float time = (float)(clock2-clock1)/CLOCKS_PER_SEC;
861
862        f = fopen( ".progress_bar", "at");     
863        fprintf(f, "\ntime:%.3g secs", time);                                                   
864        fclose( f );*/
865               
866    texTemp->UnlockRect(0);
867   
868        return texTemp;
869}
870
871/// \brief Calculates the reflectivity integral for a given texel.
872///
873/// The angle between the surface normal and texel center is described by cos_theta
874/// and the solid angle occupied by the texel is denoted by dw.
875///
876/// Instead of evaluating the reflectivity integral with only one sample belongig to the texel center
877/// (that would give us a result of cos_theta x dw), we use 2 #M x 2 #M x #M regulary spaced samples, and
878/// discard those that lie outside the unit hemisphere. The remaining samples are regulary distributed over the
879/// hemisphere.
880///
881/// For each sample, we check if it lies inside the cone of the specified solid angle.
882/// If yes, its contribution is considered.
883
884float eval( float cos_theta, float dw )
885{
886        const float PI = 3.14159f;
887       
888        float sum = 0;
889        int counter = 0;
890        int shininess = pp.GetInt( iShininess );
891       
892        float sin_theta = sqrt(1-cos_theta*cos_theta);
893       
894        D3DXVECTOR3 center( sin_theta, 0, cos_theta );
895        D3DXVECTOR3 up( 0, 0, 1 );
896
897        float cos_min = 1 - dw / 2 / PI;
898       
899        for (int x = -M; x <= M; x++)
900          for (int y = -M; y <= M; y++)
901            for (int z = /*-M*/ 0; z <= M; z++)         // z == up
902                {
903                        D3DXVECTOR3 w(0,0,0);
904                        w.x = x / (float)M;             // -1..1
905                        w.y = y / (float)M;             // -1..1
906                        w.z = z / (float)M;             // 0..1
907
908                        float len = D3DXVec3Length( &w );
909                        if ( len > 0 && len <= 1 )                      // inside the hemisphere
910                        {
911                                w /= len;                                               // normalize
912                               
913                                float cos_curr = D3DXVec3Dot( &w, &center );
914                                if ( cos_curr >= cos_min )              // w is inside the 'cone' of the given solid angle
915                                {
916                                        sum += pow( D3DXVec3Dot( &w, &up ), shininess );
917                                        //sum += D3DXVec3Dot( &w, &up );
918                                }
919
920                                counter++;                                              // number of samples
921                        }
922                }
923         
924         return sum * (2*PI / counter) * ((shininess+2) / PI);
925         //return dx;
926}
Note: See TracBrowser for help on using the repository browser.