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

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