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

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