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

Revision 1574, 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                        V( g_pEffect->SetTechnique( "EnvMapDiffuseLocalizedNew" ) );
293                        break;
294                case DIFFUSE_SPECULAR_LOCALIZED_P2P:
295                        V( g_pEffect->SetTechnique( "EnvMapDiffuseP2P" ) );
296                        break;
297                case DIFFUSE_SPECULAR_LOCALIZED_5TEX:
298                        V( g_pEffect->SetTechnique( "EnvMapDiffuseLocalized5Tex" ) );
299                        break;
300        }
301
302        // ------------------------ end choose technique ------------------------
303       
304
305        V( g_pEffect->Begin( &uPasses, 0 ) );
306        V( g_pEffect->BeginPass( 0 ) ); // csak 1 db PASS wan
307
308                DrawCenterObjects( mView, mProj );
309
310                if (pp.Get( bMultipleObjects ))
311                // draw two more object instances
312                {
313                        double offset=1.3;
314
315                        D3DXVECTOR3 pos = centralMesh->GetMeshPosition();
316                        centralMesh->SetMeshPosition( pos + D3DXVECTOR3(0,offset,0));
317                        DrawCenterObjects( mView, mProj );
318
319                        centralMesh->SetMeshPosition( pos + D3DXVECTOR3(0,-offset,0));
320                        DrawCenterObjects( mView, mProj );
321
322                        centralMesh->SetMeshPosition( pos );
323                }
324
325        V( g_pEffect->EndPass() );
326        V( g_pEffect->End() );
327
328        if (pp.GetInt( iShowCubeMap ) == 3 && pp.GetInt( iWhichMethod ) != DIFFUSE_SPECULAR_CLASSIC )
329                pp.SetInt( iShowCubeMap, 0 );
330
331        switch (pp.GetInt( iShowCubeMap ))
332        {
333                case 0: break;
334                case 1: V( g_pEffect->SetTexture( "EnvironmentMap", pCubeTexture ) );  break;
335                case 2: V( g_pEffect->SetTexture( "EnvironmentMap", pCubeTextureSmall   ) ); break;
336                case 3: V( g_pEffect->SetTexture( "EnvironmentMap", pCubeTexturePreConvolved) ); break;
337        }
338
339        // draw environment objects (room)
340        V( g_pEffect->SetTechnique( "IlluminatedScene" ) );
341        V( g_pEffect->Begin( &uPasses, 0 ) );
342        V( g_pEffect->BeginPass( 0 ) );
343
344                DrawEnvObjects( mView, mProj );
345
346        V( g_pEffect->EndPass() );
347        V( g_pEffect->End() );
348
349        V( g_pEffect->SetInt ( "iShowCubeMap", 0 ));
350}
351
352/// Draw the central diffuse/glossy object.
353void EnvMap::DrawCenterObjects( D3DXMATRIXA16& mView, D3DXMATRIXA16& mProj )
354{
355        D3DXVECTOR4 objColor(1,1,0,1);
356
357        objColor = D3DXVECTOR4(1,1,1,1);
358        V( g_pEffect->SetVector( "objColor",  &objColor ) );
359
360        float scale = centralMesh->GetMeshScale();
361        D3DXVECTOR3 offset = centralMesh->GetMeshPosition();
362
363        D3DXMATRIXA16 w, rot;
364        D3DXMatrixRotationY( &rot, - 3.14159f  /  2);
365
366        if ( pp.GetInt( iWhichMesh ) == 8)      // rotate the bunny for better look
367        {
368                D3DXMatrixRotationY( &rot, - 3.14159f);
369                w = rot * ScaleAndOffset( scale, offset );
370        }
371        else if ( pp.GetInt( iWhichMesh ) == 9) // rotate the skull for better look
372        {
373                D3DXMatrixRotationY( &rot, - 3.14159f  /  2);
374                w = rot * ScaleAndOffset( scale, offset );
375        }
376        else
377                w = ScaleAndOffset( scale, offset );
378
379        SetWorldViewProj( w, mView, mProj );
380
381        centralMesh->Draw();
382}
383
384/// Draw environment objects.
385void EnvMap::DrawEnvObjects( D3DXMATRIXA16& mView, D3DXMATRIXA16& mProj )
386{
387        D3DXVECTOR4 objColor(3,3,3,1);
388        if (bPreproc)
389                objColor *= 5;
390        g_pEffect->SetVector( "objColor", &objColor );
391        V( g_pEffect->SetFloat( "brightness", 0.0f ));
392        g_pEffect->CommitChanges();
393
394        // meshes of the environment
395        if (pp.Get( bShowFireballs ))
396        {
397                for (int i=1; i<meshCount; i++)
398                {
399                        V( g_pEffect->SetTexture( "Decoration", meshes[i]->GetTexture() ) );
400
401                        float scale = meshes[i]->GetMeshScale();
402                        D3DXVECTOR3 offset = meshes[i]->GetMeshPosition();
403                        SetWorldViewProj( ScaleAndOffset( scale, offset ), mView, mProj );
404
405                        meshes[i]->Draw();
406                }
407        }
408
409        V( g_pEffect->SetTexture( "Decoration", pRoomTexture ) );
410
411        // ----------------------------------------
412        // draw a room of size [-roomSize..roomSize]
413        // ----------------------------------------
414
415        cube->PrepareDrawing();
416        D3DXVECTOR3 scale = D3DXVECTOR3(roomSize,roomSize,roomSize);
417        SetWorldViewProj( ScaleAndOffset( scale, D3DXVECTOR3(0,0,0) ), mView, mProj );
418
419        // flip normals so that the room is visible from its inside
420        V( pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW) );
421        V( g_pEffect->SetTexture( "Decoration", pRoomTexture ) );
422        V( g_pEffect->SetFloat( "brightness", 2.8f ));
423        V( g_pEffect->SetInt ( "iShowCubeMap", 0 ));
424
425        // decide if the room should visualize one of the cube maps
426        if ( bCubeMapIsValid && pp.GetInt( iShowCubeMap ) > 0)
427                V( g_pEffect->SetInt ( "iShowCubeMap", pp.GetInt( iShowCubeMap ) ));
428
429        D3DXVECTOR4 facecolors[]={D3DXVECTOR4(1,0,0,1),
430                                                        D3DXVECTOR4(1,0,1,1),
431                                                        D3DXVECTOR4(1,1,0,1),
432                                                        D3DXVECTOR4(0,0,1,1),
433                                                        D3DXVECTOR4(0,1,0,1),
434                                                        D3DXVECTOR4(0,1,1,1)};
435        for( int i=0; i<6; i++ )
436        {
437                objColor = D3DXVECTOR4(0.4f-i*0.1f, i*0.1f, (i%2)*0.4f, 1);             // a colorful room
438                if (i==3) objColor += D3DXVECTOR4(0.05, 0.05, 0, 1);           
439
440                //objColor = facecolors[i];             
441
442                g_pEffect->SetVector( "objColor", &objColor );
443                g_pEffect->CommitChanges();
444               
445                cube->DrawFace(i);
446        }
447
448        pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
449        V( g_pEffect->SetInt ( "iShowCubeMap", 0 ));
450        //V( g_pEffect->SetInt( "shininess", 2));
451        V( g_pEffect->SetFloat( "brightness", 1.0f ));
452
453        //V( g_pEffect->SetTexture( "Decoration", pBoxTexture ) );
454
455        /*// térelválasztó fal rajzolása
456        SetWorldViewProj( ScaleAndOffset( D3DXVECTOR3(0.01,roomSizeCurr*2/3,roomSizeCurr*0.3),
457                D3DXVECTOR3(1,-roomSizeCurr/3,0) ), mView, mProj );
458
459        objColor = D3DXVECTOR4(1.3,0,0.8, 1);
460        g_pEffect->SetVector( "objColor", &objColor );
461
462        for( int i=0; i<6; i++ )
463        {
464                cube->DrawFace(i);
465        }*/
466
467        g_pEffect->CommitChanges();
468}
469
470/**
471        Sets the given scaling and offset.
472        @return The resulting world transformation matrix.
473*/
474D3DXMATRIXA16 EnvMap::ScaleAndOffset(D3DXVECTOR3 vScale, D3DXVECTOR3 vOffset)
475{
476        D3DXMATRIXA16 mScale, mOffset;
477        D3DXMatrixIdentity(&mScale);
478        D3DXMatrixIdentity(&mOffset);
479
480        D3DXMatrixTranslation( &mOffset, vOffset.x, vOffset.y, vOffset.z );
481        D3DXMatrixScaling( &mScale, vScale.x, vScale.y, vScale.z );
482
483        return mScale * mOffset;
484}
485
486/**
487        Sets the given uniform scaling and an offset.
488        @return The resulting world transformation matrix.
489*/
490D3DXMATRIXA16 EnvMap::ScaleAndOffset(float fScale, D3DXVECTOR3 vOffset)
491{
492        return ScaleAndOffset( D3DXVECTOR3(fScale,fScale,fScale), vOffset );
493}
494
495/**
496        \brief Uploads the specified world/view/projection transformation matrices to the GPU.
497*/
498void EnvMap::SetWorldViewProj(D3DXMATRIXA16& mWorld, D3DXMATRIXA16& mView, D3DXMATRIXA16& mProj )
499{
500        D3DXMATRIXA16 mWorldView = mWorld * mView;
501        D3DXMATRIXA16 mWorldViewProjection = mWorldView * mProj;
502
503        D3DXMATRIXA16 mWorldViewI, mWorldViewIT, mWorldI, mWorldIT;
504        D3DXMatrixInverse(&mWorldViewI, NULL, &mWorldView);
505        D3DXMatrixTranspose(&mWorldViewIT, &mWorldViewI);
506
507        D3DXMatrixInverse(&mWorldI, NULL, &mWorld);
508        D3DXMatrixTranspose(&mWorldIT, &mWorldI);
509
510        V( g_pEffect->SetMatrix( "World", &mWorld ) );
511        V( g_pEffect->SetMatrix( "WorldIT", &mWorldIT ) );
512        V( g_pEffect->SetMatrix( "WorldView", &mWorldView ) );
513        //V( g_pEffect->SetMatrix( "WorldViewIT", &mWorldViewIT ) );
514
515        V( g_pEffect->SetMatrix( "WorldViewProjection", &mWorldViewProjection ) );
516        V( g_pEffect->CommitChanges() );
517}
518
519/// \brief Renders the environment into the specified cubemap.
520///
521/// The camera is placed into #reference_pos. Uses technique IlluminatedScenePS() for rendering.
522void EnvMap::RenderCubeMap(IDirect3DCubeTexture9* pCubeTexture)
523{
524        IDirect3DSurface9*      oldRenderTarget;
525        IDirect3DSurface9*      oldDepthStencil;
526        IDirect3DSurface9*  newDepthStencil;
527
528        // create a CUBEMAP_SIZE x CUBEMAP_SIZE size depth buffer
529        pd3dDevice->CreateDepthStencilSurface(CUBEMAP_SIZE, CUBEMAP_SIZE, D3DFMT_D16,
530                D3DMULTISAMPLE_NONE, 0, true, &newDepthStencil, NULL);
531
532        // replace old depth buffer
533        pd3dDevice->GetDepthStencilSurface(&oldDepthStencil);
534        pd3dDevice->SetDepthStencilSurface(newDepthStencil);
535
536        pd3dDevice->GetRenderTarget(0,&oldRenderTarget);
537
538        UINT uPasses;
539        for (int i = 0; i < 6; i++)
540        {
541                IDirect3DSurface9* pFace;
542                V( pCubeTexture->GetCubeMapSurface((D3DCUBEMAP_FACES)i, 0, &pFace) );
543                V( pd3dDevice->SetRenderTarget(0, pFace) );
544
545                V( g_pEffect->SetTechnique( "IlluminatedScene" ) );
546                V( g_pEffect->SetTexture( "Decoration", pRoomTexture ) );
547
548                V( g_pEffect->Begin( &uPasses, 0 ) );
549                V( g_pEffect->BeginPass( 0 ) );
550               
551                V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
552                        D3DCOLOR_ARGB(0,/*i==0 ? 255 : */0,0,0), 1.0f, 0) );
553
554                // mView
555                D3DXMATRIXA16 mView, mProj;
556
557                // looking toward the cube map faces _from the origin_
558                // mView = DXUTGetCubeMapViewMatrix( i );                       
559
560                //float scale = centralMesh->GetMeshScale();
561                //D3DXVECTOR3 offset = centralMesh->GetMeshPosition();
562
563                D3DXVECTOR3 vecEye(0,0,0);
564            D3DXVECTOR3 vecAt(0.0f, 0.0f, 0.0f);
565            D3DXVECTOR3 vecUp(0.0f, 0.0f, 0.0f);
566
567                switch( i )
568                {
569            case D3DCUBEMAP_FACE_POSITIVE_X:
570                vecAt = D3DXVECTOR3( 1, 0, 0 );
571                vecUp = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
572                break;
573            case D3DCUBEMAP_FACE_NEGATIVE_X:
574                vecAt = D3DXVECTOR3(-1.0f, 0.0f, 0.0f );
575                vecUp = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
576                break;
577            case D3DCUBEMAP_FACE_POSITIVE_Y:
578                vecAt = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
579                vecUp = D3DXVECTOR3( 0.0f, 0.0f,-1.0f );
580                break;
581            case D3DCUBEMAP_FACE_NEGATIVE_Y:
582                vecAt = D3DXVECTOR3( 0.0f,-1.0f, 0.0f );
583                vecUp = D3DXVECTOR3( 0.0f, 0.0f, 1.0f );
584                break;
585            case D3DCUBEMAP_FACE_POSITIVE_Z:
586                vecAt = D3DXVECTOR3( 0.0f, 0.0f, 1.0f );
587                vecUp = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
588                break;
589            case D3DCUBEMAP_FACE_NEGATIVE_Z:
590                vecAt = D3DXVECTOR3( 0.0f, 0.0f,-1.0f );       
591                vecUp = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
592                break;
593        }
594
595                // reference point is the current object position
596                reference_pos = centralMesh->GetMeshPosition();
597                vecEye += reference_pos;
598                vecAt += reference_pos;
599
600                D3DXMatrixLookAtLH(&mView, &vecEye, &vecAt, &vecUp);
601                D3DXMatrixPerspectiveFovLH( &mProj, D3DX_PI/2, 1, 0.1, 100 );
602
603                bPreproc = true;
604                DrawEnvObjects(mView, mProj);   // boost lightness of the environment
605                bPreproc = false;
606
607                V( g_pEffect->EndPass() );
608                V( g_pEffect->End() );
609
610                SAFE_RELEASE( pFace );
611        }
612
613        // restore old rendertarget & depth buffer
614        pd3dDevice->SetRenderTarget(0, oldRenderTarget);
615        pd3dDevice->SetDepthStencilSurface(oldDepthStencil);
616        SAFE_RELEASE( oldDepthStencil );
617        SAFE_RELEASE( oldRenderTarget );
618        SAFE_RELEASE( newDepthStencil );
619}
620
621/// Downsample a cube map to resolution LR_CUBEMAP_SIZE
622void EnvMap::ReduceCubeMapSize(IDirect3DCubeTexture9* pSourceCube, IDirect3DCubeTexture9* pDestCube)
623{
624        // get the descriptor of the source cubemap
625        IDirect3DSurface9* pSourceFace;
626        pSourceCube->GetCubeMapSurface((D3DCUBEMAP_FACES)0, 0, &pSourceFace);
627        D3DSURFACE_DESC sourceDesc;
628        pSourceFace->GetDesc( &sourceDesc );
629        SAFE_RELEASE( pSourceFace );
630
631        // pTexture : copy of the source cubemap's face
632        IDirect3DTexture9* pTexture = NULL;
633        V( D3DXCreateTexture( pd3dDevice, sourceDesc.Width, sourceDesc.Height, 1,
634                                                D3DUSAGE_RENDERTARGET, D3DFMT_A16B16G16R16F, D3DPOOL_DEFAULT, &pTexture ) );
635
636        IDirect3DSurface9* m_backBuffer=NULL;
637        pd3dDevice->GetRenderTarget(0, &m_backBuffer);
638
639        for(int i=0; i<6; i++)
640        {
641                IDirect3DSurface9* pFace;
642                IDirect3DSurface9* pSurface;
643
644                // a forrás cubemap akt. lapjának átmásolása pTexture-be
645                V( pSourceCube->GetCubeMapSurface((D3DCUBEMAP_FACES)i, 0, &pFace) );
646                V( pTexture->GetSurfaceLevel( 0, &pSurface ) );
647                V( pd3dDevice->StretchRect(pFace, NULL, pSurface, NULL, D3DTEXF_NONE) );
648
649                // pTexture átadása a shadernek
650                V( g_pEffect->SetTexture( "Decoration", pTexture ) );
651       
652                // rendertarget: a cél lap
653                IDirect3DSurface9* pDestCubeFace;
654                V( pDestCube->GetCubeMapSurface((D3DCUBEMAP_FACES)i, 0, &pDestCubeFace) );
655                V( pd3dDevice->SetRenderTarget(0, pDestCubeFace) );
656
657                // begin drawing
658                //V( g_pEffect->SetTechnique( "ReduceTexture" ) );
659
660                char techniqueName[100];
661                sprintf(techniqueName, "ReduceTexture%i", LR_CUBEMAP_SIZE );
662                V( g_pEffect->SetTechnique( techniqueName ) );
663
664
665                UINT uPasses;
666                V( g_pEffect->Begin( &uPasses, 0 ) );
667                V( g_pEffect->BeginPass( 0 ) );
668
669                        V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
670                                        D3DCOLOR_ARGB(0,255,255,0), 1.0f, 0) );
671
672                        // draw a square
673                        DrawFullScreenQuad();
674               
675                V( g_pEffect->EndPass() );
676                V( g_pEffect->End() );
677
678                SAFE_RELEASE( pSurface );
679                SAFE_RELEASE( pFace );
680                SAFE_RELEASE( pDestCubeFace );
681        }
682
683        pd3dDevice->SetRenderTarget(0,m_backBuffer);
684
685        SAFE_RELEASE( pTexture );
686        SAFE_RELEASE( m_backBuffer );
687}
688
689/// \brief Calculates the irradiance map by convolution.
690///
691/// Convolves data from the source cubemap and stores the result in the target cubemap. Uses ConvolutionPS().
692void EnvMap::PreConvolve(IDirect3DCubeTexture9* pSourceCube, IDirect3DCubeTexture9* pDestCube)
693{
694        IDirect3DSurface9*      oldRenderTarget;
695        IDirect3DSurface9*      oldDepthStencil;
696        IDirect3DSurface9*  newDepthStencil;
697
698        // create a LR_CUBEMAP_SIZE x LR_CUBEMAP_SIZE size depth buffer
699        pd3dDevice->CreateDepthStencilSurface(LR_CUBEMAP_SIZE, LR_CUBEMAP_SIZE, D3DFMT_D16,
700                D3DMULTISAMPLE_NONE, 0, true, &newDepthStencil, NULL);
701
702        // replace old depth buffer
703        pd3dDevice->GetDepthStencilSurface(&oldDepthStencil);
704        pd3dDevice->SetDepthStencilSurface(newDepthStencil);
705        pd3dDevice->GetRenderTarget(0, &oldRenderTarget);
706
707        V( g_pEffect->SetTexture( "SmallEnvironmentMap", pSourceCube ) );
708
709        float s = (float)pp.GetInt( iShininess );
710        V( g_pEffect->SetFloat  ( "shininess", s));
711
712        for(int i=0; i<6; i++)
713        {
714                V( g_pEffect->SetInt( "nFace", i ) );
715       
716                // set a face of 'pDestCube' as rendertarget
717                IDirect3DSurface9* pDestCubeFace;
718                V( pDestCube->GetCubeMapSurface((D3DCUBEMAP_FACES)i, 0, &pDestCubeFace) );
719                V( pd3dDevice->SetRenderTarget(0, pDestCubeFace) );
720
721                // begin drawing
722                //V( g_pEffect->SetTechnique( "Convolution" ) );
723                char techniqueName[100];
724                sprintf(techniqueName, "Convolution%i", LR_CUBEMAP_SIZE );
725                V( g_pEffect->SetTechnique( techniqueName ) );
726
727
728                UINT uPasses;
729                V( g_pEffect->Begin( &uPasses, 0 ) );
730                V( g_pEffect->BeginPass( 0 ) );
731
732                        V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
733                                        D3DCOLOR_ARGB(0,255,255,255), 1.0f, 0) );
734
735                        // draw a square
736                        DrawFullScreenQuad();
737               
738                V( g_pEffect->EndPass() );
739                V( g_pEffect->End() );
740                SAFE_RELEASE( pDestCubeFace );
741        }
742
743        //SaveCubeMap( pDestCube, "ha", "");
744
745        // restore old rendertarget & depth buffer
746        pd3dDevice->SetRenderTarget(0, oldRenderTarget);
747        pd3dDevice->SetDepthStencilSurface(oldDepthStencil);
748        SAFE_RELEASE( oldDepthStencil );
749        SAFE_RELEASE( oldRenderTarget );
750        SAFE_RELEASE( newDepthStencil );
751}
752
753void EnvMap::SaveCubeMap(IDirect3DCubeTexture9* pCubeTexture, char* FileNamePrefix, char* FileNameSuffix)
754{
755        char buf[100];
756        wchar_t wbuf[100];
757
758        for(int i=0;i<6;i++)
759        {
760                sprintf(buf, "%s%i%s.png", FileNamePrefix, i, FileNameSuffix);
761                mbstowcs( wbuf, buf, 100 );
762
763                IDirect3DSurface9* pFace;
764                V( pCubeTexture->GetCubeMapSurface((D3DCUBEMAP_FACES)i, 0, &pFace) );
765                D3DXSaveSurfaceToFile(wbuf, D3DXIFF_PNG, pFace, NULL,NULL);
766        }
767}
768
769/// \brief Calls GenerateCosTexture() if the specified texture is not yet calculated
770/// and stored as a texture in the <b>cos</b> subdirectory.
771
772void EnvMap::GenerateCosTextureIfNotFound( wchar_t* fileName, eval_fn evaluator )
773// precomputing geometric factors
774{
775        wchar_t wCosTextureName[100];
776        swprintf( wCosTextureName, L"%s%02i.png", fileName, pp.GetInt( iShininess ) );
777
778        // try to open
779        hr = D3DXCreateTextureFromFile( pd3dDevice, wCosTextureName, &pCosValuesTexture);
780        if ( FAILED( hr ) )
781        {
782                wchar_t buf[ 400 ];
783                swprintf( buf, L"Preprocessed texture not found!\n"
784                        L"The program will generate the following texture:\n"
785                        L"Texture name: %s\n"
786                        L"Shininess: %i\n"
787                        L"Iterations: %i (%i%% of the original texture quality).",
788                        wCosTextureName, pp.GetInt( iShininess ), M*M, 100 * M*M/25/25 );
789                MessageBox( NULL, buf, L"Texture not found!", MB_ICONINFORMATION );                     // show message
790
791                // generate
792                pCosValuesTexture = GenerateCosTexture( evaluator );
793
794                // save
795                IDirect3DSurface9* pSurface = NULL;
796                V( pCosValuesTexture->GetSurfaceLevel( 0, &pSurface ) );
797                hr = D3DXSaveSurfaceToFile( wCosTextureName, D3DXIFF_PNG, pSurface, NULL,NULL);
798                if ( FAILED( hr ) )
799                {
800                        swprintf( buf, L"Failed to save texture %s!", wCosTextureName );
801                        MessageBox( NULL, buf, L"Texture saving failed!", MB_ICONERROR );
802                }
803                SAFE_RELEASE( pSurface );
804        }
805}
806
807/// Generates precomputed texture to store values for the reflectivity integral. Uses the eval() function.
808IDirect3DTexture9* EnvMap::GenerateCosTexture( eval_fn evaluator )
809{
810        const int X = 128;
811        const int Y = 128;
812
813    IDirect3DDevice9* pd3dDevice = DXUTGetD3DDevice();
814   
815        // Create a temporary texture
816    LPDIRECT3DTEXTURE9 texTemp;
817    V( pd3dDevice->CreateTexture( X, Y, 1,
818                                         D3DUSAGE_DYNAMIC, D3DFMT_A32B32G32R32F,
819                                         D3DPOOL_DEFAULT, &texTemp, NULL ) );
820
821    D3DLOCKED_RECT Rect;
822    V( texTemp->LockRect(0, &Rect, 0, 0) );
823   
824    int u, v;
825    float dx, dy, I;
826    float* pBits; 
827
828        FILE* f = fopen( ".progress_bar", "wt");               
829        fprintf(f, "");
830        fclose( f );
831
832        long clock1 = clock();
833
834    for( v=0; v < Y; ++v )
835    {
836        pBits = (float*)((char*)(Rect.pBits)+v*Rect.Pitch);
837       
838        for( u=0; u < X; ++u )
839        {
840            dx = u/(float)X;    // 0..1
841            dy = v/(float)Y;    // 0..1
842
843                        //*(pBits++) = eval( 2*dx-1, dy*2*3.14159f ) / 3;  // old: intensity
844                        //*(pBits++) = values[ v*X + u ] / 50; // intensity
845
846                        float result = evaluator( dx, dy );
847                *(pBits++) = result;  // intensity
848                        *(pBits++) = result;  // intensity
849                        *(pBits++) = result;  // intensity
850                        *(pBits++) = 0;  // intensity
851        }
852
853                if ( v > 0 && v % (Y/10) == 0)
854                {
855                        FILE* f = fopen( ".progress_bar", "at");                // some silly progress bar:
856                        fprintf(f, "#");                                                        // write a # for each 10% done
857                        fclose( f );
858                }
859    }
860
861/*      long clock2 = clock();
862        float time = (float)(clock2-clock1)/CLOCKS_PER_SEC;
863
864        f = fopen( ".progress_bar", "at");     
865        fprintf(f, "\ntime:%.3g secs", time);                                                   
866        fclose( f );*/
867               
868    texTemp->UnlockRect(0);
869   
870        return texTemp;
871}
872
873/// \brief Calculates the reflectivity integral for a given texel.
874///
875/// The angle between the surface normal and texel center is described by cos_theta
876/// and the solid angle occupied by the texel is denoted by dw.
877///
878/// Instead of evaluating the reflectivity integral with only one sample belongig to the texel center
879/// (that would give us a result of cos_theta x dw), we use 2 #M x 2 #M x #M regulary spaced samples, and
880/// discard those that lie outside the unit hemisphere. The remaining samples are regulary distributed over the
881/// hemisphere.
882///
883/// For each sample, we check if it lies inside the cone of the specified solid angle.
884/// If yes, its contribution is considered.
885
886float eval( float cos_theta, float dw )
887{
888        const float PI = 3.14159f;
889       
890        float sum = 0;
891        int counter = 0;
892        int shininess = pp.GetInt( iShininess );
893       
894        float sin_theta = sqrt(1-cos_theta*cos_theta);
895       
896        D3DXVECTOR3 center( sin_theta, 0, cos_theta );
897        D3DXVECTOR3 up( 0, 0, 1 );
898
899        float cos_min = 1 - dw / 2 / PI;
900       
901        for (int x = -M; x <= M; x++)
902          for (int y = -M; y <= M; y++)
903            for (int z = /*-M*/ 0; z <= M; z++)         // z == up
904                {
905                        D3DXVECTOR3 w(0,0,0);
906                        w.x = x / (float)M;             // -1..1
907                        w.y = y / (float)M;             // -1..1
908                        w.z = z / (float)M;             // 0..1
909
910                        float len = D3DXVec3Length( &w );
911                        if ( len > 0 && len <= 1 )                      // inside the hemisphere
912                        {
913                                w /= len;                                               // normalize
914                               
915                                float cos_curr = D3DXVec3Dot( &w, &center );
916                                if ( cos_curr >= cos_min )              // w is inside the 'cone' of the given solid angle
917                                {
918                                        sum += pow( D3DXVec3Dot( &w, &up ), shininess );
919                                        //sum += D3DXVec3Dot( &w, &up );
920                                }
921
922                                counter++;                                              // number of samples
923                        }
924                }
925         
926         return sum * (2*PI / counter) * ((shininess+2) / PI);
927         //return dx;
928}
Note: See TracBrowser for help on using the repository browser.