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: // 座標変換テーブル
0017: LPDIRECT3DTEXTURE8      pTransTexture=NULL;
0018: 
0019: // テクスチャーレンダリングのためのオブジェクト
0020: LPDIRECT3DSURFACE8      pBackbuffer = NULL;
0021: DWORD                   hVertexShader=~0;
0022: DWORD                   hPixelShader=~0;
0023: LPDIRECT3DVERTEXBUFFER8 pVB = NULL;
0024: LPDIRECT3DINDEXBUFFER8  pIB = NULL;
0025: 
0026: const int nTempTex = 2;
0027: LPDIRECT3DTEXTURE8      pTmpTexture[nTempTex];
0028: LPDIRECT3DSURFACE8      pTmpSurface[nTempTex];
0029: 
0030: LPDIRECT3DTEXTURE8      pInitTexture=NULL;  // 初期化テクスチャー
0031: 
0032: // ----------------------------------------------------------------------------
0033: // 頂点の定義
0034: typedef struct {
0035:     float x,y,z;
0036:     float tu,tv;
0037: }D3D_MY_VERTEX;
0038: #define D3DFVF_MY_VERTEX        (D3DFVF_XYZ | D3DFVF_TEX1)
0039: 
0040: DWORD dwMyDecl[] = {
0041:     D3DVSD_STREAM(0),
0042:     D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3 ),          //D3DVSDE_POSITION,  0
0043:     D3DVSD_REG(D3DVSDE_TEXCOORD0,D3DVSDT_FLOAT2 ),          //D3DVSDE_TEXCOORD0, 7  
0044:     D3DVSD_END()
0045: };
0046: 
0047: //-----------------------------------------------------------------------------
0048: // Name: InitRenderingTexture()
0049: // Desc: テクスチャー描画用の下準備
0050: //-----------------------------------------------------------------------------
0051: HRESULT InitRenderingTexture(LPDIRECT3DDEVICE8 lpD3DDev)
0052: {
0053:     HRESULT hr;
0054:     DWORD i;
0055:     
0056:     // 頂点バッファの作成 
0057:     D3D_MY_VERTEX *pBlurDest;
0058:     WORD *pIndex;
0059:     lpD3DDev->CreateVertexBuffer( 4 * sizeof(D3D_MY_VERTEX),
0060:                                 D3DUSAGE_WRITEONLY, D3DFVF_MY_VERTEX, D3DPOOL_MANAGED,
0061:                                 &pVB );
0062:     // 頂点をセットアップ
0063:     pVB->Lock ( 0, 0, (BYTE**)&pBlurDest, 0 );
0064:     for (i = 0; i < 4; i++) {
0065:         pBlurDest->x   = (i == 0 || i == 1)?-1:(float)1;
0066:         pBlurDest->y   = (i == 0 || i == 2)?-1:(float)1;
0067:         pBlurDest->z   = 0.5f;
0068:         pBlurDest->tu = (i == 2 || i == 3)?1:(float)0;
0069:         pBlurDest->tv = (i == 0 || i == 2)?1:(float)0;
0070:         pBlurDest++;
0071:     }       
0072:     pVB->Unlock ();
0073:     // インデックスをセットアップ
0074:     lpD3DDev->CreateIndexBuffer( 6 * sizeof(WORD),
0075:                                0,
0076:                                D3DFMT_INDEX16, D3DPOOL_MANAGED,
0077:                                &pIB );
0078:     pIB->Lock ( 0, 0, (BYTE**)&pIndex, 0 );
0079:     pIndex[0] = 0;  pIndex[1] = 1;  pIndex[2] = 2;
0080:     pIndex[3] = 1;  pIndex[4] = 3;  pIndex[5] = 2;
0081:     pIB->Unlock ();
0082: 
0083:     // 描画用テクスチャーを用意する
0084:     D3DSURFACE_DESC Desc;
0085:     LPDIRECT3DSURFACE8 lpZbuffer = NULL;
0086:     if( FAILED(hr = lpD3DDev->GetRenderTarget(&pBackbuffer))) return hr;
0087:     if( FAILED(hr = pBackbuffer->GetDesc( &Desc ))) return hr;
0088: 
0089:     // 深度バッファのサーフェスを確保する
0090:     if( FAILED(hr = lpD3DDev->GetDepthStencilSurface( &lpZbuffer ))) return hr;
0091:     
0092:     // テクスチャー作成用のリソースを確保する
0093:     for (i = 0; i < nTempTex; ++i) {
0094:         // テクスチャーの生成
0095:         if( FAILED(hr = lpD3DDev->CreateTexture(Desc.Width, Desc.Height, 1
0096:                                 , D3DUSAGE_RENDERTARGET, Desc.Format, D3DPOOL_DEFAULT, &pTmpTexture[i]))) return hr;
0097:         // テクスチャーとサーフェスを関連づける
0098:         if( FAILED(hr = pTmpTexture[i]->GetSurfaceLevel(0,&pTmpSurface[i]))) return hr;
0099:         // テクスチャー用の描画と深度バッファを関連付ける
0100:         if( FAILED(hr = lpD3DDev->SetRenderTarget(pTmpSurface[i], NULL ))) return hr;
0101:     }
0102: 
0103:     // 描画を元の画面に戻す
0104:     lpD3DDev->SetRenderTarget(pBackbuffer, lpZbuffer );
0105:     
0106:     // シェ-ダーのロード
0107:     if ( FAILED(CVertexShaderMgr::Load(lpD3DDev, "vs.vsh",     &hVertexShader, dwMyDecl)) ) return hr;
0108:     if ( FAILED( CPixelShaderMgr::Load(lpD3DDev, "ps.psh",    &hPixelShader)) ) return hr;
0109:     
0110:     return S_OK;
0111: }
0112: //-----------------------------------------------------------------------------
0113: // Name: MakeInitTexture()
0114: // Desc: 座標変換マップ
0115: //-----------------------------------------------------------------------------
0116: VOID MakeInitTexture(D3DXVECTOR4* pOut, D3DXVECTOR2 *pTexCoord, D3DXVECTOR2 *pTexelSize, LPVOID pData)
0117: {
0118:     float x = 2*pTexCoord->x-1;
0119:     float y = 2*pTexCoord->y-1;
0120:     
0121:     float dx = 5.0f*((0<x)?x:-x);
0122:     float dy = 5.0f*((0<y)?y:-y);
0123:     
0124:     while(1.0f<=dx)dx -= 1.0f;
0125:     while(1.0f<=dy)dy -= 1.0f;
0126:     float f = max(dx,dy);
0127: 
0128:     pOut->x = (0<x  )?f:0;
0129:     pOut->y = (0<y  )?f:0;
0130:     pOut->z = (0<x*y)?f:0;
0131:     pOut->w = 1.0f;
0132: }
0133: 
0134: //-----------------------------------------------------------------------------
0135: // Name: MakeTexture()
0136: // Desc: 座標変換マップ
0137: //-----------------------------------------------------------------------------
0138: VOID MakeTexture(D3DXVECTOR4* pOut, D3DXVECTOR2 *pTexCoord, D3DXVECTOR2 *pTexelSize, LPVOID pData)
0139: {
0140:     float x = 2*pTexCoord->x-1;
0141:     float y = 2*pTexCoord->y-1;
0142:     float Ar = 0.378f;
0143:     float Ai = 0.183f;
0144:     
0145:     float x1 = x*x-y*y+Ar;
0146:     float y1 = 2*x*y+Ai;
0147:     
0148:     min(1,max(x1,0));
0149:     min(1,max(y1,0));
0150: 
0151:     pOut->x = 0.0f;
0152:     pOut->y = 0.5f*x1+0.5f;
0153:     pOut->z = 0.5f*y1+0.5;
0154:     pOut->w = 1.0f;
0155: }
0156: 
0157: //-----------------------------------------------------------------------------
0158: // Name: InitRender()
0159: // Desc: Load the mesh and build the material and texture arrays
0160: //-----------------------------------------------------------------------------
0161: HRESULT InitRender(LPDIRECT3DDEVICE8 lpD3DDev)
0162: {
0163:     DWORD i;
0164:     HRESULT hr;
0165: 
0166:     // 変換テクスチャー
0167:     if( FAILED(hr = lpD3DDev->CreateTexture(512, 512, 1
0168:                                 , D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8
0169:                                 , D3DPOOL_DEFAULT, &pTransTexture))) return hr;
0170:     if( FAILED(hr = D3DXFillTexture(pTransTexture, MakeTexture, NULL))) return hr;
0171: 
0172:     // 初期化テクスチャー
0173:     if( FAILED(hr = lpD3DDev->CreateTexture(512, 512, 1
0174:                                 , D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8
0175:                                 , D3DPOOL_DEFAULT, &pInitTexture))) return hr;
0176:     if( FAILED(hr = D3DXFillTexture(pInitTexture, MakeInitTexture, NULL))) return hr;
0177: 
0178:     // ぼけテクスチャー用の初期化
0179:     InitRenderingTexture(lpD3DDev);
0180:     
0181:     // 不変なレジスタの設定
0182:     lpD3DDev->SetRenderState( D3DRS_ZENABLE, TRUE );
0183:     lpD3DDev->SetRenderState( D3DRS_LIGHTING,  FALSE );
0184:     lpD3DDev->SetTextureStageState(0, D3DTSS_COLOROP,   D3DTOP_SELECTARG1);
0185:     lpD3DDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
0186:     for (i = 0; i < 1; ++i) {
0187:         lpD3DDev->SetTextureStageState(i, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
0188:         lpD3DDev->SetTextureStageState(i, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
0189:         lpD3DDev->SetTextureStageState(i, D3DTSS_MIPFILTER, D3DTEXF_NONE);
0190:         lpD3DDev->SetTextureStageState(i, D3DTSS_ADDRESSU,  D3DTADDRESS_CLAMP);
0191:         lpD3DDev->SetTextureStageState(i, D3DTSS_ADDRESSV,  D3DTADDRESS_CLAMP);
0192:     }
0193: 
0194: 
0195:     return S_OK;
0196: }
0197: 
0198: //-----------------------------------------------------------------------------
0199: // Name: Render()
0200: // Desc: Draws the scene
0201: //-----------------------------------------------------------------------------
0202: VOID Render(LPDIRECT3DDEVICE8 lpD3DDev)
0203: {
0204:     Sleep(50);
0205:     D3DXMATRIX mWorld, mView, mProj, m;
0206:     
0207:     static int idx = 0;
0208:     idx=1-idx;
0209: 
0210:     LPDIRECT3DSURFACE8 lpZbuffer = NULL;
0211:     lpD3DDev->GetDepthStencilSurface( &lpZbuffer );
0212:     lpD3DDev->SetRenderTarget(pTmpSurface[idx], lpZbuffer);
0213:     lpD3DDev->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0),1.0f,0);
0214: 
0215:     lpD3DDev->SetTexture(0, pTransTexture);
0216:     lpD3DDev->SetTexture(1, pTmpTexture[1-idx]);
0217:     lpD3DDev->SetVertexShader(hVertexShader);
0218:     lpD3DDev->SetPixelShader(hPixelShader); 
0219:     lpD3DDev->SetStreamSource(0, pVB, sizeof(D3D_MY_VERTEX));
0220:     lpD3DDev->SetIndices(pIB,0);
0221:     lpD3DDev->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 4, 0, 2 );
0222: 
0223:     static int init=1;
0224:     if(init){// 初期化として、変換テクスチャーを最初の模様に設定する
0225:         init--;
0226:         struct TLVERTEX
0227:         {
0228:             float x,y,z,rhw;
0229:             float tu,tv;
0230:         };
0231:         #define FVF_TLVERTEX (D3DFVF_XYZRHW | D3DFVF_TEX1)
0232:         float scale = 512;
0233:         TLVERTEX Vertex[4] = {
0234:             // x       y  z rhw tu tv
0235:             {    0,    0, 0, 1, 0, 0,},
0236:             {scale,    0, 0, 1, 1, 0,},
0237:             {scale,scale, 0, 1, 1, 1,},
0238:             {    0,scale, 0, 1, 0, 1,},
0239:         };
0240:         lpD3DDev->SetTexture( 0, pTransTexture );
0241: //        lpD3DDev->SetTexture( 0, pInitTexture );
0242:         lpD3DDev->SetVertexShader( FVF_TLVERTEX );
0243:         lpD3DDev->SetPixelShader(0);
0244:         lpD3DDev->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, Vertex, sizeof( TLVERTEX ) );
0245:     }
0246:     
0247:     // 
0248:     // 完成した一枚絵を描画する
0249:     // 
0250:     lpD3DDev->SetRenderTarget(pBackbuffer, lpZbuffer );                 // 描画をバックバッファに戻す
0251:     lpD3DDev->SetVertexShader(hVertexShader);
0252:     lpD3DDev->SetPixelShader(NULL);
0253:     lpD3DDev->SetTexture( 0, pTmpTexture[idx] );
0254:     lpD3DDev->SetStreamSource(0, pVB, sizeof(D3D_MY_VERTEX));
0255:     lpD3DDev->SetIndices(pIB,0);
0256:     lpD3DDev->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 4, 0, 2 );
0257: 
0258: #if 1
0259:     // 変換テクスチャーを描く
0260:     {
0261:         struct TLVERTEX
0262:         {
0263:             float x,y,z,rhw;
0264:             float tu,tv;
0265:         };
0266:         #define FVF_TLVERTEX (D3DFVF_XYZRHW | D3DFVF_TEX1)
0267:         float scale = 128;
0268:         TLVERTEX Vertex[4] = {
0269:             // x  y  z rhw tu tv
0270:             {    0,    0, 0, 1, 0, 0,},
0271:             {scale,    0, 0, 1, 1, 0,},
0272:             {scale,scale, 0, 1, 1, 1,},
0273:             {    0,scale, 0, 1, 0, 1,},
0274:         };
0275:         lpD3DDev->SetTexture( 0, pTransTexture );
0276:         lpD3DDev->SetVertexShader( FVF_TLVERTEX );
0277:         lpD3DDev->SetPixelShader(0);
0278:         lpD3DDev->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, Vertex, sizeof( TLVERTEX ) );
0279:     }
0280: #endif
0281: }
0282: //-----------------------------------------------------------------------------
0283: // Name: CleanRender()
0284: // Desc: 後始末
0285: //-----------------------------------------------------------------------------
0286: void CleanRender(LPDIRECT3DDEVICE8 lpD3DDev)
0287: {
0288:     DWORD i;
0289: 
0290:     for (i = 0; i < nTempTex; ++i) {
0291:         RELEASE(pTmpSurface[i]);
0292:         RELEASE(pTmpTexture [i]);
0293:     }
0294:     
0295:     RELEASE(pTransTexture);
0296:     RELEASE(pInitTexture);
0297:     
0298:     RELEASE(pBackbuffer);
0299:     
0300:      CPixelShaderMgr::Release(lpD3DDev, &hPixelShader);
0301:     CVertexShaderMgr::Release(lpD3DDev, &hVertexShader);
0302: }
0303: