0001: // ----------------------------------------------------------------------------
0002: //
0003: // draw.cpp - 描画部分
0004: // 
0005: // Copyright (c) 2001 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: 
0017: 
0018: // ぼかした絵を作るためのオブジェクト
0019: LPDIRECT3DSURFACE8      pBackbuffer = NULL;
0020: LPDIRECT3DTEXTURE8      pRenderTexture[2] = {NULL,NULL};
0021: LPDIRECT3DSURFACE8      pRenderSurface[2] = {NULL,NULL};
0022: 
0023: // ----------------------------------------------------------------------------
0024: // 点を打つ
0025: // ----------------------------------------------------------------------------
0026: LPDIRECT3DTEXTURE8      pDropTexture = NULL;        // 点用テクスチャー
0027: LPDIRECT3DVERTEXBUFFER8 pDropVB = NULL;
0028: 
0029: typedef struct {
0030:     float x, y, z, rhw;
0031:     float tu,tv;
0032: }D3D_DROP_VERTEX;
0033: #define D3DFVF_DROP_VERTEX      (D3DFVF_XYZRHW  | D3DFVF_TEX1)
0034: 
0035: DWORD dwDropDecl[] = {
0036:     D3DVSD_STREAM(0),
0037:     D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3 ),          //D3DVSDE_POSITION,  0
0038:     D3DVSD_REG(D3DVSDE_TEXCOORD0,D3DVSDT_FLOAT2 ),          //D3DVSDE_TEXCOORD0, 7  
0039:     D3DVSD_END()
0040: };
0041: 
0042: // ----------------------------------------------------------------------------
0043: // 初期化
0044: HRESULT InitDrop(LPDIRECT3DDEVICE8 lpD3DDev)
0045: {
0046:     HRESULT hr = S_OK;
0047: 
0048:     // 頂点バッファの作成 
0049:     D3D_DROP_VERTEX vertices[] = {
0050:         //     x,      y,    z,  rhw,  tu  tv
0051:         { 100.0f, 100.0f, 0.5f, 1.0f, 0.0f,0.0f,},
0052:         { 420.0f, 100.0f, 0.5f, 1.0f, 1.0f,0.0f,},
0053:         { 100.0f, 340.0f, 0.5f, 1.0f, 0.0f,1.0f,},
0054:         { 420.0f, 340.0f, 0.5f, 1.0f, 1.0f,1.0f,},
0055:     };
0056:     
0057:     hr = lpD3DDev->CreateVertexBuffer( 4*sizeof(D3D_DROP_VERTEX),0,
0058:                     D3DFVF_DROP_VERTEX, D3DPOOL_DEFAULT, &pDropVB);
0059:     if(FAILED(hr)) return E_FAIL;
0060: 
0061:     VOID* pVertices;
0062:     hr = pDropVB->Lock( 0, sizeof(vertices), (BYTE**)&pVertices, 0);
0063:     if(FAILED(hr)) return E_FAIL;
0064:     memcpy( pVertices, vertices, sizeof(vertices) );
0065:     pDropVB->Unlock();
0066: 
0067:     // マスク用テクスチャーの読み込み
0068:     if ( FAILED(hr = CTextureMgr::Load(lpD3DDev, "mask.bmp",     &pDropTexture)) ) return hr;
0069:     
0070:     return hr;
0071: }
0072: // ----------------------------------------------------------------------------
0073: // リクエスト
0074: static float drop_x=0;
0075: static float drop_y=0;
0076: static int drop = 0;
0077: // ----------------------------------------------------------------------------
0078: void SetDrop(float x , float y)
0079: {
0080:     drop = 100;
0081:     drop_x = x;
0082:     drop_y = y;
0083: }
0084: // ----------------------------------------------------------------------------
0085: void ResetDrop()
0086: {
0087:     drop = 0;
0088: }
0089: // ----------------------------------------------------------------------------
0090: int IsDrop()
0091: {
0092:     return drop;
0093: }
0094: // ----------------------------------------------------------------------------
0095: // 描画
0096: void RenderDrop(LPDIRECT3DDEVICE8 lpD3DDev)
0097: {
0098:     if(drop){
0099: //      drop--;
0100: 
0101:         D3D_DROP_VERTEX *p;
0102:         pDropVB->Lock( 0, 4*sizeof(D3D_DROP_VERTEX), (BYTE**)&p, 0);
0103:         const float r = 8.0f;
0104:         p[0].x = p[2].x = drop_x-r;
0105:         p[1].x = p[3].x = drop_x+r;
0106:         p[0].y = p[1].y = drop_y-r;
0107:         p[2].y = p[3].y = drop_y+r;
0108:         pDropVB->Unlock();
0109: 
0110:         lpD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
0111:         lpD3DDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR);
0112:         lpD3DDev->SetRenderState(D3DRS_SRCBLEND,  D3DBLEND_ZERO);
0113: 
0114:         lpD3DDev->SetTexture( 0, pDropTexture);
0115:         lpD3DDev->SetTexture( 1, 0);
0116:         lpD3DDev->SetTexture( 2, 0);
0117:         lpD3DDev->SetTexture( 3, 0);
0118:         lpD3DDev->SetStreamSource( 0, pDropVB, sizeof(D3D_DROP_VERTEX) );
0119:         lpD3DDev->SetVertexShader( D3DFVF_DROP_VERTEX );
0120:         lpD3DDev->SetPixelShader ( 0 );
0121:         lpD3DDev->DrawPrimitive(  D3DPT_TRIANGLESTRIP, 0, 2 );
0122: 
0123:         lpD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
0124:     }
0125: }
0126: // ----------------------------------------------------------------------------
0127: // 後始末
0128: static void CleanDrop(LPDIRECT3DDEVICE8 lpD3DDev)
0129: {
0130:     RELEASE(pDropVB);
0131:     RELEASE(pDropTexture);
0132: }
0133: 
0134: // ----------------------------------------------------------------------------
0135: // 描画テクスチャー
0136: // ----------------------------------------------------------------------------
0137: DWORD                   hSumieVertexShader=~0;
0138: DWORD                   hSumiePixelShader=~0;
0139: LPDIRECT3DVERTEXBUFFER8 pSumieVB = NULL;
0140: LPDIRECT3DINDEXBUFFER8  pSumieIB = NULL;
0141: 
0142: typedef struct {
0143:     float x, y, z;
0144:     float tu,tv;
0145: }D3D_SUMIE_VERTEX;
0146: #define D3DFVF_SUMIE_VERTEX         (D3DFVF_XYZ | D3DFVF_TEX1 )
0147: 
0148: DWORD dwSumieDecl[] = {
0149:     D3DVSD_STREAM(0),
0150:     D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3 ),          //D3DVSDE_POSITION,  0
0151:     D3DVSD_REG(D3DVSDE_TEXCOORD0,D3DVSDT_FLOAT2 ),          //D3DVSDE_TEXCOORD0, 7  
0152:     D3DVSD_END()
0153: };
0154: 
0155: 
0156: 
0157: 
0158: //-----------------------------------------------------------------------------
0159: // Name: InitRenderTexture()
0160: // Desc: ボケたテクスチャー用の下準備
0161: //-----------------------------------------------------------------------------
0162: HRESULT InitRenderTexture(LPDIRECT3DDEVICE8 lpD3DDev)
0163: {
0164:     HRESULT hr;
0165:     DWORD i;
0166:     
0167:     // 頂点バッファの作成 
0168:     D3D_SUMIE_VERTEX *pDest;
0169:     WORD *pIndex;
0170:     hr = lpD3DDev->CreateVertexBuffer( 4 * sizeof(D3D_SUMIE_VERTEX),
0171:                                 D3DUSAGE_WRITEONLY, D3DFVF_SUMIE_VERTEX, D3DPOOL_MANAGED,
0172:                                 &pSumieVB );
0173:     // 頂点をセットアップ
0174:     pSumieVB->Lock ( 0, 0, (BYTE**)&pDest, 0 );
0175:     for (i = 0; i < 4; i++) {
0176:         pDest->x   = (i == 0 || i == 1)?-1:(float)1;
0177:         pDest->y   = (i == 0 || i == 2)?-1:(float)1;
0178:         pDest->z   = 0.5f;
0179:         pDest->tu = (i == 2 || i == 3)?1:(float)0;
0180:         pDest->tv = (i == 0 || i == 2)?1:(float)0;
0181:         pDest++;
0182:     }       
0183:     pSumieVB->Unlock ();
0184:     // インデックスをセットアップ
0185:     hr = lpD3DDev->CreateIndexBuffer( 6 * sizeof(WORD),
0186:                                0,
0187:                                D3DFMT_INDEX16, D3DPOOL_MANAGED,
0188:                                &pSumieIB );
0189:     pSumieIB->Lock ( 0, 0, (BYTE**)&pIndex, 0 );
0190:     pIndex[0] = 0;  pIndex[1] = 1;  pIndex[2] = 2;
0191:     pIndex[3] = 1;  pIndex[4] = 3;  pIndex[5] = 2;
0192:     pSumieIB->Unlock ();
0193: 
0194:     // シェ-ダーのロード
0195:     if ( FAILED(hr = CVertexShaderMgr::Load(lpD3DDev, "sumie.vsh",     &hSumieVertexShader, dwSumieDecl)) ) return hr;
0196:     if ( FAILED(hr =  CPixelShaderMgr::Load(lpD3DDev, "sumie.psh",     &hSumiePixelShader)) ) return hr;
0197: 
0198:     // 定数レジスタの設定
0199:     float const inv_w = 1.0f / (float)WIDTH;
0200:     float const inv_h = 1.0f / (float)HEIGHT;
0201:     lpD3DDev->SetVertexShaderConstant(20, &D3DXVECTOR4  (( 0.0f    +0.5f)*inv_w, ( 0.0f+0.5f)*inv_h, 0.0f, 0.0f), 1);
0202:     lpD3DDev->SetVertexShaderConstant(21, &D3DXVECTOR4  (( 0.0f    +0.5f)*inv_w, (-1.0f+0.5f)*inv_h, 0.0f, 0.0f), 1);
0203:     lpD3DDev->SetVertexShaderConstant(22, &D3DXVECTOR4  ((-0.57735f+0.5f)*inv_w, ( 0.5f+0.5f)*inv_h, 0.0f, 0.0f), 1);
0204:     lpD3DDev->SetVertexShaderConstant(23, &D3DXVECTOR4  ((+0.57735f+0.5f)*inv_w, ( 0.5f+0.5f)*inv_h, 0.0f, 0.0f), 1);
0205: 
0206: 
0207:     // 描画用テクスチャーを用意する
0208:     D3DSURFACE_DESC Desc;
0209:     LPDIRECT3DSURFACE8 lpZbuffer = NULL;
0210:     if( FAILED(hr = lpD3DDev->GetRenderTarget(&pBackbuffer))) return hr;
0211:     if( FAILED(hr = pBackbuffer->GetDesc( &Desc ))) return hr;
0212: 
0213:     // 深度バッファのサーフェスを確保する
0214:     if( FAILED(hr = lpD3DDev->GetDepthStencilSurface( &lpZbuffer ))) return hr;
0215:     
0216:     for( i=0 ; i<2 ; i++ ){
0217:         // ぼけテクスチャー作成用のリソースを確保する
0218:         if( FAILED(hr = lpD3DDev->CreateTexture(Desc.Width, Desc.Height, 1
0219:                                 , D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pRenderTexture[i]))) return hr;
0220:         // テクスチャーとサーフェスを関連づける
0221:         if( FAILED(hr = pRenderTexture[i]->GetSurfaceLevel(0,&pRenderSurface[i]))) return hr;
0222:         // テクスチャー用の描画と深度バッファを関連付ける
0223:         if( FAILED(hr = lpD3DDev->SetRenderTarget(pRenderSurface[i], lpZbuffer ))) return hr;
0224:     }
0225: 
0226:     // 描画を元の画面に戻す
0227:     lpD3DDev->SetRenderTarget(pBackbuffer, lpZbuffer );
0228:     
0229:     return S_OK;
0230: }
0231: // ----------------------------------------------------------------------------
0232: // 描画
0233: void RenderSumie(LPDIRECT3DDEVICE8 lpD3DDev, int id)
0234: {
0235:     int i;
0236:     
0237:     for (i = 0; i < 4; i++) lpD3DDev->SetTexture(i, pRenderTexture[id]);
0238:     lpD3DDev->SetVertexShader( hSumieVertexShader );
0239:     lpD3DDev->SetPixelShader ( hSumiePixelShader );
0240:     lpD3DDev->SetStreamSource( 0, pSumieVB, sizeof(D3D_SUMIE_VERTEX) );
0241:     lpD3DDev->SetIndices(pSumieIB,0);
0242:     lpD3DDev->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 4, 0, 2 );
0243: }
0244: 
0245: // ----------------------------------------------------------------------------
0246: // 最終描画
0247: // ----------------------------------------------------------------------------
0248: LPDIRECT3DVERTEXBUFFER8 pFinalVB = NULL;
0249: 
0250: typedef struct {
0251:     float x, y, z, rhw;
0252:     float tu,tv;
0253: }D3D_FINAL_VERTEX;
0254: #define D3DFVF_FINAL_VERTEX         (D3DFVF_XYZRHW | D3DFVF_TEX1)
0255: 
0256: // ----------------------------------------------------------------------------
0257: // 初期化
0258: HRESULT InitFinal(LPDIRECT3DDEVICE8 lpD3DDev)
0259: {
0260:     HRESULT hr = S_OK;
0261: 
0262:     // 頂点バッファの作成 
0263:     D3D_DROP_VERTEX vertices[] = {
0264:         //  x,      y,    z,   rhw,  tu  tv
0265:         {  0.0f,   0.0f, 0.5f, 1.0f, 0.0f,0.0f,},
0266:         { WIDTH,   0.0f, 0.5f, 1.0f, 1.0f,0.0f,},
0267:         {  0.0f, HEIGHT, 0.5f, 1.0f, 0.0f,1.0f,},
0268:         { WIDTH, HEIGHT, 0.5f, 1.0f, 1.0f,1.0f,},
0269:     };
0270:     
0271:     hr = lpD3DDev->CreateVertexBuffer( 4*sizeof(D3D_FINAL_VERTEX),0,
0272:                     D3DFVF_DROP_VERTEX, D3DPOOL_DEFAULT, &pFinalVB);
0273:     if(FAILED(hr)) return hr;
0274: 
0275:     VOID* pVertices;
0276:     hr = pFinalVB->Lock( 0, sizeof(vertices), (BYTE**)&pVertices, 0);
0277:     if(FAILED(hr)) return hr;
0278:     memcpy( pVertices, vertices, sizeof(vertices) );
0279:     pFinalVB->Unlock();
0280: 
0281:     return hr;
0282: }
0283: // ----------------------------------------------------------------------------
0284: // 描画
0285: void RenderFinal(LPDIRECT3DDEVICE8 lpD3DDev)
0286: {
0287:     lpD3DDev->SetStreamSource( 0, pFinalVB, sizeof(D3D_DROP_VERTEX) );
0288:     lpD3DDev->SetVertexShader( D3DFVF_DROP_VERTEX );
0289:     lpD3DDev->SetPixelShader(NULL); 
0290:     lpD3DDev->DrawPrimitive(  D3DPT_TRIANGLESTRIP, 0, 2 );
0291: }
0292: 
0293: 
0294: 
0295: //-----------------------------------------------------------------------------
0296: // Name: InitRender()
0297: // Desc: Load the mesh and build the material and texture arrays
0298: //-----------------------------------------------------------------------------
0299: HRESULT InitRender(LPDIRECT3DDEVICE8 lpD3DDev)
0300: {
0301:     HRESULT hr = S_OK;
0302:     int i;
0303: 
0304:     if ( FAILED(hr = InitDrop(lpD3DDev)))return hr;
0305: 
0306:     // レンダリングテクスチャー用の初期化
0307:     if ( FAILED(hr = InitRenderTexture(lpD3DDev)))return hr;
0308: 
0309:     // 最終描画頂点バッファの初期化
0310:     if ( FAILED(hr = InitFinal(lpD3DDev)))return hr;
0311: 
0312:     // 不変なレジスタの設定
0313:     lpD3DDev->SetRenderState( D3DRS_ZENABLE, TRUE );
0314:     lpD3DDev->SetRenderState( D3DRS_LIGHTING,  FALSE );
0315:     for (i = 0; i < 4; ++i) {
0316:         lpD3DDev->SetTextureStageState(i, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
0317:         lpD3DDev->SetTextureStageState(i, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
0318:         lpD3DDev->SetTextureStageState(i, D3DTSS_MIPFILTER, D3DTEXF_NONE);
0319:         lpD3DDev->SetTextureStageState(i, D3DTSS_ADDRESSU,  D3DTADDRESS_CLAMP);
0320:         lpD3DDev->SetTextureStageState(i, D3DTSS_ADDRESSV,  D3DTADDRESS_CLAMP);
0321:         lpD3DDev->SetTextureStageState(i, D3DTSS_COLOROP,   D3DTOP_SELECTARG1);
0322:         lpD3DDev->SetTextureStageState(i, D3DTSS_COLORARG1, D3DTA_TEXTURE);
0323:     }
0324: 
0325:     return hr;
0326: }
0327: 
0328: //-----------------------------------------------------------------------------
0329: // Name: Render()
0330: // Desc: Draws the scene
0331: //-----------------------------------------------------------------------------
0332: VOID Render(LPDIRECT3DDEVICE8 lpD3DDev)
0333: {
0334:     static DWORD id = 0;
0335:     id = 1-id;
0336: 
0337:     LPDIRECT3DSURFACE8 lpZbuffer = NULL;
0338:     lpD3DDev->GetDepthStencilSurface( &lpZbuffer );
0339:     lpD3DDev->SetRenderTarget(pRenderSurface[id], lpZbuffer);
0340: 
0341:     RenderSumie(lpD3DDev, 1-id);
0342:     RenderDrop(lpD3DDev);
0343: 
0344:     static int first = 2;
0345:     if(0<first){
0346:         first--;
0347:         lpD3DDev->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA(255,255,255,255),1.0f,0);
0348:     }
0349: 
0350:     lpD3DDev->SetRenderTarget(pBackbuffer, lpZbuffer );                 // 描画をバックバッファに戻す
0351:     lpD3DDev->SetTexture( 0, pRenderTexture[id]);
0352:     lpD3DDev->SetTexture( 1, NULL);
0353:     lpD3DDev->SetTexture( 2, NULL);
0354:     lpD3DDev->SetTexture( 3, NULL);
0355:     RenderFinal(lpD3DDev);
0356: }
0357: //-----------------------------------------------------------------------------
0358: // Name: CleanRender()
0359: // Desc: 後始末
0360: //-----------------------------------------------------------------------------
0361: void CleanRender(LPDIRECT3DDEVICE8 lpD3DDev)
0362: {
0363:     DWORD i;
0364: 
0365:     RELEASE(pFinalVB);
0366:     
0367:     for( i=0 ; i<2 ; i++ ){
0368:         RELEASE(pRenderSurface[i]);
0369:         RELEASE(pRenderTexture[i]);
0370:     }
0371:     
0372:     RELEASE(pBackbuffer);
0373:     
0374:      CPixelShaderMgr::Release(lpD3DDev, &hSumiePixelShader);
0375:     CVertexShaderMgr::Release(lpD3DDev, &hSumieVertexShader);
0376:     
0377:     CleanDrop(lpD3DDev);
0378: }
0379: