#include "stdafx.h" #include "KViewport.h" #include "KPrimitiveSpeedTree.h" #include "KSeqSpeedTree.h" #include #include "SSpeedTreeConfig.h" #include "SSpeedTreeVertexShaders.h" #include "KRenderDeviceDX.h" #include namespace { const DWORD SPEEDTREE_BRANCHALPHATEST=0; const DWORD SPEEDTREE_FRONDALPHATEST=96; const DWORD SPEEDTREE_LEAFALPHATEST=64; const DWORD SPEEDTREE_BILLBOARDALPHATEST=32; bool SPEEDTREEPRIMITIVE_TRANSPARENTRENDERMODE=false; } SSpeedTreePrimitive::SSpeedTreePrimitive() : m_nSubCount(0), m_nTexCount(0), m_nTexActiveCount(0), m_ppVB(NULL), m_ppIB(NULL), m_ppTex(NULL), m_ppMtl(NULL), m_nRenderState(0) { m_type = KPRIMITIVE_SSPEEDTREE; m_registerTable = 0; m_cntTable = 0; m_pTable = NULL; m_bIsValid = true; m_registerVecConstant = 0; m_cntVecConstant = 0; m_pvecConstant = NULL; m_registerUsefulConstants = 0; m_cntUsefulConstants = 0; m_pafUsefulConstants = NULL; m_registerMaterial = 0; m_cntMaterial = 0; m_pafMaterial = NULL; m_pGeometryCache = NULL; m_pSpeedTree = NULL; m_nType = -1; m_pBranchIndexCounts = NULL; m_pFrondIndexCounts = NULL; m_bLeavesUpdatedByCpu = false; } SSpeedTreePrimitive::~SSpeedTreePrimitive() { Clear(); } void SSpeedTreePrimitive::Clear() { SAFE_DELETE_ARRAY( m_ppVB ); SAFE_DELETE_ARRAY( m_ppIB ); SAFE_DELETE_ARRAY( m_ppTex ); SAFE_DELETE_ARRAY( m_ppMtl ); } void SSpeedTreePrimitive::SetSubMeshCount( int count ) { if( count == 0 ) { // _oprint( "SpeedTree Mesh Count Invalid!!!\n" ); return; } Clear(); m_ppIB = new K3DIndexBuffer*[count]; memset( m_ppIB, 0, sizeof(K3DIndexBuffer*)*count ); m_ppVB = new K3DVertexBuffer*[count]; m_ppMtl = new K3DMaterial*[count]; for( int i(0); count>i; i++ ) { m_ppVB[i] = NULL; m_ppMtl[i] = NULL; } m_nSubCount = count; } void SSpeedTreePrimitive::SetTextureCount( int count ) { m_ppTex = new K3DTexture*[count]; m_nTexCount = count; } namespace { void SetShaderConstants(K3DRenderDevice *dev, const float* pMaterial, float leaflightingadj, float opacity=1.0f) { // // Lighting direction에 의해 감소되는 광량이 leaflightingadj이하로 내려가지 않게 vertex shader에서 계산함 // const float afUsefulConstants[] = { leaflightingadj, 0.0f, 0.0f, 0.0f }; dev->SetVertexShaderConstant(c_nVertexShader_LeafLightingAdjustment, afUsefulConstants, 1); // // Vertex color rgba // const float afMaterial[] = { //Modulate 2X // pMaterial[0]/2.f, pMaterial[1]/2.f, pMaterial[2]/2.f, opacity, // 1.0f, // pMaterial[3]/2.f, pMaterial[4]/2.f, pMaterial[5]/2.f, opacity // 1.0f pMaterial[0], pMaterial[1], pMaterial[2], opacity, // 1.0f, pMaterial[3], pMaterial[4], pMaterial[5], opacity // 1.0f }; //m_prBranch.SetShaderMaterial( c_nVertexShader_Material, m_afMaterial, 2 ); //m_prFrond.SetShaderMaterial ( c_nVertexShader_Material, m_afMaterial, 2 ); //m_prLeaf.SetShaderMaterial ( c_nVertexShader_Material, m_afMaterial, 2 ); dev->SetVertexShaderConstant(c_nVertexShader_Material, afMaterial, 2); // Vertex shader에 직접 넘김 } }; void SSpeedTreePrimitive::setTransparentRenderMode(bool bTransparent) { SPEEDTREEPRIMITIVE_TRANSPARENTRENDERMODE=bTransparent; } bool SSpeedTreePrimitive::getTransparentRenderMode() { return SPEEDTREEPRIMITIVE_TRANSPARENTRENDERMODE; } void SSpeedTreePrimitive::Render( KViewportObject *viewport, class K3DRenderDevice *dev, bool bUseAccum ) { if( m_nType == -1 ) return; if(!IsValid()) return; //if( m_ppVB[0] == NULL ) return; //if( m_nType != TREE_BILLBOARD && ( m_ppVB[0] == NULL )) return; // ?? K3DMatrix world; K3DMatrixIdentity( world ); K3DMatrixMultiply( world, *m_pTransform, m_RootMat ); K3DVector posvec; K3DMatrixGetPosVector( posvec, world ); K3DMatrixIdentity( world ); world.SetPosVector( posvec ); dev->SetTransform( K3DRenderDevice::TS_WORLD, &world ); D3DXVECTOR4 vecConstant = D3DXVECTOR4( posvec.x, posvec.y, posvec.z, 0.0f); SetShaderVecConstant( c_nVertexShader_TreePos, ( float* ) &vecConstant, 1 ); if( m_pvecConstant ) dev->SetVertexShaderConstant( m_registerVecConstant , m_pvecConstant , m_cntVecConstant ); //dev->SetVertexShaderConstant( c_nVertexShader_TreePos, ( float* ) &vecConstant, 1 ); /*if( m_pafUsefulConstants ) dev->SetVertexShaderConstant( m_registerUsefulConstants, m_pafUsefulConstants, m_cntUsefulConstants ); if( m_pafMaterial ) dev->SetVertexShaderConstant( m_registerMaterial , m_pafMaterial , m_cntMaterial );*/ if( m_pTable && m_nType == TREE_LEAF ) dev->SetVertexShaderConstant( m_registerTable , m_pTable , m_cntTable ); // // 바람 효과 계산 (Vertex shader사용 안할 경우만) // if( m_nType == TREE_BRANCH ) { #ifdef WRAPPER_USE_CPU_WIND // ?? m_pSpeedTree->GetGeometry(*m_pGeometryCache, SpeedTree_BranchGeometry); if (m_pGeometryCache->m_sBranches.m_usNumStrips > 0) { // update the vertex array SFVFBranchVertex* pVertexBuffer = NULL; int nVtxSize = 0; m_ppVB[0]->Lock( reinterpret_cast(&pVertexBuffer), nVtxSize ); assert(pVertexBuffer && "m_ppVB[0]->Lock( reinterpret_cast(&pVertexBuffer), nVtxSize );"); for (unsigned int i = 0; i < m_unVertexCount; ++i) { memcpy(&(pVertexBuffer[i].m_vPosition), &(m_pGeometryCache->m_sBranches.m_pCoords[i * 3]), sizeof(pVertexBuffer[i].m_vPosition)); } m_ppVB[0]->Unlock( ); } #endif } else if( m_nType == TREE_FROND ) { #ifdef WRAPPER_USE_CPU_WIND // update the frond geometry for CPU wind m_pSpeedTree->GetGeometry(*m_pGeometryCache, SpeedTree_FrondGeometry); if (m_pGeometryCache->m_sFronds.m_usNumStrips > 0) { // update the vertex array SFVFBranchVertex* pVertexBuffer = NULL; int nVtxSize = 0; m_ppVB[0]->Lock(reinterpret_cast(&pVertexBuffer), nVtxSize); assert(pVertexBuffer && "m_ppVB[0]->Lock(reinterpret_cast(&pVertexBuffer), nVtxSize);"); for (unsigned int i = 0; i < m_unVertexCount; ++i) { memcpy(&(pVertexBuffer[i].m_vPosition), &(m_pGeometryCache->m_sFronds.m_pCoords[i * 3]), sizeof(pVertexBuffer[i].m_vPosition)); } m_ppVB[0]->Unlock( ); } #endif } else if( m_nType == TREE_LEAF ) { #ifdef WRAPPER_USE_GPU_LEAF_PLACEMENT m_pSpeedTree->GetGeometry(*m_pGeometryCache, SpeedTree_LeafGeometry, -1, -1, 0); #endif m_pSpeedTree->GetGeometry(*m_pGeometryCache, SpeedTree_LeafGeometry); // update the LOD level vertex arrays we need #if defined(WRAPPER_USE_GPU_LEAF_PLACEMENT) && defined(WRAPPER_USE_GPU_WIND) // do nothing #else #if !defined WRAPPER_USE_NO_WIND || defined WRAPPER_USE_CPU_LEAF_PLACEMENT // might need to draw 2 LOD's for (unsigned int i = 0; i < 2; ++i) { // reference to leaves structure const CSpeedTreeRT::SGeometry::SLeaf* pLeaf = (i == 0) ? &m_pGeometryCache->m_sLeaves0 : &m_pGeometryCache->m_sLeaves1; int unLod = pLeaf->m_nDiscreteLodLevel; #if defined WRAPPER_USE_GPU_LEAF_PLACEMENT //if (pLeaf->m_bIsActive && !m_bLeavesUpdatedByCpu) if (pLeaf->m_bIsActive && pLeaf->m_usLeafCount > 0 && !m_bLeavesUpdatedByCpu) { // update the centers SFVFLeafVertex* pVertex = NULL; int nVtxSize = 0; // ?? m_ppVB[unLod]->Lock(reinterpret_cast(&pVertex), nVtxSize); assert(pVertex && "m_ppVB[unLod]->Lock(reinterpret_cast(&pVertex), nVtxSize);"); for (unsigned int unLeaf = 0; unLeaf < pLeaf->m_usLeafCount; ++unLeaf) { D3DXVECTOR3 vecCenter(&(pLeaf->m_pCenterCoords[unLeaf * 3])); (pVertex++)->m_vPosition = vecCenter; // vertex 0 (pVertex++)->m_vPosition = vecCenter; // vertex 1 (pVertex++)->m_vPosition = vecCenter; // vertex 2 (pVertex++)->m_vPosition = vecCenter; // vertex 0 (pVertex++)->m_vPosition = vecCenter; // vertex 2 (pVertex++)->m_vPosition = vecCenter; // vertex 3 } m_ppVB[unLod]->Unlock( ); m_bLeavesUpdatedByCpu = true; } #else //if (pLeaf->m_bIsActive) if (pLeaf->m_bIsActive && pLeaf->m_usLeafCount > 0) { // update the vertices SFVFLeafVertex* pVertex = NULL; int nVtxSize = 0; m_ppVB[unLod]->Lock(reinterpret_cast(&pVertex),nVtxSize); assert(pVertex && "m_ppVB[unLod]->Lock(reinterpret_cast(&pVertex),nVtxSize);"); for (unsigned int unLeaf = 0; unLeaf < pLeaf->m_usLeafCount; ++unLeaf) { D3DXVECTOR3 vecCenter(&(pLeaf->m_pCenterCoords[unLeaf * 3])); D3DXVECTOR3 vec0(&pLeaf->m_pLeafMapCoords[unLeaf][0]); D3DXVECTOR3 vec1(&pLeaf->m_pLeafMapCoords[unLeaf][4]); D3DXVECTOR3 vec2(&pLeaf->m_pLeafMapCoords[unLeaf][8]); D3DXVECTOR3 vec3(&pLeaf->m_pLeafMapCoords[unLeaf][12]); (pVertex++)->m_vPosition = vecCenter + vec0; // vertex 0 (pVertex++)->m_vPosition = vecCenter + vec1; // vertex 1 (pVertex++)->m_vPosition = vecCenter + vec2; // vertex 2 (pVertex++)->m_vPosition = vecCenter + vec0; // vertex 0 (pVertex++)->m_vPosition = vecCenter + vec2; // vertex 2 (pVertex++)->m_vPosition = vecCenter + vec3; // vertex 3 } m_ppVB[unLod]->Unlock( ); } #endif // #if defined WRAPPER_USE_GPU_LEAF_PLACEMENT } #endif // #if !defined WRAPPER_USE_NO_WIND || defined WRAPPER_USE_CPU_LEAF_PLACEMENT #endif // #if defined(WRAPPER_USE_GPU_LEAF_PLACEMENT) && defined(WRAPPER_USE_GPU_WIND) } else if(m_nType == TREE_BILLBOARD) { //m_pSpeedTree->GetGeometry(*m_pGeometryCache, SpeedTree_BillboardGeometry); } // // 텍스처 설정 / fog설정 // Note : vertex 돌아가는 방향 설정 (CW/CCW)이 caller가 아니라 여기 어디쯤 있어야 맞는게 아닐까? (flag로 연속 XOR?) // for ( int j=0 ; jSetTexture( j, m_ppTex[j] ); float fFogStart, fFogEnd; ((K3DRenderDeviceDX*) dev)->GetD3DDevice()->GetRenderState(D3DRS_FOGSTART, (DWORD*)&fFogStart); ((K3DRenderDeviceDX*) dev)->GetD3DDevice()->GetRenderState(D3DRS_FOGEND, (DWORD*)&fFogEnd); // // 폴리곤 draw // for ( int j=0 ; jSetTransparency( m_fVisibility ); //dev->SetMaterial( m_ppMtl[0] ); //CSpeedTreeMaterial mtl; //mtl.Set(m_pSpeedTree->GetBranchMaterial()); //dev->SetMaterial( mtl.m_cMaterial ); } if( m_nType == TREE_BRANCH && m_ppIB[0] != NULL ) { m_pSpeedTree->GetGeometry(*m_pGeometryCache, SpeedTree_BranchGeometry); // ?? if (m_pGeometryCache->m_fBranchAlphaTestValue > 0.0f) { if (m_pBranchIndexCounts && m_pGeometryCache->m_sBranches.m_nDiscreteLodLevel > -1 && m_pBranchIndexCounts[m_pGeometryCache->m_sBranches.m_nDiscreteLodLevel] > 0) { const K3DLight * pLight = viewport->GetLight(m_nLightIndex); CSpeedTreeMaterial mtl; mtl.Set(m_pSpeedTree->GetBranchMaterial()); //mtl.SetLight( pLight ); dev->SetMaterial( mtl.GetMaterial() ); SetShaderConstants(dev, m_pSpeedTree->GetBranchMaterial(), m_pSpeedTree->GetLeafLightingAdjustment(), m_fVisibility); #ifndef _RAC //TOOL dev->SetAlpharef(0x00000000/*DWORD(m_pGeometryCache->m_fBranchAlphaTestValue)*/); // ?? #else if (SPEEDTREEPRIMITIVE_TRANSPARENTRENDERMODE) dev->SetAlpharef(SPEEDTREE_BRANCHALPHATEST); else dev->SetAlpharef(SPEEDTREE_BRANCHALPHATEST/*DWORD(m_pGeometryCache->m_fBranchAlphaTestValue)*/); #endif //나무 몸통 그리는곳 문제가 생길것 같아서 수정 //vb, ib 0번만 적용 하게 수정 //폴리곤이 생성될때 1개씩만 만들어 진다. //2009-12-23 : hunee dev->DrawIndexedTriangleStripVB( m_ppVB[0], m_ppIB[0], m_pGeometryCache->m_sBranches.m_usVertexCount, m_pBranchIndexCounts[m_pGeometryCache->m_sBranches.m_nDiscreteLodLevel] - 2 ); } } } else if( m_nType == TREE_FROND && m_ppIB[0] != NULL ) { m_pSpeedTree->GetGeometry(*m_pGeometryCache, SpeedTree_FrondGeometry); // ?? if (m_pGeometryCache->m_fFrondAlphaTestValue > 0.0f) { if (m_pFrondIndexCounts && m_pGeometryCache->m_sFronds.m_nDiscreteLodLevel > -1 && m_pFrondIndexCounts[m_pGeometryCache->m_sFronds.m_nDiscreteLodLevel] > 0) { const K3DLight * pLight = viewport->GetLight(m_nLightIndex); CSpeedTreeMaterial mtl; mtl.Set(m_pSpeedTree->GetFrondMaterial()); //mtl.SetLight( pLight ); dev->SetMaterial( mtl.GetMaterial() ); SetShaderConstants(dev, m_pSpeedTree->GetFrondMaterial(), m_pSpeedTree->GetLeafLightingAdjustment(), m_fVisibility); #ifndef _RAC //TOOL dev->SetAlpharef( 0x00000000/*DWORD(m_pGeometryCache->m_fFrondAlphaTestValue)*/ ); #else if (SPEEDTREEPRIMITIVE_TRANSPARENTRENDERMODE) dev->SetAlpharef(SPEEDTREE_FRONDALPHATEST); else dev->SetAlpharef( DWORD(m_pGeometryCache->m_fFrondAlphaTestValue) ); #endif //dev->DrawIndexedTriangleStripVB( m_ppVB[j], m_ppIB[j], m_pGeometryCache->m_sFronds.m_usVertexCount, m_pFrondIndexCounts[m_pGeometryCache->m_sFronds.m_nDiscreteLodLevel] - 2 ); dev->DrawIndexedTriangleStripVB( m_ppVB[0], m_ppIB[m_pGeometryCache->m_sFronds.m_nDiscreteLodLevel], m_pGeometryCache->m_sFronds.m_usVertexCount, m_pFrondIndexCounts[m_pGeometryCache->m_sFronds.m_nDiscreteLodLevel] - 2 ); } } } else if( m_nType == TREE_LEAF ) { // might need to draw 2 LOD's for (unsigned int unLeafLevel = 0; unLeafLevel < 2; ++unLeafLevel) { const CSpeedTreeRT::SGeometry::SLeaf* pLeaf = (unLeafLevel == 0) ? &m_pGeometryCache->m_sLeaves0 : pLeaf = &m_pGeometryCache->m_sLeaves1; // int unLod = pLeaf->m_nDiscreteLodLevel; // if this LOD is active and has leaves, draw it if (unLod > -1 && pLeaf->m_bIsActive && pLeaf->m_usLeafCount > 0) { const K3DLight * pLight = viewport->GetLight(m_nLightIndex); CSpeedTreeMaterial mtl; mtl.Set(m_pSpeedTree->GetLeafMaterial()); //mtl.SetLight( pLight ); dev->SetMaterial( mtl.GetMaterial() ); //dev->SetRenderState( K3DRenderDevice::RS_SPEED_TREE ); //dev->SetCullMode( K3DRenderDevice::KCM_CCW ); #ifndef _RAC //TOOL SetShaderConstants(dev, m_pSpeedTree->GetLeafMaterial(), m_pSpeedTree->GetLeafLightingAdjustment()); dev->SetAlpharef( DWORD(pLeaf->m_fAlphaTestValue) ); #else if (SPEEDTREEPRIMITIVE_TRANSPARENTRENDERMODE) { SetShaderConstants(dev, m_pSpeedTree->GetLeafMaterial(), m_pSpeedTree->GetLeafLightingAdjustment(), m_fVisibility); dev->SetAlpharef(SPEEDTREE_LEAFALPHATEST); } else { SetShaderConstants(dev, m_pSpeedTree->GetLeafMaterial(), m_pSpeedTree->GetLeafLightingAdjustment()); dev->SetAlpharef( DWORD(pLeaf->m_fAlphaTestValue) ); } #endif //dev->DrawTriangleVB( m_ppVB[unLod], pLeaf->m_usLeafCount * 2 ); dev->DrawTriangleVB( m_ppVB[unLod], pLeaf->m_usLeafCount * 6 ); } } m_bLeavesUpdatedByCpu = false; return; // <- 여기 왜 있는것일까?? } else if( m_nType == TREE_BILLBOARD ) { //if (m_pGeometryCache->m_fBranchAlphaTestValue > 0.0f) { //if (m_pBranchIndexCounts && m_pGeometryCache->m_sBranches.m_nDiscreteLodLevel > -1 && m_pBranchIndexCounts[m_pGeometryCache->m_sBranches.m_nDiscreteLodLevel] > 0) { //CSpeedTreeMaterial mtl; //memset(&mtl, 0, sizeof(mtl)); // ?? //mtl.Set(m_pSpeedTree->GetBranchMaterial()); //dev->SetMaterial( mtl.GetMaterial() ); //SetShaderConstants(dev, m_pSpeedTree->GetBranchMaterial(), m_pSpeedTree->GetLeafLightingAdjustment()); //dev->SetAlpharef( 0/*DWORD(m_pGeometryCache->m_fBranchAlphaTestValue)*/ ); //dev->DrawIndexedTriangleStripVB( m_ppVB[j], m_ppIB[j], m_pGeometryCache->m_sBranches.m_usVertexCount, m_pBranchIndexCounts[m_pGeometryCache->m_sBranches.m_nDiscreteLodLevel] - 2 ); // draw billboards in immediate mode (as close as directx gets to immediate mode) //#ifdef WRAPPER_BILLBOARD_MODE //PositionTree( ); // sonador #2.1.7.1 스피드 트리 퍼포먼스 증가 struct SBillboardVertex { float fX, fY, fZ; float fNX, fNY, fNZ; //DWORD color; float fU, fV; }; m_pSpeedTree->GetGeometry(*m_pGeometryCache, SpeedTree_BillboardGeometry); //dev->SetCullMode(K3DRenderDevice::KCM_CCW); //dev->SetCullMode(K3DRenderDevice::KCM_CW); //dev->SetCullMode(K3DRenderDevice::KCM_NONE); //dev->EnableLightEffect(true); const K3DLight * pLight = viewport->GetLight(m_nLightIndex); // ?? -> CSpeedTreeMaterial mtl; mtl.Set(m_pSpeedTree->GetLeafMaterial()); //mtl.SetLight(pLight); dev->SetMaterial( mtl.GetMaterial() ); SetShaderConstants(dev, m_pSpeedTree->GetLeafMaterial(), m_pSpeedTree->GetLeafLightingAdjustment()); // <- ?? // ?? -> //IDirect3DDevice9* pD3dDev = ((K3DRenderDeviceDX*) dev)->GetD3DDevice(); //pD3dDev->SetRenderState(D3DRS_FOGENABLE, FALSE); //float f = fFogEnd/3.0f; //pD3dDev->SetRenderState(D3DRS_FOGSTART, *(DWORD*)(&f)); // <- ?? if (m_pGeometryCache->m_sBillboard0.m_bIsActive) { const float* pCoords = m_pGeometryCache->m_sBillboard0.m_pCoords; const float* pTexCoords = m_pGeometryCache->m_sBillboard0.m_pTexCoords; K3DVector view = -pLight->direction; SBillboardVertex sVertex[4] = { { pCoords[0], pCoords[1], pCoords[2], /*0xffffffff*/view.x, view.y, view.z, pTexCoords[2], pTexCoords[3] }, { pCoords[3], pCoords[4], pCoords[5], /*0xffffffff*/view.x, view.y, view.z, pTexCoords[0], pTexCoords[1] }, { pCoords[6], pCoords[7], pCoords[8], /*0xffffffff*/view.x, view.y, view.z, pTexCoords[6], pTexCoords[7] }, { pCoords[9], pCoords[10], pCoords[11], /*0xffffffff*/view.x, view.y, view.z, pTexCoords[4], pTexCoords[5] }, /*{ pCoords[0], pCoords[1], pCoords[2], 0xffffff, pTexCoords[0], pTexCoords[1] }, { pCoords[3], pCoords[4], pCoords[5], 0xffffff, pTexCoords[2], pTexCoords[3] }, { pCoords[6], pCoords[7], pCoords[8], 0xffffff, pTexCoords[4], pTexCoords[5] }, { pCoords[9], pCoords[10], pCoords[11], 0xffffff, pTexCoords[6], pTexCoords[7] }, { pCoords[0], pCoords[1], pCoords[2], pTexCoords[0], pTexCoords[1] }, { pCoords[3], pCoords[4], pCoords[5], pTexCoords[2], pTexCoords[3] }, { pCoords[6], pCoords[7], pCoords[8], pTexCoords[4], pTexCoords[5] }, { pCoords[9], pCoords[10], pCoords[11], pTexCoords[6], pTexCoords[7] }, */ }; //m_pDx->SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1); //m_pDx->SetRenderState(D3DRS_ALPHAREF, DWORD(m_pGeometryCache->m_sBillboard0.m_fAlphaTestValue)); //m_pDx->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, sVertex, sizeof(SBillboardVertex)); #ifndef _RAC //TOOL dev->SetAlpharef(DWORD(m_pGeometryCache->m_sBillboard0.m_fAlphaTestValue)); #else if (SPEEDTREEPRIMITIVE_TRANSPARENTRENDERMODE) dev->SetAlpharef(SPEEDTREE_BILLBOARDALPHATEST); else dev->SetAlpharef(DWORD(m_pGeometryCache->m_sBillboard0.m_fAlphaTestValue)); #endif dev->DrawTriangleFan(D3DFVF_SPEEDTREE_BILLBOARD_VERTEX, sVertex, 4, sizeof(SBillboardVertex)); //dev->DrawTriangleFan(D3DFVF_XYZ | D3DFVF_TEX1, sVertex, 4, sizeof(SBillboardVertex)); //dev->DrawTriangleFan(D3DFVF_XYZ, sVertex, 4, sizeof(SBillboardVertex)); } // if there is a 360 degree billboard, then we need to draw the second one if (m_pGeometryCache->m_sBillboard1.m_bIsActive) { const float* pCoords = m_pGeometryCache->m_sBillboard1.m_pCoords; const float* pTexCoords = m_pGeometryCache->m_sBillboard1.m_pTexCoords; K3DVector view = -pLight->direction; SBillboardVertex sVertex[4] = { { pCoords[0], pCoords[1], pCoords[2], /*0xffffffff*/view.x, view.y, view.z, pTexCoords[2], pTexCoords[3] }, { pCoords[3], pCoords[4], pCoords[5], /*0xffffffff*/view.x, view.y, view.z, pTexCoords[0], pTexCoords[1] }, { pCoords[6], pCoords[7], pCoords[8], /*0xffffffff*/view.x, view.y, view.z, pTexCoords[6], pTexCoords[7] }, { pCoords[9], pCoords[10], pCoords[11], /*0xffffffff*/view.x, view.y, view.z, pTexCoords[4], pTexCoords[5] }, /* { pCoords[0], pCoords[1], pCoords[2], pTexCoords[0], pTexCoords[1] }, { pCoords[3], pCoords[4], pCoords[5], pTexCoords[2], pTexCoords[3] }, { pCoords[6], pCoords[7], pCoords[8], pTexCoords[4], pTexCoords[5] }, { pCoords[9], pCoords[10], pCoords[11], pTexCoords[6], pTexCoords[7] }, */ }; //m_pDx->SetRenderState(D3DRS_ALPHAREF, DWORD(m_pGeometryCache->m_sBillboard1.m_fAlphaTestValue)); //m_pDx->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, sVertex, sizeof(SBillboardVertex)); #ifndef _RAC //TOOL dev->SetAlpharef(DWORD(m_pGeometryCache->m_sBillboard1.m_fAlphaTestValue)); #else if (SPEEDTREEPRIMITIVE_TRANSPARENTRENDERMODE) dev->SetAlpharef(SPEEDTREE_BILLBOARDALPHATEST); else dev->SetAlpharef(DWORD(m_pGeometryCache->m_sBillboard1.m_fAlphaTestValue)); #endif dev->DrawTriangleFan(D3DFVF_SPEEDTREE_BILLBOARD_VERTEX, sVertex, 4, sizeof(SBillboardVertex)); //dev->DrawTriangleFan(D3DFVF_XYZ | D3DFVF_TEX1, sVertex, 4, sizeof(SBillboardVertex)); //dev->DrawTriangleFan(D3DFVF_XYZ, sVertex, 4, sizeof(SBillboardVertex)); } // if we have a horizontal bilboard and it is enabled, draw it too #ifdef WRAPPER_RENDER_HORIZONTAL_BILLBOARD if (m_pGeometryCache->m_sHorizontalBillboard.m_bIsActive) { const float* pCoords = m_pGeometryCache->m_sHorizontalBillboard.m_pCoords; const float* pTexCoords = m_pGeometryCache->m_sHorizontalBillboard.m_pTexCoords; SBillboardVertex sVertex[4] = { { pCoords[0], pCoords[1], pCoords[2], 0xffffffff, pTexCoords[0], pTexCoords[1] }, { pCoords[3], pCoords[4], pCoords[5], 0xffffffff, pTexCoords[2], pTexCoords[3] }, { pCoords[6], pCoords[7], pCoords[8], 0xffffffff, pTexCoords[4], pTexCoords[5] }, { pCoords[9], pCoords[10], pCoords[11], 0xffffffff, pTexCoords[6], pTexCoords[7] }, /* { pCoords[0], pCoords[1], pCoords[2], pTexCoords[0], pTexCoords[1] }, { pCoords[3], pCoords[4], pCoords[5], pTexCoords[2], pTexCoords[3] }, { pCoords[6], pCoords[7], pCoords[8], pTexCoords[4], pTexCoords[5] }, { pCoords[9], pCoords[10], pCoords[11], pTexCoords[6], pTexCoords[7] }, */ }; //m_pDx->SetRenderState(D3DRS_ALPHAREF, DWORD(m_pGeometryCache->m_sHorizontalBillboard.m_fAlphaTestValue)); //m_pDx->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, sVertex, sizeof(SBillboardVertex)); #ifndef _RAC //TOOL dev->SetAlpharef(DWORD(m_pGeometryCache->m_sHorizontalBillboard.m_fAlphaTestValue)); #else if (SPEEDTREEPRIMITIVE_TRANSPARENTRENDERMODE) dev->SetAlpharef(SPEEDTREE_BILLBOARDALPHATEST); else dev->SetAlpharef(DWORD(m_pGeometryCache->m_sHorizontalBillboard.m_fAlphaTestValue)); #endif dev->DrawTriangleFan(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1, sVertex, 4, sizeof(SBillboardVertex)); //dev->DrawTriangleFan(D3DFVF_XYZ | D3DFVF_TEX1, sVertex, 4, sizeof(SBillboardVertex)); //dev->DrawTriangleFan(D3DFVF_XYZ, sVertex, 4, sizeof(SBillboardVertex)); } #endif //#endif } } } ((K3DRenderDeviceDX*) dev)->GetD3DDevice()->SetRenderState(D3DRS_FOGSTART, *((DWORD*)&fFogStart)); } for ( int j=0 ; jSetTexture( j, NULL ); }