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