0001: // ----------------------------------------------------------------------------
0002: //
0003: // draw.cpp : Render scene
0004: // 
0005: // Copyright (c) 2002 imagire takashi (imagire@gmail.com)
0006: // All Rights Reserved.
0007: //
0008: // ----------------------------------------------------------------------------
0009: #define STRICT
0010: 
0011: #include <windows.h>
0012: #include "Cg/cgD3D.h"
0013: #include "main.h"
0014: #include "draw.h"
0015: 
0016: // ----------------------------------------------------------------------------
0017: // ----------------------------------------------------------------------------
0018: // Objects
0019: // ----------------------------------------------------------------------------
0020: // ----------------------------------------------------------------------------
0021: 
0022: // ----------------------------------------------------------------------------
0023: // Cg object
0024: cgDirect3D cg;
0025: cgContextContainer * pCg = 0;
0026: 
0027: // ----------------------------------------------------------------------------
0028: // vertex shader
0029: cgProgramContainer      *pVs = 0;           // vertex container
0030: cgBindIter              *const_texcoord0= 0;// texture coord
0031: cgBindIter              *const_texcoord1= 0;// texture coord
0032: cgBindIter              *const_texcoord2= 0;// texture coord
0033: cgBindIter              *const_texcoord3= 0;// texture coord
0034: 
0035: cgVertexAttribute vertex_attributes[] = {   // input
0036:     {4, "Position", 0},
0037:     {2, "Texcoord", 0},
0038:     {0, 0, 0},
0039: };
0040: 
0041: // ----------------------------------------------------------------------------
0042: // pixel shader
0043: cgProgramContainer      *pPs = 0;           // pixel shader
0044: cgBindIter * tex0_iter = 0;                 // texture
0045: cgBindIter * tex1_iter = 0;                 // texture
0046: cgBindIter * tex2_iter = 0;                 // texture
0047: cgBindIter * tex3_iter = 0;                 // texture
0048: 
0049: 
0050: // ----------------------------------------------------------------------------
0051: // vertex & index buffer
0052: 
0053: #define D3DFVF_SUMIE_VERTEX     (D3DFVF_XYZ    | D3DFVF_TEX1)
0054: #define D3DFVF_DROP_VERTEX      (D3DFVF_XYZRHW | D3DFVF_TEX1)   // for Drop texture
0055: typedef struct {
0056:     float x, y, z, w;
0057:     float tu,tv;
0058: }D3D_SUMIE_VERTEX;
0059: 
0060: LPDIRECT3DVERTEXBUFFER8 pFinalVB = NULL;
0061: LPDIRECT3DVERTEXBUFFER8 pDropVB = NULL;
0062: LPDIRECT3DVERTEXBUFFER8 pSumieVB = NULL;
0063: LPDIRECT3DINDEXBUFFER8  pSumieIB = NULL;
0064: 
0065: // ----------------------------------------------------------------------------
0066: // Surface & texture
0067: LPDIRECT3DTEXTURE8      pDropTexture = NULL;        // dot texture
0068: LPDIRECT3DTEXTURE8      pRenderTexture[2] = {NULL,NULL};
0069: LPDIRECT3DSURFACE8      pRenderSurface[2] = {NULL,NULL};
0070: LPDIRECT3DSURFACE8      pBackbuffer = NULL;
0071: 
0072: 
0073: 
0074: // ----------------------------------------------------------------------------
0075: // ----------------------------------------------------------------------------
0076: // Drop dot
0077: // ----------------------------------------------------------------------------
0078: // ----------------------------------------------------------------------------
0079: 
0080: // ----------------------------------------------------------------------------
0081: // Initialize
0082: HRESULT InitDrop(LPDIRECT3DDEVICE8 lpD3DDev)
0083: {
0084:     HRESULT hr = S_OK;
0085: 
0086:     // Create vertex buffers
0087:     D3D_SUMIE_VERTEX vertices[] = {
0088:         //     x,      y,    z,  rhw,  tu  tv
0089:         { 100.0f, 100.0f, 0.5f, 1.0f, 0.0f,0.0f,},
0090:         { 420.0f, 100.0f, 0.5f, 1.0f, 1.0f,0.0f,},
0091:         { 100.0f, 340.0f, 0.5f, 1.0f, 0.0f,1.0f,},
0092:         { 420.0f, 340.0f, 0.5f, 1.0f, 1.0f,1.0f,},
0093:     };
0094:     
0095:     hr = lpD3DDev->CreateVertexBuffer( 4*sizeof(D3D_SUMIE_VERTEX),0,
0096:                     D3DFVF_DROP_VERTEX, D3DPOOL_DEFAULT, &pDropVB);
0097:     if(FAILED(hr)) return E_FAIL;
0098: 
0099:     VOID* pVertices;
0100:     hr = pDropVB->Lock( 0, sizeof(vertices), (BYTE**)&pVertices, 0);
0101:     if(FAILED(hr)) return E_FAIL;
0102:     memcpy( pVertices, vertices, sizeof(vertices) );
0103:     pDropVB->Unlock();
0104: 
0105:     // Load texture
0106:     D3DXCreateTextureFromFileEx(lpD3DDev, "mask.bmp",0,0,0,0,D3DFMT_A8R8G8B8,
0107:                                 D3DPOOL_MANAGED, D3DX_FILTER_LINEAR, D3DX_FILTER_LINEAR,
0108:                                 0, NULL, NULL, &pDropTexture);
0109: 
0110:     return hr;
0111: }
0112: // ----------------------------------------------------------------------------
0113: // Request
0114: static float drop_x=0;
0115: static float drop_y=0;
0116: static int drop = 0;
0117: // ----------------------------------------------------------------------------
0118: void SetDrop(float x , float y)
0119: {
0120:     drop = 100;
0121:     drop_x = x;
0122:     drop_y = y;
0123: }
0124: // ----------------------------------------------------------------------------
0125: void ResetDrop()
0126: {
0127:     drop = 0;
0128: }
0129: // ----------------------------------------------------------------------------
0130: int IsDrop()
0131: {
0132:     return drop;
0133: }
0134: // ----------------------------------------------------------------------------
0135: // Rendering
0136: void RenderDrop(LPDIRECT3DDEVICE8 lpD3DDev)
0137: {
0138:     if(drop){
0139:         D3D_SUMIE_VERTEX *p;
0140:         pDropVB->Lock( 0, 4*sizeof(D3D_SUMIE_VERTEX), (BYTE**)&p, 0);
0141:         const float r = 8.0f;// radius of dot
0142:         p[0].x = p[2].x = drop_x-r;
0143:         p[1].x = p[3].x = drop_x+r;
0144:         p[0].y = p[1].y = drop_y-r;
0145:         p[2].y = p[3].y = drop_y+r;
0146:         pDropVB->Unlock();
0147: 
0148:         lpD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
0149:         lpD3DDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR);
0150:         lpD3DDev->SetRenderState(D3DRS_SRCBLEND,  D3DBLEND_ZERO);
0151: 
0152:         lpD3DDev->SetTexture( 0, pDropTexture);
0153:         lpD3DDev->SetTexture( 1, 0);
0154:         lpD3DDev->SetTexture( 2, 0);
0155:         lpD3DDev->SetTexture( 3, 0);
0156:         lpD3DDev->SetStreamSource( 0, pDropVB, sizeof(D3D_SUMIE_VERTEX) );
0157:         lpD3DDev->SetVertexShader( D3DFVF_DROP_VERTEX );
0158:         lpD3DDev->SetPixelShader ( 0 );
0159:         lpD3DDev->DrawPrimitive(  D3DPT_TRIANGLESTRIP, 0, 2 );
0160: 
0161:         lpD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
0162:     }
0163: }
0164: 
0165: // ----------------------------------------------------------------------------
0166: // ----------------------------------------------------------------------------
0167: // Render Target
0168: // ----------------------------------------------------------------------------
0169: // ----------------------------------------------------------------------------
0170: 
0171: 
0172: //-----------------------------------------------------------------------------
0173: // Initialize Rendering Texture
0174: //-----------------------------------------------------------------------------
0175: HRESULT InitRenderTexture(LPDIRECT3DDEVICE8 lpD3DDev)
0176: {
0177:     HRESULT hr;
0178:     DWORD i;
0179:     
0180:     // ==================================================
0181:     // Vertex & Index buffer
0182:     // ==================================================
0183:     // Create Vertex buffer
0184:     D3D_SUMIE_VERTEX *pDest;
0185:     WORD *pIndex;
0186:     hr = lpD3DDev->CreateVertexBuffer( 4 * sizeof(D3D_SUMIE_VERTEX),
0187:                                 D3DUSAGE_WRITEONLY, D3DFVF_SUMIE_VERTEX, D3DPOOL_MANAGED,
0188:                                 &pSumieVB );
0189:     pSumieVB->Lock ( 0, 0, (BYTE**)&pDest, 0 );
0190:     for (i = 0; i < 4; i++) {
0191:         pDest->x   = (i == 0 || i == 1)?-1:(float)1;
0192:         pDest->y   = (i == 0 || i == 2)?-1:(float)1;
0193:         pDest->z   = 0.5f;
0194:         pDest->w   = 1.0f;
0195:         pDest->tu = (i == 2 || i == 3)?1:(float)0;
0196:         pDest->tv = (i == 0 || i == 2)?1:(float)0;
0197:         pDest++;
0198:     }       
0199:     pSumieVB->Unlock ();
0200:     // Create Index Buffer
0201:     hr = lpD3DDev->CreateIndexBuffer( 6 * sizeof(WORD),
0202:                                0,
0203:                                D3DFMT_INDEX16, D3DPOOL_MANAGED,
0204:                                &pSumieIB );
0205:     pSumieIB->Lock ( 0, 0, (BYTE**)&pIndex, 0 );
0206:     pIndex[0] = 0;  pIndex[1] = 1;  pIndex[2] = 2;
0207:     pIndex[3] = 1;  pIndex[4] = 3;  pIndex[5] = 2;
0208:     pSumieIB->Unlock ();
0209: 
0210:     // ==================================================
0211:     // Programmable shader
0212:     // ==================================================
0213:     cg.AddFilePath("..");
0214:     pCg = cg.CreateContextContainer(lpD3DDev);
0215: 
0216:     // ==================================================
0217:     // Vertex Shader
0218:     pVs = pCg->LoadCGProgramFromFile(
0219:         "sumie.vsh", "Sumie Vertex Shader", cgDX8VertexProfile, vertex_attributes);
0220:     
0221:    if (NULL == pVs) {
0222:         // ERROR
0223:         const char * listing = pCg->GetLastListing();
0224:         if (listing == 0) listing = "Could not find cgc.exe.";
0225:         cg.NotePad("Failed to Create Vertex Program\n\n", listing);    // Output error
0226:         exit(1);    // END
0227:     }
0228:   
0229:     const_texcoord0 = pVs->GetParameterBindByName("const_texcoord0");
0230:     const_texcoord1 = pVs->GetParameterBindByName("const_texcoord1");
0231:     const_texcoord2 = pVs->GetParameterBindByName("const_texcoord2");
0232:     const_texcoord3 = pVs->GetParameterBindByName("const_texcoord3");
0233: 
0234:     float const inv_w = 1.0f / (float)WIDTH;
0235:     float const inv_h = 1.0f / (float)HEIGHT;
0236:     pVs->SetShaderConstant( const_texcoord0, &D3DXVECTOR2  (( 0.0f    +0.5f)*inv_w, ( 0.0f+0.5f)*inv_h)  );
0237:     pVs->SetShaderConstant( const_texcoord1, &D3DXVECTOR2  (( 0.0f    +0.5f)*inv_w, (-1.0f+0.5f)*inv_h)  );
0238:     pVs->SetShaderConstant( const_texcoord2, &D3DXVECTOR2  ((-0.57735f+0.5f)*inv_w, ( 0.5f+0.5f)*inv_h)  );
0239:     pVs->SetShaderConstant( const_texcoord3, &D3DXVECTOR2  ((+0.57735f+0.5f)*inv_w, ( 0.5f+0.5f)*inv_h)  );
0240: 
0241:     // ==================================================
0242:     // Pixel Shader
0243:     pPs = pCg->LoadCGProgramFromFile( "sumie.psh", "Sumie Pixel Shader", cgDX8PixelProfile);
0244:     
0245:     if (NULL == pPs) {
0246:         // ERROR
0247:         const char * error_text = pCg->GetLastListing();
0248:         cg.NotePad("Failed to Create Pixel Program\n\n", error_text);    // Output error
0249: 
0250:         exit(1);    // END
0251:     }
0252:  
0253:     tex0_iter = pPs->GetTextureBindByName("tex0");
0254:     tex1_iter = pPs->GetTextureBindByName("tex1");
0255:     tex2_iter = pPs->GetTextureBindByName("tex2");
0256:     tex3_iter = pPs->GetTextureBindByName("tex3");
0257: 
0258:     // ==================================================
0259:     // Surface
0260:     // ==================================================
0261:     D3DSURFACE_DESC Desc;
0262:     LPDIRECT3DSURFACE8 lpZbuffer = NULL;
0263:     if( FAILED(hr = lpD3DDev->GetRenderTarget(&pBackbuffer))) return hr;
0264:     if( FAILED(hr = pBackbuffer->GetDesc( &Desc ))) return hr;
0265: 
0266:     if( FAILED(hr = lpD3DDev->GetDepthStencilSurface( &lpZbuffer ))) return hr;
0267:     
0268:     for( i=0 ; i<2 ; i++ ){
0269:         if( FAILED(hr = lpD3DDev->CreateTexture(Desc.Width, Desc.Height, 1
0270:                                 , D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pRenderTexture[i]))) return hr;
0271:         if( FAILED(hr = pRenderTexture[i]->GetSurfaceLevel(0,&pRenderSurface[i]))) return hr;
0272:         if( FAILED(hr = lpD3DDev->SetRenderTarget(pRenderSurface[i], lpZbuffer ))) return hr;
0273:     }
0274: 
0275:     lpD3DDev->SetRenderTarget(pBackbuffer, lpZbuffer );
0276:     
0277:     return S_OK;
0278: }
0279: // ----------------------------------------------------------------------------
0280: // Rendering
0281: // ----------------------------------------------------------------------------
0282: void RenderSumie(LPDIRECT3DDEVICE8 lpD3DDev, int id)
0283: {
0284:     pVs->SetShaderActive();
0285:     pPs->SetShaderActive();
0286:     pPs->SetTexture(tex0_iter, pRenderTexture[id]);
0287:     pPs->SetTexture(tex1_iter, pRenderTexture[id]);
0288:     pPs->SetTexture(tex2_iter, pRenderTexture[id]);
0289:     pPs->SetTexture(tex3_iter, pRenderTexture[id]);
0290:     lpD3DDev->SetStreamSource( 0, pSumieVB, sizeof(D3D_SUMIE_VERTEX) );
0291:     lpD3DDev->SetIndices(pSumieIB,0);
0292:     lpD3DDev->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 4, 0, 2 );
0293: }
0294: 
0295: // ----------------------------------------------------------------------------
0296: // ----------------------------------------------------------------------------
0297: // Final rendering
0298: // ----------------------------------------------------------------------------
0299: // ----------------------------------------------------------------------------
0300: 
0301: // ----------------------------------------------------------------------------
0302: // Initialize
0303: HRESULT InitFinal(LPDIRECT3DDEVICE8 lpD3DDev)
0304: {
0305:     HRESULT hr = S_OK;
0306: 
0307:     // Create vertex buffer
0308:     D3D_SUMIE_VERTEX vertices[] = {
0309:         //  x,      y,    z,   rhw,  tu  tv
0310:         {  0.0f,   0.0f, 0.5f, 1.0f, 0.0f,0.0f,},
0311:         { WIDTH,   0.0f, 0.5f, 1.0f, 1.0f,0.0f,},
0312:         {  0.0f, HEIGHT, 0.5f, 1.0f, 0.0f,1.0f,},
0313:         { WIDTH, HEIGHT, 0.5f, 1.0f, 1.0f,1.0f,},
0314:     };
0315:     
0316:     hr = lpD3DDev->CreateVertexBuffer( 4*sizeof(D3D_SUMIE_VERTEX),0,
0317:                     D3DFVF_DROP_VERTEX, D3DPOOL_DEFAULT, &pFinalVB);
0318:     if(FAILED(hr)) return hr;
0319: 
0320:     VOID* pVertices;
0321:     hr = pFinalVB->Lock( 0, sizeof(vertices), (BYTE**)&pVertices, 0);
0322:     if(FAILED(hr)) return hr;
0323:     memcpy( pVertices, vertices, sizeof(vertices) );
0324:     pFinalVB->Unlock();
0325: 
0326:     return hr;
0327: }
0328: // ----------------------------------------------------------------------------
0329: // Rendering
0330: void RenderFinal(LPDIRECT3DDEVICE8 lpD3DDev)
0331: {
0332:     lpD3DDev->SetStreamSource( 0, pFinalVB, sizeof(D3D_SUMIE_VERTEX) );
0333:     lpD3DDev->SetVertexShader( D3DFVF_DROP_VERTEX );
0334:     lpD3DDev->SetPixelShader(NULL); 
0335:     lpD3DDev->DrawPrimitive(  D3DPT_TRIANGLESTRIP, 0, 2 );
0336: }
0337: 
0338: 
0339: 
0340: //-----------------------------------------------------------------------------
0341: // Name: Initialize and setup some rendering states
0342: //-----------------------------------------------------------------------------
0343: HRESULT InitRender(LPDIRECT3DDEVICE8 lpD3DDev)
0344: {
0345:     HRESULT hr = S_OK;
0346:     int i;
0347: 
0348:     if ( FAILED(hr = InitDrop(lpD3DDev)))return hr;
0349: 
0350:     // レンダリングテクスチャー用の初期化
0351:     if ( FAILED(hr = InitRenderTexture(lpD3DDev)))return hr;
0352: 
0353:     // 最終描画頂点バッファの初期化
0354:     if ( FAILED(hr = InitFinal(lpD3DDev)))return hr;
0355: 
0356:     // 不変なレジスタの設定
0357:     lpD3DDev->SetRenderState( D3DRS_ZENABLE, TRUE );
0358:     lpD3DDev->SetRenderState( D3DRS_LIGHTING,  FALSE );
0359:     for (i = 0; i < 4; ++i) {
0360:         lpD3DDev->SetTextureStageState(i, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
0361:         lpD3DDev->SetTextureStageState(i, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
0362:         lpD3DDev->SetTextureStageState(i, D3DTSS_MIPFILTER, D3DTEXF_NONE);
0363:         lpD3DDev->SetTextureStageState(i, D3DTSS_ADDRESSU,  D3DTADDRESS_CLAMP);
0364:         lpD3DDev->SetTextureStageState(i, D3DTSS_ADDRESSV,  D3DTADDRESS_CLAMP);
0365:         lpD3DDev->SetTextureStageState(i, D3DTSS_COLOROP,   D3DTOP_SELECTARG1);
0366:         lpD3DDev->SetTextureStageState(i, D3DTSS_COLORARG1, D3DTA_TEXTURE);
0367:     }
0368: 
0369:     return hr;
0370: }
0371: 
0372: //-----------------------------------------------------------------------------
0373: // Name: Render()
0374: // Desc: Draws the scene
0375: //-----------------------------------------------------------------------------
0376: VOID Render(LPDIRECT3DDEVICE8 lpD3DDev)
0377: {
0378:     static DWORD id = 0;
0379:     id = 1-id;
0380: 
0381:     LPDIRECT3DSURFACE8 lpZbuffer = NULL;
0382:     lpD3DDev->GetDepthStencilSurface( &lpZbuffer );
0383:     lpD3DDev->SetRenderTarget(pRenderSurface[id], lpZbuffer);
0384: 
0385:     RenderSumie(lpD3DDev, 1-id);
0386:     RenderDrop(lpD3DDev);
0387: 
0388:     static int first = 2;
0389:     if(0<first){
0390:         first--;
0391:         lpD3DDev->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA(255,255,255,255),1.0f,0);
0392:     }
0393: 
0394:     lpD3DDev->SetRenderTarget(pBackbuffer, lpZbuffer );
0395:     lpD3DDev->SetTexture( 0, pRenderTexture[id]);
0396:     lpD3DDev->SetTexture( 1, NULL);
0397:     lpD3DDev->SetTexture( 2, NULL);
0398:     lpD3DDev->SetTexture( 3, NULL);
0399:     RenderFinal(lpD3DDev);
0400: }
0401: //-----------------------------------------------------------------------------
0402: // Name: CleanRender()
0403: //-----------------------------------------------------------------------------
0404: void CleanRender(LPDIRECT3DDEVICE8 lpD3DDev)
0405: {
0406:     DWORD i;
0407:     
0408:     for( i=0 ; i<2 ; i++ ){
0409:         RELEASE(pRenderSurface[i]);
0410:         RELEASE(pRenderTexture[i]);
0411:     }
0412:     RELEASE(pBackbuffer);
0413:     
0414:     RELEASE(pFinalVB);
0415:     RELEASE(pDropVB);
0416:     RELEASE(pDropTexture);
0417: }
0418: