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: #include "rigidbody.h"
0016: 
0017: CMyMesh mesh;
0018: CMyView view;
0019: 
0020: #define NUM_VS  8       // 頂点シェーダーの種類
0021: DWORD                   gVs = 0;
0022: DWORD                   hVertexShader[NUM_VS]={
0023:                         ~0,~0,~0,~0,~0,~0,~0,~0
0024:                         };
0025: DWORD                   hVsEdge=~0;
0026: DWORD                   gEdge = 0;
0027: LPDIRECT3DTEXTURE8      pSpecTexture  = NULL;           // すぺきゅらのテクスチャー
0028: LPDIRECT3DTEXTURE8      pMetalTexture  = NULL;          // メタルのテクスチャー
0029: LPDIRECT3DTEXTURE8      pSoftTexture  = NULL;           // ソフトライティングのテクスチャー
0030: 
0031: D3DXVECTOR4 rot = D3DXVECTOR4(PI/12.0f, -PI, 0.0f, 0.0f);
0032: 
0033: // ライトの方向
0034: static D3DXVECTOR4 lpos;
0035: D3DXVECTOR4 lrot = D3DXVECTOR4(PI/6.0f, PI/4.0f, 0.0f, 0.0f);
0036: 
0037: // ----------------------------------------------------------------------------
0038: // 外部変数
0039: void SetLight(LPDIRECT3DDEVICE8 lpD3DDEV, D3DXVECTOR4 *pRot);
0040: void InitLightEff(LPDIRECT3DDEVICE8 lpD3DDEV, D3DXVECTOR4 pos);
0041: void DrawLightEff(LPDIRECT3DDEVICE8 lpD3DDEV, D3DXMATRIX mView, D3DXMATRIX mProj);
0042: void CleanLightEff();
0043: 
0044: void InitBg(LPDIRECT3DDEVICE8 lpD3DDev);
0045: void DrawBg(LPDIRECT3DDEVICE8 lpD3DDev, D3DXMATRIX *pWorld);
0046: void CleanBg(LPDIRECT3DDEVICE8 lpD3DDev);
0047: 
0048: // ----------------------------------------------------------------------------
0049: // Name: Render()
0050: // Desc: ポリゴンの初期化
0051: //-----------------------------------------------------------------------------
0052: typedef struct{
0053:     char *name;
0054: }VS_INFO;
0055: HRESULT InitRender(LPDIRECT3DDEVICE8 lpD3DDEV)
0056: {
0057:     HRESULT hr;
0058: 
0059:     hr = mesh.Load(lpD3DDEV, "nsx.x");
0060:  
0061:     // バーテックスシェーダーを作成する
0062:     if ( FAILED(CVertexShaderMgr::Load(lpD3DDEV, "edge.vsh", &hVsEdge, dwDecl)) ) return hr;
0063:     
0064:     VS_INFO vs_info[] = {
0065:         "diffuse.vsh",
0066:         "specular.vsh",
0067:         "texspec.vsh",
0068:         "texspec.vsh",
0069:         "hemisphere.vsh",
0070:         "hemi_amb.vsh",
0071:         "hemi_spec.vsh",
0072:         "soft.vsh",
0073:     };
0074:     for(int i = 0; i < NUM_VS; i++){
0075:         if ( FAILED(CVertexShaderMgr::Load(lpD3DDEV, vs_info[i].name, &hVertexShader[i], dwDecl)) ) return hr;
0076:     }
0077:     
0078:     // 演出用テクスチャーの読み込み
0079:     D3DXCreateTextureFromFileEx(lpD3DDEV, "spec.bmp",0,0,0,0,D3DFMT_A8R8G8B8,
0080:                                 D3DPOOL_MANAGED, D3DX_FILTER_LINEAR, D3DX_FILTER_LINEAR,
0081:                                 0, NULL, NULL, &pSpecTexture);
0082:     
0083:     D3DXCreateTextureFromFileEx(lpD3DDEV, "metal.bmp",0,0,0,0,D3DFMT_A8R8G8B8,
0084:                                 D3DPOOL_MANAGED, D3DX_FILTER_LINEAR, D3DX_FILTER_LINEAR,
0085:                                 0, NULL, NULL, &pMetalTexture);
0086:     
0087:     D3DXCreateTextureFromFileEx(lpD3DDEV, "soft.bmp",0,0,0,0,D3DFMT_A8R8G8B8,
0088:                                 D3DPOOL_MANAGED, D3DX_FILTER_LINEAR, D3DX_FILTER_LINEAR,
0089:                                 0, NULL, NULL, &pSoftTexture);
0090:     
0091:     // レンダリングの状態の設定
0092:     lpD3DDEV->SetRenderState( D3DRS_ZENABLE, TRUE);
0093:     lpD3DDEV->SetRenderState( D3DRS_LIGHTING,  FALSE );
0094:     SetLight(lpD3DDEV, &lrot);  // 光源の初期化
0095: 
0096:     // 値の変わらない定数レジスタの設定
0097:     lpD3DDEV->SetVertexShaderConstant(12, D3DXVECTOR4(0.0f, 0.5f, 1.0f, 2.0f), 1);
0098:     lpD3DDEV->SetVertexShaderConstant(16, D3DXVECTOR4(0.7f, 0.6f, 0.4f, 0.0f), 1);// ライトの色
0099:     lpD3DDEV->SetVertexShaderConstant(17, D3DXVECTOR4(0.5f, 0.5f, 0.5f, 1.0f), 1);// すぺきゅらーライトの色
0100:     lpD3DDEV->SetVertexShaderConstant(18, D3DXVECTOR4(0.3f, 0.3f, 0.3f, 0.0f), 1);// 上半球の色
0101:     lpD3DDEV->SetVertexShaderConstant(19, D3DXVECTOR4(0.7f, 0.3f, 0.1f, 0.0f), 1);// 下半球の色
0102:     
0103:     InitBg(lpD3DDEV);
0104: 
0105:     car.Init();
0106: 
0107:     return S_OK;
0108: }
0109: // ----------------------------------------------------------------------------
0110: // Name: Render()
0111: // Desc: ポリゴンの描画
0112: //-----------------------------------------------------------------------------
0113: void Render(LPDIRECT3DDEVICE8 lpD3DDEV)
0114: {
0115:     if(!mesh.bActive) return;
0116:     
0117:     car.Control();
0118: 
0119:     D3DXMATRIX m, m2, mLocal, mWorld, mLW, mProj;
0120:     D3DXVECTOR4 tr;
0121: 
0122:     D3DXMatrixPerspectiveFovLH(&mProj
0123:         ,60.0f*PI/180.0f                        // 視野角
0124:         ,(float)WIDTH/(float)HEIGHT             // アスペクト比
0125:         ,0.1f                                   // 最近接距離
0126:         ,500.0f                                 // 最遠方距離
0127:         );
0128:     D3DXMatrixRotationYawPitchRoll(&mWorld, rot.y, rot.x, rot.z);
0129:     tr = car.GetTranslate();
0130:     D3DXMatrixTranslation(&m, -tr.x, -tr.y, -tr.z);
0131:     mWorld = m * mWorld;
0132: 
0133:     D3DXMatrixTranslation(&m,  0.0f, 2.2f, 0.0f);
0134:     D3DXMatrixTranslation(&m2, 0.0f,-2.2f, 0.0f);
0135:     mLocal = m2 * car.GetRotation() * m;// 重心は少し上にあるので、その効果
0136:     D3DXMatrixTranslation(&m, tr.x, tr.y, tr.z);
0137:     mLocal = mLocal * m;
0138:     mLW = mLocal*mWorld;
0139:     
0140:     // 背景描画
0141:     lpD3DDEV->SetTransform( D3DTS_WORLD, &mWorld );
0142:     lpD3DDEV->SetTransform( D3DTS_VIEW, &view.Get() );
0143:     lpD3DDEV->SetTransform( D3DTS_PROJECTION, &mProj );
0144:     DrawBg(lpD3DDEV, &mWorld);
0145: 
0146:     // モデル描画
0147:     m = mLW * view.Get() * mProj;
0148:     D3DXMatrixTranspose( &m ,  &m);
0149:     lpD3DDEV->SetVertexShaderConstant(0,&m, 4);
0150:     D3DXMatrixTranspose( &m ,  &mLW);
0151:     lpD3DDEV->SetVertexShaderConstant(4, &m, 4);
0152:     D3DXMatrixInverse( &m,  NULL, &mLW);
0153:     lpD3DDEV->SetVertexShaderConstant(8, &m, 4);
0154:     
0155:     // ローカル座標変換行列
0156:     D3DXVECTOR4 lightDir;
0157:     D3DXMatrixInverse( &m,  NULL, &mLW);
0158:     
0159:     // ローカル座標でのライトの方向
0160:     D3DXVec4Transform(&lightDir, &lpos, &m);
0161:     D3DXVec4Normalize(&lightDir, &lightDir);
0162:     lightDir[3] =0.3f;
0163:     lpD3DDEV->SetVertexShaderConstant(13, &lightDir, 1);
0164:     
0165:     // ローカル座標での視点
0166:     D3DXVECTOR4 eye_pos;
0167:     D3DXVec4Transform(&eye_pos, &view.GetEye(), &m);
0168:     lpD3DDEV->SetVertexShaderConstant(14, &eye_pos, 1);
0169: 
0170:     // 半球ライティング用のローカル座標での垂直軸
0171:     D3DXVECTOR4 axis(0.0f, 1.0f, 0.0f, 0.1f);
0172:     D3DXVec4Transform(&axis, &axis, &m);
0173:     D3DXVec4Normalize(&axis, &axis);
0174:     lpD3DDEV->SetVertexShaderConstant(20, &axis, 1);
0175:     
0176:     // 輪郭の厚さ
0177:     lpD3DDEV->SetVertexShaderConstant(40
0178:         , D3DXVECTOR4(0.015f*mesh.radius, 
0179:                       0.015f*mesh.radius,
0180:                       -0.0002f*mesh.radius, 0.0f), 1);
0181:     
0182:     lpD3DDEV->SetStreamSource(0, mesh.pVB, sizeof(D3D_CUSTOMVERTEX));
0183:     lpD3DDEV->SetIndices(mesh.pIndex,0);
0184:     
0185:     // 輪郭抽出
0186:     if(gEdge){
0187:         lpD3DDEV->SetVertexShader(hVsEdge);
0188:         lpD3DDEV->SetTexture(0,NULL);
0189:         lpD3DDEV->SetRenderState( D3DRS_ZWRITEENABLE, FALSE );    // 深度バッファの書き込みを止める
0190:         lpD3DDEV->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE);
0191:         for(DWORD i=0;i<mesh.dwNumMaterials;i++){
0192:             //色をセット
0193:             lpD3DDEV->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 
0194:                                             mesh.pSubsetTable[i].VertexStart,
0195:                                             mesh.pSubsetTable[i].VertexCount,
0196:                                             mesh.pSubsetTable[i].FaceStart * 3,
0197:                                             mesh.pSubsetTable[i].FaceCount);
0198:         }
0199:         lpD3DDEV->SetRenderState( D3DRS_ZWRITEENABLE, TRUE );    // 深度バッファの書き込みを戻す
0200:         lpD3DDEV->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW);
0201:     }
0202:     
0203:     lpD3DDEV->SetVertexShader(hVertexShader[gVs]);
0204:     
0205:     switch(gVs){
0206:     case 0:// diffuse
0207:     case 1:// 頂点ライトスペキュラー
0208:         lpD3DDEV->SetTextureStageState(0,D3DTSS_COLOROP,    D3DTOP_MODULATE);
0209:         lpD3DDEV->SetTextureStageState(0,D3DTSS_COLORARG1,  D3DTA_TEXTURE);
0210:         lpD3DDEV->SetTextureStageState(0,D3DTSS_COLORARG2,  D3DTA_DIFFUSE);
0211:         lpD3DDEV->SetTextureStageState(1,D3DTSS_COLOROP,    D3DTOP_DISABLE);
0212:         break;
0213:     case 2:// テクスチャースペキュラー
0214:         lpD3DDEV->SetTexture(1, pSpecTexture);
0215:     case 3:// メタルテクスチャー
0216:         if(3==gVs)lpD3DDEV->SetTexture(1, pMetalTexture);
0217:         lpD3DDEV->SetTextureStageState(0,D3DTSS_MAGFILTER , D3DTEXF_LINEAR);
0218:         lpD3DDEV->SetTextureStageState(0,D3DTSS_MINFILTER,  D3DTEXF_LINEAR);
0219:         lpD3DDEV->SetTextureStageState(1,D3DTSS_MAGFILTER , D3DTEXF_LINEAR);
0220:         lpD3DDEV->SetTextureStageState(1,D3DTSS_MINFILTER,  D3DTEXF_LINEAR);
0221:         lpD3DDEV->SetTextureStageState(0,D3DTSS_COLOROP,    D3DTOP_MODULATE);
0222:         lpD3DDEV->SetTextureStageState(0,D3DTSS_COLORARG1,  D3DTA_TEXTURE);
0223:         lpD3DDEV->SetTextureStageState(0,D3DTSS_COLORARG2,  D3DTA_DIFFUSE);
0224:         lpD3DDEV->SetTextureStageState(1,D3DTSS_COLOROP,    D3DTOP_ADD);
0225:         lpD3DDEV->SetTextureStageState(1,D3DTSS_COLORARG1,  D3DTA_TEXTURE);
0226:         lpD3DDEV->SetTextureStageState(1,D3DTSS_COLORARG2,  D3DTA_CURRENT);
0227:         lpD3DDEV->SetTextureStageState(1,D3DTSS_ADDRESSU,   D3DTADDRESS_CLAMP);
0228:         break;
0229:     case 4:// 半球ライティング
0230:     case 5:// 半球ライティング
0231:     case 6:// 半球ライティング
0232:         lpD3DDEV->SetTextureStageState(0,D3DTSS_COLOROP,    D3DTOP_MODULATE);
0233:         lpD3DDEV->SetTextureStageState(0,D3DTSS_COLORARG1,  D3DTA_TEXTURE);
0234:         lpD3DDEV->SetTextureStageState(0,D3DTSS_COLORARG2,  D3DTA_DIFFUSE);
0235:         lpD3DDEV->SetTextureStageState(1,D3DTSS_COLOROP,    D3DTOP_DISABLE);
0236:         break;
0237:     case 7:// ソフトトゥーン
0238:         lpD3DDEV->SetTexture(1, pSoftTexture);
0239:         lpD3DDEV->SetTextureStageState(0,D3DTSS_MAGFILTER , D3DTEXF_LINEAR);
0240:         lpD3DDEV->SetTextureStageState(0,D3DTSS_MINFILTER,  D3DTEXF_LINEAR);
0241:         lpD3DDEV->SetTextureStageState(1,D3DTSS_MAGFILTER , D3DTEXF_LINEAR);
0242:         lpD3DDEV->SetTextureStageState(1,D3DTSS_MINFILTER,  D3DTEXF_LINEAR);
0243:         lpD3DDEV->SetTextureStageState(0,D3DTSS_COLOROP,    D3DTOP_MODULATE);
0244:         lpD3DDEV->SetTextureStageState(0,D3DTSS_COLORARG1,  D3DTA_TEXTURE);
0245:         lpD3DDEV->SetTextureStageState(0,D3DTSS_COLORARG2,  D3DTA_DIFFUSE);
0246:         lpD3DDEV->SetTextureStageState(1,D3DTSS_COLOROP,    D3DTOP_MODULATE);
0247:         lpD3DDEV->SetTextureStageState(1,D3DTSS_COLORARG1,  D3DTA_TEXTURE);
0248:         lpD3DDEV->SetTextureStageState(1,D3DTSS_COLORARG2,  D3DTA_CURRENT);
0249:         lpD3DDEV->SetTextureStageState(1,D3DTSS_ADDRESSU,   D3DTADDRESS_CLAMP);
0250:         break;
0251:     }
0252:     
0253:     //メッシュの描画
0254:     for(DWORD i=0;i<mesh.dwNumMaterials;i++){
0255:         //色をセット
0256:         D3DXVECTOR4 vl(
0257: //          0,0,0,
0258:             mesh.pMaterials[i].Diffuse.r*0.7f,
0259:             mesh.pMaterials[i].Diffuse.g*0.7f,
0260:             mesh.pMaterials[i].Diffuse.b*0.7f,
0261:             1.0f);
0262:         lpD3DDEV->SetVertexShaderConstant(15,&vl,1);
0263:         if(mesh.pTextures[i]){
0264:             lpD3DDEV->SetTextureStageState(0,D3DTSS_COLOROP, D3DTOP_MODULATE);
0265:             lpD3DDEV->SetTexture(0, mesh.pTextures[i]);
0266:         }else{
0267:             lpD3DDEV->SetTextureStageState(0,D3DTSS_COLOROP, D3DTOP_SELECTARG2);
0268:         }
0269:         lpD3DDEV->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 
0270:                                         mesh.pSubsetTable[i].VertexStart,
0271:                                         mesh.pSubsetTable[i].VertexCount,
0272:                                         mesh.pSubsetTable[i].FaceStart * 3,
0273:                                         mesh.pSubsetTable[i].FaceCount);
0274:     }
0275:     lpD3DDEV->SetTexture(0,NULL);
0276:     lpD3DDEV->SetTexture(1,NULL);
0277:     
0278:     // 光源の位置を描く
0279:     DrawLightEff(lpD3DDEV, view.Get(), mProj);
0280: }
0281: 
0282: //-----------------------------------------------------------------------------
0283: // 光源の設定
0284: //-----------------------------------------------------------------------------
0285: void SetLight(LPDIRECT3DDEVICE8 lpD3DDEV, D3DXVECTOR4 *pRot)
0286: {
0287:     D3DXMATRIX m;
0288:     D3DXMatrixRotationYawPitchRoll(&m, pRot->y, pRot->x, pRot->z);
0289:     D3DXVec4Transform(&lpos, &D3DXVECTOR4(0.0f, 0.0f,-1.0f, 0.0f), &m);
0290:     D3DXVec4Normalize(&lpos, &lpos);
0291:     InitLightEff(lpD3DDEV, lpos);
0292: }
0293: //-----------------------------------------------------------------------------
0294: // Name: CleanRender()
0295: // Desc: 後始末
0296: //-----------------------------------------------------------------------------
0297: void CleanRender(LPDIRECT3DDEVICE8 lpD3DDEV)
0298: {
0299:     CleanBg(lpD3DDEV);
0300:     CleanLightEff();
0301:     
0302:     RELEASE(pSoftTexture);
0303:     RELEASE(pMetalTexture);
0304:     RELEASE(pSpecTexture);
0305:     
0306:     // 頂点シェーダーの開放
0307:     for(int i = 0; i < NUM_VS; i++){
0308:         CVertexShaderMgr::Release(lpD3DDEV, &hVertexShader[i]);
0309:     }
0310:     CVertexShaderMgr::Release(lpD3DDEV, &hVsEdge);
0311:     
0312:     mesh.Release();
0313: }
0314: