home *** CD-ROM | disk | FTP | other *** search
/ PC World 2006 July & August / PCWorld_2006-07-08_cd.bin / temacd / planearcade / planearcade.exe / Tank3.bmp / stencil.cpp < prev    next >
C/C++ Source or Header  |  2004-11-08  |  10KB  |  367 lines

  1.  
  2. #include "main.h"
  3.  
  4. STENCIL StencilShadow;
  5.  
  6. //------------------------------------------------------------------
  7. // Name: STENCIL()
  8. // Desc: konstruktor
  9. //------------------------------------------------------------------
  10. STENCIL::STENCIL()
  11. {
  12.     SquareVB = NULL;
  13.  
  14.     NumVertices = 0;
  15.  
  16.     LightPosition = Get3D( 100.0f,100.0f,100.0f);
  17.  
  18. }
  19.  
  20. //------------------------------------------------------------------
  21. // Name: ~STENCIL()
  22. // Desc: destruktor
  23. //------------------------------------------------------------------
  24. STENCIL::~STENCIL()
  25. {
  26.  
  27.     if (SquareVB != NULL)
  28.         SquareVB->Release();
  29.  
  30. }
  31.  
  32.  
  33. //------------------------------------------------------------------
  34. // Name: Initialize()
  35. // Desc: inicializacia 
  36. //------------------------------------------------------------------
  37. void STENCIL::Initialize()
  38. {
  39.     //ak nieje zapnuty stencil prec
  40.     if (Engine.StencilShadows == false)
  41.         return;
  42.     
  43.     LogPrint("Inicializuje Stencil");
  44.  
  45.     //////////////
  46.     //Big Square//
  47.     //////////////
  48.     if (FAILED(g_pd3dDevice->CreateVertexBuffer( 4*sizeof(CUSTOMVERTEXSTENCILSQUARE ),
  49.                                       D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEXSTENCILSQUARE ,
  50.                                       D3DPOOL_DEFAULT, &SquareVB, NULL )))
  51.     {
  52.         LogPrint(" Chyba pri vytvarani VB");
  53.     }
  54.     else
  55.     {
  56.         LogPrint(" Vertex Buffer vytvoreny");
  57.     }
  58.  
  59.  
  60.     CUSTOMVERTEXSTENCILSQUARE *v;
  61.  
  62.     SquareVB->Lock( 0, 0, (void**)&v, 0 );
  63.     {
  64.         v[0].p = D3DXVECTOR4(  0, (float)Engine.Height, 0.0f, 1.0f );
  65.         v[1].p = D3DXVECTOR4(  0, 0, 0.0f, 1.0f );
  66.         v[2].p = D3DXVECTOR4( (float)Engine.Width, (float)Engine.Height, 0.0f, 1.0f );
  67.         v[3].p = D3DXVECTOR4( (float)Engine.Width, 0.0f, 0.0f, 1.0f );
  68.         v[0].color = 0x60000000;
  69.         v[1].color = 0x60000000;
  70.         v[2].color = 0x60000000;
  71.         v[3].color = 0x60000000;
  72.     }
  73.     SquareVB->Unlock();
  74.  
  75.  
  76. }
  77.  
  78.  
  79. //------------------------------------------------------------------
  80. // Name: AddEdge()
  81. // Desc: prida quad od hrany
  82. //------------------------------------------------------------------
  83. void STENCIL::AddEdge(VECTOR3D V1,VECTOR3D V2)
  84. {
  85.     //ak nieje zapnuty stencil prec
  86.     if (Engine.StencilShadows == false)
  87.         return;
  88.  
  89.  
  90.     Edge[NumEdges].V1 = V1;
  91.     Edge[NumEdges].V2 = V2;
  92.     NumEdges++;
  93.  
  94. }
  95.  
  96. //------------------------------------------------------------------
  97. // Name: ProcessEdge()
  98. // Desc: z hrany urobi quad
  99. //------------------------------------------------------------------
  100. void STENCIL::AddQuad(VECTOR3D V1,VECTOR3D V2,VECTOR3D LightPos)
  101. {
  102.  
  103.     //ak nieje zapnuty stencil prec
  104.     if (Engine.StencilShadows == false)
  105.         return;
  106.  
  107.  
  108.     VECTOR3D Sme1,Sme2;
  109.     Sub(&Sme1,V1,LightPos);
  110.     Sub(&Sme2,V2,LightPos);
  111.  
  112.     VECTOR3D E0 ;
  113.     VECTOR3D E1 ;
  114.     VECTOR3D E2 ;
  115.     VECTOR3D E3 ;
  116.  
  117.     E0.X = V1.X ;
  118.     E0.Y = V1.Y ;
  119.     E0.Z = V1.Z ;
  120.  
  121.     E1.X = V2.X ;
  122.     E1.Y = V2.Y ;
  123.     E1.Z = V2.Z ;
  124.  
  125.     E2.X = V1.X + Sme1.X*100.0f;
  126.     E2.Y = V1.Y + Sme1.Y*100.0f;
  127.     E2.Z = V1.Z + Sme1.Z*100.0f;
  128.  
  129.     E3.X = V2.X + Sme2.X*100.0f;
  130.     E3.Y = V2.Y + Sme2.Y*100.0f;
  131.     E3.Z = V2.Z + Sme2.Z*100.0f;
  132.  
  133.     /////
  134.     //1//
  135.     /////
  136.     Vertices[NumVertices].x = E0.X;
  137.     Vertices[NumVertices].y = E0.Y;
  138.     Vertices[NumVertices].z = E0.Z;
  139.     NumVertices++;
  140.  
  141.     Vertices[NumVertices].x = E1.X;
  142.     Vertices[NumVertices].y = E1.Y;
  143.     Vertices[NumVertices].z = E1.Z;
  144.     NumVertices++;
  145.  
  146.     Vertices[NumVertices].x = E2.X;
  147.     Vertices[NumVertices].y = E2.Y;
  148.     Vertices[NumVertices].z = E2.Z;
  149.     NumVertices++;
  150.  
  151.     /////
  152.     //2//
  153.     /////
  154.     Vertices[NumVertices].x = E2.X;
  155.     Vertices[NumVertices].y = E2.Y;
  156.     Vertices[NumVertices].z = E2.Z;
  157.     NumVertices++;
  158.  
  159.     Vertices[NumVertices].x = E1.X;
  160.     Vertices[NumVertices].y = E1.Y;
  161.     Vertices[NumVertices].z = E1.Z;
  162.     NumVertices++;
  163.  
  164.     Vertices[NumVertices].x = E3.X;
  165.     Vertices[NumVertices].y = E3.Y;
  166.     Vertices[NumVertices].z = E3.Z;
  167.     NumVertices++;
  168.  
  169. }
  170.  
  171. //------------------------------------------------------------------
  172. // Name: ProcessEdge()
  173. // Desc: Vyberie iba hrany ktore s nikim nesusedia
  174. //------------------------------------------------------------------
  175. void STENCIL::ProcessEdge(VECTOR3D LightPos)
  176. {
  177.  
  178.     //ak nieje zapnuty stencil prec
  179.     if (Engine.StencilShadows == false)
  180.         return;
  181.  
  182.     int NumIdent = 0,i,u;
  183.  
  184.     for    (i=0;i<NumEdges;i++)
  185.     {
  186.         NumIdent = 0;
  187.  
  188.         for (u=0;u<NumEdges;u++)
  189.         {
  190.              if(( (Edge[u].V1.X == Edge[i].V1.X && Edge[u].V1.Y == Edge[i].V1.Y && Edge[u].V1.Z == Edge[i].V1.Z)  &&
  191.                  (Edge[u].V2.X == Edge[i].V2.X && Edge[u].V2.Y == Edge[i].V2.Y && Edge[u].V2.Z == Edge[i].V2.Z) )||
  192.                ( (Edge[u].V1.X == Edge[i].V2.X && Edge[u].V1.Y == Edge[i].V2.Y && Edge[u].V1.Z == Edge[i].V2.Z)  &&
  193.                  (Edge[u].V2.X == Edge[i].V1.X && Edge[u].V2.Y == Edge[i].V1.Y && Edge[u].V2.Z == Edge[i].V1.Z) ))
  194.             {
  195.                 NumIdent++;
  196.             }
  197.         }
  198.  
  199.         if (NumIdent == 1)
  200.         {
  201.             AddQuad(Edge[i].V1,Edge[i].V2,LightPos);
  202.         }
  203.  
  204.  
  205.     }
  206.  
  207. }
  208.  
  209. //------------------------------------------------------------------
  210. // Name: RenderShadowQuads()
  211. // Desc: vyrenderuje quady
  212. //------------------------------------------------------------------
  213. void STENCIL::RenderShadowQuads()
  214. {
  215.  
  216.     //ak nieje zapnuty stencil prec
  217.     if (Engine.StencilShadows == false)
  218.         return;
  219.  
  220.     g_pd3dDevice->SetFVF( D3DFVF_XYZ );
  221.     g_pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLELIST, NumVertices/3,
  222.                                  Vertices, sizeof(D3DXVECTOR3) );
  223.  
  224.  
  225. }
  226.  
  227. //------------------------------------------------------------------
  228. // Name: RenderShadow()
  229. // Desc: vyrenderuje hotovy tien
  230. //------------------------------------------------------------------
  231. void STENCIL::RenderShadow()
  232. {
  233.  
  234.     //ak nieje zapnuty stencil prec
  235.     if (Engine.StencilShadows == false)
  236.         return;
  237.  
  238.     RenderShadowBuffer();
  239.     RenderShadowScreen();
  240.  
  241.     //reset
  242.     NumVertices = 0;
  243.     NumEdges = 0;
  244.  
  245. }
  246.  
  247. //------------------------------------------------------------------
  248. // Name: RenderShadowBuffer()
  249. // Desc: vyrenderuje tien do stencil bufferu
  250. //------------------------------------------------------------------
  251. void STENCIL::RenderShadowBuffer()
  252. {
  253.  
  254.     //ak nieje zapnuty stencil prec
  255.     if (Engine.StencilShadows == false)
  256.         return;
  257.  
  258.     // Disable z-buffer writes (note: z-testing still occurs), and enable the
  259.     // stencil-buffer
  260.     g_pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE,  FALSE );
  261.     g_pd3dDevice->SetRenderState( D3DRS_STENCILENABLE, TRUE );
  262.  
  263.     // Dont bother with interpolating color
  264.     g_pd3dDevice->SetRenderState( D3DRS_SHADEMODE, D3DSHADE_FLAT );
  265.  
  266.     // Set up stencil compare fuction, reference value, and masks.
  267.     // Stencil test passes if ((ref & mask) cmpfn (stencil & mask)) is true.
  268.     // Note: since we set up the stencil-test to always pass, the STENCILFAIL
  269.     // renderstate is really not needed.
  270.  
  271.     g_pd3dDevice->SetRenderState( D3DRS_STENCILFUNC,  D3DCMP_ALWAYS );
  272.     g_pd3dDevice->SetRenderState( D3DRS_STENCILFAIL,  D3DSTENCILOP_KEEP );  //ak je stencil test false
  273.     g_pd3dDevice->SetRenderState( D3DRS_STENCILPASS,  D3DSTENCILOP_KEEP );  //ak je stencil test a ztest true
  274.  
  275.     // If z-test passes, inc/decrement stencil buffer value
  276.     g_pd3dDevice->SetRenderState( D3DRS_STENCILREF,       0x0 );
  277.     g_pd3dDevice->SetRenderState( D3DRS_STENCILMASK,      0xffffffff );
  278.     g_pd3dDevice->SetRenderState( D3DRS_STENCILWRITEMASK, 0xffffffff );
  279.     
  280.     // Make sure that no pixels get drawn to the frame buffer
  281.     g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
  282.     g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND,  D3DBLEND_ZERO );
  283.     g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
  284.     
  285.     
  286.     Engine.SetZBuffer(true);
  287.  
  288.         ///////////////////
  289.         //increment Front//
  290.         ///////////////////
  291.  
  292.         //increment
  293.         //ak nieje pixel vidiet - zfail (ztest = false), pricitaj jednotu
  294.         g_pd3dDevice->SetRenderState( D3DRS_STENCILZFAIL, D3DSTENCILOP_INCR );
  295.  
  296.         //fron culling
  297.         g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW );
  298.  
  299.         // Draw front-side of shadow volume in stencil/z only
  300.         RenderShadowQuads();
  301.         
  302.  
  303.         //////////////////
  304.         //decrement Back//
  305.         //////////////////
  306.  
  307.         // Decrement stencil buffer value
  308.         // ak nieje pixel vidiet - zfail (ztest = false), odcitaj jednotu
  309.         g_pd3dDevice->SetRenderState( D3DRS_STENCILZFAIL, D3DSTENCILOP_DECR );
  310.  
  311.         // Now reverse cull order so back sides of shadow volume are written.
  312.         g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW);
  313.  
  314.         // Draw back-side of shadow volume in stencil/z only
  315.         RenderShadowQuads();
  316.  
  317.  
  318.     //reset
  319.     Engine.ResetToDefault();
  320.     Engine.SetBlendNone();
  321.  
  322. }
  323.  
  324. //------------------------------------------------------------------
  325. // Name: RenderShadowScreen()
  326. // Desc: vyrenderuje tien (stencil buffer) na obrazovku
  327. //------------------------------------------------------------------
  328. void STENCIL::RenderShadowScreen()
  329. {
  330.     //ak nieje zapnuty stencil prec
  331.     if (Engine.StencilShadows == false)
  332.         return;
  333.  
  334.     // Set render states
  335.     g_pd3dDevice->SetRenderState( D3DRS_ZENABLE,          FALSE );
  336.     g_pd3dDevice->SetRenderState( D3DRS_STENCILENABLE,    TRUE );
  337.     g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
  338.     g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA );
  339.     g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
  340.  
  341.     g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  342.     g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
  343.     g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );
  344.     g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
  345.     g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
  346.     g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_MODULATE );
  347.  
  348.     // Only write where stencil value >= 1 (count indicates # of shadows that
  349.     // overlap that pixel)
  350.     g_pd3dDevice->SetRenderState( D3DRS_STENCILREF,  0x1 );
  351.     g_pd3dDevice->SetRenderState( D3DRS_STENCILFUNC, D3DCMP_LESSEQUAL );
  352.     g_pd3dDevice->SetRenderState( D3DRS_STENCILPASS, D3DSTENCILOP_KEEP );
  353.  
  354.     // Draw a big, gray square
  355.     g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEXSTENCILSQUARE );
  356.     g_pd3dDevice->SetStreamSource( 0, SquareVB, 0, sizeof(CUSTOMVERTEXSTENCILSQUARE) );
  357.     g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );
  358.  
  359.     // Restore render states
  360.     Engine.ResetToDefault();
  361.     Engine.SetBlendNone();
  362.  
  363. }
  364.  
  365.  
  366.  
  367.