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 "Cg/cgD3D.h"
0012: #include "main.h"
0013: #include "d3dx8.h"
0014: 
0015: // 頂点シェーダー
0016: static cgProgramContainer *pVs = 0;         // 頂点シェーダーを扱うコンテナ
0017: static cgBindIter * vertex_mat_iter = 0;        // ローカル/射影変換を扱う反復子
0018: // ピクセルシェーダー
0019: static cgProgramContainer  *pPs = 0;            // ピクセルシェーダーを扱うコンテナ
0020: static cgBindIter * tex0_iter = 0;              // テクスチャーを扱う反復子
0021: 
0022: 
0023: // ----------------------------------------------------------------------------
0024: // 頂点情報
0025: typedef struct{
0026:     float x,y,z,w;
0027:     float tu,tv;
0028: } MyVertex;
0029: 
0030: // シェーダーに渡す
0031: static cgVertexDefinition vertex_attributes[] = {
0032:     {D3DVSDT_FLOAT4, "position", 0},
0033:     {D3DVSDT_FLOAT2, "texcoord0", 0},
0034:     CGVERTEXDEFINITIONEND
0035: };
0036: 
0037: // ----------------------------------------------------------------------------
0038: // 空
0039: #define NUM_Y       1   // 縦方向に何ポリゴン使うか
0040: #define NUM_CIRCLE  32  // 一回り何ポリゴンか
0041: #define NUM_VERTICES            ((NUM_Y+1)*(NUM_CIRCLE+1))
0042: #define NUM_INDICES_PERFACE     (3*2)
0043: #define NUM_FACES               (NUM_Y*NUM_CIRCLE)
0044: #define NUM_VERTICES_PERFACE    4
0045: 
0046: LPDIRECT3DVERTEXBUFFER8     pCylinderVB;
0047: LPDIRECT3DINDEXBUFFER8      pCylinderIB;
0048: LPDIRECT3DTEXTURE8          pCylinderTex;
0049: 
0050: // ----------------------------------------------------------------------------
0051: // 初期化
0052: static void InitSky(LPDIRECT3DDEVICE8 lpD3DDev)
0053: {
0054:     // 頂点バッファの作成 
0055:     MyVertex *pDest;
0056:     lpD3DDev->CreateVertexBuffer( NUM_VERTICES * sizeof(MyVertex),
0057:                                 0, 0, D3DPOOL_MANAGED, &pCylinderVB );
0058: 
0059:     // 頂点をセットアップ
0060:     WORD k=0;
0061:     pCylinderVB->Lock ( 0, 0, (BYTE**)&pDest, 0 );
0062:     float r = 10.0f;
0063:     float h = 10.0f;
0064:     for (DWORD i = 0; i <= NUM_CIRCLE; i++) {
0065:         float theta = (2*PI*(float)i)/(float)NUM_CIRCLE;
0066:         for (DWORD j = 0; j <= NUM_Y; j++) {
0067:             pDest->x = r * (float)cos(theta);
0068:             pDest->z = r * (float)sin(theta);
0069:             pDest->y = h*((float)j/(float)NUM_Y-0.0f);
0070:             pDest->w   = 1.0f;
0071:             pDest->tu = (float)i / (float)NUM_CIRCLE;
0072:             pDest->tv = 1.0f-(float)j / (float)NUM_Y;
0073:             pDest += 1;
0074:         }
0075:     }       
0076:     pCylinderVB->Unlock ();
0077: 
0078: 
0079:     // インデックスをセットアップ
0080:     WORD *pIndex;
0081:     lpD3DDev->CreateIndexBuffer( NUM_INDICES_PERFACE  * NUM_FACES * sizeof(WORD),
0082:                                      0 ,
0083:                                      D3DFMT_INDEX16, D3DPOOL_DEFAULT,
0084:                                      &pCylinderIB );
0085:     pCylinderIB->Lock ( 0, 0, (BYTE**)&pIndex, 0 );
0086:     {
0087:     for (WORD i = 0; i < NUM_CIRCLE; i++) {
0088:         for (WORD j = 0; j < NUM_Y; j++) {
0089:             *pIndex++ = j + 0 + (i+0) * (NUM_Y+1);
0090:             *pIndex++ = j + 0 + (i+1) * (NUM_Y+1);
0091:             *pIndex++ = j + 1 + (i+0) * (NUM_Y+1);
0092: 
0093:             *pIndex++ = j + 1 + (i+0) * (NUM_Y+1);
0094:             *pIndex++ = j + 0 + (i+1) * (NUM_Y+1);
0095:             *pIndex++ = j + 1 + (i+1) * (NUM_Y+1);
0096:         }
0097:     }
0098:     }
0099:     pCylinderIB->Unlock ();
0100: 
0101:     D3DXCreateTextureFromFileEx(lpD3DDev, "sky.bmp", 0,0,0,0,D3DFMT_A8R8G8B8,
0102:                                 D3DPOOL_MANAGED, D3DX_FILTER_LINEAR, D3DX_FILTER_LINEAR,
0103:                                 0, NULL, NULL, &pCylinderTex);
0104: }
0105: 
0106: 
0107: // ----------------------------------------------------------------------------
0108: // 初期化
0109: 
0110: // ----------------------------------------------------------------------------
0111: // 床
0112: #define FLOOR_SIZE  (10.0f)
0113: #define FLOOR_UV    (10.0f)     // テクスチャーの繰り返し回数
0114: LPDIRECT3DVERTEXBUFFER8     pFloorVB;
0115: LPDIRECT3DINDEXBUFFER8      pFloorIB;
0116: LPDIRECT3DTEXTURE8          pFloorTex;
0117: 
0118: // ----------------------------------------------------------------------------
0119: // 初期化
0120: static void InitFloor(LPDIRECT3DDEVICE8 lpD3DDev)
0121: {
0122:     WORD *pIndex;
0123: 
0124:     // 頂点バッファの作成 
0125:     MyVertex *pFloorDest;
0126:     lpD3DDev->CreateVertexBuffer( 4 * sizeof(MyVertex),
0127:                                 0, 0, D3DPOOL_MANAGED, &pFloorVB );
0128:     // 頂点をセットアップ
0129:     {
0130:     pFloorVB->Lock ( 0, 0, (BYTE**)&pFloorDest, 0 );
0131:     for (DWORD i = 0; i < 4; i++) {
0132:         pFloorDest->x   = (i == 0 || i == 1)?(-FLOOR_SIZE):(+FLOOR_SIZE);
0133:         pFloorDest->z   = (i == 0 || i == 2)?(-FLOOR_SIZE):(+FLOOR_SIZE);
0134:         pFloorDest->y   = 0.0f;
0135:         pFloorDest->w   = 1.0f;
0136:         pFloorDest->tu = (i == 0 || i == 1)?0:FLOOR_UV;
0137:         pFloorDest->tv = (i == 0 || i == 2)?0:FLOOR_UV;
0138:         pFloorDest += 1;
0139:     }       
0140:     pFloorVB->Unlock ();
0141:     }
0142: 
0143: 
0144:     // インデックスをセットアップ
0145:     lpD3DDev->CreateIndexBuffer( 6 * sizeof(WORD),
0146:                                0,
0147:                                D3DFMT_INDEX16, D3DPOOL_MANAGED,
0148:                                &pFloorIB );
0149:     pFloorIB->Lock ( 0, 0, (BYTE**)&pIndex, 0 );
0150:     pIndex[0] = 0;  pIndex[1] = 1;  pIndex[2] = 2;
0151:     pIndex[3] = 1;  pIndex[4] = 3;  pIndex[5] = 2;
0152:     pFloorIB->Unlock ();
0153: 
0154:     D3DXCreateTextureFromFileEx(lpD3DDev, "tile.bmp", 0,0,0,0,D3DFMT_A8R8G8B8,
0155:                                 D3DPOOL_MANAGED, D3DX_FILTER_LINEAR, D3DX_FILTER_LINEAR,
0156:                                 0, NULL, NULL, &pFloorTex);
0157:     
0158: }
0159: 
0160: // ----------------------------------------------------------------------------
0161: // 地球
0162: // ----------------------------------------------------------------------------
0163: LPDIRECT3DVERTEXBUFFER8     pEarthVB;
0164: LPDIRECT3DINDEXBUFFER8      pEarthIB;
0165: LPDIRECT3DTEXTURE8          pEarthTex;
0166: #define EARTH_R             (0.7f)
0167: #define NUM_EARTH_X         32  // 縦に分割
0168: #define NUM_EARTH_Y         16  // 横に分割
0169: #define NUM_EARTH_VERTICES  ((NUM_EARTH_X+1)*(NUM_EARTH_Y+1))
0170: #define NUM_EARTH_POLYGONE  (2*NUM_EARTH_X*NUM_EARTH_Y)
0171: #define NUM_EARTH_INDEX     (6*NUM_EARTH_X*NUM_EARTH_Y)
0172: 
0173: // ----------------------------------------------------------------------------
0174: // 初期化
0175: static void InitEarth(LPDIRECT3DDEVICE8 lpD3DDev)
0176: {
0177:     WORD i, j;
0178:     
0179:     // 頂点バッファの作成 
0180:     MyVertex *pEarthDest;
0181:     lpD3DDev->CreateVertexBuffer( NUM_EARTH_VERTICES * sizeof(MyVertex),
0182:                                 0, 0, D3DPOOL_MANAGED,
0183:                                 &pEarthVB );
0184:     // 頂点をセットアップ
0185:     pEarthVB->Lock ( 0, 0, (BYTE**)&pEarthDest, 0 );
0186:     for ( j = 0; j <= NUM_EARTH_Y; j++) {
0187:     for ( i = 0; i <= NUM_EARTH_X; i++) {
0188:         float theta = ((float)i)*2*D3DX_PI/NUM_EARTH_X;
0189:         float phi   = ((float)j)*  D3DX_PI/NUM_EARTH_Y-D3DX_PI/2;
0190:         pEarthDest->x   = EARTH_R * (float)cos(phi) * (float)cos(theta);
0191:         pEarthDest->z   = EARTH_R * (float)cos(phi) * (float)sin(theta);
0192:         pEarthDest->y   = EARTH_R * (float)sin(phi);
0193:         pEarthDest->w   = 1.0f;
0194:         pEarthDest->tu = (float)i/NUM_EARTH_X;
0195:         pEarthDest->tv = 1.0f-(float)j/NUM_EARTH_Y;
0196:         pEarthDest++;
0197:     }
0198:     }
0199:     pEarthVB->Unlock ();
0200: 
0201: 
0202:     // インデックスをセットアップ
0203:     WORD *pIndex;
0204:     lpD3DDev->CreateIndexBuffer( NUM_EARTH_INDEX * sizeof(WORD),
0205:                                0,
0206:                                D3DFMT_INDEX16, D3DPOOL_MANAGED,
0207:                                &pEarthIB );
0208:     pEarthIB->Lock ( 0, 0, (BYTE**)&pIndex, 0 );
0209:     for ( j = 0; j < NUM_EARTH_Y; j++) {
0210:     for ( i = 0; i < NUM_EARTH_X; i++) {
0211:         *pIndex++ = (j+0)*(NUM_EARTH_X+1)+i+0;
0212:         *pIndex++ = (j+1)*(NUM_EARTH_X+1)+i+0;
0213:         *pIndex++ = (j+0)*(NUM_EARTH_X+1)+i+1;
0214:         *pIndex++ = (j+0)*(NUM_EARTH_X+1)+i+1;
0215:         *pIndex++ = (j+1)*(NUM_EARTH_X+1)+i+0;
0216:         *pIndex++ = (j+1)*(NUM_EARTH_X+1)+i+1;
0217:     }
0218:     }
0219:     pEarthIB->Unlock ();
0220: 
0221:     D3DXCreateTextureFromFileEx(lpD3DDev, "earth.bmp", 0,0,0,0,D3DFMT_A8R8G8B8,
0222:                                 D3DPOOL_MANAGED, D3DX_FILTER_LINEAR, D3DX_FILTER_LINEAR,
0223:                                 0, NULL, NULL, &pEarthTex);
0224: 
0225: }
0226: // ----------------------------------------------------------------------------
0227: // シェーダーの設定
0228: // ----------------------------------------------------------------------------
0229: void InitShader(LPDIRECT3DDEVICE8 lpD3DDev, cgContextContainer *pCg)
0230: {
0231:     // ==================================================
0232:     // 頂点シェーダー
0233:     // ==================================================
0234:     pVs = pCg->LoadCGProgramFromFile(
0235:         "bgvs.cg", "Vertex Shader", cgDX8VertexProfile, vertex_attributes);
0236: extern cgDirect3D cg;
0237:     if (pVs == NULL) {
0238:         // エラー表示
0239:         const char * listing = pCg->GetLastListing();
0240:         if (listing == 0) listing = "Could not find cgc.exe.";
0241:         cg.NotePad("頂点シェーダープログラムの生成に失敗しました\n\n", listing);    // メモ帳に出力
0242: 
0243:         exit(1);    // 終了
0244:     }
0245: 
0246:     // 頂点データの反復子と、.cg ファイルの引数を関連付ける
0247:     vertex_mat_iter = pVs->GetParameterBindByName("worldviewproj_matrix");
0248: 
0249:     // ==================================================
0250:     // ピクセルシェーダー
0251:     // ==================================================
0252:     pPs = pCg->LoadCGProgramFromFile(
0253:         "bgps.cg", "test", cgDX8PixelProfile);
0254:     
0255:     if (pPs == NULL) {
0256:         // エラー表示
0257:         const char * listing = pCg->GetLastListing();
0258:         if (listing == 0) listing = "Could not find cgc.exe.";
0259:         cg.NotePad("ピクセルシェーダープログラムの生成に失敗しました\n\n", listing);    // メモ帳に出力
0260: 
0261:         exit(1);    // 終了
0262:     }
0263:     // テクスチャーの反復子と、.cg ファイルの引数を関連付ける
0264:     tex0_iter = pPs->GetTextureBindByName("tex0");
0265:     int t0 = pPs->GetTexturePosition(tex0_iter);
0266: }
0267: // ----------------------------------------------------------------------------
0268: void InitBg(LPDIRECT3DDEVICE8 lpD3DDev, cgContextContainer *pCg)
0269: {
0270:     InitShader(lpD3DDev, pCg);
0271:     
0272:     InitSky(lpD3DDev);      // 空
0273:     InitFloor(lpD3DDev);    // 床
0274:     InitEarth(lpD3DDev);    // 地球
0275: }
0276: // ----------------------------------------------------------------------------
0277: void DrawBg(LPDIRECT3DDEVICE8 lpD3DDev, D3DXMATRIX &mVP)
0278: {
0279:     D3DXMATRIX mWorld, m;
0280: 
0281:     // プログラマぶるシェーダーを有効にする
0282:     pVs->SetShaderActive();
0283:     pPs->SetShaderActive();
0284:     
0285:     D3DXMatrixTranspose( &m, &mVP );
0286:     pVs->SetShaderConstant( vertex_mat_iter, &m  );
0287: 
0288:     lpD3DDev->SetTextureStageState(0,D3DTSS_COLOROP,    D3DTOP_MODULATE);
0289:     lpD3DDev->SetTextureStageState(0,D3DTSS_COLORARG1,  D3DTA_TEXTURE);
0290:     lpD3DDev->SetTextureStageState(0,D3DTSS_COLORARG2,  D3DTA_DIFFUSE);
0291:     lpD3DDev->SetTextureStageState(1,D3DTSS_COLOROP,    D3DTOP_DISABLE);
0292:     
0293:     //
0294:     // 空
0295:     //
0296:     lpD3DDev->SetTextureStageState(0,D3DTSS_ADDRESSU,   D3DTADDRESS_WRAP);
0297:     lpD3DDev->SetTextureStageState(0,D3DTSS_ADDRESSV,   D3DTADDRESS_CLAMP);
0298:     pPs->SetTexture(tex0_iter, pCylinderTex);
0299:     lpD3DDev->SetStreamSource(0, pCylinderVB, sizeof(MyVertex));
0300:     lpD3DDev->SetIndices(pCylinderIB,0);
0301:     lpD3DDev->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, NUM_VERTICES, 0 , NUM_FACES*2 );
0302:     
0303:     //
0304:     // 床
0305:     //
0306:     lpD3DDev->SetTextureStageState(0,D3DTSS_ADDRESSU,   D3DTADDRESS_WRAP);
0307:     lpD3DDev->SetTextureStageState(0,D3DTSS_ADDRESSV,   D3DTADDRESS_WRAP);
0308:     pPs->SetTexture(tex0_iter, pFloorTex);
0309:     lpD3DDev->SetStreamSource(0, pFloorVB, sizeof(MyVertex));
0310:     lpD3DDev->SetIndices(pFloorIB,0);
0311:     lpD3DDev->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 4, 0, 2 );
0312: 
0313:     //
0314:     // 地球
0315:     //
0316:     lpD3DDev->SetTextureStageState(0,D3DTSS_ADDRESSU,   D3DTADDRESS_WRAP);
0317:     D3DXMATRIX m1, m2;
0318:     float t = 2.0f*D3DX_PI*(1.0f-(float)(timeGetTime()%0x1fff)/(32.0f*256.0f));
0319:     while(t<0)t+=2.0f*D3DX_PI;
0320:     D3DXMatrixRotationY( &m1, t );
0321:     D3DXMatrixTranslation(&m2, 3.0f,3.0f,-10.0f);
0322:     m = m1*m2*mVP;
0323:     D3DXMatrixTranspose( &m, &m );
0324:     pVs->SetShaderConstant( vertex_mat_iter, &m  );
0325:     pPs->SetTexture(tex0_iter, pEarthTex);
0326:     lpD3DDev->SetStreamSource(0, pEarthVB, sizeof(MyVertex));
0327:     lpD3DDev->SetIndices(pEarthIB,0);
0328:     lpD3DDev->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, NUM_EARTH_VERTICES, 0 , NUM_EARTH_POLYGONE );
0329:     
0330: }
0331: // ----------------------------------------------------------------------------
0332: void CleanBg(LPDIRECT3DDEVICE8 lpD3DDev)
0333: {
0334:     RELEASE(pEarthTex);
0335:     RELEASE(pEarthIB);
0336:     RELEASE(pEarthVB);
0337: 
0338:     RELEASE(pFloorTex);
0339:     RELEASE(pFloorIB);
0340:     RELEASE(pFloorVB);
0341:     
0342:     RELEASE(pCylinderTex);
0343:     RELEASE(pCylinderIB);
0344:     RELEASE(pCylinderVB);
0345: }