0001: // ---------------------------------------------------------------------------- 0002: // 0003: // draw.cpp - 描画部分 0004: // 0005: // Copyright (c) 2001 if (if@edokko.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: LPDIRECT3DVERTEXBUFFER8 pMeshVB = NULL; 0017: LPDIRECT3DINDEXBUFFER8 pMeshIndex = NULL; 0018: D3DXATTRIBUTERANGE *pSubsetTable = NULL; 0019: DWORD nMeshFaces = 0; 0020: DWORD nMeshVertices = 0; 0021: D3DMATERIAL8 *pMeshMaterials = NULL; // メッシュの質感 0022: LPDIRECT3DTEXTURE8 *pMeshTextures = NULL; // メッシュのテクスチャー 0023: DWORD dwNumMaterials = 0L; // マテリアルの数 0024: FLOAT MeshRadius; // メッシュの大きさ 0025: 0026: DWORD hVertexShader=~0; // モデルの描画 0027: DWORD hShadowVertexShader=~0; 0028: 0029: 0030: 0031: // ---------------------------------------------------------------------------- 0032: // 外部関数 0033: void InitBg(LPDIRECT3DDEVICE8 lpD3DDev); 0034: void DrawBg(LPDIRECT3DDEVICE8 lpD3DDev); 0035: void CleanBg(LPDIRECT3DDEVICE8 lpD3DDev); 0036: 0037: 0038: 0039: // ---------------------------------------------------------------------------- 0040: // Name: LoadXFile(char* filename, LPDIRECT3DDEVICE8 lpD3DDev) 0041: // Desc: X-Fileの読み込み 0042: //----------------------------------------------------------------------------- 0043: HRESULT LoadXFile(char* filename, LPDIRECT3DDEVICE8 lpD3DDev) 0044: { 0045: LPD3DXMESH pMesh, pMeshOpt; 0046: LPD3DXBUFFER pD3DXMtrlBuffer = NULL; 0047: DWORD i; 0048: HRESULT hr; 0049: 0050: hr = D3DXLoadMeshFromX(filename, D3DXMESH_MANAGED, 0051: lpD3DDev, NULL, 0052: &pD3DXMtrlBuffer, &dwNumMaterials, 0053: &pMesh); 0054: if(FAILED(hr)) return E_FAIL; 0055: 0056: //並び替えておく 0057: pMesh->Optimize(D3DXMESHOPT_ATTRSORT, NULL, NULL, NULL, NULL, &pMeshOpt); 0058: RELEASE(pMesh); 0059: 0060: //アトリビュートテーブル 0061: pMeshOpt->GetAttributeTable(NULL,&dwNumMaterials); 0062: pSubsetTable = new D3DXATTRIBUTERANGE[dwNumMaterials]; 0063: pMeshOpt->GetAttributeTable(pSubsetTable, &dwNumMaterials); 0064: 0065: // FVF変換 0066: hr = pMeshOpt->CloneMeshFVF(pMeshOpt->GetOptions(), D3DFVF_VERTEX, lpD3DDev, &pMesh); 0067: if(FAILED(hr)) return E_FAIL; 0068: RELEASE(pMeshOpt); 0069: D3DXComputeNormals(pMesh, NULL); 0070: 0071: //Vertex Bufferにコピーする 0072: D3DVERTEX* pSrc; 0073: D3D_CUSTOMVERTEX* pDest; 0074: LPDIRECT3DINDEXBUFFER8 pSrcIndex; 0075: WORD* pISrc; 0076: WORD* pIDest; 0077: 0078: DWORD nMeshVertices = pMesh->GetNumVertices(); 0079: DWORD nMeshFaces = pMesh->GetNumFaces(); 0080: lpD3DDev->CreateVertexBuffer(nMeshVertices * sizeof(D3D_CUSTOMVERTEX),0,D3DFVF_CUSTOMVERTEX,D3DPOOL_MANAGED,&pMeshVB); 0081: lpD3DDev->CreateIndexBuffer(nMeshFaces * 3 * sizeof(WORD),0,D3DFMT_INDEX16,D3DPOOL_MANAGED,&pMeshIndex); 0082: 0083: LPDIRECT3DVERTEXBUFFER8 pVB; 0084: pMesh->GetVertexBuffer(&pVB); 0085: pVB->Lock(0,0,(BYTE**)&pSrc,0); 0086: pMeshVB->Lock(0,0,(BYTE**)&pDest,0); 0087: MeshRadius = 0.0f; 0088: for(i=0;i<nMeshVertices;i++){ 0089: pDest->x = pSrc->x; 0090: pDest->y = pSrc->y; 0091: pDest->z = pSrc->z; 0092: pDest->nx = pSrc->nx; 0093: pDest->ny = pSrc->ny; 0094: pDest->nz = pSrc->nz; 0095: pDest->tu0 = pSrc->tu0; 0096: pDest->tu0 = pSrc->tu0; 0097: // サイズの計算 0098: FLOAT radius = sqrtf( pSrc->x*pSrc->x + pSrc->y*pSrc->y + pSrc->z*pSrc->z ); 0099: if (MeshRadius < radius) MeshRadius = radius; 0100: 0101: pSrc += 1; 0102: pDest += 1; 0103: } 0104: pVB->Unlock(); 0105: pVB->Release(); 0106: pMeshVB->Unlock(); 0107: 0108: //インデックスのコピー 0109: pMesh->GetIndexBuffer(&pSrcIndex); 0110: pSrcIndex->Lock(0,0,(BYTE**)&pISrc,0); 0111: pMeshIndex->Lock(0,0,(BYTE**)&pIDest,0); 0112: CopyMemory(pIDest,pISrc,nMeshFaces * 3 * sizeof(WORD)); 0113: pSrcIndex->Unlock(); 0114: pMeshIndex->Unlock(); 0115: pSrcIndex->Release(); 0116: 0117: // pD3DXMtrlBuffer から、質感やテクスチャーの情報を読み取る 0118: D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer(); 0119: pMeshTextures = new LPDIRECT3DTEXTURE8[dwNumMaterials]; 0120: pMeshMaterials = new D3DMATERIAL8[dwNumMaterials]; 0121: 0122: for(i = 0; i < dwNumMaterials; i++){ 0123: pMeshMaterials[i] = d3dxMaterials[i].MatD3D; 0124: pMeshMaterials[i].Ambient = pMeshMaterials[i].Diffuse; 0125: hr = D3DXCreateTextureFromFile( lpD3DDev, 0126: d3dxMaterials[i].pTextureFilename, 0127: &pMeshTextures[i] ); 0128: if(FAILED(hr)) pMeshTextures[i] = NULL; 0129: } 0130: RELEASE(pD3DXMtrlBuffer); 0131: 0132: RELEASE(pMesh); 0133: 0134: return S_OK; 0135: } 0136: //----------------------------------------------------------------------------- 0137: // Name: InitRender() 0138: // Desc: Load the mesh and build the material and texture arrays 0139: //----------------------------------------------------------------------------- 0140: HRESULT InitRender(LPDIRECT3DDEVICE8 lpD3DDev) 0141: { 0142: HRESULT hr; 0143: 0144: // モデルの読み込み 0145: if ( FAILED(hr = LoadXFile("knot.x", lpD3DDev)) ) return hr; 0146: 0147: // バーテックスシェーダーを作成する 0148: if ( FAILED(CVertexShaderMgr::Load(lpD3DDev, "vs.vsh", &hVertexShader, dwDecl)) ) return hr; 0149: if ( FAILED(CVertexShaderMgr::Load(lpD3DDev, "shadow.vsh", &hShadowVertexShader, dwDecl)) ) return hr; 0150: 0151: // 背景部分の初期化 0152: InitBg(lpD3DDev); 0153: 0154: // 不変なレジスタの設定 0155: lpD3DDev->SetRenderState( D3DRS_ZENABLE, TRUE ); 0156: lpD3DDev->SetRenderState( D3DRS_LIGHTING, FALSE ); 0157: lpD3DDev->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE); 0158: lpD3DDev->SetVertexShaderConstant(12, &D3DXVECTOR4(0.0f, 0.5f, 1.0f, 2.0f), 1); 0159: 0160: // デカール 0161: lpD3DDev->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR); 0162: lpD3DDev->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR); 0163: lpD3DDev->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_NONE); 0164: 0165: return S_OK; 0166: } 0167: //----------------------------------------------------------------------------- 0168: // Name: Render() 0169: // Desc: Draws the scene 0170: //----------------------------------------------------------------------------- 0171: VOID DrawModel(LPDIRECT3DDEVICE8 lpD3DDev, BOOL bBg) 0172: { 0173: D3DXMATRIX mVP, mWorld, mView, mProj; 0174: D3DXMATRIX mVPL, mViewL, mProjL; 0175: D3DXMATRIX m; 0176: D3DXVECTOR4 vl; 0177: DWORD i; 0178: 0179: const D3DXVECTOR4 lightDir(1.0f, 1.0f, 0.5f, 0.0f); 0180: const float shadow_scale = 10.0f; 0181: 0182: // 0183: // 通常レンダリング用の行列を作成 0184: // 0185: // ビュー行列 0186: D3DXVECTOR3 eye = D3DXVECTOR3(0.0f,1.4f*MeshRadius,2.5f*MeshRadius); 0187: D3DXVECTOR3 lookAt = D3DXVECTOR3(0.0f, 0.0f, 0.0f); 0188: D3DXVECTOR3 up = D3DXVECTOR3(0.0f, 1.0f, 0.0f); 0189: D3DXMatrixLookAtLH(&mView, &eye, &lookAt, &up); 0190: // 射影行列 0191: D3DXMatrixPerspectiveFovLH(&mProj 0192: , D3DXToRadian(60.0f) // 視野角 0193: , (float)WIDTH/(float)HEIGHT // アスペクト比 0194: , 1.0f, 70.0f // 最近接距離,最遠方距離 0195: ); 0196: 0197: mVP = mView * mProj; 0198: 0199: 0200: // 0201: // ライト方向からのレンダリング用の定数を作成 0202: // 0203: D3DXVECTOR4 l_eye = 30.0f*lightDir; 0204: l_eye.w = 40.0f; 0205: lpD3DDev->SetVertexShaderConstant(15,&l_eye, 1); 0206: lpD3DDev->SetVertexShaderConstant(16,&D3DXVECTOR4(0,0,0,0.0001f), 1); 0207: 0208: // 0209: // 外側もでる描画 0210: // 0211: lpD3DDev->SetTextureStageState(0,D3DTSS_COLORARG1, D3DTA_DIFFUSE); 0212: 0213: int t = timeGetTime()%(314159*3); 0214: D3DXMatrixTranslation(&m, MeshRadius, 0.05f*MeshRadius,0); 0215: D3DXMatrixRotationY( &mWorld, t/1000.0f ); 0216: mWorld = m * mWorld; 0217: 0218: m = mWorld * mVP; 0219: D3DXMatrixTranspose( &m , &m); 0220: lpD3DDev->SetVertexShaderConstant(0,&m, 4); 0221: 0222: D3DXMatrixInverse( &m, NULL, &mWorld); 0223: D3DXVec4Transform(&vl, &lightDir, &m); 0224: D3DXVec4Normalize(&vl, &vl); 0225: vl[3] = 0.1f;// w成分は環境色の強さ 0226: lpD3DDev->SetVertexShaderConstant(13, &vl, 1); 0227: D3DXVec4Scale(&vl, &vl, shadow_scale);vl.w=0; 0228: lpD3DDev->SetVertexShaderConstant(15, &vl, 1); 0229: 0230: lpD3DDev->SetStreamSource(0, pMeshVB, sizeof(D3D_CUSTOMVERTEX)); 0231: lpD3DDev->SetIndices(pMeshIndex,0); 0232: 0233: for(i=0;i<dwNumMaterials;i++){ 0234: //色をセット 0235: D3DXVECTOR4 vl; 0236: vl.x = pMeshMaterials[i].Diffuse.r; 0237: vl.y = pMeshMaterials[i].Diffuse.g; 0238: vl.z = pMeshMaterials[i].Diffuse.b; 0239: lpD3DDev->SetVertexShaderConstant(14, &vl, 1); 0240: 0241: lpD3DDev->SetTexture(0,pMeshTextures[i]); 0242: lpD3DDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0243: pSubsetTable[i].VertexStart, 0244: pSubsetTable[i].VertexCount, 0245: pSubsetTable[i].FaceStart * 3, 0246: pSubsetTable[i].FaceCount); 0247: } 0248: // 0249: // モデル2 0250: // 0251: D3DXMatrixTranslation(&m, 0, 0.1f*MeshRadius, 0); 0252: D3DXMatrixRotationY( &mWorld, -t/3000.0f ); 0253: mWorld=m*mWorld; 0254: 0255: m = mWorld * mVP; 0256: D3DXMatrixTranspose( &m , &m); 0257: lpD3DDev->SetVertexShaderConstant(0,&m, 4); 0258: 0259: D3DXMatrixInverse( &m, NULL, &mWorld); 0260: D3DXVec4Transform(&vl, &lightDir, &m); 0261: D3DXVec4Normalize(&vl, &vl); 0262: vl[3] = 0.1f;// w成分は環境色の強さ 0263: lpD3DDev->SetVertexShaderConstant(13, &vl, 1); 0264: D3DXVec4Scale(&vl, &vl, shadow_scale);vl.w=0; 0265: lpD3DDev->SetVertexShaderConstant(15, &vl, 1); 0266: 0267: for(i=0;i<dwNumMaterials;i++){ 0268: //色をセット 0269: D3DXVECTOR4 vl; 0270: vl.x = pMeshMaterials[i].Diffuse.r; 0271: vl.y = pMeshMaterials[i].Diffuse.g; 0272: vl.z = pMeshMaterials[i].Diffuse.b; 0273: lpD3DDev->SetVertexShaderConstant(14, &vl, 1); 0274: 0275: lpD3DDev->SetTexture(0,pMeshTextures[i]); 0276: lpD3DDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0277: pSubsetTable[i].VertexStart, 0278: pSubsetTable[i].VertexCount, 0279: pSubsetTable[i].FaceStart * 3, 0280: pSubsetTable[i].FaceCount); 0281: } 0282: // 0283: // 背景描画 0284: // 0285: if(bBg){ 0286: D3DXMatrixScaling(&mWorld, 3.0f, 3.0f, 3.0f); 0287: 0288: m = mWorld * mVP; 0289: D3DXMatrixTranspose( &m , &m); 0290: lpD3DDev->SetVertexShaderConstant(0,&m, 4); 0291: 0292: lpD3DDev->SetVertexShaderConstant(13, &D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f), 1); 0293: lpD3DDev->SetVertexShaderConstant(14, &D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f), 1); 0294: lpD3DDev->SetTextureStageState(0,D3DTSS_COLORARG1, D3DTA_TEXTURE); 0295: DrawBg(lpD3DDev); 0296: } 0297: } 0298: //----------------------------------------------------------------------------- 0299: // Name: Render() 0300: // Desc: Draws the scene 0301: //----------------------------------------------------------------------------- 0302: VOID Render(LPDIRECT3DDEVICE8 lpD3DDev) 0303: { 0304: // 深度を初期化する 0305: lpD3DDev->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL 0306: , D3DCOLOR_RGBA(0,0,0,0), 1.0f, 0L); 0307: 0308: // ------------------------------------------------------------------------ 0309: // 通常レンダリング 0310: // ------------------------------------------------------------------------ 0311: lpD3DDev->SetTextureStageState(0,D3DTSS_COLOROP, D3DTOP_SELECTARG1); 0312: lpD3DDev->SetVertexShader(hVertexShader); 0313: DrawModel(lpD3DDev, 1); 0314: 0315: // ------------------------------------------------------------------------ 0316: // 影の作成 0317: // ------------------------------------------------------------------------ 0318: lpD3DDev->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);// zバッファの更新無し 0319: lpD3DDev->SetRenderState(D3DRS_STENCILENABLE, TRUE);// ステンシルバッファ使用 0320: lpD3DDev->SetRenderState(D3DRS_COLORWRITEENABLE, 0);// 色は書かない 0321: 0322: lpD3DDev->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);// 常に合格 0323: lpD3DDev->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);// z落ちはそのまま 0324: lpD3DDev->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_INCR); 0325: lpD3DDev->SetRenderState(D3DRS_STENCILREF, 1);// ステンシル基準値は1 0326: lpD3DDev->SetRenderState(D3DRS_STENCILMASK, 0xffffffff); 0327: lpD3DDev->SetRenderState(D3DRS_STENCILWRITEMASK, 0xffffffff); 0328: lpD3DDev->SetVertexShader(hShadowVertexShader); 0329: lpD3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); 0330: DrawModel(lpD3DDev, 0); 0331: 0332: lpD3DDev->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_DECR); 0333: lpD3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW); 0334: DrawModel(lpD3DDev, 0); 0335: 0336: lpD3DDev->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); 0337: lpD3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); 0338: lpD3DDev->SetRenderState(D3DRS_COLORWRITEENABLE, 0xf); 0339: 0340: 0341: // ------------------------------------------------------------------------ 0342: // 影の描画 0343: // ------------------------------------------------------------------------ 0344: lpD3DDev->SetRenderState(D3DRS_ZENABLE, FALSE); 0345: lpD3DDev->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_LESSEQUAL);// ステンシルが0の時に描画 0346: lpD3DDev->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);// ステンシル落ちは描画しない 0347: lpD3DDev->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);// 描画時は何もしない 0348: lpD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); 0349: lpD3DDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); 0350: lpD3DDev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); 0351: lpD3DDev->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); 0352: 0353: { 0354: typedef struct{ 0355: float x, y, z, w; 0356: DWORD color; 0357: } LVERTEX; 0358: #define FVF_LVERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE) 0359: lpD3DDev->SetTextureStageState(0,D3DTSS_COLORARG1, D3DTA_DIFFUSE); 0360: float size = 512.0f; 0361: LVERTEX Vertex[4] = { 0362: // x y z rhw color 0363: { 0, 0, 0, 1, D3DCOLOR_RGBA(0x0,0x0,0x0,0x80),}, 0364: {size, 0, 0, 1, D3DCOLOR_RGBA(0x0,0x0,0x0,0x80),}, 0365: {size,size, 0, 1, D3DCOLOR_RGBA(0x0,0x0,0x0,0x80),}, 0366: { 0,size, 0, 1, D3DCOLOR_RGBA(0x0,0x0,0x0,0x80),}, 0367: }; 0368: lpD3DDev->SetVertexShader( FVF_LVERTEX ); 0369: lpD3DDev->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, Vertex, sizeof( LVERTEX ) ); 0370: } 0371: 0372: // ------------------------------------------------------------------------ 0373: // 元に戻す 0374: // ------------------------------------------------------------------------ 0375: lpD3DDev->SetRenderState(D3DRS_ZENABLE, TRUE); 0376: lpD3DDev->SetRenderState(D3DRS_STENCILENABLE, FALSE); 0377: lpD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); 0378: } 0379: //----------------------------------------------------------------------------- 0380: // メッシュオブジェクト削除 0381: //----------------------------------------------------------------------------- 0382: void DeleteMeshObject(void) 0383: { 0384: DWORD i; 0385: 0386: if(pMeshVB == NULL) return; 0387: 0388: for(i=0; i<dwNumMaterials; i++){ 0389: RELEASE(pMeshTextures[i]); 0390: } 0391: delete[] pMeshTextures; 0392: delete[] pMeshMaterials; 0393: delete[] pSubsetTable; 0394: 0395: RELEASE(pMeshVB); 0396: RELEASE(pMeshIndex); 0397: } 0398: //----------------------------------------------------------------------------- 0399: // Name: CleanRender() 0400: // Desc: 後始末 0401: //----------------------------------------------------------------------------- 0402: void CleanRender(LPDIRECT3DDEVICE8 lpD3DDev) 0403: { 0404: CleanBg(lpD3DDev); 0405: 0406: CVertexShaderMgr::Release(lpD3DDev, &hShadowVertexShader); 0407: CVertexShaderMgr::Release(lpD3DDev, &hVertexShader); 0408: 0409: DeleteMeshObject(); 0410: } 0411: