0001:
0002:
0003:
0004:
0005:
0006:
0007: #define STRICT
0008: #include <windows.h>
0009: #include <commctrl.h>
0010: #include <commdlg.h>
0011: #include <basetsd.h>
0012: #include <math.h>
0013: #include <stdio.h>
0014: #include <d3dx9.h>
0015: #include <dxerr9.h>
0016: #include <tchar.h>
0017: #include "DXUtil.h"
0018: #include "D3DEnumeration.h"
0019: #include "D3DSettings.h"
0020: #include "D3DApp.h"
0021: #include "D3DFont.h"
0022: #include "D3DFile.h"
0023: #include "D3DUtil.h"
0024: #include "resource.h"
0025: #include "main.h"
0026:
0027: #define MAP_SIZE 256
0028: #define DIFFUSE_SIZE 64
0029:
0030:
0031:
0032:
0033:
0034: typedef struct {
0035: FLOAT p[4];
0036: FLOAT tu, tv;
0037: } TVERTEX;
0038:
0039:
0040:
0041:
0042: CMyD3DApplication* g_pApp = NULL;
0043: HINSTANCE g_hInst = NULL;
0044:
0045:
0046:
0047:
0048:
0049: INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
0050: {
0051: CMyD3DApplication d3dApp;
0052:
0053: g_pApp = &d3dApp;
0054: g_hInst = hInst;
0055:
0056: InitCommonControls();
0057: if( FAILED( d3dApp.Create( hInst ) ) )
0058: return 0;
0059:
0060: return d3dApp.Run();
0061: }
0062:
0063:
0064:
0065:
0066:
0067:
0068:
0069:
0070: CMyD3DApplication::CMyD3DApplication()
0071: {
0072: m_iState = -1;
0073: m_Shader = 0;
0074:
0075: m_pMeshBg = new CD3DMesh();
0076:
0077: m_pMapZ = NULL;
0078: m_pPosTex = NULL;
0079: m_pPosSurf = NULL;
0080: m_pPosLockTex = NULL;
0081: m_pPosLockSurf = NULL;
0082: m_pNormalTex = NULL;
0083: m_pNormalSurf = NULL;
0084: m_pNormalLockTex = NULL;
0085: m_pNormalLockSurf = NULL;
0086:
0087: for(int i=0;i<TEX_MAX;i++){
0088: m_pFinalTex[i] = NULL;
0089: m_pFinalSurf[i] = NULL;
0090: }
0091: for(int j=0;j<REDUCTION_MAPS;j++){
0092: m_pReductionTex[i] = NULL;
0093: m_pReductionSurf[i] = NULL;
0094: }
0095:
0096: m_pEffect = NULL;
0097: m_hTechnique = NULL;
0098: m_hmWVP = NULL;
0099: m_htSrcTex = NULL;
0100:
0101: m_fWorldRotX = -0.5f;
0102: m_fWorldRotY = 0.0f;
0103: m_fViewZoom = 13.0f;
0104:
0105: m_fLightRotX = -0.80116916f;
0106: m_fLightRotY = 1.4874420f;
0107:
0108: m_dwCreationWidth = 512;
0109: m_dwCreationHeight = 512;
0110: m_strWindowTitle = TEXT( "main" );
0111: m_d3dEnumeration.AppUsesDepthBuffer = TRUE;
0112: m_bStartFullscreen = false;
0113: m_bShowCursorWhenFullscreen = false;
0114:
0115: m_pFont = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD );
0116: m_bLoadingApp = TRUE;
0117:
0118: ZeroMemory( &m_UserInput, sizeof(m_UserInput) );
0119: }
0120:
0121:
0122:
0123:
0124:
0125:
0126:
0127:
0128: CMyD3DApplication::~CMyD3DApplication()
0129: {
0130: }
0131:
0132:
0133:
0134:
0135:
0136:
0137:
0138:
0139:
0140:
0141: HRESULT CMyD3DApplication::OneTimeSceneInit()
0142: {
0143:
0144: SendMessage( m_hWnd, WM_PAINT, 0, 0 );
0145:
0146: m_bLoadingApp = FALSE;
0147:
0148: return S_OK;
0149: }
0150:
0151:
0152:
0153:
0154:
0155:
0156:
0157:
0158: HRESULT CMyD3DApplication::ConfirmDevice( D3DCAPS9* pCaps,
0159: DWORD dwBehavior, D3DFORMAT Format )
0160: {
0161: UNREFERENCED_PARAMETER( Format );
0162: UNREFERENCED_PARAMETER( dwBehavior );
0163: UNREFERENCED_PARAMETER( pCaps );
0164:
0165:
0166:
0167: if( pCaps->PixelShaderVersion < D3DPS_VERSION(2,0) )
0168: return E_FAIL;
0169:
0170:
0171: if( pCaps->VertexShaderVersion < D3DVS_VERSION(1,1)
0172: && 0==(dwBehavior & D3DCREATE_SOFTWARE_VERTEXPROCESSING) )
0173: return E_FAIL;
0174:
0175: return S_OK;
0176: }
0177:
0178:
0179:
0180:
0181:
0182:
0183:
0184:
0185:
0186: HRESULT CMyD3DApplication::InitDeviceObjects()
0187: {
0188: HRESULT hr;
0189:
0190:
0191: if(FAILED(hr=m_pMeshBg->Create( m_pd3dDevice, _T("map.x"))))
0192: return DXTRACE_ERR( "Load Model", hr );
0193: m_pMeshBg->UseMeshMaterials(FALSE);
0194:
0195:
0196: LPD3DXBUFFER pErr;
0197: if( FAILED( hr = D3DXCreateEffectFromFile(
0198: m_pd3dDevice, "hlsl.fx", NULL, NULL,
0199: D3DXSHADER_DEBUG , NULL, &m_pEffect, &pErr ))){
0200: MessageBox( NULL, (LPCTSTR)pErr->GetBufferPointer()
0201: , "ERROR", MB_OK);
0202: return DXTRACE_ERR( "CreateEffectFromFile", hr );
0203: }
0204: m_hTechnique = m_pEffect->GetTechniqueByName( "TShader" );
0205: m_hmWVP = m_pEffect->GetParameterByName( NULL, "mWVP" );
0206: m_htSrcTex = m_pEffect->GetParameterByName( NULL, "SrcTex" );
0207:
0208:
0209: m_pFont->InitDeviceObjects( m_pd3dDevice );
0210:
0211: return S_OK;
0212: }
0213:
0214:
0215:
0216:
0217: VOID WINAPI FillTex (D3DXVECTOR4* pOut, CONST D3DXVECTOR2* pTexCoord,
0218: CONST D3DXVECTOR2* pTexelSize, LPVOID pData)
0219: {
0220: UNREFERENCED_PARAMETER( pTexelSize );
0221: UNREFERENCED_PARAMETER( pData );
0222:
0223: FLOAT x = 2.0f*(pTexCoord->x-0.5f);
0224: FLOAT y = 2.0f*(pTexCoord->y-0.5f);
0225: FLOAT col = (x*x+y*y<(1.0f-1.0f/DIFFUSE_SIZE)*(1.0f-1.0f/DIFFUSE_SIZE))
0226: ? 1.0f : 0.0f;
0227:
0228: pOut->x = pOut->y = pOut->z = pOut->w = col;
0229: }
0230:
0231:
0232:
0233:
0234:
0235:
0236: HRESULT CMyD3DApplication::RestoreDeviceObjects()
0237: {
0238: m_iState = -1;
0239: m_iChangeState = TRUE;
0240:
0241: DWORD i;
0242:
0243:
0244: m_pMeshBg->RestoreDeviceObjects( m_pd3dDevice );
0245:
0246:
0247: D3DMATERIAL9 mtrl;
0248: D3DUtil_InitMaterial( mtrl, 1.0f, 0.0f, 0.0f );
0249: m_pd3dDevice->SetMaterial( &mtrl );
0250:
0251:
0252:
0253: m_pd3dDevice->SetRenderState( D3DRS_DITHERENABLE, FALSE );
0254: m_pd3dDevice->SetRenderState( D3DRS_SPECULARENABLE, FALSE );
0255: m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
0256: m_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0x000F0F0F );
0257:
0258: m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
0259: m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
0260: m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
0261: m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
0262: m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
0263: m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
0264: m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
0265: m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
0266: m_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP );
0267: m_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP );
0268:
0269:
0270: D3DXMATRIX matIdentity;
0271: D3DXMatrixIdentity( &m_mWorld );
0272:
0273:
0274: D3DXVECTOR3 vFromPt = D3DXVECTOR3( 0.0f, 0.0f, -5.0f );
0275: D3DXVECTOR3 vLookatPt = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
0276: D3DXVECTOR3 vUpVec = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
0277: D3DXMatrixLookAtLH( &m_mView, &vFromPt, &vLookatPt, &vUpVec );
0278:
0279:
0280: FLOAT fAspect = ((FLOAT)m_d3dsdBackBuffer.Width) / m_d3dsdBackBuffer.Height;
0281: D3DXMatrixPerspectiveFovLH( &m_mProj, D3DX_PI/4, fAspect, 1.0f, 100.0f );
0282:
0283:
0284: m_pFont->RestoreDeviceObjects();
0285:
0286:
0287: if (FAILED(m_pd3dDevice->CreateDepthStencilSurface(MAP_SIZE, MAP_SIZE,
0288: D3DFMT_D16, D3DMULTISAMPLE_NONE, 0, TRUE, &m_pMapZ, NULL)))
0289: return E_FAIL;
0290:
0291: if (FAILED(m_pd3dDevice->CreateTexture(MAP_SIZE, MAP_SIZE, 1,
0292: D3DUSAGE_RENDERTARGET, D3DFMT_A32B32G32R32F, D3DPOOL_DEFAULT, &m_pPosTex, NULL)))
0293: return E_FAIL;
0294: if (FAILED(m_pPosTex->GetSurfaceLevel(0, &m_pPosSurf)))
0295: return E_FAIL;
0296: if (FAILED(m_pd3dDevice->CreateTexture(MAP_SIZE, MAP_SIZE, 1,
0297: 0, D3DFMT_A32B32G32R32F, D3DPOOL_SYSTEMMEM , &m_pPosLockTex, NULL)))
0298: return E_FAIL;
0299: if (FAILED(m_pPosLockTex->GetSurfaceLevel(0, &m_pPosLockSurf)))
0300: return E_FAIL;
0301:
0302: if (FAILED(m_pd3dDevice->CreateTexture(MAP_SIZE, MAP_SIZE, 1,
0303: D3DUSAGE_RENDERTARGET, D3DFMT_A32B32G32R32F, D3DPOOL_DEFAULT, &m_pNormalTex, NULL)))
0304: return E_FAIL;
0305: if (FAILED(m_pNormalTex->GetSurfaceLevel(0, &m_pNormalSurf)))
0306: return E_FAIL;
0307: if (FAILED(m_pd3dDevice->CreateTexture(MAP_SIZE, MAP_SIZE, 1,
0308: 0, D3DFMT_A32B32G32R32F, D3DPOOL_SYSTEMMEM , &m_pNormalLockTex, NULL)))
0309: return E_FAIL;
0310: if (FAILED(m_pNormalLockTex->GetSurfaceLevel(0, &m_pNormalLockSurf)))
0311: return E_FAIL;
0312:
0313: for(i=0;i<TEX_MAX;i++){
0314: if (FAILED(m_pd3dDevice->CreateTexture(MAP_SIZE, MAP_SIZE, 1,
0315: D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_pFinalTex[i], NULL)))
0316: return E_FAIL;
0317: if (FAILED(m_pFinalTex[i]->GetSurfaceLevel(0, &m_pFinalSurf[i])))
0318: return E_FAIL;
0319: }
0320:
0321:
0322: for(i=0;i<REDUCTION_MAPS;i++){
0323: int size = 1<<(3*(REDUCTION_MAPS-i));
0324: if (FAILED(m_pd3dDevice->CreateTexture(size, size, 1,
0325: D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_pReductionTex[i], NULL)))
0326: return E_FAIL;
0327: if (FAILED(m_pReductionTex[i]->GetSurfaceLevel(0, &m_pReductionSurf[i])))
0328: return E_FAIL;
0329: }
0330:
0331:
0332: if( FAILED(m_pd3dDevice->CreateTexture(DIFFUSE_SIZE, DIFFUSE_SIZE, 1
0333: , D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8
0334: , D3DPOOL_DEFAULT, &m_pMaskTex, NULL)))
0335: return E_FAIL;
0336: if( FAILED(D3DXFillTexture(m_pMaskTex, FillTex, NULL)))
0337: return E_FAIL;
0338:
0339: m_pEffect->OnResetDevice();
0340:
0341: return S_OK;
0342: }
0343:
0344:
0345:
0346:
0347:
0348:
0349: int CMyD3DApplication::FrameMoveCreateMap()
0350: {
0351:
0352: if(1<m_iCount) return 1;
0353:
0354: return 0;
0355: }
0356:
0357:
0358:
0359:
0360: void CMyD3DApplication::RenderCreateMap()
0361: {
0362: LPDIRECT3DSURFACE9 pOldBackBuffer, pOldZBuffer;
0363: D3DVIEWPORT9 oldViewport;
0364:
0365: if( SUCCEEDED( m_pd3dDevice->BeginScene() ) )
0366: {
0367:
0368:
0369:
0370: m_pd3dDevice->GetRenderTarget(0, &pOldBackBuffer);
0371: m_pd3dDevice->GetDepthStencilSurface(&pOldZBuffer);
0372: m_pd3dDevice->GetViewport(&oldViewport);
0373:
0374:
0375:
0376:
0377: m_pd3dDevice->SetRenderTarget(0, m_pPosSurf);
0378: m_pd3dDevice->SetRenderTarget(1, m_pNormalSurf);
0379: m_pd3dDevice->SetDepthStencilSurface(NULL);
0380:
0381: D3DVIEWPORT9 viewport_height = {0,0
0382: , MAP_SIZE
0383: , MAP_SIZE
0384: , 0.0f,1.0f};
0385: m_pd3dDevice->SetViewport(&viewport_height);
0386:
0387:
0388:
0389:
0390: m_pd3dDevice->Clear(0L, NULL
0391: , D3DCLEAR_TARGET
0392: , 0x00000000, 1.0f, 0L);
0393:
0394: if( m_pEffect != NULL )
0395: {
0396:
0397:
0398:
0399: m_pEffect->SetTechnique( m_hTechnique );
0400: m_pEffect->Begin( NULL, 0 );
0401: m_pEffect->Pass( 0 );
0402:
0403: m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE );
0404: m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
0405:
0406:
0407:
0408:
0409: m_pMeshBg->Render(m_pd3dDevice);
0410:
0411: m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
0412: m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
0413:
0414: m_pEffect->End();
0415: }
0416:
0417:
0418:
0419:
0420: m_pd3dDevice->SetRenderTarget(0, pOldBackBuffer);
0421: m_pd3dDevice->SetRenderTarget(1, NULL);
0422: m_pd3dDevice->SetDepthStencilSurface(pOldZBuffer);
0423: m_pd3dDevice->SetViewport(&oldViewport);
0424: pOldBackBuffer->Release();
0425: pOldZBuffer->Release();
0426:
0427:
0428:
0429:
0430: m_pd3dDevice->Clear(0L, NULL
0431: , D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER
0432: , 0xff000000, 1.0f, 0L);
0433:
0434: m_pd3dDevice->EndScene();
0435: }
0436: }
0437:
0438:
0439:
0440:
0441:
0442:
0443: static int itex=0;
0444: static int ix=0;
0445: static int iy=0;
0446: static float pos[MAP_SIZE][MAP_SIZE][3];
0447: static float normal[MAP_SIZE][MAP_SIZE][3];
0448: int CMyD3DApplication::FrameMoveFinalGathering()
0449: {
0450: itex = this->m_iCount / (MAP_SIZE*MAP_SIZE);
0451: ix = this->m_iCount % MAP_SIZE;
0452: iy = (this->m_iCount / MAP_SIZE) % MAP_SIZE;
0453:
0454: if(0==this->m_iCount){
0455: D3DLOCKED_RECT d3dlr;
0456: float *p;
0457: m_pd3dDevice->GetRenderTargetData(m_pPosSurf,m_pPosLockSurf);
0458: m_pPosLockSurf->LockRect(&d3dlr,NULL,D3DLOCK_READONLY);
0459: p = (float *)d3dlr.pBits;
0460: for(int y=0;y<MAP_SIZE;y++){
0461: for(int x=0;x<MAP_SIZE;x++){
0462: pos[x][y][0]=p[0];
0463: pos[x][y][1]=p[1];
0464: pos[x][y][2]=p[2];
0465: p+=4;
0466: }
0467: }
0468: m_pPosLockSurf->UnlockRect();
0469:
0470: m_pd3dDevice->GetRenderTargetData(m_pNormalSurf,m_pNormalLockSurf);
0471: m_pNormalLockSurf->LockRect(&d3dlr,NULL,D3DLOCK_READONLY);
0472: p = (float *)d3dlr.pBits;
0473: for(int y=0;y<MAP_SIZE;y++){
0474: for(int x=0;x<MAP_SIZE;x++){
0475: normal[x][y][0]=p[0];
0476: normal[x][y][1]=p[1];
0477: normal[x][y][2]=p[2];
0478: p+=4;
0479: }
0480: }
0481: m_pNormalLockSurf->UnlockRect();
0482: }
0483:
0484:
0485: if(MAP_SIZE-1==ix && MAP_SIZE-1==iy && TEX_MAX-1==itex) return 1;
0486:
0487: return 0;
0488: }
0489:
0490:
0491:
0492:
0493: void CMyD3DApplication::RenderFinalGathering()
0494: {
0495: int i;
0496: D3DXMATRIX m, mView;
0497: LPDIRECT3DSURFACE9 pOldBackBuffer, pOldZBuffer;
0498: D3DVIEWPORT9 oldViewport;
0499: D3DSURFACE_DESC d3dsd;
0500:
0501: D3DVIEWPORT9 viewport = {0,0
0502: , 1, 1
0503: , 0.0f,1.0f};
0504:
0505: if( SUCCEEDED( m_pd3dDevice->BeginScene() ) )
0506: {
0507: m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE );
0508: m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
0509:
0510:
0511:
0512:
0513: m_pd3dDevice->GetRenderTarget(0, &pOldBackBuffer);
0514: m_pd3dDevice->GetDepthStencilSurface(&pOldZBuffer);
0515: m_pd3dDevice->GetViewport(&oldViewport);
0516:
0517:
0518:
0519:
0520:
0521:
0522:
0523:
0524:
0525:
0526: m_pd3dDevice->SetRenderTarget(0, m_pReductionSurf[0]);
0527: m_pd3dDevice->SetDepthStencilSurface(NULL);
0528:
0529: m_pReductionSurf[0]->GetDesc(&d3dsd);
0530: viewport.Height = d3dsd.Width;
0531: viewport.Width = d3dsd.Height;
0532: m_pd3dDevice->SetViewport(&viewport);
0533:
0534: if( m_pEffect != NULL )
0535: {
0536:
0537:
0538:
0539: float x[3] = {pos[ix][iy][0], pos[ix][iy][1], pos[ix][iy][2]};
0540: float n[3] = {normal[ix][iy][0], normal[ix][iy][1], normal[ix][iy][2]};
0541: D3DXVECTOR3 vFromPt = D3DXVECTOR3( x[0], x[1], x[2] ) + 0.001f*D3DXVECTOR3( n[0], n[1], n[2] );
0542: D3DXVECTOR3 vLookatPt = D3DXVECTOR3( n[0], n[1], n[2] ) + vFromPt;
0543: D3DXVECTOR3 vUpVec = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
0544: D3DXMatrixLookAtLH( &mView, &vFromPt, &vLookatPt, &vUpVec );
0545: m_pEffect->SetMatrix( "mWV", &mView );
0546:
0547: D3DXMatrixTranspose(&m, &mView);
0548: m_pEffect->SetMatrix( "mST", &m );
0549:
0550:
0551: m_pEffect->SetTechnique( "TSphericalHarmonics" );
0552: m_pEffect->Begin( NULL, 0 );
0553:
0554: TVERTEX Vertex[4] = {
0555:
0556: {-1,-1,0, 0, 0,},
0557: {+1,-1,0, 1, 0,},
0558: {+1,+1,0, 1, 1,},
0559: {-1,+1,0, 0, 1,},
0560: };
0561: m_pd3dDevice->SetFVF( D3DFVF_XYZ | D3DFVF_TEX1 );
0562: m_pEffect->SetTexture(m_htSrcTex, m_pMaskTex);
0563:
0564: for(i=0;i<4;i++){
0565: switch(i){
0566: case 0:
0567: m_pd3dDevice->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED );
0568: break;
0569: case 1:
0570: m_pd3dDevice->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN );
0571: break;
0572: case 2:
0573: m_pd3dDevice->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_BLUE );
0574: break;
0575: case 3:
0576: m_pd3dDevice->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA );
0577: break;
0578: }
0579: int no = 4*itex+i;
0580: m_pEffect->Pass( no );
0581: m_pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, Vertex, sizeof( TVERTEX ) );
0582: }
0583: m_pEffect->End();
0584:
0585:
0586:
0587:
0588: m_pEffect->SetTechnique( "TShader" );
0589: m_pEffect->Begin( NULL, 0 );
0590: m_pEffect->Pass( 1 );
0591:
0592: m_pd3dDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0xf );
0593:
0594:
0595:
0596:
0597: m_pMeshBg->Render(m_pd3dDevice);
0598:
0599: m_pEffect->End();
0600: }
0601:
0602:
0603:
0604:
0605:
0606: m_pd3dDevice->SetRenderTarget(0, m_pReductionSurf[1]);
0607: m_pd3dDevice->SetDepthStencilSurface(NULL);
0608:
0609: m_pReductionSurf[1]->GetDesc(&d3dsd);
0610: viewport.Height = d3dsd.Width;
0611: viewport.Width = d3dsd.Height;
0612: m_pd3dDevice->SetViewport(&viewport);
0613:
0614: if( m_pEffect != NULL ) {
0615:
0616:
0617:
0618: m_pEffect->SetTechnique( m_hTechnique );
0619: m_pEffect->Begin( NULL, 0 );
0620: m_pEffect->Pass( 2 );
0621:
0622: m_pEffect->SetFloat("MAP_WIDTH", DIFFUSE_SIZE);
0623: m_pEffect->SetFloat("MAP_HEIGHT", DIFFUSE_SIZE);
0624:
0625:
0626:
0627:
0628: TVERTEX Vertex1[4] = {
0629:
0630: {-1.0f, +1.0f, 0.1f, 0, 0},
0631: {+1.0f, +1.0f, 0.1f, 1, 0},
0632: {+1.0f, -1.0f, 0.1f, 1, 1},
0633: {-1.0f, -1.0f, 0.1f, 0, 1},
0634: };
0635: m_pd3dDevice->SetFVF( D3DFVF_XYZ | D3DFVF_TEX1 );
0636: m_pEffect->SetTexture("ReductionMap", m_pReductionTex[0]);
0637: m_pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLEFAN
0638: , 2, Vertex1, sizeof( TVERTEX ) );
0639:
0640: m_pEffect->End();
0641: }
0642:
0643:
0644:
0645:
0646:
0647:
0648: m_pd3dDevice->SetRenderTarget(0, m_pFinalSurf[itex]);
0649: m_pd3dDevice->SetDepthStencilSurface(NULL);
0650:
0651: m_pFinalSurf[itex]->GetDesc(&d3dsd);
0652: viewport.Height = d3dsd.Width;
0653: viewport.Width = d3dsd.Height;
0654: m_pd3dDevice->SetViewport(&viewport);
0655:
0656:
0657: if(0==ix&&0==iy)m_pd3dDevice->Clear(0L, NULL, D3DCLEAR_TARGET, 0x80808080, 1.0f, 0L);
0658:
0659: if( m_pEffect != NULL ) {
0660:
0661:
0662:
0663: m_pEffect->SetTechnique( m_hTechnique );
0664: m_pEffect->Begin( NULL, 0 );
0665: m_pEffect->Pass( 2 );
0666:
0667: m_pEffect->SetFloat("MAP_WIDTH", 8);
0668: m_pEffect->SetFloat("MAP_HEIGHT", 8);
0669:
0670:
0671:
0672:
0673: float x = 2.0f*((float)ix/(float)MAP_SIZE) - 1.0f;
0674: float y = -2.0f*((float)iy/(float)MAP_SIZE) + 1.0f;
0675: TVERTEX Vertex1[4] = {
0676:
0677: {x, y, 0.1f, 0, 0},
0678: {x+2.0f/(float)MAP_SIZE, y, 0.1f, 1, 0},
0679: {x+2.0f/(float)MAP_SIZE, y-2.0f/(float)MAP_SIZE,0.1f, 1, 1},
0680: {x, y-2.0f/(float)MAP_SIZE,0.1f, 0, 1},
0681: };
0682: m_pd3dDevice->SetFVF( D3DFVF_XYZ | D3DFVF_TEX1 );
0683: m_pEffect->SetTexture("ReductionMap", m_pReductionTex[1]);
0684: m_pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLEFAN
0685: , 2, Vertex1, sizeof( TVERTEX ) );
0686:
0687: m_pEffect->End();
0688: }
0689:
0690:
0691:
0692:
0693:
0694: m_pd3dDevice->SetRenderTarget(0, pOldBackBuffer);
0695: m_pd3dDevice->SetRenderTarget(1, NULL);
0696: m_pd3dDevice->SetDepthStencilSurface(pOldZBuffer);
0697: m_pd3dDevice->SetViewport(&oldViewport);
0698: pOldBackBuffer->Release();
0699: pOldZBuffer->Release();
0700:
0701: m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
0702: m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
0703:
0704:
0705:
0706:
0707: m_pd3dDevice->Clear(0L, NULL
0708: , D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER
0709: , 0x00001020, 1.0f, 0L);
0710:
0711: #if 1
0712: {
0713: m_pd3dDevice->SetTextureStageState(0,D3DTSS_COLOROP, D3DTOP_SELECTARG1);
0714: m_pd3dDevice->SetTextureStageState(0,D3DTSS_COLORARG1, D3DTA_TEXTURE);
0715: m_pd3dDevice->SetTextureStageState(1,D3DTSS_COLOROP, D3DTOP_DISABLE);
0716: m_pd3dDevice->SetVertexShader(NULL);
0717: m_pd3dDevice->SetFVF( D3DFVF_XYZRHW | D3DFVF_TEX1 );
0718: m_pd3dDevice->SetPixelShader(0);
0719: float scale = 256.0f*2/3;
0720: for(DWORD i=0; i<3; i++){
0721: TVERTEX Vertex[4] = {
0722:
0723: { 0,(i+0)*scale,0, 1, 0, 0,},
0724: {scale,(i+0)*scale,0, 1, 1, 0,},
0725: {scale,(i+1)*scale,0, 1, 1, 1,},
0726: { 0,(i+1)*scale,0, 1, 0, 1,},
0727: };
0728: if(0==i) m_pd3dDevice->SetTexture( 0, m_pFinalTex[itex] );
0729: if(1==i) m_pd3dDevice->SetTexture( 0, m_pReductionTex[0] );
0730: if(2==i) m_pd3dDevice->SetTexture( 0, m_pReductionTex[1] );
0731: m_pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, Vertex, sizeof( TVERTEX ) );
0732: }
0733: }
0734: #endif
0735:
0736: D3DCOLOR fontColor = D3DCOLOR_ARGB(255,255,255,0);
0737: TCHAR szMsg[MAX_PATH] = TEXT("");
0738:
0739: sprintf( szMsg, TEXT("x:%4d\ny:%4d"), ix, iy);
0740: m_pFont->DrawText( 2, (FLOAT)m_d3dsdBackBuffer.Height-40, fontColor, szMsg );
0741:
0742: m_pd3dDevice->EndScene();
0743: }
0744: }
0745:
0746:
0747:
0748:
0749:
0750:
0751: HRESULT CMyD3DApplication::FrameMove()
0752: {
0753: m_iCount++;
0754:
0755: if(m_iChangeState) {m_iState++;m_iCount=0;m_iChangeState=0;}
0756:
0757: switch(m_iState){
0758: case 0:
0759: m_iChangeState = this->FrameMoveCreateMap();
0760: return S_OK;
0761: case 1:
0762: m_iChangeState = this->FrameMoveFinalGathering();
0763: return S_OK;
0764: default:
0765: break;
0766: }
0767:
0768:
0769:
0770: UpdateInput( &m_UserInput );
0771:
0772:
0773:
0774:
0775:
0776: D3DXMATRIX matRotY;
0777: D3DXMATRIX matRotX;
0778:
0779: if(!m_UserInput.bShift){
0780: if( m_UserInput.bRotateLeft && !m_UserInput.bRotateRight )
0781: m_fWorldRotY += m_fElapsedTime;
0782: else
0783: if( m_UserInput.bRotateRight && !m_UserInput.bRotateLeft )
0784: m_fWorldRotY -= m_fElapsedTime;
0785:
0786: if( m_UserInput.bRotateUp && !m_UserInput.bRotateDown )
0787: m_fWorldRotX += m_fElapsedTime;
0788: else
0789: if( m_UserInput.bRotateDown && !m_UserInput.bRotateUp )
0790: m_fWorldRotX -= m_fElapsedTime;
0791: }
0792:
0793: D3DXMatrixRotationX( &matRotX, m_fWorldRotX );
0794: D3DXMatrixRotationY( &matRotY, m_fWorldRotY );
0795:
0796: D3DXMatrixMultiply( &m_mWorld, &matRotY, &matRotX );
0797:
0798:
0799:
0800:
0801: if(m_UserInput.bShift){
0802: if( m_UserInput.bRotateLeft && !m_UserInput.bRotateRight )
0803: m_fLightRotY += m_fElapsedTime;
0804: else if( m_UserInput.bRotateRight && !m_UserInput.bRotateLeft )
0805: m_fLightRotY -= m_fElapsedTime;
0806:
0807: if( m_UserInput.bRotateUp && !m_UserInput.bRotateDown )
0808: m_fLightRotX += m_fElapsedTime;
0809: else if( m_UserInput.bRotateDown && !m_UserInput.bRotateUp )
0810: m_fLightRotX -= m_fElapsedTime;
0811: }
0812:
0813: D3DXMatrixRotationX( &matRotX, m_fLightRotX );
0814: D3DXMatrixRotationY( &matRotY, m_fLightRotY );
0815: D3DXMatrixMultiply( &m_mLight, &matRotX, &matRotY );
0816:
0817:
0818:
0819:
0820:
0821: if( m_UserInput.bZoomIn && !m_UserInput.bZoomOut )
0822: m_fViewZoom += m_fElapsedTime;
0823: else if( m_UserInput.bZoomOut && !m_UserInput.bZoomIn )
0824: m_fViewZoom -= m_fElapsedTime;
0825:
0826: D3DXVECTOR3 vFromPt = D3DXVECTOR3( 0.0f, 0.0f, -m_fViewZoom );
0827: D3DXVECTOR3 vLookatPt = D3DXVECTOR3( 0.0f, 0.3f, 0.0f );
0828: D3DXVECTOR3 vUpVec = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
0829: D3DXMatrixLookAtLH( &m_mView, &vFromPt, &vLookatPt, &vUpVec );
0830:
0831:
0832:
0833:
0834: if( m_UserInput.bChangeShader ) m_Shader = (m_Shader + 1) % 3;
0835:
0836: return S_OK;
0837: }
0838:
0839:
0840:
0841:
0842: void CMyD3DApplication::UpdateInput( UserInput* pUserInput )
0843: {
0844: pUserInput->bRotateUp = ( m_bActive && (GetAsyncKeyState( VK_UP ) & 0x8000) == 0x8000 );
0845: pUserInput->bRotateDown = ( m_bActive && (GetAsyncKeyState( VK_DOWN ) & 0x8000) == 0x8000 );
0846: pUserInput->bRotateLeft = ( m_bActive && (GetAsyncKeyState( VK_LEFT ) & 0x8000) == 0x8000 );
0847: pUserInput->bRotateRight = ( m_bActive && (GetAsyncKeyState( VK_RIGHT ) & 0x8000) == 0x8000 );
0848:
0849: pUserInput->bZoomIn = ( m_bActive && (GetAsyncKeyState( 'Z' ) & 0x8000) == 0x8000 );
0850: pUserInput->bZoomOut = ( m_bActive && (GetAsyncKeyState( 'X' ) & 0x8000) == 0x8000 );
0851:
0852: pUserInput->bChangeShader= ( m_bActive && (GetAsyncKeyState( 'A' ) & 0x8001) == 0x8001 );
0853:
0854: pUserInput->bShift = ((GetAsyncKeyState( VK_SHIFT ) & 0x8000) == 0x8000);
0855: }
0856:
0857:
0858:
0859:
0860: static float P(int l, int m, float x)
0861: {
0862: float pmm=1.0;
0863:
0864: if(0<m){
0865: float somx2 = sqrtf((1.0f-x)*(1.0f+x));
0866: float fact = 1.0;
0867: for(int i=1; i<=m; i++){
0868: pmm *= (-fact)*somx2;
0869: fact += 2.0f;
0870: }
0871: }
0872: if(l==m) return pmm;
0873:
0874: float pmmp1=x*(2.0f*m+1.0f) * pmm;
0875: if(l==m+1) return pmmp1;
0876:
0877: float pll = 0.0;
0878:
0879: for(int ll=m+2; ll<=l; ll++){
0880: pll = ((2.0f*ll-1.0f)*x*pmmp1-(ll+m-1.0f)*pmm) / (ll-m);
0881: pmm = pmmp1;
0882: pmmp1 = pll;
0883: }
0884:
0885: return pll;
0886: }
0887:
0888: static float K(int l, int m)
0889: {
0890: int i;
0891: float lpm=1;
0892: float lnm=1;
0893:
0894: if(m<0)m=-m;
0895:
0896: for(i=l-m;0<i;i--)lnm *= i;
0897: for(i=l+m;0<i;i--)lpm *= i;
0898:
0899: return ((2*l+1)*lnm)/(4*D3DX_PI*lpm);
0900:
0901: }
0902:
0903: static float SphericalHarmonics(int l, int m, float theta, float phi)
0904: {
0905: float ret = K(l,m);
0906:
0907: if(0<m){
0908: ret *= 2.f * cosf( m*phi) * P(l, m, cosf(theta));
0909:
0910: }else if(m<0){
0911: ret *= 2.f * sinf(-m*phi) * P(l, -m, cosf(theta));
0912:
0913: }else{
0914: ret *= P(l, m, cosf(theta));
0915: }
0916:
0917: return ret;
0918: }
0919:
0920:
0921:
0922:
0923:
0924: HRESULT CMyD3DApplication::Render()
0925: {
0926: switch(m_iState){
0927: case 0:
0928: this->RenderCreateMap();
0929: return S_OK;
0930: case 1:
0931: this->RenderFinalGathering();
0932: return S_OK;
0933: default:
0934: break;
0935: }
0936:
0937: D3DXMATRIX m, mT, mR, mW, mView, mProj;
0938: DWORD i;
0939: D3DXVECTOR4 v;
0940: D3DMATERIAL9 *pMtrl;
0941:
0942:
0943: m = m_mLight * m_mWorld;
0944: D3DXVECTOR4 LightPos = D3DXVECTOR4(0.0f, 0.0f, 5.0f, 0.0f);
0945: D3DXVec4Transform( &LightPos, &LightPos, &m );
0946: D3DXVECTOR4 LightDir = D3DXVECTOR4(0.0f, 0.0f, 1.0f, 0.0f);
0947: D3DXVec4Transform( &LightDir, &LightDir, &m_mLight );
0948:
0949:
0950:
0951:
0952: if( SUCCEEDED( m_pd3dDevice->BeginScene() ) )
0953: {
0954:
0955: m_pd3dDevice->Clear(0L, NULL
0956: , D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER
0957: , 0xff000000, 1.0f, 0L);
0958:
0959: if( m_pEffect != NULL )
0960: {
0961:
0962:
0963:
0964: m_pEffect->SetTechnique( m_hTechnique );
0965: m_pEffect->Begin( NULL, 0 );
0966: m_pEffect->Pass( 3+m_Shader );
0967:
0968:
0969:
0970:
0971:
0972: m = m_mWorld * m_mView * m_mProj;
0973: m_pEffect->SetMatrix( m_hmWVP, &m );
0974:
0975: D3DXVECTOR4 vSH[TEX_MAX];
0976:
0977: float ref = 3.0f;
0978:
0979: float phi = atan2f(LightDir.z, LightDir.x);
0980: float theta = acosf(LightDir.y);
0981:
0982: for(int l=0; l<=L_MAX; l++){
0983: for(int m=-l; m<=l; m++){
0984: int n = l*(l+1) + m;
0985: ((float*)&vSH[0])[n] = ref * SphericalHarmonics(l, m, theta, phi);
0986:
0987: if(2==l){
0988: ((float*)&vSH[0])[n] *= 3;
0989: }
0990: if(3==l){
0991: ((float*)&vSH[0])[n] *= 15;
0992: }
0993: }
0994: }
0995:
0996: m_pEffect->SetVectorArray("vSH", vSH, (L_MAX+1)*(L_MAX+1)/4);
0997:
0998:
0999: for(int tex = 0; tex < TEX_MAX; tex++){
1000: char str[256];
1001: sprintf(str, "PrtTex%d", tex);
1002: m_pEffect->SetTexture(str, this->m_pFinalTex[tex] );
1003: }
1004:
1005: pMtrl = m_pMeshBg->m_pMaterials;
1006: for( i=0; i<m_pMeshBg->m_dwNumMaterials; i++ ) {
1007: m_pEffect->SetTexture(m_htSrcTex, m_pMeshBg->m_pTextures[i] );
1008: m_pMeshBg->m_pLocalMesh->DrawSubset( i );
1009: pMtrl++;
1010: }
1011:
1012: m_pEffect->End();
1013: }
1014:
1015:
1016:
1017:
1018: {
1019: m = m_mView * m_mProj;
1020: v = LightPos;
1021: v.w = 1;
1022: D3DXVec4Transform( &v, &v, &m );
1023: float x = (this->m_rcWindowClient.right-this->m_rcWindowClient.left)*( 0.5f*v.x/v.w+0.5f);
1024: float y = (this->m_rcWindowClient.bottom-this->m_rcWindowClient.top)*(-0.5f*v.y/v.w+0.5f);
1025:
1026: m_pd3dDevice->SetTextureStageState(0,D3DTSS_COLOROP, D3DTOP_SELECTARG1);
1027: m_pd3dDevice->SetTextureStageState(0,D3DTSS_COLORARG1, D3DTA_DIFFUSE);
1028: m_pd3dDevice->SetTextureStageState(1,D3DTSS_COLOROP, D3DTOP_DISABLE);
1029: m_pd3dDevice->SetVertexShader(NULL);
1030: m_pd3dDevice->SetFVF( D3DFVF_XYZRHW | D3DFVF_DIFFUSE );
1031: m_pd3dDevice->SetPixelShader(0);
1032:
1033: typedef struct {FLOAT p[4]; DWORD color;} LVERTEX;
1034: for(DWORD i=0; i<2; i++){
1035: LVERTEX Vertex[4] = {
1036:
1037: {x-3,y-3, v.z/v.w, 1, 0xffffc0,},
1038: {x+3,y-3, v.z/v.w, 1, 0xffffc0,},
1039: {x+3,y+3, v.z/v.w, 1, 0xffffc0,},
1040: {x-3,y+3, v.z/v.w, 1, 0xffffc0,},
1041: };
1042: m_pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, Vertex, sizeof( LVERTEX ) );
1043: }
1044: }
1045:
1046:
1047:
1048: RenderText();
1049:
1050: #if 1
1051: {
1052: m_pd3dDevice->SetTextureStageState(0,D3DTSS_COLOROP, D3DTOP_SELECTARG1);
1053: m_pd3dDevice->SetTextureStageState(0,D3DTSS_COLORARG1, D3DTA_TEXTURE);
1054: m_pd3dDevice->SetTextureStageState(1,D3DTSS_COLOROP, D3DTOP_DISABLE);
1055: m_pd3dDevice->SetVertexShader(NULL);
1056: m_pd3dDevice->SetFVF( D3DFVF_XYZRHW | D3DFVF_TEX1 );
1057: m_pd3dDevice->SetPixelShader(0);
1058: float scale = 96.0f;
1059: for(DWORD i=0; i<2+TEX_MAX; i++){
1060: TVERTEX Vertex[4] = {
1061:
1062: {(i+0)*scale, 0,0, 1, 0, 0,},
1063: {(i+1)*scale, 0,0, 1, 1, 0,},
1064: {(i+1)*scale,scale,0, 1, 1, 1,},
1065: {(i+0)*scale,scale,0, 1, 0, 1,},
1066: };
1067: if(0==i) m_pd3dDevice->SetTexture( 0, m_pPosTex );
1068: if(1==i) m_pd3dDevice->SetTexture( 0, m_pNormalTex );
1069: if(2<=i) m_pd3dDevice->SetTexture( 0, m_pFinalTex[i-2] );
1070: m_pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, Vertex, sizeof( TVERTEX ) );
1071: }
1072: }
1073: #endif
1074:
1075:
1076: m_pd3dDevice->EndScene();
1077: }
1078:
1079: return S_OK;
1080: }
1081:
1082:
1083:
1084:
1085:
1086:
1087:
1088:
1089: HRESULT CMyD3DApplication::RenderText()
1090: {
1091: D3DCOLOR fontColor = D3DCOLOR_ARGB(255,255,255,0);
1092: TCHAR szMsg[MAX_PATH] = TEXT("");
1093:
1094: FLOAT fNextLine = 40.0f;
1095:
1096:
1097: fNextLine = (FLOAT) m_d3dsdBackBuffer.Height;
1098:
1099: lstrcpy( szMsg, TEXT("Press 'F2' to configure display") );
1100: fNextLine -= 20.0f;
1101: m_pFont->DrawText( 2, fNextLine, fontColor, szMsg );
1102:
1103: lstrcpy( szMsg, TEXT("Press 'A' to change shader") );
1104: fNextLine -= 20.0f;
1105: m_pFont->DrawText( 2, fNextLine, fontColor, szMsg );
1106:
1107: lstrcpy( szMsg, m_strDeviceStats );
1108: fNextLine -= 20.0f;
1109: m_pFont->DrawText( 2, fNextLine, fontColor, szMsg );
1110: lstrcpy( szMsg, m_strFrameStats );
1111: fNextLine -= 20.0f;
1112: m_pFont->DrawText( 2, fNextLine, fontColor, szMsg );
1113:
1114: return S_OK;
1115: }
1116:
1117:
1118:
1119:
1120:
1121:
1122:
1123:
1124: LRESULT CMyD3DApplication::MsgProc( HWND hWnd, UINT msg,
1125: WPARAM wParam, LPARAM lParam )
1126: {
1127: switch( msg )
1128: {
1129: case WM_PAINT:
1130: {
1131: if( m_bLoadingApp )
1132: {
1133:
1134: HDC hDC = GetDC( hWnd );
1135: TCHAR strMsg[MAX_PATH];
1136: wsprintf(strMsg, TEXT("Loading... Please wait"));
1137: RECT rct;
1138: GetClientRect( hWnd, &rct );
1139: DrawText( hDC, strMsg, -1, &rct
1140: , DT_CENTER|DT_VCENTER|DT_SINGLELINE );
1141: ReleaseDC( hWnd, hDC );
1142: }
1143: break;
1144: }
1145:
1146: }
1147:
1148: return CD3DApplication::MsgProc( hWnd, msg, wParam, lParam );
1149: }
1150:
1151:
1152:
1153:
1154:
1155:
1156:
1157:
1158: HRESULT CMyD3DApplication::InvalidateDeviceObjects()
1159: {
1160:
1161: SAFE_RELEASE(m_pMaskTex);
1162: for(int i=0;i<REDUCTION_MAPS;i++){
1163: SAFE_RELEASE(m_pReductionSurf[i]);
1164: SAFE_RELEASE(m_pReductionTex[i]);
1165: }
1166: for(int j=0;j<TEX_MAX;j++){
1167: SAFE_RELEASE(m_pFinalSurf[j]);
1168: SAFE_RELEASE(m_pFinalTex[j]);
1169: }
1170: SAFE_RELEASE(m_pNormalLockSurf);
1171: SAFE_RELEASE(m_pNormalLockTex);
1172: SAFE_RELEASE(m_pNormalSurf);
1173: SAFE_RELEASE(m_pNormalTex);
1174: SAFE_RELEASE(m_pPosLockSurf);
1175: SAFE_RELEASE(m_pPosLockTex);
1176: SAFE_RELEASE(m_pPosSurf);
1177: SAFE_RELEASE(m_pPosTex);
1178: SAFE_RELEASE(m_pMapZ);
1179:
1180: m_pMeshBg->InvalidateDeviceObjects();
1181:
1182: m_pFont->InvalidateDeviceObjects();
1183:
1184:
1185: if( m_pEffect != NULL ) m_pEffect->OnLostDevice();
1186:
1187: return S_OK;
1188: }
1189:
1190:
1191:
1192:
1193:
1194:
1195:
1196:
1197: HRESULT CMyD3DApplication::DeleteDeviceObjects()
1198: {
1199:
1200: SAFE_RELEASE( m_pEffect );
1201:
1202:
1203: m_pMeshBg->Destroy();
1204:
1205:
1206: m_pFont->DeleteDeviceObjects();
1207:
1208: return S_OK;
1209: }
1210:
1211:
1212:
1213:
1214:
1215:
1216:
1217:
1218: HRESULT CMyD3DApplication::FinalCleanup()
1219: {
1220: SAFE_DELETE( m_pMeshBg );
1221:
1222: SAFE_DELETE( m_pFont );
1223:
1224: return S_OK;
1225: }
1226:
1227:
1228:
1229:
1230: