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

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