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 >
Wrap
C/C++ Source or Header
|
2004-11-08
|
10KB
|
367 lines
#include "main.h"
STENCIL StencilShadow;
//------------------------------------------------------------------
// Name: STENCIL()
// Desc: konstruktor
//------------------------------------------------------------------
STENCIL::STENCIL()
{
SquareVB = NULL;
NumVertices = 0;
LightPosition = Get3D( 100.0f,100.0f,100.0f);
}
//------------------------------------------------------------------
// Name: ~STENCIL()
// Desc: destruktor
//------------------------------------------------------------------
STENCIL::~STENCIL()
{
if (SquareVB != NULL)
SquareVB->Release();
}
//------------------------------------------------------------------
// Name: Initialize()
// Desc: inicializacia
//------------------------------------------------------------------
void STENCIL::Initialize()
{
//ak nieje zapnuty stencil prec
if (Engine.StencilShadows == false)
return;
LogPrint("Inicializuje Stencil");
//////////////
//Big Square//
//////////////
if (FAILED(g_pd3dDevice->CreateVertexBuffer( 4*sizeof(CUSTOMVERTEXSTENCILSQUARE ),
D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEXSTENCILSQUARE ,
D3DPOOL_DEFAULT, &SquareVB, NULL )))
{
LogPrint(" Chyba pri vytvarani VB");
}
else
{
LogPrint(" Vertex Buffer vytvoreny");
}
CUSTOMVERTEXSTENCILSQUARE *v;
SquareVB->Lock( 0, 0, (void**)&v, 0 );
{
v[0].p = D3DXVECTOR4( 0, (float)Engine.Height, 0.0f, 1.0f );
v[1].p = D3DXVECTOR4( 0, 0, 0.0f, 1.0f );
v[2].p = D3DXVECTOR4( (float)Engine.Width, (float)Engine.Height, 0.0f, 1.0f );
v[3].p = D3DXVECTOR4( (float)Engine.Width, 0.0f, 0.0f, 1.0f );
v[0].color = 0x60000000;
v[1].color = 0x60000000;
v[2].color = 0x60000000;
v[3].color = 0x60000000;
}
SquareVB->Unlock();
}
//------------------------------------------------------------------
// Name: AddEdge()
// Desc: prida quad od hrany
//------------------------------------------------------------------
void STENCIL::AddEdge(VECTOR3D V1,VECTOR3D V2)
{
//ak nieje zapnuty stencil prec
if (Engine.StencilShadows == false)
return;
Edge[NumEdges].V1 = V1;
Edge[NumEdges].V2 = V2;
NumEdges++;
}
//------------------------------------------------------------------
// Name: ProcessEdge()
// Desc: z hrany urobi quad
//------------------------------------------------------------------
void STENCIL::AddQuad(VECTOR3D V1,VECTOR3D V2,VECTOR3D LightPos)
{
//ak nieje zapnuty stencil prec
if (Engine.StencilShadows == false)
return;
VECTOR3D Sme1,Sme2;
Sub(&Sme1,V1,LightPos);
Sub(&Sme2,V2,LightPos);
VECTOR3D E0 ;
VECTOR3D E1 ;
VECTOR3D E2 ;
VECTOR3D E3 ;
E0.X = V1.X ;
E0.Y = V1.Y ;
E0.Z = V1.Z ;
E1.X = V2.X ;
E1.Y = V2.Y ;
E1.Z = V2.Z ;
E2.X = V1.X + Sme1.X*100.0f;
E2.Y = V1.Y + Sme1.Y*100.0f;
E2.Z = V1.Z + Sme1.Z*100.0f;
E3.X = V2.X + Sme2.X*100.0f;
E3.Y = V2.Y + Sme2.Y*100.0f;
E3.Z = V2.Z + Sme2.Z*100.0f;
/////
//1//
/////
Vertices[NumVertices].x = E0.X;
Vertices[NumVertices].y = E0.Y;
Vertices[NumVertices].z = E0.Z;
NumVertices++;
Vertices[NumVertices].x = E1.X;
Vertices[NumVertices].y = E1.Y;
Vertices[NumVertices].z = E1.Z;
NumVertices++;
Vertices[NumVertices].x = E2.X;
Vertices[NumVertices].y = E2.Y;
Vertices[NumVertices].z = E2.Z;
NumVertices++;
/////
//2//
/////
Vertices[NumVertices].x = E2.X;
Vertices[NumVertices].y = E2.Y;
Vertices[NumVertices].z = E2.Z;
NumVertices++;
Vertices[NumVertices].x = E1.X;
Vertices[NumVertices].y = E1.Y;
Vertices[NumVertices].z = E1.Z;
NumVertices++;
Vertices[NumVertices].x = E3.X;
Vertices[NumVertices].y = E3.Y;
Vertices[NumVertices].z = E3.Z;
NumVertices++;
}
//------------------------------------------------------------------
// Name: ProcessEdge()
// Desc: Vyberie iba hrany ktore s nikim nesusedia
//------------------------------------------------------------------
void STENCIL::ProcessEdge(VECTOR3D LightPos)
{
//ak nieje zapnuty stencil prec
if (Engine.StencilShadows == false)
return;
int NumIdent = 0,i,u;
for (i=0;i<NumEdges;i++)
{
NumIdent = 0;
for (u=0;u<NumEdges;u++)
{
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) &&
(Edge[u].V2.X == Edge[i].V2.X && Edge[u].V2.Y == Edge[i].V2.Y && Edge[u].V2.Z == Edge[i].V2.Z) )||
( (Edge[u].V1.X == Edge[i].V2.X && Edge[u].V1.Y == Edge[i].V2.Y && Edge[u].V1.Z == Edge[i].V2.Z) &&
(Edge[u].V2.X == Edge[i].V1.X && Edge[u].V2.Y == Edge[i].V1.Y && Edge[u].V2.Z == Edge[i].V1.Z) ))
{
NumIdent++;
}
}
if (NumIdent == 1)
{
AddQuad(Edge[i].V1,Edge[i].V2,LightPos);
}
}
}
//------------------------------------------------------------------
// Name: RenderShadowQuads()
// Desc: vyrenderuje quady
//------------------------------------------------------------------
void STENCIL::RenderShadowQuads()
{
//ak nieje zapnuty stencil prec
if (Engine.StencilShadows == false)
return;
g_pd3dDevice->SetFVF( D3DFVF_XYZ );
g_pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLELIST, NumVertices/3,
Vertices, sizeof(D3DXVECTOR3) );
}
//------------------------------------------------------------------
// Name: RenderShadow()
// Desc: vyrenderuje hotovy tien
//------------------------------------------------------------------
void STENCIL::RenderShadow()
{
//ak nieje zapnuty stencil prec
if (Engine.StencilShadows == false)
return;
RenderShadowBuffer();
RenderShadowScreen();
//reset
NumVertices = 0;
NumEdges = 0;
}
//------------------------------------------------------------------
// Name: RenderShadowBuffer()
// Desc: vyrenderuje tien do stencil bufferu
//------------------------------------------------------------------
void STENCIL::RenderShadowBuffer()
{
//ak nieje zapnuty stencil prec
if (Engine.StencilShadows == false)
return;
// Disable z-buffer writes (note: z-testing still occurs), and enable the
// stencil-buffer
g_pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE, FALSE );
g_pd3dDevice->SetRenderState( D3DRS_STENCILENABLE, TRUE );
// Dont bother with interpolating color
g_pd3dDevice->SetRenderState( D3DRS_SHADEMODE, D3DSHADE_FLAT );
// Set up stencil compare fuction, reference value, and masks.
// Stencil test passes if ((ref & mask) cmpfn (stencil & mask)) is true.
// Note: since we set up the stencil-test to always pass, the STENCILFAIL
// renderstate is really not needed.
g_pd3dDevice->SetRenderState( D3DRS_STENCILFUNC, D3DCMP_ALWAYS );
g_pd3dDevice->SetRenderState( D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP ); //ak je stencil test false
g_pd3dDevice->SetRenderState( D3DRS_STENCILPASS, D3DSTENCILOP_KEEP ); //ak je stencil test a ztest true
// If z-test passes, inc/decrement stencil buffer value
g_pd3dDevice->SetRenderState( D3DRS_STENCILREF, 0x0 );
g_pd3dDevice->SetRenderState( D3DRS_STENCILMASK, 0xffffffff );
g_pd3dDevice->SetRenderState( D3DRS_STENCILWRITEMASK, 0xffffffff );
// Make sure that no pixels get drawn to the frame buffer
g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ZERO );
g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
Engine.SetZBuffer(true);
///////////////////
//increment Front//
///////////////////
//increment
//ak nieje pixel vidiet - zfail (ztest = false), pricitaj jednotu
g_pd3dDevice->SetRenderState( D3DRS_STENCILZFAIL, D3DSTENCILOP_INCR );
//fron culling
g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW );
// Draw front-side of shadow volume in stencil/z only
RenderShadowQuads();
//////////////////
//decrement Back//
//////////////////
// Decrement stencil buffer value
// ak nieje pixel vidiet - zfail (ztest = false), odcitaj jednotu
g_pd3dDevice->SetRenderState( D3DRS_STENCILZFAIL, D3DSTENCILOP_DECR );
// Now reverse cull order so back sides of shadow volume are written.
g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW);
// Draw back-side of shadow volume in stencil/z only
RenderShadowQuads();
//reset
Engine.ResetToDefault();
Engine.SetBlendNone();
}
//------------------------------------------------------------------
// Name: RenderShadowScreen()
// Desc: vyrenderuje tien (stencil buffer) na obrazovku
//------------------------------------------------------------------
void STENCIL::RenderShadowScreen()
{
//ak nieje zapnuty stencil prec
if (Engine.StencilShadows == false)
return;
// Set render states
g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE );
g_pd3dDevice->SetRenderState( D3DRS_STENCILENABLE, TRUE );
g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
// Only write where stencil value >= 1 (count indicates # of shadows that
// overlap that pixel)
g_pd3dDevice->SetRenderState( D3DRS_STENCILREF, 0x1 );
g_pd3dDevice->SetRenderState( D3DRS_STENCILFUNC, D3DCMP_LESSEQUAL );
g_pd3dDevice->SetRenderState( D3DRS_STENCILPASS, D3DSTENCILOP_KEEP );
// Draw a big, gray square
g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEXSTENCILSQUARE );
g_pd3dDevice->SetStreamSource( 0, SquareVB, 0, sizeof(CUSTOMVERTEXSTENCILSQUARE) );
g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );
// Restore render states
Engine.ResetToDefault();
Engine.SetBlendNone();
}