0001: // ----------------------------------------------------------------------------
0002: //
0003: // draw.cpp - 描画部分
0004: // 
0005: // Copyright (c) 2002 IMAGIRE Takashi (imagire@gmail.com)
0006: // All Rights Reserved.
0007: //
0008: // ----------------------------------------------------------------------------
0009: #define STRICT
0010: 
0011: #include <windows.h>
0012: #include "main.h"
0013: #include "draw.h"
0014: #include "load.h"
0015: 
0016: #define frand()   rand()/((float)RAND_MAX)
0017: 
0018: LPDIRECT3DVERTEXBUFFER8 pMeshVB = NULL;
0019: LPDIRECT3DINDEXBUFFER8  pMeshIndex = NULL;
0020: D3DXATTRIBUTERANGE      *pSubsetTable = NULL;
0021: DWORD                   nMeshFaces = 0;
0022: DWORD                   nMeshVertices = 0;
0023: D3DMATERIAL8            *pMeshMaterials = NULL;     // メッシュの質感
0024: LPDIRECT3DTEXTURE8      *pMeshTextures  = NULL;     // メッシュのテクスチャー
0025: DWORD                   dwNumMaterials = 0L;        // マテリアルの数
0026: FLOAT                   MeshRadius;                 // メッシュの大きさ
0027: 
0028: DWORD                   hVertexShader=~0;           // モデルの描画
0029: DWORD                   hPixelShader=~0;            // モデルの描画
0030: LPDIRECT3DCUBETEXTURE8  pNormalCubeMap=NULL;
0031: LPDIRECT3DCUBETEXTURE8  pCubeMap=NULL;
0032: 
0033: DWORD                   hSpecularVertexShader=~0;   // モデルの描画
0034: DWORD                   hSpecularPixelShader=~0;        // モデルの描画
0035: LPDIRECT3DCUBETEXTURE8  pSpecularMap=NULL;
0036: 
0037: LPDIRECT3DVERTEXBUFFER8 pBlurVB = NULL;
0038: LPDIRECT3DINDEXBUFFER8  pBlurIB = NULL;
0039: typedef struct {
0040:     float x,y,z;
0041:     float tu,tv;
0042: }D3D_BLUR_VERTEX;
0043: #define D3DFVF_BLUR_VERTEX      (D3DFVF_XYZ | D3DFVF_TEX1)
0044: 
0045: DWORD dwBlurDecl[] = {
0046:     D3DVSD_STREAM(0),
0047:     D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3 ),          //D3DVSDE_POSITION,  0
0048:     D3DVSD_REG(D3DVSDE_TEXCOORD0,D3DVSDT_FLOAT2 ),          //D3DVSDE_TEXCOORD0, 7  
0049:     D3DVSD_END()
0050: };
0051: 
0052: // ----------------------------------------------------------------------------
0053: // 外部関数
0054: void InitBg ( LPDIRECT3DDEVICE8 lpD3DDev );
0055: void DrawBg ( LPDIRECT3DDEVICE8 lpD3DDev );
0056: void CleanBg( LPDIRECT3DDEVICE8 lpD3DDev );
0057: 
0058: 
0059: 
0060: // ----------------------------------------------------------------------------
0061: // Name: LoadXFile(char* filename, LPDIRECT3DDEVICE8 lpD3DDev)
0062: // Desc: X-Fileの読み込み
0063: //-----------------------------------------------------------------------------
0064: HRESULT LoadXFile(char* filename, LPDIRECT3DDEVICE8 lpD3DDev)
0065: {
0066:     LPD3DXMESH pMesh, pMeshOpt;
0067:     LPD3DXBUFFER pD3DXMtrlBuffer = NULL;
0068:     DWORD i;
0069:     HRESULT hr;
0070: 
0071:     hr = D3DXLoadMeshFromX(filename, D3DXMESH_MANAGED,
0072:                                 lpD3DDev, NULL,
0073:                                 &pD3DXMtrlBuffer, &dwNumMaterials,
0074:                                 &pMesh);
0075:     if(FAILED(hr)) return E_FAIL;
0076: 
0077:     //並び替えておく
0078:     pMesh->Optimize(D3DXMESHOPT_ATTRSORT, NULL, NULL, NULL, NULL, &pMeshOpt);
0079:     RELEASE(pMesh);
0080: 
0081:     //アトリビュートテーブル
0082:     pMeshOpt->GetAttributeTable(NULL,&dwNumMaterials);
0083:     pSubsetTable = new D3DXATTRIBUTERANGE[dwNumMaterials];
0084:     pMeshOpt->GetAttributeTable(pSubsetTable, &dwNumMaterials);
0085: 
0086:     // FVF変換
0087:     hr = pMeshOpt->CloneMeshFVF(pMeshOpt->GetOptions(), D3DFVF_VERTEX, lpD3DDev, &pMesh);
0088:     if(FAILED(hr)) return E_FAIL;
0089:     RELEASE(pMeshOpt);
0090:     D3DXComputeNormals(pMesh, NULL);
0091: 
0092:     //Vertex Bufferにコピーする
0093:     D3DVERTEX* pSrc;
0094:     D3D_CUSTOMVERTEX* pDest;
0095:     LPDIRECT3DINDEXBUFFER8 pSrcIndex;
0096:     WORD* pISrc;
0097:     WORD* pIDest;
0098: 
0099:     DWORD nMeshVertices = pMesh->GetNumVertices();
0100:     DWORD nMeshFaces = pMesh->GetNumFaces();
0101:     lpD3DDev->CreateVertexBuffer(nMeshVertices * sizeof(D3D_CUSTOMVERTEX),0,D3DFVF_CUSTOMVERTEX,D3DPOOL_MANAGED,&pMeshVB);
0102:     lpD3DDev->CreateIndexBuffer(nMeshFaces * 3 * sizeof(WORD),0,D3DFMT_INDEX16,D3DPOOL_MANAGED,&pMeshIndex);
0103: 
0104:     LPDIRECT3DVERTEXBUFFER8 pVB;
0105:     pMesh->GetVertexBuffer(&pVB);
0106:     pVB->Lock(0,0,(BYTE**)&pSrc,0);
0107:     pMeshVB->Lock(0,0,(BYTE**)&pDest,0);
0108:     MeshRadius = 0.0f;
0109:     for(i=0;i<nMeshVertices;i++){
0110:         pDest->x = pSrc->x;
0111:         pDest->y = pSrc->y;
0112:         pDest->z = pSrc->z;
0113:         pDest->nx = pSrc->nx;
0114:         pDest->ny = pSrc->ny;
0115:         pDest->nz = pSrc->nz;
0116:         pDest->tu0 = pSrc->tu0;
0117:         pDest->tu0 = pSrc->tu0;
0118:         // サイズの計算
0119:         FLOAT radius = sqrtf( pSrc->x*pSrc->x + pSrc->y*pSrc->y + pSrc->z*pSrc->z );
0120:         if (MeshRadius < radius) MeshRadius = radius;
0121:         
0122:         pSrc += 1;
0123:         pDest += 1;
0124:     }
0125:     pVB->Unlock();
0126:     pVB->Release();
0127:     pMeshVB->Unlock();
0128: 
0129:     //インデックスのコピー
0130:     pMesh->GetIndexBuffer(&pSrcIndex);
0131:     pSrcIndex->Lock(0,0,(BYTE**)&pISrc,0);
0132:     pMeshIndex->Lock(0,0,(BYTE**)&pIDest,0);
0133:     CopyMemory(pIDest,pISrc,nMeshFaces * 3 * sizeof(WORD));
0134:     pSrcIndex->Unlock();
0135:     pMeshIndex->Unlock();
0136:     pSrcIndex->Release();
0137: 
0138:     // pD3DXMtrlBuffer から、質感やテクスチャーの情報を読み取る
0139:     D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
0140:     pMeshTextures = new LPDIRECT3DTEXTURE8[dwNumMaterials];
0141:     pMeshMaterials = new D3DMATERIAL8[dwNumMaterials];
0142: 
0143:     for(i = 0; i < dwNumMaterials; i++){
0144:         pMeshMaterials[i] = d3dxMaterials[i].MatD3D;
0145:         pMeshMaterials[i].Ambient = pMeshMaterials[i].Diffuse;
0146:         hr = D3DXCreateTextureFromFile( lpD3DDev, 
0147:                                         d3dxMaterials[i].pTextureFilename, 
0148:                                         &pMeshTextures[i] );
0149:         if(FAILED(hr)) pMeshTextures[i] = NULL;
0150:     }
0151:     RELEASE(pD3DXMtrlBuffer);
0152:     
0153:     RELEASE(pMesh);
0154: 
0155:     return S_OK;
0156: }
0157: //-----------------------------------------------------------------------------
0158: // 正規化キューブマップの作成
0159: //-----------------------------------------------------------------------------
0160: void make_normalize_cubemap( D3DXVECTOR4 *pOut, D3DXVECTOR3 *pTexCoord,
0161: D3DXVECTOR3 *pTexelSize, LPVOID pData)
0162: {
0163:     D3DXVECTOR3 n;
0164:     D3DXVec3Normalize( &n, pTexCoord );
0165: 
0166:     pOut->x = 0.5f*(n.x + 1.0f);
0167:     pOut->y = 0.5f*(n.y + 1.0f);
0168:     pOut->z = 0.5f*(n.z + 1.0f);
0169:     pOut->w = 1.0f;
0170: }
0171: static const int BLUR_GRID = 10;
0172: static const float BLURSIZE = 1.0f;
0173: //-----------------------------------------------------------------------------
0174: // Name: InitRender()
0175: // Desc: Load the mesh and build the material and texture arrays
0176: //-----------------------------------------------------------------------------
0177: HRESULT InitRender(LPDIRECT3DDEVICE8 lpD3DDev)
0178: {
0179:     HRESULT hr;
0180: 
0181:     // モデルの読み込み
0182:     if ( FAILED(hr = LoadXFile("nsx.x", lpD3DDev)) ) return hr;
0183:     
0184:     // 頂点バッファの作成 
0185:     D3D_BLUR_VERTEX *pBlurDest;
0186:     lpD3DDev->CreateVertexBuffer( (BLUR_GRID+1)*(BLUR_GRID+1)*sizeof(D3DVERTEX),
0187:                                 D3DUSAGE_WRITEONLY, D3DFVF_VERTEX, D3DPOOL_MANAGED,
0188:                                 &pBlurVB );
0189:     // 頂点をセットアップ
0190:     {
0191:     pBlurVB->Lock ( 0, 0, (BYTE**)&pBlurDest, 0 );
0192:     float pos_z = -BLURSIZE;
0193:     for(DWORD z = 0; z <= BLUR_GRID; z++){
0194:         float pos_x = -BLURSIZE;
0195:         for(DWORD x = 0; x <= BLUR_GRID; x++){
0196:             pBlurDest->x  = pos_x;
0197:             pBlurDest->y  = pos_z;
0198:             pBlurDest->z  = 1.0f;
0199:             pBlurDest->tu = (pos_x+BLURSIZE)/(2.0f*BLURSIZE);
0200:             pBlurDest->tv = (pos_z+BLURSIZE)/(2.0f*BLURSIZE);
0201:             pBlurDest++;
0202:             pos_x += 2*BLURSIZE/BLUR_GRID;
0203:         }
0204:         pos_z += 2*BLURSIZE/BLUR_GRID;
0205:     }
0206:     pBlurVB->Unlock ();
0207:     }
0208: 
0209: 
0210:     // インデックスをセットアップ
0211:     WORD *pIndex;
0212:     lpD3DDev->CreateIndexBuffer( 3*2*BLUR_GRID*BLUR_GRID * sizeof(WORD),
0213:                                0,
0214:                                D3DFMT_INDEX16, D3DPOOL_MANAGED,
0215:                                &pBlurIB );
0216:     pBlurIB->Lock ( 0, 0, (BYTE**)&pIndex, 0 );
0217:     {
0218:     for (WORD i = 0; i < BLUR_GRID; i++) {
0219:         for (WORD j = 0; j < BLUR_GRID; j++) {
0220:             *pIndex++ = j + 0 + (i+0) * (BLUR_GRID+1);
0221:             *pIndex++ = j + 0 + (i+1) * (BLUR_GRID+1);
0222:             *pIndex++ = j + 1 + (i+0) * (BLUR_GRID+1);
0223: 
0224:             *pIndex++ = j + 1 + (i+0) * (BLUR_GRID+1);
0225:             *pIndex++ = j + 0 + (i+1) * (BLUR_GRID+1);
0226:             *pIndex++ = j + 1 + (i+1) * (BLUR_GRID+1);
0227:         }
0228:     }
0229:     }
0230: 
0231:     pBlurIB->Unlock ();
0232: 
0233:     
0234:     
0235:     // シェ-ダーのロード
0236:     if ( FAILED(CVertexShaderMgr::Load(lpD3DDev, "vs.vsh",     &hVertexShader, dwDecl)) ) return hr;
0237:     if ( FAILED( CPixelShaderMgr::Load(lpD3DDev, "ps.psh",     &hPixelShader)) ) return hr;
0238:     if ( FAILED(CVertexShaderMgr::Load(lpD3DDev, "specular.vsh",&hSpecularVertexShader, dwBlurDecl)) ) return hr;
0239:     if ( FAILED( CPixelShaderMgr::Load(lpD3DDev, "specular.psh", &hSpecularPixelShader)) ) return hr;
0240:     
0241:     // 正規化キューブマップの作成
0242:     hr = lpD3DDev->CreateCubeTexture( 512, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
0243:                                 D3DPOOL_DEFAULT , &pNormalCubeMap );
0244:     if ( FAILED(hr) ) return hr;
0245:     hr = D3DXFillCubeTexture( pNormalCubeMap, make_normalize_cubemap, NULL );
0246:     if ( FAILED(hr) ) return hr;
0247: 
0248:     // 環境キューブマップの作成
0249:     hr = lpD3DDev->CreateCubeTexture( 512, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
0250:                                 D3DPOOL_DEFAULT , &pCubeMap );
0251:     if ( FAILED(hr) ) return hr;
0252:     // ディフューズマップの作成
0253:     hr = lpD3DDev->CreateCubeTexture( 512, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
0254:                                 D3DPOOL_DEFAULT , &pSpecularMap );
0255:     if ( FAILED(hr) ) return hr;
0256: 
0257:     // 背景部分の初期化
0258:     InitBg(lpD3DDev);
0259: 
0260:     // 不変なレジスタの設定
0261:     lpD3DDev->SetRenderState( D3DRS_ZENABLE, TRUE );
0262:     lpD3DDev->SetRenderState( D3DRS_LIGHTING,  FALSE );
0263:     lpD3DDev->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE);
0264:     lpD3DDev->SetVertexShaderConstant(12, &D3DXVECTOR4(0.0f, 0.5f, 1.0f, 2.0f), 1);
0265: 
0266:     lpD3DDev->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
0267:     lpD3DDev->SetTextureStageState(1, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
0268:     lpD3DDev->SetTextureStageState(2, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
0269:     lpD3DDev->SetTextureStageState(3, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
0270:     lpD3DDev->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
0271:     lpD3DDev->SetTextureStageState(1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
0272:     lpD3DDev->SetTextureStageState(2, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
0273:     lpD3DDev->SetTextureStageState(3, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
0274:     lpD3DDev->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_NONE);
0275:     lpD3DDev->SetTextureStageState(1, D3DTSS_MIPFILTER, D3DTEXF_NONE);
0276:     lpD3DDev->SetTextureStageState(2, D3DTSS_MIPFILTER, D3DTEXF_NONE);
0277:     lpD3DDev->SetTextureStageState(3, D3DTSS_MIPFILTER, D3DTEXF_NONE);
0278:     lpD3DDev->SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
0279:     lpD3DDev->SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
0280:     lpD3DDev->SetTextureStageState(1, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
0281:     lpD3DDev->SetTextureStageState(1, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
0282:     lpD3DDev->SetTextureStageState(2, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
0283:     lpD3DDev->SetTextureStageState(2, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
0284:     lpD3DDev->SetTextureStageState(3, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
0285:     lpD3DDev->SetTextureStageState(3, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
0286: 
0287:     return S_OK;
0288: }
0289: //-----------------------------------------------------------------------------
0290: // Name: Render()
0291: // Desc: Draws the scene
0292: //-----------------------------------------------------------------------------
0293: const float z_min =   1.0f;
0294: const float z_max  = 80.0f;
0295: D3DXVECTOR4 lightDir(1.0f, 1.0f, 0.0, 0.0f);
0296: 
0297: VOID DrawModel( LPDIRECT3DDEVICE8 lpD3DDev )
0298: {
0299:     D3DXMATRIX mVP,  mWorld, mView,  mProj, mTex;
0300:     D3DXMATRIX mVPL, mLight, mViewL, mProjL;
0301:     D3DXMATRIX  m;
0302:     D3DXVECTOR4 vl;
0303:     DWORD i;
0304:     
0305:     D3DXVec4Normalize(&vl, &lightDir);
0306:     lpD3DDev->SetVertexShaderConstant(11, &vl, 1);
0307: 
0308:     // 
0309:     // 通常レンダリング用の行列を作成
0310:     // 
0311:     // ビュー行列
0312:     D3DXVECTOR3 eye    = D3DXVECTOR3(0.0f,1.4f*MeshRadius, 2.5f*MeshRadius);
0313:     D3DXVECTOR3 lookAt = D3DXVECTOR3(0.0f,  0.0f,  0.0f);
0314:     D3DXVECTOR3 up     = D3DXVECTOR3(0.0f,  1.0f,  0.0f);
0315:     D3DXMatrixLookAtLH(&mView, &eye, &lookAt, &up);
0316:     // 射影行列
0317:     D3DXMatrixPerspectiveFovLH(&mProj
0318:         , D3DXToRadian(60.0f)                       // 視野角
0319:         , (float)WIDTH/(float)HEIGHT                // アスペクト比
0320:         , z_min, z_max                              // 最近接距離,最遠方距離
0321:         );
0322:     
0323:     mVP = mView * mProj;
0324:     lpD3DDev->SetVertexShaderConstant( 15, &eye, 1);
0325: 
0326:     //
0327:     // 外側もでる描画
0328:     //
0329:     float t = 0.0001f*(timeGetTime()%10000);
0330:     D3DXMatrixTranslation(&m, 1.5f*MeshRadius, 0,0);
0331:     D3DXMatrixRotationY( &mWorld, 3.0f*2.0f*D3DX_PI*t );
0332: //D3DXMatrixRotationY( &mWorld, -0.2*PI/2 ); // 撮影角度
0333:     mWorld = m * mWorld;
0334:     
0335:     m = mWorld * mVP;
0336:     lpD3DDev->SetVertexShaderConstant( 0,D3DXMatrixTranspose(&m,&m), 4);
0337:     lpD3DDev->SetVertexShaderConstant( 4,D3DXMatrixTranspose(&m,&mWorld), 4);
0338: 
0339:     D3DXMatrixInverse( &m,  NULL, &mWorld);
0340:     D3DXVec4Transform(&vl, &lightDir, &m);
0341:     D3DXVec4Normalize(&vl, &vl);
0342:     vl.w = 0.3f;
0343:     lpD3DDev->SetVertexShaderConstant(13, &vl, 1);
0344:     
0345:     lpD3DDev->SetStreamSource(0, pMeshVB, sizeof(D3D_CUSTOMVERTEX));
0346:     lpD3DDev->SetIndices(pMeshIndex,0);
0347:     
0348:     for(i=0;i<dwNumMaterials;i++){
0349:         //色をセット
0350:         D3DXVECTOR4 vl;
0351:         vl.x = pMeshMaterials[i].Diffuse.r;
0352:         vl.y = pMeshMaterials[i].Diffuse.g;
0353:         vl.z = pMeshMaterials[i].Diffuse.b;
0354:         lpD3DDev->SetVertexShaderConstant(14, &vl, 1);
0355: 
0356:         lpD3DDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 
0357:                                         pSubsetTable[i].VertexStart,
0358:                                         pSubsetTable[i].VertexCount,
0359:                                         pSubsetTable[i].FaceStart * 3,
0360:                                         pSubsetTable[i].FaceCount);
0361:     }
0362:     //
0363:     // 内側モデル
0364:     //
0365:     D3DXMatrixRotationY( &mWorld, -1.0f*2.0f*D3DX_PI*t );
0366: //D3DXMatrixRotationY( &mWorld,-1.10f*PI/2 ); // 撮影角度
0367: 
0368:     m = mWorld * mVP;
0369:     lpD3DDev->SetVertexShaderConstant( 0,D3DXMatrixTranspose(&m,&m), 4);
0370:     lpD3DDev->SetVertexShaderConstant( 4,D3DXMatrixTranspose(&m,&mWorld), 4);
0371: 
0372:     D3DXMatrixInverse( &m,  NULL, &mWorld);
0373:     D3DXVec4Transform(&vl, &lightDir, &m);
0374:     D3DXVec4Normalize(&vl, &vl);
0375:     lpD3DDev->SetVertexShaderConstant(13, &vl, 1);
0376:     
0377:     for(i=0;i<dwNumMaterials;i++){
0378:         //色をセット
0379:         D3DXVECTOR4 vl;
0380:         vl.x = pMeshMaterials[i].Diffuse.r;
0381:         vl.y = pMeshMaterials[i].Diffuse.g;
0382:         vl.z = pMeshMaterials[i].Diffuse.b;
0383:         lpD3DDev->SetVertexShaderConstant(14, &vl, 1);
0384: 
0385:         lpD3DDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 
0386:                                         pSubsetTable[i].VertexStart,
0387:                                         pSubsetTable[i].VertexCount,
0388:                                         pSubsetTable[i].FaceStart * 3,
0389:                                         pSubsetTable[i].FaceCount);
0390:     }
0391: 
0392:     //
0393:     // 背景描画
0394:     // 
0395:     D3DXMatrixIdentity(&mWorld);
0396:     lpD3DDev->SetTransform(D3DTS_WORLD, &mWorld);
0397:     lpD3DDev->SetTransform(D3DTS_VIEW,  &mView);
0398:     lpD3DDev->SetTransform(D3DTS_PROJECTION, &mProj);
0399:     lpD3DDev->SetTexture( 1, NULL );
0400:     lpD3DDev->SetTexture( 2, NULL );
0401:     lpD3DDev->SetPixelShader (  0 );
0402: 
0403:     DrawBg(lpD3DDev);
0404: }
0405: //-----------------------------------------------------------------------------
0406: // Name: MakeCubeMap()
0407: // Desc: 環境マップを作成する
0408: //-----------------------------------------------------------------------------
0409: VOID MakeCubeMap(LPDIRECT3DDEVICE8 lpD3DDev )
0410: {
0411:     // デバイスのトランスフォーム行列を保存する。
0412:     D3DXMATRIX matProjSave, matViewSave;
0413:     lpD3DDev->GetTransform( D3DTS_VIEW,       &matViewSave );
0414:     lpD3DDev->GetTransform( D3DTS_PROJECTION, &matProjSave );
0415: 
0416:     // 現在のバック バッファと z バッファを格納する。
0417:     LPDIRECT3DSURFACE8 pBackBuffer, pZBuffer;
0418:     lpD3DDev->GetRenderTarget( &pBackBuffer );
0419:     lpD3DDev->GetDepthStencilSurface( &pZBuffer );
0420: 
0421:     // 90°の視野を射影に使用する。
0422:     D3DXMATRIX matProj;
0423:     D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/2, 1.0f, 0.5f, 1000.0f );
0424:     lpD3DDev->SetTransform( D3DTS_PROJECTION, &matProj );
0425: 
0426:     // キューブ マップの 6 つのサーフェスに対してループ処理を実行する。
0427:     for( DWORD i=0 ; i<6 ; i++ ) {
0428:         D3DXVECTOR3 vEnvEyePt = D3DXVECTOR3( 0.0f, 10.0f, 0.0f );
0429:         D3DXVECTOR3 vLookatPt, vUpVec;
0430: 
0431:         switch( i ){
0432:         case D3DCUBEMAP_FACE_POSITIVE_X:
0433:             vLookatPt = D3DXVECTOR3( 1.0f, 0.0f, 0.0f )+vEnvEyePt;
0434:             vUpVec    = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
0435:             break;
0436:         case D3DCUBEMAP_FACE_NEGATIVE_X:
0437:             vLookatPt = D3DXVECTOR3(-1.0f, 0.0f, 0.0f )+vEnvEyePt;
0438:             vUpVec    = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
0439:             break;
0440:         case D3DCUBEMAP_FACE_POSITIVE_Y:
0441:             vLookatPt = D3DXVECTOR3( 0.0f, 1.0f, 0.0f )+vEnvEyePt;
0442:             vUpVec    = D3DXVECTOR3( 0.0f, 0.0f,-1.0f );
0443:             break;
0444:         case D3DCUBEMAP_FACE_NEGATIVE_Y:
0445:             vLookatPt = D3DXVECTOR3( 0.0f,-1.0f, 0.0f )+vEnvEyePt;
0446:             vUpVec    = D3DXVECTOR3( 0.0f, 0.0f, 1.0f );
0447:             break;
0448:         case D3DCUBEMAP_FACE_POSITIVE_Z:
0449:             vLookatPt = D3DXVECTOR3( 0.0f, 0.0f, 1.0f )+vEnvEyePt;
0450:             vUpVec    = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
0451:             break;
0452:         case D3DCUBEMAP_FACE_NEGATIVE_Z:
0453:             vLookatPt = D3DXVECTOR3( 0.0f, 0.0f,-1.0f )+vEnvEyePt;
0454:             vUpVec    = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
0455:             break;
0456:         }
0457: 
0458:         D3DXMATRIX matView;
0459:         D3DXMatrixLookAtLH( &matView, &vEnvEyePt, &vLookatPt, &vUpVec );
0460:         lpD3DDev->SetTransform( D3DTS_VIEW, &matView );
0461: 
0462:         //レンダリングするサーフェスへのポインタを取得する。
0463:         LPDIRECT3DSURFACE8 pFace;
0464:         pCubeMap->GetCubeMapSurface( (D3DCUBEMAP_FACES)i, 0, &pFace );
0465:         lpD3DDev->SetRenderTarget ( pFace , pZBuffer );
0466:         pFace->Release();
0467: 
0468:         lpD3DDev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x000000, 1.0f, 0L);
0469:         lpD3DDev->BeginScene();
0470:         // ここで、シーンをレンダリングする。
0471:         DrawBg(lpD3DDev);
0472:         lpD3DDev->EndScene();
0473:     }
0474: 
0475:     // レンダリング ターゲットをメイン バック バッファに戻す。
0476:     lpD3DDev->SetRenderTarget( pBackBuffer, pZBuffer );
0477:     pBackBuffer->Release();
0478:     pZBuffer->Release();
0479: 
0480:     // 元のトランスフォーム行列をリストアする。
0481:     lpD3DDev->SetTransform( D3DTS_VIEW,       &matViewSave );
0482:     lpD3DDev->SetTransform( D3DTS_PROJECTION, &matProjSave );
0483: }
0484: //-----------------------------------------------------------------------------
0485: // Name: MakeSpecularMap()
0486: // Desc: 拡散マップを作成する
0487: //-----------------------------------------------------------------------------
0488: VOID MakeSpecularMap(LPDIRECT3DDEVICE8 lpD3DDev
0489:                     , LPDIRECT3DCUBETEXTURE8 pSpecularMap
0490:                     , LPDIRECT3DCUBETEXTURE8 pEnvMap )
0491: {
0492:     static int n = 0;
0493:     
0494:     if(256<=n)return;
0495:     n++;
0496: 
0497:     lpD3DDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE );
0498:     lpD3DDev->SetTextureStageState(0, D3DTSS_COLOROP,   D3DTOP_SELECTARG1);
0499:     lpD3DDev->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
0500:     lpD3DDev->SetTextureStageState(1, D3DTSS_COLOROP,   D3DTOP_SELECTARG1);
0501:     lpD3DDev->SetTextureStageState(2, D3DTSS_COLORARG1, D3DTA_TEXTURE );
0502:     lpD3DDev->SetTextureStageState(2, D3DTSS_COLOROP,   D3DTOP_SELECTARG1);
0503:     lpD3DDev->SetTextureStageState(3, D3DTSS_COLORARG1, D3DTA_TEXTURE );
0504:     lpD3DDev->SetTextureStageState(3, D3DTSS_COLOROP,   D3DTOP_SELECTARG1);
0505: 
0506:     lpD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
0507:     lpD3DDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
0508:     lpD3DDev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
0509:     lpD3DDev->SetVertexShader( hSpecularVertexShader );
0510:     lpD3DDev->SetPixelShader ( hSpecularPixelShader );
0511:     lpD3DDev->SetTexture( 0, pEnvMap );
0512:     lpD3DDev->SetTexture( 1, pEnvMap );
0513:     lpD3DDev->SetTexture( 2, pEnvMap );
0514:     lpD3DDev->SetTexture( 3, pEnvMap );
0515: 
0516:     // デバイスのトランスフォーム行列を保存する。
0517:     D3DXMATRIX matProjSave, matViewSave;
0518:     lpD3DDev->GetTransform( D3DTS_VIEW,       &matViewSave );
0519:     lpD3DDev->GetTransform( D3DTS_PROJECTION, &matProjSave );
0520: 
0521:     // 現在のバック バッファと z バッファを格納する。
0522:     LPDIRECT3DSURFACE8 pBackBuffer, pZBuffer;
0523:     lpD3DDev->GetRenderTarget( &pBackBuffer );
0524:     lpD3DDev->GetDepthStencilSurface( &pZBuffer );
0525: 
0526:     // 90°の視野を射影に使用する。
0527:     D3DXMATRIX matProj;
0528:     D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/2, 1.0f, 0.5f, 1000.0f );
0529:     lpD3DDev->SetTransform( D3DTS_PROJECTION, &matProj );
0530: 
0531:     // キューブ マップの 6 つのサーフェスに対してループ処理を実行する。
0532:     for( DWORD i=0 ; i<6 ; i++ ) {
0533:         D3DXVECTOR3 vEnvEyePt = D3DXVECTOR3( 0.0f, 10.0f, 0.0f );
0534:         D3DXVECTOR3 vLookatPt, vUpVec;
0535: 
0536:         switch( i ){
0537:         case D3DCUBEMAP_FACE_POSITIVE_X:
0538:             vLookatPt = D3DXVECTOR3( 1.0f, 0.0f, 0.0f )+vEnvEyePt;
0539:             vUpVec    = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
0540:             break;
0541:         case D3DCUBEMAP_FACE_NEGATIVE_X:
0542:             vLookatPt = D3DXVECTOR3(-1.0f, 0.0f, 0.0f )+vEnvEyePt;
0543:             vUpVec    = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
0544:             break;
0545:         case D3DCUBEMAP_FACE_POSITIVE_Y:
0546:             vLookatPt = D3DXVECTOR3( 0.0f, 1.0f, 0.0f )+vEnvEyePt;
0547:             vUpVec    = D3DXVECTOR3( 0.0f, 0.0f,-1.0f );
0548:             break;
0549:         case D3DCUBEMAP_FACE_NEGATIVE_Y:
0550:             vLookatPt = D3DXVECTOR3( 0.0f,-1.0f, 0.0f )+vEnvEyePt;
0551:             vUpVec    = D3DXVECTOR3( 0.0f, 0.0f, 1.0f );
0552:             break;
0553:         case D3DCUBEMAP_FACE_POSITIVE_Z:
0554:             vLookatPt = D3DXVECTOR3( 0.0f, 0.0f, 1.0f )+vEnvEyePt;
0555:             vUpVec    = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
0556:             break;
0557:         case D3DCUBEMAP_FACE_NEGATIVE_Z:
0558:             vLookatPt = D3DXVECTOR3( 0.0f, 0.0f,-1.0f )+vEnvEyePt;
0559:             vUpVec    = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
0560:             break;
0561:         }
0562: 
0563:         D3DXMATRIX matView;
0564:         D3DXMatrixLookAtLH( &matView, &vEnvEyePt, &vLookatPt, &vUpVec );
0565:         lpD3DDev->SetTransform( D3DTS_VIEW, &matView );
0566: 
0567:         D3DXMATRIX m = matView * matProj;
0568:         D3DXMatrixInverse( &m,  NULL, &m);
0569:         lpD3DDev->SetVertexShaderConstant( 8, D3DXMatrixTranspose(&m,&m), 4);
0570: 
0571:         //レンダリングするサーフェスへのポインタを取得する。
0572:         LPDIRECT3DSURFACE8 pFace;
0573:         pSpecularMap->GetCubeMapSurface( (D3DCUBEMAP_FACES)i, 0, &pFace );
0574:         lpD3DDev->SetRenderTarget ( pFace , pZBuffer );
0575:         pFace->Release();
0576: 
0577:         if(1==n){
0578:             lpD3DDev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x000000, 1.0f, 0L);
0579:         }
0580:         lpD3DDev->BeginScene();
0581:         
0582:         // 等方的サンプリング (Thanks Bee さん)
0583:         D3DXVECTOR4 l[4];
0584:         for(int k=0;k<4;k++){
0585:             float d;
0586:             l[k].w = 0;
0587:             do{
0588:                 l[k].x = 2.0f*frand()-1.0f; 
0589:                 l[k].y = 2.0f*frand()-1.0f; 
0590:                 l[k].z = 2.0f*frand()-1.0f;
0591:                 d = D3DXVec4LengthSq(&l[k]);
0592:             }while(1.0f<d);
0593:         }
0594:         D3DXVec4Normalize(&l[0], &l[0]);
0595:         D3DXVec4Normalize(&l[1], &l[1]);
0596:         D3DXVec4Normalize(&l[2], &l[2]);
0597:         D3DXVec4Normalize(&l[3], &l[3]);
0598:         lpD3DDev->SetVertexShaderConstant(32, l, 4);
0599:         lpD3DDev->SetPixelShaderConstant(1, &D3DXVECTOR4(0,0,0,1.0f/((float)n)), 1);
0600: 
0601:         lpD3DDev->SetStreamSource( 0, pBlurVB, sizeof(D3D_BLUR_VERTEX) );
0602:         lpD3DDev->SetIndices(pBlurIB,0);
0603:         lpD3DDev->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0,
0604:                             (BLUR_GRID+1)*(BLUR_GRID+1), 0, 2*BLUR_GRID*BLUR_GRID );
0605: 
0606:         lpD3DDev->EndScene();
0607:     }
0608:     lpD3DDev->SetTexture( 0, NULL );
0609:     lpD3DDev->SetTexture( 1, NULL );
0610:     lpD3DDev->SetTexture( 2, NULL );
0611:     lpD3DDev->SetTexture( 3, NULL );
0612: 
0613:     // レンダリング ターゲットをメイン バック バッファに戻す。
0614:     lpD3DDev->SetRenderTarget( pBackBuffer, pZBuffer );
0615:     pBackBuffer->Release();
0616:     pZBuffer->Release();
0617: 
0618:     // 元のトランスフォーム行列をリストアする。
0619:     lpD3DDev->SetTransform( D3DTS_VIEW,       &matViewSave );
0620:     lpD3DDev->SetTransform( D3DTS_PROJECTION, &matProjSave );
0621:     lpD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
0622: }
0623: //-----------------------------------------------------------------------------
0624: // Name: Render()
0625: // Desc: Draws the scene
0626: //-----------------------------------------------------------------------------
0627: VOID Render(LPDIRECT3DDEVICE8 lpD3DDev)
0628: {
0629:     static int init=0;
0630:     if(!init){
0631:         init=1;
0632:         MakeCubeMap(lpD3DDev);
0633:     }
0634:     // スペキュラマップを半リアルタイムに作成する
0635:     MakeSpecularMap(lpD3DDev, pSpecularMap, pCubeMap);
0636: 
0637:     // シーン開始
0638:     lpD3DDev->BeginScene();
0639: 
0640:     // ------------------------------------------------------------------------
0641:     // シーンの作成
0642:     // ------------------------------------------------------------------------
0643:     lpD3DDev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x000000, 1.0f, 0L);
0644: 
0645:     lpD3DDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE );
0646:     lpD3DDev->SetTextureStageState(0, D3DTSS_COLOROP,   D3DTOP_SELECTARG1);
0647:     lpD3DDev->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
0648:     lpD3DDev->SetTextureStageState(1, D3DTSS_COLOROP,   D3DTOP_SELECTARG1);
0649:     lpD3DDev->SetTextureStageState(2, D3DTSS_COLORARG1, D3DTA_TEXTURE );
0650:     lpD3DDev->SetTextureStageState(2, D3DTSS_COLOROP,   D3DTOP_SELECTARG1);
0651:     lpD3DDev->SetTextureStageState(3, D3DTSS_COLOROP,   D3DTOP_DISABLE);
0652:     lpD3DDev->SetVertexShader( hVertexShader );
0653:     lpD3DDev->SetPixelShader (  hPixelShader );
0654:     lpD3DDev->SetTexture( 0, pSpecularMap );
0655:     lpD3DDev->SetTexture( 1, pNormalCubeMap );
0656:     lpD3DDev->SetTexture( 2, pNormalCubeMap );
0657: 
0658:     DrawModel(lpD3DDev );
0659:     
0660:     // 他でレンダリングしても問題が出ない設定にする
0661:     lpD3DDev->SetTexture( 0, NULL );
0662:     lpD3DDev->SetTexture( 1, NULL );
0663:     lpD3DDev->SetTexture( 2, NULL );
0664:     lpD3DDev->SetPixelShader(0);
0665: #if 1
0666:     //-----------------------------------------------------------------------------
0667:     // デバッグ用、適当にテクスチャーを表示する
0668:     //-----------------------------------------------------------------------------
0669:     struct TLVERTEX {
0670:         float x,y,z,rhw;
0671:         float tu,tv,tr;
0672:     };
0673:     #define FVF_TLVERTEX (D3DFVF_XYZRHW | D3DFVF_TEX1)
0674: 
0675:     float scale = 64.0f;
0676:     TLVERTEX Vertex[6][4] = {
0677:         {
0678:             //   x     y     z rhw tu tv tr
0679:             {0*scale,1*scale,0, 1, -1, 1,-1,},
0680:             {1*scale,1*scale,0, 1, -1, 1, 1,},
0681:             {1*scale,2*scale,0, 1, -1,-1, 1,},
0682:             {0*scale,2*scale,0, 1, -1,-1,-1,},
0683:         },{
0684:             //   x     y     z rhw tu tv tr
0685:             {1*scale,1*scale,0, 1, -1, 1, 1,},
0686:             {2*scale,1*scale,0, 1,  1, 1, 1,},
0687:             {2*scale,2*scale,0, 1,  1,-1, 1,},
0688:             {1*scale,2*scale,0, 1, -1,-1, 1,},
0689:         },{
0690:             //   x     y     z rhw tu tv tr
0691:             {2*scale,1*scale,0, 1,  1, 1, 1,},
0692:             {3*scale,1*scale,0, 1,  1, 1,-1,},
0693:             {3*scale,2*scale,0, 1,  1,-1,-1,},
0694:             {2*scale,2*scale,0, 1,  1,-1, 1,},
0695:         },{
0696:             //   x     y     z rhw tu tv tr
0697:             {3*scale,1*scale,0, 1,  1, 1,-1,},
0698:             {4*scale,1*scale,0, 1, -1, 1,-1,},
0699:             {4*scale,2*scale,0, 1, -1,-1,-1,},
0700:             {3*scale,2*scale,0, 1,  1,-1,-1,},
0701:         },{
0702:             //   x     y     z rhw tu tv tr
0703:             {1*scale,0*scale,0, 1, -1, 1,-1,},
0704:             {2*scale,0*scale,0, 1,  1, 1,-1,},
0705:             {2*scale,1*scale,0, 1,  1, 1, 1,},
0706:             {1*scale,1*scale,0, 1, -1, 1, 1,},
0707:         },{
0708:             //   x     y     z rhw tu tv tr
0709:             {1*scale,2*scale,0, 1, -1,-1, 1,},
0710:             {2*scale,2*scale,0, 1,  1,-1, 1,},
0711:             {2*scale,3*scale,0, 1,  1,-1,-1,},
0712:             {1*scale,3*scale,0, 1, -1,-1,-1,},
0713:         },
0714:     };
0715: 
0716:     lpD3DDev->SetRenderState( D3DRS_ZENABLE,  D3DZB_FALSE );
0717:     lpD3DDev->SetTextureStageState(0,D3DTSS_COLOROP,    D3DTOP_SELECTARG1);
0718:     lpD3DDev->SetTextureStageState(0,D3DTSS_COLORARG1,  D3DTA_TEXTURE);
0719:     lpD3DDev->SetTextureStageState(1,D3DTSS_COLOROP,    D3DTOP_DISABLE);
0720:     lpD3DDev->SetVertexShader( FVF_TLVERTEX | D3DFVF_TEXCOORDSIZE3(0) );
0721:     lpD3DDev->SetPixelShader(0);
0722: 
0723:     for( int n=0 ; n<2 ; n++ ){
0724:         if(0==n){
0725:             lpD3DDev->SetTexture( 0, pCubeMap );
0726:         }else{
0727:             lpD3DDev->SetTexture( 0, pSpecularMap );
0728:         }
0729:         for(int i=0;i<6;i++){
0730:             lpD3DDev->SetTextureStageState(0,D3DTSS_COLORARG1,  D3DTA_DIFFUSE);
0731:             lpD3DDev->DrawPrimitiveUP( D3DPT_LINELIST, 2, Vertex[i], sizeof( TLVERTEX ) );
0732:             lpD3DDev->SetTextureStageState(0,D3DTSS_COLORARG1,  D3DTA_TEXTURE);
0733:             lpD3DDev->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, Vertex[i], sizeof( TLVERTEX ) );
0734:             
0735:             Vertex[i][0].x += 4*scale;
0736:             Vertex[i][1].x += 4*scale;
0737:             Vertex[i][2].x += 4*scale;
0738:             Vertex[i][3].x += 4*scale;
0739:         }
0740:     }
0741:     lpD3DDev->SetRenderState( D3DRS_ZENABLE,  D3DZB_TRUE );
0742: #endif
0743:     // シーン終了
0744:     lpD3DDev->EndScene();
0745: }
0746: //-----------------------------------------------------------------------------
0747: // メッシュオブジェクト削除
0748: //-----------------------------------------------------------------------------
0749: void DeleteMeshObject(void)
0750: {
0751:     DWORD i;
0752: 
0753:     if(pMeshVB == NULL) return;
0754: 
0755:     for(i=0; i<dwNumMaterials; i++){
0756:         RELEASE(pMeshTextures[i]);
0757:     }
0758:     delete[] pMeshTextures;
0759:     delete[] pMeshMaterials;
0760:     delete[] pSubsetTable;
0761: 
0762:     RELEASE(pMeshVB);
0763:     RELEASE(pMeshIndex);
0764: }
0765: //-----------------------------------------------------------------------------
0766: // Name: CleanRender()
0767: // Desc: 後始末
0768: //-----------------------------------------------------------------------------
0769: void CleanRender(LPDIRECT3DDEVICE8 lpD3DDev)
0770: {
0771:     CleanBg(lpD3DDev);
0772:     
0773:     CPixelShaderMgr::Release(lpD3DDev, &hSpecularPixelShader);
0774:     CVertexShaderMgr::Release(lpD3DDev, &hSpecularVertexShader);
0775:     CPixelShaderMgr::Release(lpD3DDev, &hPixelShader);
0776:     CVertexShaderMgr::Release(lpD3DDev, &hVertexShader);
0777: 
0778:     RELEASE(pSpecularMap);
0779:     RELEASE(pCubeMap);
0780:     RELEASE(pNormalCubeMap);
0781: 
0782:     
0783:     RELEASE(pBlurIB);
0784:     RELEASE(pBlurVB);
0785: 
0786:     DeleteMeshObject();
0787: }
0788: