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

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