345 lines
11 KiB
C++
345 lines
11 KiB
C++
|
///////////////////////////////////////////////////////////////////////
|
|||
|
// CSpeedTreeForestDirectX8 Class
|
|||
|
//
|
|||
|
// (c) 2003 IDV, Inc.
|
|||
|
//
|
|||
|
// This class is provided to illustrate one way to incorporate
|
|||
|
// SpeedTreeRT into an OpenGL application. All of the SpeedTreeRT
|
|||
|
// calls that must be made on a per tree basis are done by this class.
|
|||
|
// Calls that apply to all trees (i.e. static SpeedTreeRT functions)
|
|||
|
// are made in the functions in main.cpp.
|
|||
|
//
|
|||
|
//
|
|||
|
// *** INTERACTIVE DATA VISUALIZATION (IDV) PROPRIETARY INFORMATION ***
|
|||
|
//
|
|||
|
// This software is supplied under the terms of a license agreement or
|
|||
|
// nondisclosure agreement with Interactive Data Visualization and may
|
|||
|
// not be copied or disclosed except in accordance with the terms of
|
|||
|
// that agreement.
|
|||
|
//
|
|||
|
// Copyright (c) 2001-2003 IDV, Inc.
|
|||
|
// All Rights Reserved.
|
|||
|
//
|
|||
|
// IDV, Inc.
|
|||
|
// 1233 Washington St. Suite 610
|
|||
|
// Columbia, SC 29201
|
|||
|
// Voice: (803) 799-1699
|
|||
|
// Fax: (803) 931-0320
|
|||
|
// Web: http://www.idvinc.com
|
|||
|
|
|||
|
#include "StdAfx.h"
|
|||
|
|
|||
|
#include <stdio.h>
|
|||
|
#include <d3d8.h>
|
|||
|
#include <d3d8types.h>
|
|||
|
#include <d3dx8.h>
|
|||
|
|
|||
|
#include "../eterBase/Timer.h"
|
|||
|
#include "../eterlib/StateManager.h"
|
|||
|
#include "../eterlib/Camera.h"
|
|||
|
|
|||
|
#include "SpeedTreeForestDirectX8.h"
|
|||
|
#include "SpeedTreeConfig.h"
|
|||
|
#include "VertexShaders.h"
|
|||
|
|
|||
|
///////////////////////////////////////////////////////////////////////
|
|||
|
// CSpeedTreeForestDirectX8::CSpeedTreeForestDirectX8
|
|||
|
|
|||
|
CSpeedTreeForestDirectX8::CSpeedTreeForestDirectX8() : m_dwBranchVertexShader(0), m_dwLeafVertexShader(0)
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
///////////////////////////////////////////////////////////////////////
|
|||
|
// CSpeedTreeForestDirectX8::~CSpeedTreeForestDirectX8
|
|||
|
|
|||
|
CSpeedTreeForestDirectX8::~CSpeedTreeForestDirectX8()
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
///////////////////////////////////////////////////////////////////////
|
|||
|
// CSpeedTreeForestDirectX8::InitVertexShaders
|
|||
|
bool CSpeedTreeForestDirectX8::InitVertexShaders(void)
|
|||
|
{
|
|||
|
NANOBEGIN
|
|||
|
// load the vertex shaders
|
|||
|
if (!m_dwBranchVertexShader)
|
|||
|
m_dwBranchVertexShader = LoadBranchShader(m_pDx);
|
|||
|
|
|||
|
if (!m_dwLeafVertexShader)
|
|||
|
m_dwLeafVertexShader = LoadLeafShader(m_pDx);
|
|||
|
|
|||
|
if (m_dwBranchVertexShader && m_dwLeafVertexShader)
|
|||
|
{
|
|||
|
CSpeedTreeWrapper::SetVertexShaders(m_dwBranchVertexShader, m_dwLeafVertexShader);
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
NANOEND
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
bool CSpeedTreeForestDirectX8::SetRenderingDevice(LPDIRECT3DDEVICE8 lpDevice)
|
|||
|
{
|
|||
|
m_pDx = lpDevice;
|
|||
|
|
|||
|
if (!InitVertexShaders())
|
|||
|
return false;
|
|||
|
|
|||
|
const float c_afLightPosition[4] = { -0.707f, -0.300f, 0.707f, 0.0f };
|
|||
|
const float c_afLightAmbient[4] = { 0.5f, 0.5f, 0.5f, 1.0f };
|
|||
|
const float c_afLightDiffuse[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
|||
|
const float c_afLightSpecular[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
|||
|
|
|||
|
float afLight1[] =
|
|||
|
{
|
|||
|
c_afLightPosition[0], c_afLightPosition[1], c_afLightPosition[2], // pos
|
|||
|
c_afLightDiffuse[0], c_afLightDiffuse[1], c_afLightDiffuse[2], // diffuse
|
|||
|
c_afLightAmbient[0], c_afLightAmbient[1], c_afLightAmbient[2], // ambient
|
|||
|
c_afLightSpecular[0], c_afLightSpecular[1], c_afLightSpecular[2], // specular
|
|||
|
c_afLightPosition[3], // directional flag
|
|||
|
1.0f, 0.0f, 0.0f // attenuation (constant, linear, quadratic)
|
|||
|
};
|
|||
|
|
|||
|
CSpeedTreeRT::SetNumWindMatrices(c_nNumWindMatrices);
|
|||
|
|
|||
|
CSpeedTreeRT::SetLightAttributes(0, afLight1);
|
|||
|
CSpeedTreeRT::SetLightState(0, true);
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
///////////////////////////////////////////////////////////////////////
|
|||
|
// CSpeedTreeForestDirectX8::UploadWindMatrix
|
|||
|
|
|||
|
void CSpeedTreeForestDirectX8::UploadWindMatrix(UINT uiLocation, const float* pMatrix) const
|
|||
|
{
|
|||
|
STATEMANAGER.SetVertexShaderConstant(uiLocation, pMatrix, 4);
|
|||
|
}
|
|||
|
|
|||
|
void CSpeedTreeForestDirectX8::UpdateCompundMatrix(const D3DXVECTOR3 & c_rEyeVec, const D3DXMATRIX & c_rmatView, const D3DXMATRIX & c_rmatProj)
|
|||
|
{
|
|||
|
// setup composite matrix for shader
|
|||
|
D3DXMATRIX matBlend;
|
|||
|
D3DXMatrixIdentity(&matBlend);
|
|||
|
|
|||
|
D3DXMATRIX matBlendShader;
|
|||
|
D3DXMatrixMultiply(&matBlendShader, &c_rmatView, &c_rmatProj);
|
|||
|
|
|||
|
float afDirection[3];
|
|||
|
afDirection[0] = matBlendShader.m[0][2];
|
|||
|
afDirection[1] = matBlendShader.m[1][2];
|
|||
|
afDirection[2] = matBlendShader.m[2][2];
|
|||
|
CSpeedTreeRT::SetCamera(c_rEyeVec, afDirection);
|
|||
|
|
|||
|
D3DXMatrixTranspose(&matBlendShader, &matBlendShader);
|
|||
|
STATEMANAGER.SetVertexShaderConstant(c_nVertexShader_CompoundMatrix, &matBlendShader, 4);
|
|||
|
}
|
|||
|
|
|||
|
///////////////////////////////////////////////////////////////////////
|
|||
|
// CSpeedTreeForestDirectX8::Render
|
|||
|
|
|||
|
void CSpeedTreeForestDirectX8::Render(unsigned long ulRenderBitVector)
|
|||
|
{
|
|||
|
UpdateSystem(CTimer::Instance().GetCurrentSecond());
|
|||
|
|
|||
|
if (m_pMainTreeMap.empty())
|
|||
|
return;
|
|||
|
|
|||
|
if (!(ulRenderBitVector & Forest_RenderToShadow) && !(ulRenderBitVector & Forest_RenderToMiniMap))
|
|||
|
UpdateCompundMatrix(CCameraManager::Instance().GetCurrentCamera()->GetEye(), ms_matView, ms_matProj);
|
|||
|
|
|||
|
DWORD dwLightState = STATEMANAGER.GetRenderState(D3DRS_LIGHTING);
|
|||
|
DWORD dwColorVertexState = STATEMANAGER.GetRenderState(D3DRS_COLORVERTEX);
|
|||
|
DWORD dwFogVertexMode = STATEMANAGER.GetRenderState(D3DRS_FOGVERTEXMODE);
|
|||
|
|
|||
|
#ifdef WRAPPER_USE_DYNAMIC_LIGHTING
|
|||
|
STATEMANAGER.SetRenderState(D3DRS_LIGHTING, TRUE);
|
|||
|
#else
|
|||
|
STATEMANAGER.SetRenderState(D3DRS_LIGHTING, FALSE);
|
|||
|
STATEMANAGER.SetRenderState(D3DRS_COLORVERTEX, TRUE);
|
|||
|
#endif
|
|||
|
|
|||
|
TTreeMap::iterator itor;
|
|||
|
UINT uiCount;
|
|||
|
|
|||
|
itor = m_pMainTreeMap.begin();
|
|||
|
|
|||
|
while (itor != m_pMainTreeMap.end())
|
|||
|
{
|
|||
|
CSpeedTreeWrapper * pMainTree = (itor++)->second;
|
|||
|
CSpeedTreeWrapper ** ppInstances = pMainTree->GetInstances(uiCount);
|
|||
|
|
|||
|
for (UINT i = 0; i < uiCount; ++i)
|
|||
|
{
|
|||
|
ppInstances[i]->Advance();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
STATEMANAGER.SetVertexShaderConstant(c_nVertexShader_Light, m_afLighting, 3);
|
|||
|
STATEMANAGER.SetVertexShaderConstant(c_nVertexShader_Fog, m_afFog, 1);
|
|||
|
|
|||
|
if (ulRenderBitVector & Forest_RenderToShadow)
|
|||
|
{
|
|||
|
//STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
|||
|
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
|
|||
|
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
|
|||
|
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
|||
|
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
|
|||
|
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
|||
|
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
|
|||
|
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
|
|||
|
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
|
|||
|
STATEMANAGER.SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
|
|||
|
STATEMANAGER.SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
|
|||
|
STATEMANAGER.SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
|
|||
|
|
|||
|
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
|||
|
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
|
|||
|
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
|||
|
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
|
|||
|
STATEMANAGER.SetTextureStageState(1, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
|
|||
|
STATEMANAGER.SetTextureStageState(1, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
|
|||
|
}
|
|||
|
|
|||
|
STATEMANAGER.SaveRenderState(D3DRS_ALPHATESTENABLE, TRUE);
|
|||
|
STATEMANAGER.SaveRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);
|
|||
|
STATEMANAGER.SaveRenderState(D3DRS_CULLMODE, D3DCULL_CW);
|
|||
|
|
|||
|
// set up fog if it is enabled
|
|||
|
if (STATEMANAGER.GetRenderState(D3DRS_FOGENABLE))
|
|||
|
{
|
|||
|
#ifdef WRAPPER_USE_GPU_WIND
|
|||
|
STATEMANAGER.SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_NONE); // GPU needs to work on all cards
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
// choose fixed function pipeline or custom shader for fronds and branches
|
|||
|
STATEMANAGER.SetVertexShader(m_dwBranchVertexShader);
|
|||
|
|
|||
|
// render branches
|
|||
|
if (ulRenderBitVector & Forest_RenderBranches)
|
|||
|
{
|
|||
|
itor = m_pMainTreeMap.begin();
|
|||
|
|
|||
|
while (itor != m_pMainTreeMap.end())
|
|||
|
{
|
|||
|
CSpeedTreeWrapper * pMainTree = (itor++)->second;
|
|||
|
CSpeedTreeWrapper ** ppInstances = pMainTree->GetInstances(uiCount);
|
|||
|
|
|||
|
pMainTree->SetupBranchForTreeType();
|
|||
|
|
|||
|
for (UINT i = 0; i < uiCount; ++i)
|
|||
|
if (ppInstances[i]->isShow())
|
|||
|
ppInstances[i]->RenderBranches();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// set render states
|
|||
|
STATEMANAGER.SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
|||
|
|
|||
|
// render fronds
|
|||
|
if (ulRenderBitVector & Forest_RenderFronds)
|
|||
|
{
|
|||
|
itor = m_pMainTreeMap.begin();
|
|||
|
|
|||
|
while (itor != m_pMainTreeMap.end())
|
|||
|
{
|
|||
|
CSpeedTreeWrapper * pMainTree = (itor++)->second;
|
|||
|
CSpeedTreeWrapper ** ppInstances = pMainTree->GetInstances(uiCount);
|
|||
|
|
|||
|
pMainTree->SetupFrondForTreeType();
|
|||
|
|
|||
|
for (UINT i = 0; i < uiCount; ++i)
|
|||
|
if (ppInstances[i]->isShow())
|
|||
|
ppInstances[i]->RenderFronds();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// render leaves
|
|||
|
if (ulRenderBitVector & Forest_RenderLeaves)
|
|||
|
{
|
|||
|
STATEMANAGER.SetVertexShader(m_dwLeafVertexShader);
|
|||
|
|
|||
|
if (STATEMANAGER.GetRenderState(D3DRS_FOGENABLE))
|
|||
|
{
|
|||
|
#if defined WRAPPER_USE_GPU_WIND || defined WRAPPER_USE_GPU_LEAF_PLACEMENT
|
|||
|
STATEMANAGER.SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
if (ulRenderBitVector & Forest_RenderToShadow || ulRenderBitVector & Forest_RenderToMiniMap)
|
|||
|
{
|
|||
|
STATEMANAGER.SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_NOTEQUAL);
|
|||
|
STATEMANAGER.SaveRenderState(D3DRS_ALPHAREF, 0x00000000);
|
|||
|
}
|
|||
|
|
|||
|
itor = m_pMainTreeMap.begin();
|
|||
|
|
|||
|
while (itor != m_pMainTreeMap.end())
|
|||
|
{
|
|||
|
CSpeedTreeWrapper * pMainTree = (itor++)->second;
|
|||
|
CSpeedTreeWrapper ** ppInstances = pMainTree->GetInstances(uiCount);
|
|||
|
|
|||
|
pMainTree->SetupLeafForTreeType();
|
|||
|
|
|||
|
for (UINT i = 0; i < uiCount; ++i)
|
|||
|
if (ppInstances[i]->isShow())
|
|||
|
ppInstances[i]->RenderLeaves();
|
|||
|
}
|
|||
|
|
|||
|
while (itor != m_pMainTreeMap.end())
|
|||
|
(itor++)->second->EndLeafForTreeType();
|
|||
|
|
|||
|
if (ulRenderBitVector & Forest_RenderToShadow || ulRenderBitVector & Forest_RenderToMiniMap)
|
|||
|
{
|
|||
|
STATEMANAGER.SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);
|
|||
|
STATEMANAGER.RestoreRenderState(D3DRS_ALPHAREF);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// render billboards
|
|||
|
#ifndef WRAPPER_NO_BILLBOARD_MODE
|
|||
|
if (ulRenderBitVector & Forest_RenderBillboards)
|
|||
|
{
|
|||
|
STATEMANAGER.SetRenderState(D3DRS_LIGHTING, FALSE);
|
|||
|
STATEMANAGER.SetRenderState(D3DRS_COLORVERTEX, FALSE);
|
|||
|
|
|||
|
itor = m_pMainTreeMap.begin();
|
|||
|
|
|||
|
while (itor != m_pMainTreeMap.end())
|
|||
|
{
|
|||
|
CSpeedTreeWrapper * pMainTree = (itor++)->second;
|
|||
|
CSpeedTreeWrapper ** ppInstances = pMainTree->GetInstances(uiCount);
|
|||
|
|
|||
|
pMainTree->SetupBranchForTreeType();
|
|||
|
|
|||
|
for (UINT i = 0; i < uiCount; ++i)
|
|||
|
if (ppInstances[i]->isShow())
|
|||
|
ppInstances[i]->RenderBillboards();
|
|||
|
}
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
STATEMANAGER.SetRenderState(D3DRS_LIGHTING, dwLightState);
|
|||
|
STATEMANAGER.SetRenderState(D3DRS_COLORVERTEX, dwColorVertexState);
|
|||
|
STATEMANAGER.SetRenderState(D3DRS_FOGVERTEXMODE, dwFogVertexMode);
|
|||
|
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> TextureStage 1<><31> COLOROP<4F><50> ALPHAOP<4F><50> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>´<EFBFBD>. (<28>ȱ<C8B1><D7B7><EFBFBD> <20>˰<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ɼ<EFBFBD><C9BC><EFBFBD>..)
|
|||
|
if (!(ulRenderBitVector & Forest_RenderToShadow))
|
|||
|
{
|
|||
|
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
|||
|
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
|
|||
|
}
|
|||
|
|
|||
|
STATEMANAGER.RestoreRenderState(D3DRS_ALPHATESTENABLE);
|
|||
|
STATEMANAGER.RestoreRenderState(D3DRS_ALPHAFUNC);
|
|||
|
STATEMANAGER.RestoreRenderState(D3DRS_CULLMODE);
|
|||
|
}
|
|||
|
|