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

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