/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see .
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: W3DShaderManager.cpp ////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//
// Westwood Studios Pacific.
//
// Confidential Information
// Copyright (C) 2001 - All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// Project: RTS3
//
// File name: W3DShaderManager.cpp
//
// Created: Mark Wilczynski, August 2001
//
// Desc: Perform tests on currently selected WW3D/D3D device to determine
// which of our rendering features are supported. The system allows
// setting up a few custom shaders that are selected based on video
// card features.
//
// To add a new shader to the system:
// 0) Add your shader to the ShaderTypes enum
// 1) Create shader using W3DShaderInterface
// 2) Repeat step 1 for any alternate shaders
// 3) Create list of alternate shaders sorted by order of preference.
// The first shader which passes hardware validation will be selected.
// 4) Add list from step 3) to MasterShaderList[].
//
//-----------------------------------------------------------------------------
#include "dx8wrapper.h"
#include "assetmgr.h"
#include "Lib/BaseType.h"
#include "Common/File.h"
#include "Common/FileSystem.h"
#include "W3DDevice/GameClient/W3DShaderManager.h"
#include "W3DDevice/GameClient/W3DShroud.h"
#include "W3DDevice/GameClient/HeightMap.h"
#include "W3DDevice/GameClient/W3DCustomScene.h"
#include "W3DDevice/GameClient/W3DSmudge.h"
#include "GameClient/view.h"
#include "GameClient/CommandXlat.h"
#include "GameClient/display.h"
#include "GameClient/Water.h"
#include "GameLogic/GameLogic.h"
#include "common/GlobalData.h"
#include "common/GameLOD.h"
#include "d3dx8tex.h"
#include "dx8caps.h"
#include "common/gamelod.h"
#include "Benchmark.h"
#ifdef _INTERNAL
// for occasional debugging...
//#pragma optimize("", off)
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
#endif
// Turn this on to turn off pixel shaders. jba[4/3/2003]
#define do_not_DISABLE_PIXEL_SHADERS 1
/** Interface definition for custom shaders we define in our app. These shaders can perform more complex
operations than those allowed in the WW3D2 shader system.
*/
class W3DShaderInterface
{
public:
Int getNumPasses(void) {return m_numPasses;}; ///SetTexture(0, NULL);
DX8Wrapper::_Get_D3D_Device8()->SetTexture(1, NULL);};
virtual Int init(void) = 0; ///= DC_GEFORCE2)
{
//Check if their driver is newer than what we tested for this vendor
/* if (TheGameLODManager)
{
if (TheGameLODManager->getTestedDriverVersion(W3DShaderManager::getCurrentVendor()) < W3DShaderManager::getCurrentDriverVersion())
return FALSE;
}*/
}
}
W3DFilters[FT_VIEW_DEFAULT]=&screenDefaultFilter;
return TRUE;
}
Bool ScreenDefaultFilter::preRender(Bool &skipRender, CustomScenePassModes &scenePassMode)
{
//Right now this filter is only used for smudges, so don't bother if none are present.
if (TheSmudgeManager)
{ if (((W3DSmudgeManager *)TheSmudgeManager)->getSmudgeCountLastFrame() == 0)
return FALSE;
}
W3DShaderManager::startRenderToTexture();
return true;
}
Bool ScreenDefaultFilter::postRender(enum FilterModes mode, Coord2D &scrollDelta,Bool &doExtraRender)
{
IDirect3DTexture8 * tex = W3DShaderManager::endRenderToTexture();
DEBUG_ASSERTCRASH(tex, ("Require rendered texture."));
if (!tex) return false;
if (!set(mode)) return false;
LPDIRECT3DDEVICE8 pDev=DX8Wrapper::_Get_D3D_Device8();
struct _TRANS_LIT_TEX_VERTEX {
D3DXVECTOR4 p;
DWORD color; // diffuse color
float u;
float v;
} v[4];
Int xpos, ypos, width, height;
DX8Wrapper::_Get_D3D_Device8()->SetTexture(0,tex); //previously rendered frame inside this texture
TheTacticalView->getOrigin(&xpos,&ypos);
width=TheTacticalView->getWidth();
height=TheTacticalView->getHeight();
//bottom right
v[0].p = D3DXVECTOR4( xpos+width-0.5f, ypos+height-0.5f, 0.0f, 1.0f );
v[0].u = (Real)(xpos+width)/(Real)TheDisplay->getWidth(); v[0].v = (Real)(ypos+height)/(Real)TheDisplay->getHeight();
//top right
v[1].p = D3DXVECTOR4( xpos+width-0.5f, ypos-0.5f, 0.0f, 1.0f );
v[1].u = (Real)(xpos+width)/(Real)TheDisplay->getWidth(); v[1].v = (Real)(ypos)/(Real)TheDisplay->getHeight();
//bottom left
v[2].p = D3DXVECTOR4( xpos-0.5f, ypos+height-0.5f, 0.0f, 1.0f );
v[2].u = (Real)(xpos)/(Real)TheDisplay->getWidth(); v[2].v = (Real)(ypos+height)/(Real)TheDisplay->getHeight();
//top left
v[3].p = D3DXVECTOR4( xpos-0.5f, ypos-0.5f, 0.0f, 1.0f );
v[3].u = (Real)(xpos)/(Real)TheDisplay->getWidth(); v[3].v = (Real)(ypos)/(Real)TheDisplay->getHeight();
v[0].color = 0xffffffff;
v[1].color = 0xffffffff;
v[2].color = 0xffffffff;
v[3].color = 0xffffffff;
//draw polygons like this is very inefficient but for only 2 triangles, it's
//not worth bothering with index/vertex buffers.
pDev->SetVertexShader(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
pDev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v, sizeof(_TRANS_LIT_TEX_VERTEX));
reset();
return true;
}
Int ScreenDefaultFilter::set(enum FilterModes mode)
{
VertexMaterialClass *vmat=VertexMaterialClass::Get_Preset(VertexMaterialClass::PRELIT_DIFFUSE);
DX8Wrapper::Set_Material(vmat);
REF_PTR_RELEASE(vmat); //no need to keep a reference since it's a preset.
DX8Wrapper::Set_Shader(ShaderClass::_PresetOpaqueShader);
DX8Wrapper::Set_Texture(0,NULL);
DX8Wrapper::Apply_Render_State_Changes(); //force update of view and projection matrices
DX8Wrapper::Set_DX8_Render_State(D3DRS_ZFUNC,D3DCMP_ALWAYS);
DX8Wrapper::Set_DX8_Render_State(D3DRS_ZWRITEENABLE,FALSE);
DX8Wrapper::Apply_Render_State_Changes(); //force update of view and projection matrices
return true;
}
void ScreenDefaultFilter::reset(void)
{
DX8Wrapper::_Get_D3D_Device8()->SetTexture(0,NULL); //previously rendered frame inside this texture
DX8Wrapper::Invalidate_Cached_Render_States();
}
/*========= ScreenBWFilter =============================================================*/
///converts viewport to black & white.
Int ScreenBWFilter::m_fadeFrames;
Int ScreenBWFilter::m_curFadeFrame;
Real ScreenBWFilter::m_curFadeValue;
Int ScreenBWFilter::m_fadeDirection;
ScreenBWFilter screenBWFilter;
ScreenBWFilterDOT3 screenBWFilterDOT3; //slower version for older cards without pixel shaders.
///List of different BW shader implementations in order of preference
W3DFilterInterface *ScreenBWFilterList[]=
{
&screenBWFilter,
&screenBWFilterDOT3, //slower version for older cards without pixel shaders.
NULL
};
Int ScreenBWFilter::init(void)
{
Int res;
HRESULT hr;
m_dwBWPixelShader = NULL;
m_curFadeFrame = 0;
if (!W3DShaderManager::canRenderToTexture()) {
// Have to be able to render to texture.
return false;
}
if ((res=W3DShaderManager::getChipset()) != 0)
{
if (res >= DC_GENERIC_PIXEL_SHADER_1_1)
{
//this shader needs some assets that need to be loaded
//shader decleration
DWORD Declaration[]=
{
(D3DVSD_STREAM(0)),
(D3DVSD_REG(0, D3DVSDT_FLOAT3)), // Position
(D3DVSD_REG(1, D3DVSDT_D3DCOLOR)), // Diffuse
(D3DVSD_REG(2, D3DVSDT_FLOAT2)), // Texture Coordinates
(D3DVSD_END())
};
//Monochrome pixel shader.
hr = W3DShaderManager::LoadAndCreateD3DShader("shaders\\monochrome.pso", &Declaration[0], 0, false, &m_dwBWPixelShader);
if (FAILED(hr))
return FALSE;
W3DFilters[FT_VIEW_BW_FILTER]=&screenBWFilter;
return TRUE;
}
}
return FALSE;
}
Bool ScreenBWFilter::preRender(Bool &skipRender, CustomScenePassModes &scenePassMode)
{
skipRender = false;
W3DShaderManager::startRenderToTexture();
return true;
}
Bool ScreenBWFilter::postRender(enum FilterModes mode, Coord2D &scrollDelta,Bool &doExtraRender)
{
IDirect3DTexture8 * tex = W3DShaderManager::endRenderToTexture();
DEBUG_ASSERTCRASH(tex, ("Require rendered texture."));
if (!tex) return false;
if (!set(mode)) return false;
LPDIRECT3DDEVICE8 pDev=DX8Wrapper::_Get_D3D_Device8();
struct _TRANS_LIT_TEX_VERTEX {
D3DXVECTOR4 p;
DWORD color; // diffuse color
float u;
float v;
} v[4];
Int xpos, ypos, width, height;
DX8Wrapper::_Get_D3D_Device8()->SetTexture(0,tex); //previously rendered frame inside this texture
TheTacticalView->getOrigin(&xpos,&ypos);
width=TheTacticalView->getWidth();
height=TheTacticalView->getHeight();
//bottom right
v[0].p = D3DXVECTOR4( xpos+width-0.5f, ypos+height-0.5f, 0.0f, 1.0f );
v[0].u = (Real)(xpos+width)/(Real)TheDisplay->getWidth(); v[0].v = (Real)(ypos+height)/(Real)TheDisplay->getHeight();
//top right
v[1].p = D3DXVECTOR4( xpos+width-0.5f, ypos-0.5f, 0.0f, 1.0f );
v[1].u = (Real)(xpos+width)/(Real)TheDisplay->getWidth(); v[1].v = (Real)(ypos)/(Real)TheDisplay->getHeight();
//bottom left
v[2].p = D3DXVECTOR4( xpos-0.5f, ypos+height-0.5f, 0.0f, 1.0f );
v[2].u = (Real)(xpos)/(Real)TheDisplay->getWidth(); v[2].v = (Real)(ypos+height)/(Real)TheDisplay->getHeight();
//top left
v[3].p = D3DXVECTOR4( xpos-0.5f, ypos-0.5f, 0.0f, 1.0f );
v[3].u = (Real)(xpos)/(Real)TheDisplay->getWidth(); v[3].v = (Real)(ypos)/(Real)TheDisplay->getHeight();
v[0].color = 0xffffffff;
v[1].color = 0xffffffff;
v[2].color = 0xffffffff;
v[3].color = 0xffffffff;
//draw polygons like this is very inefficient but for only 2 triangles, it's
//not worth bothering with index/vertex buffers.
pDev->SetVertexShader(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
pDev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v, sizeof(_TRANS_LIT_TEX_VERTEX));
reset();
return true;
}
Int ScreenBWFilter::set(enum FilterModes mode)
{
HRESULT hr;
if (mode > FM_NULL_MODE)
{ //rendering a quad with redirected rendering surface tinted by pixel shader
if (m_fadeDirection > 0)
{ //turning effect on
m_curFadeFrame++;
Int fade = m_curFadeFrame;
if (fadesetViewFilterMode(FM_NULL_MODE);
TheTacticalView->setViewFilter(FT_NULL_FILTER);
m_curFadeFrame = 0;
m_fadeDirection = 0;
}
}
VertexMaterialClass *vmat=VertexMaterialClass::Get_Preset(VertexMaterialClass::PRELIT_DIFFUSE);
DX8Wrapper::Set_Material(vmat);
REF_PTR_RELEASE(vmat); //no need to keep a reference since it's a preset.
DX8Wrapper::Set_Shader(ShaderClass::_PresetOpaqueShader);
DX8Wrapper::Set_Texture(0,NULL);
DX8Wrapper::Apply_Render_State_Changes(); //force update of view and projection matrices
DX8Wrapper::Set_DX8_Render_State(D3DRS_ZFUNC,D3DCMP_ALWAYS);
DX8Wrapper::Set_DX8_Render_State(D3DRS_ZWRITEENABLE,FALSE);
DX8Wrapper::Apply_Render_State_Changes(); //force update of view and projection matrices
hr=DX8Wrapper::_Get_D3D_Device8()->SetPixelShader(m_dwBWPixelShader);
DX8Wrapper::_Get_D3D_Device8()->SetPixelShaderConstant(0, D3DXVECTOR4(0.3f, 0.59f, 0.11f, 1.0f), 1);
D3DXVECTOR4 color(1.0f,1.0f,1.0f,1.0f); //multiply color
if (mode == FM_VIEW_BW_BLACK_AND_WHITE)
{ //back & white mode
color.x=1.0f;
color.y=1.0f;
color.z=1.0f;
}
if (mode == FM_VIEW_BW_RED_AND_WHITE)
{ //red is on
color.x = 1.0f;
color.y = 0.0f;
color.z = 0.0f;
//inverse red is on
//red is on
// color.x = 0.0f;
// color.y = 1.0f;
// color.z = 1.0f;
}
if (mode == FM_VIEW_BW_GREEN_AND_WHITE)
{
color.x = 0.0f;
color.y = 1.0f;
color.z = 0.0f;
}
DX8Wrapper::_Get_D3D_Device8()->SetPixelShaderConstant(1, color, 1);
DX8Wrapper::_Get_D3D_Device8()->SetPixelShaderConstant(2, D3DXVECTOR4(m_curFadeValue, m_curFadeValue, m_curFadeValue, 1.0f), 1);
/* DX8Wrapper::_Get_D3D_Device8()->SetPixelShaderConstant(2, D3DXVECTOR4(150.0f/255.0f, 150.0f/255.0f, 150.0f/255.0f, 0.0f), 1);
DX8Wrapper::_Get_D3D_Device8()->SetPixelShaderConstant(3, D3DXVECTOR4((765.0f/450.0f)/3, (765.0f/450.0f)/3, (765.0f/450.0f)/3, 1.0f), 1);
DX8Wrapper::_Get_D3D_Device8()->SetPixelShaderConstant(4, D3DXVECTOR4(0.5f, 0.5f, 0.5f, 0), 1);
DX8Wrapper::_Get_D3D_Device8()->SetPixelShaderConstant(5, D3DXVECTOR4((60.0f)/255.0f, (60.0f)/255.0f, (60.0f)/255.0f, 0), 1);
DX8Wrapper::_Get_D3D_Device8()->SetPixelShaderConstant(6, D3DXVECTOR4((157.0f)/255.0f, (157.0f)/255.0f, (157.0f)/255.0f, 0), 1);
DX8Wrapper::_Get_D3D_Device8()->SetPixelShaderConstant(7, D3DXVECTOR4((30.0f)/255.0f, (30.0f)/255.0f, (30.0f)/255.0f, 0), 1);
*/
return true;
}
return false;
}
void ScreenBWFilter::reset(void)
{
DX8Wrapper::_Get_D3D_Device8()->SetTexture(0,NULL); //previously rendered frame inside this texture
DX8Wrapper::_Get_D3D_Device8()->SetPixelShader(0); //turn off pixel shader
DX8Wrapper::Invalidate_Cached_Render_States();
}
Int ScreenBWFilter::shutdown(void)
{
if (m_dwBWPixelShader)
DX8Wrapper::_Get_D3D_Device8()->DeletePixelShader(m_dwBWPixelShader);
m_dwBWPixelShader=NULL;
return TRUE;
}
/**Alternate version of the above filter which does not require pixel shaders - good for older cards*/
Int ScreenBWFilterDOT3::init(void)
{
Int res;
m_curFadeFrame = 0;
if (!W3DShaderManager::canRenderToTexture()) {
// Have to be able to render to texture.
return false;
}
if ((res=W3DShaderManager::getChipset()) != 0)
{
W3DFilters[FT_VIEW_BW_FILTER]=&screenBWFilterDOT3;
return TRUE;
}
return FALSE;
}
Bool ScreenBWFilterDOT3::preRender(Bool &skipRender, CustomScenePassModes &scenePassMode)
{
skipRender = false;
W3DShaderManager::startRenderToTexture();
return true;
}
Bool ScreenBWFilterDOT3::postRender(enum FilterModes mode, Coord2D &scrollDelta,Bool &doExtraRender)
{
IDirect3DTexture8 * tex = W3DShaderManager::endRenderToTexture();
DEBUG_ASSERTCRASH(tex, ("Require rendered texture."));
if (!tex) return false;
if (!set(mode)) return false;
LPDIRECT3DDEVICE8 pDev=DX8Wrapper::_Get_D3D_Device8();
struct _TRANS_LIT_TEX_VERTEX {
D3DXVECTOR4 p;
DWORD color; // diffuse color
float u;
float v;
} v[4];
Int xpos, ypos, width, height;
TheTacticalView->getOrigin(&xpos,&ypos);
width=TheTacticalView->getWidth();
height=TheTacticalView->getHeight();
//bottom right
v[0].p = D3DXVECTOR4( xpos+width-0.5f, ypos+height-0.5f, 0.0f, 1.0f );
v[0].u = (Real)(xpos+width)/(Real)TheDisplay->getWidth(); v[0].v = (Real)(ypos+height)/(Real)TheDisplay->getHeight();
//top right
v[1].p = D3DXVECTOR4( xpos+width-0.5f, ypos-0.5f, 0.0f, 1.0f );
v[1].u = (Real)(xpos+width)/(Real)TheDisplay->getWidth(); v[1].v = (Real)(ypos)/(Real)TheDisplay->getHeight();
//bottom left
v[2].p = D3DXVECTOR4( xpos-0.5f, ypos+height-0.5f, 0.0f, 1.0f );
v[2].u = (Real)(xpos)/(Real)TheDisplay->getWidth(); v[2].v = (Real)(ypos+height)/(Real)TheDisplay->getHeight();
//top left
v[3].p = D3DXVECTOR4( xpos-0.5f, ypos-0.5f, 0.0f, 1.0f );
v[3].u = (Real)(xpos)/(Real)TheDisplay->getWidth(); v[3].v = (Real)(ypos)/(Real)TheDisplay->getHeight();
DWORD currentFade=(((Int)((1.0f-m_curFadeValue) * 255.0f))<<24) | 0x00ffffff; //store alpha value
v[0].color = currentFade;
v[1].color = currentFade;
v[2].color = currentFade;
v[3].color = currentFade;
//draw polygons like this is very inefficient but for only 2 triangles, it's
//not worth bothering with index/vertex buffers.
pDev->SetVertexShader(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
//Draw B&W version first
if (DX8Wrapper::Get_Current_Caps()->Support_Dot3())
{ //Override W3D states with customizations for grayscale
DX8Wrapper::Set_DX8_Render_State(D3DRS_TEXTUREFACTOR, 0x80A5CA8E);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG0, D3DTA_TFACTOR | D3DTA_ALPHAREPLICATE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG2, D3DTA_TFACTOR | D3DTA_ALPHAREPLICATE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLOROP, D3DTOP_MULTIPLYADD);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG1, D3DTA_CURRENT);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG2, D3DTA_TFACTOR);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3);
}
else
{ //doesn't have DOT3 blend mode so fake it another way.
DX8Wrapper::Set_DX8_Render_State(D3DRS_TEXTUREFACTOR, 0x60606060);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
}
DX8Wrapper::_Get_D3D_Device8()->SetTexture(0,tex); //previously rendered frame inside this texture
pDev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v, sizeof(_TRANS_LIT_TEX_VERTEX));
//Draw normal view blended by current fade level
ShaderClass::Invalidate(); //reset DOT3 blend from above.
ShaderClass shader=ShaderClass::_PresetAlphaShader;
shader.Set_Depth_Compare(ShaderClass::PASS_ALWAYS);
DX8Wrapper::Set_Shader(shader);
DX8Wrapper::Apply_Render_State_Changes(); //force update of view and projection matrices
//replace texture alpha with vertex alpha
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2);
pDev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v, sizeof(_TRANS_LIT_TEX_VERTEX));
reset();
return true;
}
Int ScreenBWFilterDOT3::set(enum FilterModes mode)
{
if (mode > FM_NULL_MODE)
{ //rendering a quad with redirected rendering surface tinted by pixel shader
if (m_fadeDirection > 0)
{ //turning effect on
m_curFadeFrame++;
Int fade = m_curFadeFrame;
if (fadesetViewFilterMode(FM_NULL_MODE);
TheTacticalView->setViewFilter(FT_NULL_FILTER);
m_curFadeFrame = 0;
m_fadeDirection = 0;
}
}
VertexMaterialClass *vmat=VertexMaterialClass::Get_Preset(VertexMaterialClass::PRELIT_DIFFUSE);
DX8Wrapper::Set_Material(vmat);
REF_PTR_RELEASE(vmat); //no need to keep a reference since it's a preset.
DX8Wrapper::Set_Shader(ShaderClass::_PresetOpaqueShader);
DX8Wrapper::Set_Texture(0,NULL);
DX8Wrapper::Apply_Render_State_Changes(); //force update of view and projection matrices
DX8Wrapper::Set_DX8_Render_State(D3DRS_ZFUNC,D3DCMP_ALWAYS);
DX8Wrapper::Set_DX8_Render_State(D3DRS_ZWRITEENABLE,FALSE);
DX8Wrapper::Apply_Render_State_Changes(); //force update of view and projection matrices
return true;
}
return false;
}
void ScreenBWFilterDOT3::reset(void)
{
DX8Wrapper::_Get_D3D_Device8()->SetTexture(0,NULL); //previously rendered frame inside this texture
DX8Wrapper::Invalidate_Cached_Render_States();
}
Int ScreenBWFilterDOT3::shutdown(void)
{
return TRUE;
}
/*========= ScreenCrossFadeFilter =============================================================*/
///Fades screen between 2 different views of the scene with both being visible at once.
Int ScreenCrossFadeFilter::m_fadeFrames;
Int ScreenCrossFadeFilter::m_curFadeFrame;
Real ScreenCrossFadeFilter::m_curFadeValue;
Int ScreenCrossFadeFilter::m_fadeDirection;
TextureClass *ScreenCrossFadeFilter::m_fadePatternTexture=NULL;
Bool ScreenCrossFadeFilter::m_skipRender = FALSE;
ScreenCrossFadeFilter screenCrossFadeFilter;
///List of different BW shader implementations in order of preference
///@todo: Add a version that doesn't require pixel shader
W3DFilterInterface *ScreenCrossFadeFilterList[]=
{
&screenCrossFadeFilter,
NULL
};
Int ScreenCrossFadeFilter::init(void)
{
if (!TheDisplay)
return FALSE; //effect is useless without a view so no point initializing for the WB, etc.
m_curFadeFrame = 0;
if (!W3DShaderManager::canRenderToTexture())
// Have to be able to render to texture.
return FALSE;
//Load an alpha mask texture that will mix foreground/background views.
m_fadePatternTexture=WW3DAssetManager::Get_Instance()->Get_Texture("exmask_g.tga");
if (!m_fadePatternTexture)
return FALSE;
m_fadePatternTexture->Get_Filter().Set_U_Addr_Mode(TextureFilterClass::TEXTURE_ADDRESS_CLAMP);
m_fadePatternTexture->Get_Filter().Set_V_Addr_Mode(TextureFilterClass::TEXTURE_ADDRESS_CLAMP);
m_fadePatternTexture->Get_Filter().Set_Mip_Mapping(TextureFilterClass::FILTER_TYPE_NONE);
W3DFilters[FT_VIEW_CROSSFADE]=&screenCrossFadeFilter;
return TRUE;
}
Bool ScreenCrossFadeFilter::updateFadeLevel(void)
{
if (m_fadeDirection > 0)
{ //turning effect on
m_curFadeFrame++;
Int fade = m_curFadeFrame;
if (fadesetViewFilterMode(FM_NULL_MODE);
TheTacticalView->setViewFilter(FT_NULL_FILTER);
m_curFadeFrame = 0;
m_fadeDirection = 0;
return false;
}
}
return true;
}
Bool ScreenCrossFadeFilter::preRender(Bool &skipRender, CustomScenePassModes &scenePassMode)
{
if (updateFadeLevel())
{ //if fade has not completed
W3DShaderManager::startRenderToTexture();
scenePassMode=SCENE_PASS_ALPHA_MASK;
skipRender = false;
m_skipRender=true; //tell the postRender function not to draw into framebuffer yet.
return true;
}
//fade must have completed
return true;
}
Bool ScreenCrossFadeFilter::postRender(enum FilterModes mode, Coord2D &scrollDelta,Bool &doExtraRender)
{
IDirect3DTexture8 * tex;
if (m_skipRender)
{
//don't render anything to frame buffer because we still need to draw the new scene
//that we're fading into. Okay to render on the next call.
m_skipRender = false;
doExtraRender = TRUE;
tex = W3DShaderManager::endRenderToTexture();
return true;
}
tex=W3DShaderManager::getRenderTexture();
DEBUG_ASSERTCRASH(tex, ("Require last rendered texture."));
if (!tex) return false;
if (!set(mode)) return false;
LPDIRECT3DDEVICE8 pDev=DX8Wrapper::_Get_D3D_Device8();
struct _TRANS_LIT_TEX_VERTEX {
D3DXVECTOR4 p;
DWORD color; // diffuse color
float u;
float v;
float u1;
float v1;
} v[4];
Int xpos, ypos, width, height;
Real radius = 0.0f;
DX8Wrapper::_Get_D3D_Device8()->SetTexture(0,tex); //previously rendered frame inside this texture
if (mode == FM_VIEW_CROSSFADE_CIRCLE)
{ DX8Wrapper::_Get_D3D_Device8()->SetTexture(1,m_fadePatternTexture->Peek_D3D_Texture());
//Use the current fade level to scale the mask texture, for other modes the texture
//comes pre-scaled so doesn't require uv scaling.
radius = (1.0f-m_curFadeValue)*2.0f;
if (radius <= 0)
radius = 0.01f;
radius = 0.5f/radius;
}
TheTacticalView->getOrigin(&xpos,&ypos);
width=TheTacticalView->getWidth();
height=TheTacticalView->getHeight();
/* Real radius = (1.0f-m_curFadeValue);
if (radius <= 0)
radius = 0.01f;
radius = 25.0f-radius*24.75f;
*/
//bottom right
v[0].p = D3DXVECTOR4( xpos+width-0.5f, ypos+height-0.5f, 0.0f, 1.0f );
v[0].u = (Real)(xpos+width)/(Real)TheDisplay->getWidth(); v[0].v = (Real)(ypos+height)/(Real)TheDisplay->getHeight();
v[0].u1 = 0.5f+radius; v[0].v1 = 0.5f+radius;
//top right
v[1].p = D3DXVECTOR4( xpos+width-0.5f, ypos-0.5f, 0.0f, 1.0f );
v[1].u = (Real)(xpos+width)/(Real)TheDisplay->getWidth(); v[1].v = (Real)(ypos)/(Real)TheDisplay->getHeight();
v[1].u1 = 0.5f+radius; v[1].v1 = 0.5f-radius;
//bottom left
v[2].p = D3DXVECTOR4( xpos-0.5f, ypos+height-0.5f, 0.0f, 1.0f );
v[2].u = (Real)(xpos)/(Real)TheDisplay->getWidth(); v[2].v = (Real)(ypos+height)/(Real)TheDisplay->getHeight();
v[2].u1 = 0.5f-radius; v[2].v1 = 0.5f+radius;
//top left
v[3].p = D3DXVECTOR4( xpos-0.5f, ypos-0.5f, 0.0f, 1.0f );
v[3].u = (Real)(xpos)/(Real)TheDisplay->getWidth(); v[3].v = (Real)(ypos)/(Real)TheDisplay->getHeight();
v[3].u1 = 0.5f-radius; v[3].v1 = 0.5f-radius;
DWORD diffuse = 0xffffffff;//((Int)((m_curFadeValue) * 255.0f) << 24) | 0x00ffffff; //store alpha value in vertex diffuse
v[0].color = diffuse;
v[1].color = diffuse;
v[2].color = diffuse;
v[3].color = diffuse;
//draw polygons like this is very inefficient but for only 2 triangles, it's
//not worth bothering with index/vertex buffers.
pDev->SetVertexShader(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX2);
// m_pDev->SetTextureStageState(0,D3DTSS_MAGFILTER,D3DTEXF_POINT);
// m_pDev->SetTextureStageState(0,D3DTSS_MINFILTER,D3DTEXF_POINT);
pDev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v, sizeof(_TRANS_LIT_TEX_VERTEX));
reset();
return true;
}
Int ScreenCrossFadeFilter::set(enum FilterModes mode)
{
if (mode > FM_NULL_MODE)
{ //rendering a quad with redirected rendering surface
VertexMaterialClass *vmat=VertexMaterialClass::Get_Preset(VertexMaterialClass::PRELIT_DIFFUSE);
DX8Wrapper::Set_Material(vmat);
REF_PTR_RELEASE(vmat); //no need to keep a reference since it's a preset.
DX8Wrapper::Set_Shader(ShaderClass::_PresetAlphaShader);
DX8Wrapper::Set_Texture(0,NULL);
DX8Wrapper::Set_Texture(1,NULL);
DX8Wrapper::Apply_Render_State_Changes(); //force update of view and projection matrices
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
if (mode == FM_VIEW_CROSSFADE_CIRCLE)
{ //cross-fading using circle mask stored in stage 1
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_MODULATE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAARG2, D3DTA_CURRENT );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_TEXCOORDINDEX, 1 );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_MIPFILTER, D3DTEXF_NONE);
}
DX8Wrapper::Set_DX8_Render_State(D3DRS_ZFUNC,D3DCMP_ALWAYS);
DX8Wrapper::Set_DX8_Render_State(D3DRS_ZWRITEENABLE,FALSE);
return true;
}
return false;
}
void ScreenCrossFadeFilter::reset(void)
{
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
DX8Wrapper::_Get_D3D_Device8()->SetTexture(0,NULL); //previously rendered frame inside this texture
DX8Wrapper::Invalidate_Cached_Render_States();
}
Int ScreenCrossFadeFilter::shutdown(void)
{
REF_PTR_RELEASE(m_fadePatternTexture);
return TRUE;
}
/*========= ScreenMotionBlurFilter =============================================================*/
///applies motion blur to viewport.
ScreenMotionBlurFilter screenMotionBlurFilter;
Coord3D ScreenMotionBlurFilter::m_zoomToPos;
Bool ScreenMotionBlurFilter::m_zoomToValid = false;
ScreenMotionBlurFilter::ScreenMotionBlurFilter():
m_decrement(false),
m_maxCount(0),
m_lastFrame(0),
m_skipRender(false)
{
}
///List of different motion blur implementations in order of preference
W3DFilterInterface *ScreenMotionBlurFilterList[]=
{
&screenMotionBlurFilter,
NULL
};
Int ScreenMotionBlurFilter::init(void)
{
if (!W3DShaderManager::canRenderToTexture()) {
// Have to be able to render to texture.
return false;
}
W3DFilters[FT_VIEW_MOTION_BLUR_FILTER]=this;
return true;
}
Bool ScreenMotionBlurFilter::preRender(Bool &skipRender, CustomScenePassModes &scenePassMode)
{
skipRender = m_skipRender;
W3DShaderManager::startRenderToTexture();
return true;
}
Bool ScreenMotionBlurFilter::postRender(enum FilterModes mode, Coord2D &scrollDelta,Bool &doExtraRender)
{
IDirect3DTexture8 * tex = W3DShaderManager::endRenderToTexture();
DEBUG_ASSERTCRASH(tex, ("Require rendered texture."));
if (!tex) return false;
if (!set(mode)) return false;
LPDIRECT3DDEVICE8 pDev=DX8Wrapper::_Get_D3D_Device8();
Bool continueEffect = true;
struct _TRANS_LIT_TEX_VERTEX {
D3DXVECTOR4 p;
DWORD color; // diffuse color
float u;
float v;
} v[4];
Int xpos, ypos, width, height;
DX8Wrapper::_Get_D3D_Device8()->SetTexture(0,tex); //previously rendered frame inside this texture
TheTacticalView->getOrigin(&xpos,&ypos);
width=TheTacticalView->getWidth();
height=TheTacticalView->getHeight();
//bottom right
v[0].p = D3DXVECTOR4( xpos+width-0.5f, ypos+height-0.5f, 0.0f, 1.0f );
v[0].u = (Real)(xpos+width)/(Real)TheDisplay->getWidth(); v[0].v = (Real)(ypos+height)/(Real)TheDisplay->getHeight();
//top right
v[1].p = D3DXVECTOR4( xpos+width-0.5f, ypos-0.5f, 0.0f, 1.0f );
v[1].u = (Real)(xpos+width)/(Real)TheDisplay->getWidth(); v[1].v = (Real)(ypos)/(Real)TheDisplay->getHeight();
//bottom left
v[2].p = D3DXVECTOR4( xpos-0.5f, ypos+height-0.5f, 0.0f, 1.0f );
v[2].u = (Real)(xpos)/(Real)TheDisplay->getWidth(); v[2].v = (Real)(ypos+height)/(Real)TheDisplay->getHeight();
//top left
v[3].p = D3DXVECTOR4( xpos-0.5f, ypos-0.5f, 0.0f, 1.0f );
v[3].u = (Real)(xpos)/(Real)TheDisplay->getWidth(); v[3].v = (Real)(ypos)/(Real)TheDisplay->getHeight();
v[0].color = 0xffffffff;
v[1].color = 0xffffffff;
v[2].color = 0xffffffff;
v[3].color = 0xffffffff;
if (m_additive) {
DX8Wrapper::Set_DX8_Render_State(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);
DX8Wrapper::Set_DX8_Render_State(D3DRS_DESTBLEND,D3DBLEND_ONE);
} else {
DX8Wrapper::Set_DX8_Render_State(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);
DX8Wrapper::Set_DX8_Render_State(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);
}
DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHABLENDENABLE,false);
//draw polygons like this is very inefficient but for only 2 triangles, it's
//not worth bothering with index/vertex buffers.
DX8Wrapper::Apply_Render_State_Changes();
pDev->SetVertexShader(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
Coord2D center;
center.x = 0.5f;
center.y = 0.5f;
Bool pan = false;
if (mode>=FM_VIEW_MB_PAN_ALPHA) {
Real len = sqrt(scrollDelta.x*scrollDelta.x + scrollDelta.y*scrollDelta.y);
//center.x += 0.5f * (scrollDelta.x/len);
center.y -= 0.5f; // * (scrollDelta.y/len);
m_decrement = false;
m_maxCount = (len*200*m_panFactor/(Real)DEFAULT_PAN_FACTOR);
if (m_maxCountm_panFactor)
m_maxCount=m_panFactor;
pan = true;
m_priorDelta = scrollDelta;
} else if (mode == FM_VIEW_MB_END_PAN_ALPHA) {
Real len = sqrt(m_priorDelta.x*m_priorDelta.x + m_priorDelta.y*m_priorDelta.y);
center.x += 0.5f * (m_priorDelta.x/len);
center.y -= 0.5f * (m_priorDelta.y/len);
m_decrement = false;
m_maxCount--;
if (m_maxCount<2) {
continueEffect = false;
}
pan = true;
}
m_skipRender = false;
if (!pan && m_lastFrame != TheGameLogic->getFrame()) {
if (m_decrement) {
m_maxCount-=COUNT_STEP;
if (m_maxCount<1) {
m_decrement = false;
continueEffect = false;
} else {
m_skipRender = true;
}
} else {
m_maxCount+=COUNT_STEP;
if (m_maxCount>=MAX_COUNT) {
m_decrement = true;
if (m_doZoomTo && m_zoomToValid) {
TheTacticalView->lookAt(&m_zoomToPos);
} else {
continueEffect = false;
}
} else {
m_skipRender = true;
}
}
}
Int i, j;
if (!pan) {
for (i=0; i<4; i++) {
Real factor = 1.0f - (m_maxCount/(Real)MAX_COUNT)*0.90f;
factor = sqrt(factor);
v[i].u = ((v[i].u-center.x)*factor) + center.x;
v[i].v = ((v[i].v-center.y)*factor) + center.y;
}
}
pDev->SetTextureStageState(0,D3DTSS_ALPHAARG1, D3DTA_CURRENT);
pDev->SetTextureStageState(0,D3DTSS_ALPHAARG2, D3DTA_TEXTURE);
pDev->SetTextureStageState(0,D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
pDev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v, sizeof(_TRANS_LIT_TEX_VERTEX));
DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHABLENDENABLE,true);
DX8Wrapper::Apply_Render_State_Changes();
{
Int limit = m_maxCount;
if (m_maxCount>30) limit = 30;
for (j=0; jlimit) {
alpha += (m_maxCount-limit)/5;
}
if (m_maxCount==MAX_COUNT) alpha += 60;
}
v[i].color = (alpha<<24)|0x00ffffff; //
if (pan) {
v[i].u = ((v[i].u-center.x)*(factor+.006)) + center.x;
v[i].v = ((v[i].v-center.y)*factor) + center.y;
} else {
v[i].u = ((v[i].u-center.x)*factor) + center.x;
v[i].v = ((v[i].v-center.y)*factor) + center.y;
}
}
pDev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v, sizeof(_TRANS_LIT_TEX_VERTEX));
}
}
m_lastFrame = TheGameLogic->getFrame();
if (pan){
m_skipRender = false;
}
reset();
if (!continueEffect) {
m_zoomToValid = false;
}
return continueEffect;
}
Bool ScreenMotionBlurFilter::setup(enum FilterModes mode)
{
m_additive = false;
if (mode == FM_VIEW_MB_IN_AND_OUT_SATURATE ||
mode == FM_VIEW_MB_IN_SATURATE ||
mode == FM_VIEW_MB_OUT_SATURATE) {
m_additive = true;
}
m_doZoomTo = false;
if (mode == FM_VIEW_MB_IN_AND_OUT_SATURATE ||
mode == FM_VIEW_MB_IN_AND_OUT_ALPHA ) {
m_doZoomTo = true;
}
if (mode >= FM_VIEW_MB_PAN_ALPHA) {
m_panFactor = (int)mode - FM_VIEW_MB_PAN_ALPHA;
if (m_panFactor<1) m_panFactor = DEFAULT_PAN_FACTOR;
}
m_skipRender = false;
if (mode != FM_VIEW_MB_END_PAN_ALPHA)
m_maxCount = 0;
m_decrement = false;
m_skipRender = false;
switch (mode) {
case FM_VIEW_MB_OUT_SATURATE:
case FM_VIEW_MB_OUT_ALPHA:
m_maxCount = MAX_COUNT;
m_decrement = TRUE;
break;
}
return true;
}
Int ScreenMotionBlurFilter::set(enum FilterModes mode)
{
if (mode > FM_NULL_MODE)
{ //rendering a quad with redirected rendering surface motion blurred
VertexMaterialClass *vmat=VertexMaterialClass::Get_Preset(VertexMaterialClass::PRELIT_DIFFUSE);
DX8Wrapper::Set_Material(vmat);
REF_PTR_RELEASE(vmat); //no need to keep a reference since it's a preset.
DX8Wrapper::Set_Shader(ShaderClass::_PresetOpaqueShader);
DX8Wrapper::Set_Texture(0,NULL);
DX8Wrapper::Set_Texture(1,NULL);
DX8Wrapper::Apply_Render_State_Changes(); //force update of view and projection matrices
DX8Wrapper::Set_DX8_Render_State(D3DRS_ZFUNC,D3DCMP_ALWAYS);
DX8Wrapper::Set_DX8_Render_State(D3DRS_ZWRITEENABLE,FALSE);
DX8Wrapper::Apply_Render_State_Changes(); //force update of view and projection matrices
}
return TRUE;
}
void ScreenMotionBlurFilter::reset(void)
{
DX8Wrapper::_Get_D3D_Device8()->SetTexture(0,NULL); //previously rendered frame inside this texture
DX8Wrapper::Invalidate_Cached_Render_States();
}
Int ScreenMotionBlurFilter::shutdown(void)
{
return TRUE;
}
/*===========================================================================================*/
/*========= Shroud Shaders =============================================================*/
/*===========================================================================================*/
///Shroud layer rendering shader
class ShroudTextureShader : public W3DShaderInterface
{
virtual Int set(Int pass); ///m_fogOfWarOn)
DX8Wrapper::Set_Shader(ShaderClass::_PresetAlphaSpriteShader);
else
DX8Wrapper::Set_Shader(ShaderClass::_PresetMultiplicativeSpriteShader);
#else
DX8Wrapper::Set_Shader(ShaderClass::_PresetMultiplicativeSpriteShader);
#endif
}
DX8Wrapper::Apply_Render_State_Changes();
DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
DX8Wrapper::Set_DX8_Render_State(D3DRS_ZFUNC,D3DCMP_EQUAL);
//We need to scale so shroud texel stretches over one full terrain cell. Each texel
//is 1/128 the size of full texture. (assuming 128x128 vid-mem texture).
W3DShroud *shroud;
if ((shroud=TheTerrainRenderObject->getShroud()) != 0)
{ ///@todo: All this code really only need to be done once per camera/view. Find a way to optimize it out.
D3DXMATRIX inv;
float det;
Matrix4x4 curView;
DX8Wrapper::_Get_DX8_Transform(D3DTS_VIEW, curView);
D3DXMatrixInverse(&inv, &det, (D3DXMATRIX*)&curView);
D3DXMATRIX scale,offset;
//We need to make all world coordinates be relative to the heightmap data origin since that
//is where the shroud begins.
float xoffset = 0;
float yoffset = 0;
Real width=shroud->getCellWidth();
Real height=shroud->getCellHeight();
if (TheTerrainRenderObject->getMap())
{ //subtract origin position from all coordinates. Origin is shifted by 1 cell width/height to allow for unused border texels.
xoffset = -(float)shroud->getDrawOriginX() + width;
yoffset = -(float)shroud->getDrawOriginY() + height;
}
D3DXMatrixTranslation(&offset, xoffset, yoffset,0);
width = 1.0f/(width*shroud->getTextureWidth());
height = 1.0f/(height*shroud->getTextureHeight());
D3DXMatrixScaling(&scale, width, height, 1);
*((D3DXMATRIX *)&curView) = (inv * offset) * scale;
DX8Wrapper::_Set_DX8_Transform((D3DTRANSFORMSTATETYPE )(D3DTS_TEXTURE0+stage), *((Matrix4x4*)&curView));
}
m_stageOfSet=stage;
return TRUE;
}
void ShroudTextureShader::reset(void)
{
DX8Wrapper::Set_Texture(m_stageOfSet,NULL);
DX8Wrapper::Set_DX8_Render_State(D3DRS_ZFUNC,D3DCMP_LESSEQUAL);
DX8Wrapper::Set_DX8_Texture_Stage_State(m_stageOfSet, D3DTSS_TEXCOORDINDEX, m_stageOfSet);
DX8Wrapper::Set_DX8_Texture_Stage_State(m_stageOfSet, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
}
///Shroud layer rendering shader
class FlatShroudTextureShader : public W3DShaderInterface
{
virtual Int set(Int pass); ///Peek_D3D_Texture());
DX8Wrapper::Set_DX8_Texture_Stage_State( stage, D3DTSS_COLORARG1, D3DTA_TEXTURE );
DX8Wrapper::Set_DX8_Texture_Stage_State( stage, D3DTSS_COLORARG2, D3DTA_CURRENT );
DX8Wrapper::Set_DX8_Texture_Stage_State( stage, D3DTSS_COLOROP, D3DTOP_MODULATE );
DX8Wrapper::Set_DX8_Texture_Stage_State( stage, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
//DX8Wrapper::Apply_Render_State_Changes();
DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
//We need to scale so shroud texel stretches over one full terrain cell. Each texel
//is 1/128 the size of full texture. (assuming 128x128 vid-mem texture).
W3DShroud *shroud;
if ((shroud=TheTerrainRenderObject->getShroud()) != 0)
{ ///@todo: All this code really only need to be done once per camera/view. Find a way to optimize it out.
D3DXMATRIX inv;
float det;
Matrix4x4 curView;
DX8Wrapper::_Get_DX8_Transform(D3DTS_VIEW, curView);
D3DXMatrixInverse(&inv, &det, (D3DXMATRIX*)&curView);
D3DXMATRIX scale,offset;
//We need to make all world coordinates be relative to the heightmap data origin since that
//is where the shroud begins.
float xoffset = 0;
float yoffset = 0;
Real width=shroud->getCellWidth();
Real height=shroud->getCellHeight();
if (TheTerrainRenderObject->getMap())
{ //subtract origin position from all coordinates. Origin is shifted by 1 cell width/height to allow for unused border texels.
xoffset = -(float)shroud->getDrawOriginX() + width;
yoffset = -(float)shroud->getDrawOriginY() + height;
}
D3DXMatrixTranslation(&offset, xoffset, yoffset,0);
width = 1.0f/(width*shroud->getTextureWidth());
height = 1.0f/(height*shroud->getTextureHeight());
D3DXMatrixScaling(&scale, width, height, 1);
*((D3DXMATRIX *)&curView) = (inv * offset) * scale;
DX8Wrapper::_Set_DX8_Transform((D3DTRANSFORMSTATETYPE )(D3DTS_TEXTURE0+stage), *((Matrix4x4*)&curView));
}
m_stageOfSet=stage;
return TRUE;
}
void FlatShroudTextureShader::reset(void)
{
if (m_stageOfSet < MAX_TEXTURE_STAGES)
DX8Wrapper::Set_Texture(m_stageOfSet,NULL);
DX8Wrapper::Set_DX8_Render_State(D3DRS_ZFUNC,D3DCMP_LESSEQUAL);
DX8Wrapper::Set_DX8_Texture_Stage_State(m_stageOfSet, D3DTSS_TEXCOORDINDEX, m_stageOfSet);
DX8Wrapper::Set_DX8_Texture_Stage_State(m_stageOfSet, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
}
///Mask layer rendering shader
class MaskTextureShader : public W3DShaderInterface
{
virtual Int set(Int pass); ///getOrigin(&xpos,&ypos);
ICoord2D screenPos;
screenPos.x=(Real)TheTacticalView->getWidth()*0.5f;
screenPos.y=(Real)TheTacticalView->getHeight()*0.5f;
TheTacticalView->screenToTerrain(&screenPos,¢erPos);
}
D3DXMatrixTranslation(&offset, -centerPos.x, -centerPos.y,0);
D3DXMatrixTranslation(&offsetTextureCenter, 0.5f, 0.5f, 0); //shift coordinates so center of projection falls at uv 0.5,0.5
Real worldTexelWidth=(1.0f-fadeLevel)*25.0f; //9 worked well for circle but weird shape requires more stretch to cover.
Real worldTexelHeight=(1.0f-fadeLevel)*25.0f;
///@todo: Fix this to work with non 128x128 textures.
if (worldTexelWidth != 0 && worldTexelHeight != 0)
{ Real widthScale = 1.0f/(worldTexelWidth*128.0f);
Real heightScale = 1.0f/(worldTexelHeight*128.0f);
D3DXMatrixScaling(&scale, widthScale, heightScale, 1);
*((D3DXMATRIX *)&curView) = ((inv * offset) * scale)*offsetTextureCenter;
}
else
{ D3DXMatrixScaling(&scale, 0, 0, 1); //scaling by 0 will set uv coordinates to 0,0
*((D3DXMATRIX *)&curView) = ((inv * offset) * scale);
}
DX8Wrapper::_Set_DX8_Transform(D3DTS_TEXTURE0, *((Matrix4x4*)&curView));
return TRUE;
}
void MaskTextureShader::reset(void)
{
DX8Wrapper::Set_Texture(0,NULL);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_TEXCOORDINDEX, 0);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
}
/*===========================================================================================*/
/*========= Terrain Shaders =========================================================*/
/*===========================================================================================*/
///regular terrain shader that should work on all multi-texture video cards (slowest version)
class TerrainShader2Stage : public W3DShaderInterface
{
public:
float m_xSlidePerSecond ; ///< How far the clouds move per second.
float m_ySlidePerSecond ; ///< How far the clouds move per second.
int m_curTick;
float m_xOffset;
float m_yOffset;
virtual Int set(Int pass); ///clip space.
///Pixel shader based terrain shader - fastest method for the newest cards.
class TerrainShaderPixelShader : public W3DShaderInterface
{
DWORD m_dwBasePixelShader; ///SetTexture(0, NULL);
DX8Wrapper::_Get_D3D_Device8()->SetTexture(1, NULL);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU|0);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU|1);
}
void TerrainShader2Stage::updateNoise1(D3DXMATRIX *destMatrix,D3DXMATRIX *curViewInverse, Bool doUpdate)
{
#define STRETCH_FACTOR ((float)(1/(63.0*MAP_XY_FACTOR/2))) /* covers 63/2 tiles */
D3DXMATRIX scale;
D3DXMatrixScaling(&scale, STRETCH_FACTOR, STRETCH_FACTOR,1);
*destMatrix = *curViewInverse * scale;
D3DXMATRIX offset;
Int delta = m_curTick;
m_curTick = WW3D::Get_Sync_Time();//::GetTickCount();
delta = m_curTick-delta;
m_xOffset += m_xSlidePerSecond*delta/1000;
m_yOffset += m_ySlidePerSecond*delta/1000;
//m_xOffset += m_xSlidePerSecond*delta/500;
//m_yOffset += m_ySlidePerSecond*delta/500;
//m_yOffset = sinf( (float)m_curTick * 0.0001f );
//m_xOffset = cosf( (float)m_curTick * 0.0001f );
while (m_xOffset > 1) m_xOffset -= 1;
while (m_yOffset > 1) m_yOffset -= 1;
while (m_xOffset < -1) m_xOffset += 1;
while (m_yOffset < -1) m_yOffset += 1;
D3DXMatrixTranslation(&offset, m_xOffset, m_yOffset,0);
*destMatrix *= offset;
}
void TerrainShader2Stage::updateNoise2(D3DXMATRIX *destMatrix,D3DXMATRIX *curViewInverse, Bool doUpdate)
{
D3DXMATRIX scale;
D3DXMatrixScaling(&scale, STRETCH_FACTOR, STRETCH_FACTOR,1);
*destMatrix = *curViewInverse * scale;
}
Int TerrainShader2Stage::set(Int pass)
{
//force WW3D2 system to set it's states so it won't later overwrite our custom settings.
DX8Wrapper::Apply_Render_State_Changes();
if (TheGlobalData && TheGlobalData->m_bilinearTerrainTex || TheGlobalData->m_trilinearTerrainTex) {
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
} else {
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MINFILTER, D3DTEXF_POINT);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MAGFILTER, D3DTEXF_POINT);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MINFILTER, D3DTEXF_POINT);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MAGFILTER, D3DTEXF_POINT);
}
if (TheGlobalData && TheGlobalData->m_trilinearTerrainTex) {
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
} else {
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MIPFILTER, D3DTEXF_POINT);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
}
switch (pass)
{
case 0:
DX8Wrapper::_Get_D3D_Device8()->SetTexture(0, W3DShaderManager::getShaderTexture(0)->Peek_D3D_Texture());
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
// Modulate the diffuse color with the texture as lighting comes from diffuse.
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_TEXCOORDINDEX, 0 );
DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHABLENDENABLE,false);
break;
case 1:
DX8Wrapper::_Get_D3D_Device8()->SetTexture(0, W3DShaderManager::getShaderTexture(1)->Peek_D3D_Texture());
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
// Modulate the diffuse color with the texture as lighting comes from diffuse.
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_TEXCOORDINDEX, 1 );
// Blend the result using the alpha. (came from diffuse mod texture)
DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHABLENDENABLE,true);
DX8Wrapper::Set_DX8_Render_State(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);
DX8Wrapper::Set_DX8_Render_State(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);
// Disable stage 2.
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
break;
case 2:
// Noise/cloud pass
Matrix4x4 curView;
DX8Wrapper::_Get_DX8_Transform(D3DTS_VIEW, curView);
//these states apply to all noise/cloud combination passes
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
// Two output coordinates are used.
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
//blend into frame buffer
DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHABLENDENABLE,true);
DX8Wrapper::Set_DX8_Render_State(D3DRS_SRCBLEND,D3DBLEND_DESTCOLOR);
DX8Wrapper::Set_DX8_Render_State(D3DRS_DESTBLEND,D3DBLEND_ZERO);
D3DXMATRIX inv;
float det;
D3DXMatrixInverse(&inv, &det, (D3DXMATRIX*)&curView);
if (W3DShaderManager::getCurrentShader() == W3DShaderManager::ST_TERRAIN_BASE_NOISE12)
{
//setup cloud pass
DX8Wrapper::_Get_D3D_Device8()->SetTexture(0, W3DShaderManager::getShaderTexture(2)->Peek_D3D_Texture());
updateNoise1(((D3DXMATRIX*)&curView),&inv); //update curView with texture matrix
DX8Wrapper::_Set_DX8_Transform(D3DTS_TEXTURE0, curView);
//clouds always need bilinear filtering
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
//setup noise pass
DX8Wrapper::_Get_D3D_Device8()->SetTexture(1, W3DShaderManager::getShaderTexture(3)->Peek_D3D_Texture());
updateNoise2(((D3DXMATRIX*)&curView),&inv);
DX8Wrapper::_Set_DX8_Transform(D3DTS_TEXTURE1, curView);
//noise always needs point/linear filtering. Why point!?
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MINFILTER, D3DTEXF_POINT);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_MODULATE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
// Two output coordinates are used.
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
} //ST_TERRAIN_BASE_NOISE12
else
{ //only 1 noise or cloud texture
// Now setup the texture pipeline.
if (W3DShaderManager::getCurrentShader() == W3DShaderManager::ST_TERRAIN_BASE_NOISE1)
{ //setup cloud pass
DX8Wrapper::_Get_D3D_Device8()->SetTexture(0, W3DShaderManager::getShaderTexture(2)->Peek_D3D_Texture());
updateNoise1(((D3DXMATRIX*)&curView),&inv); //update curView with texture matrix
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
}
else
{
//setup noise pass
DX8Wrapper::_Get_D3D_Device8()->SetTexture(0, W3DShaderManager::getShaderTexture(3)->Peek_D3D_Texture());
updateNoise2(((D3DXMATRIX*)&curView),&inv); //update curView with texture matrix
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MINFILTER, D3DTEXF_POINT);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
}
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
DX8Wrapper::_Set_DX8_Transform(D3DTS_TEXTURE0, *((Matrix4x4*)&curView));
}
break;
}
return TRUE;
}
Int TerrainShader8Stage::init( void )
{
ChipsetType res;
//this shader will also use the 2Stage shader for some of the passes so initialize it too.
if (terrainShader2Stage.init() && (res=W3DShaderManager::getChipset()) >= DC_TNT && res <= DC_GEFORCE2)
{
W3DShaders[W3DShaderManager::ST_TERRAIN_BASE]=&terrainShader8Stage;
W3DShadersPassCount[W3DShaderManager::ST_TERRAIN_BASE]=1;
W3DShaders[W3DShaderManager::ST_TERRAIN_BASE_NOISE1]=&terrainShader8Stage;
W3DShadersPassCount[W3DShaderManager::ST_TERRAIN_BASE_NOISE1]=2;
W3DShaders[W3DShaderManager::ST_TERRAIN_BASE_NOISE2]=&terrainShader8Stage;
W3DShadersPassCount[W3DShaderManager::ST_TERRAIN_BASE_NOISE2]=2;
W3DShaders[W3DShaderManager::ST_TERRAIN_BASE_NOISE12]=&terrainShader8Stage;
W3DShadersPassCount[W3DShaderManager::ST_TERRAIN_BASE_NOISE12]=2;
return TRUE;
}
return FALSE;
}
Int TerrainShader8Stage::set(Int pass)
{
if (pass == 0)
{
//force WW3D2 system to set it's states so it won't later overwrite our custom settings.
DX8Wrapper::Apply_Render_State_Changes();
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
if (TheGlobalData && TheGlobalData->m_bilinearTerrainTex || TheGlobalData->m_trilinearTerrainTex) {
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
} else {
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MINFILTER, D3DTEXF_POINT);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MAGFILTER, D3DTEXF_POINT);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MINFILTER, D3DTEXF_POINT);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MAGFILTER, D3DTEXF_POINT);
}
if (TheGlobalData && TheGlobalData->m_trilinearTerrainTex) {
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
} else {
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MIPFILTER, D3DTEXF_POINT);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
}
DX8Wrapper::_Get_D3D_Device8()->SetTexture(0, W3DShaderManager::getShaderTexture(0)->Peek_D3D_Texture());
DX8Wrapper::_Get_D3D_Device8()->SetTexture(1, W3DShaderManager::getShaderTexture(1)->Peek_D3D_Texture());
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_TEXCOORDINDEX, 0);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_ADD);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_TEXCOORDINDEX, 1);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG1, D3DTA_DIFFUSE | D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAOP, D3DTOP_ADD);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAARG1, D3DTA_TFACTOR | D3DTA_COMPLEMENT);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAARG2, D3DTA_TFACTOR);
DX8Wrapper::Set_DX8_Texture(2, NULL);
DX8Wrapper::Set_DX8_Texture_Stage_State( 2, D3DTSS_COLOROP, D3DTOP_MODULATE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 2, D3DTSS_TEXCOORDINDEX, 2);
DX8Wrapper::Set_DX8_Texture_Stage_State( 2, D3DTSS_COLORARG1, D3DTA_TEXTURE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 2, D3DTSS_COLORARG2, D3DTA_TEXTURE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 2, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 2, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
DX8Wrapper::Set_DX8_Texture_Stage_State( 2, D3DTSS_ALPHAARG2, D3DTA_TFACTOR);
DX8Wrapper::Set_DX8_Texture(3, NULL);
DX8Wrapper::Set_DX8_Texture_Stage_State( 3, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
DX8Wrapper::Set_DX8_Texture_Stage_State( 3, D3DTSS_TEXCOORDINDEX, 3);
DX8Wrapper::Set_DX8_Texture_Stage_State( 3, D3DTSS_COLORARG1, D3DTA_DIFFUSE | 0 | D3DTA_ALPHAREPLICATE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 3, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 3, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
DX8Wrapper::Set_DX8_Texture_Stage_State( 3, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
DX8Wrapper::Set_DX8_Texture_Stage_State( 3, D3DTSS_ALPHAARG2, D3DTA_TFACTOR);
DX8Wrapper::Set_DX8_Texture(4, NULL);
DX8Wrapper::Set_DX8_Texture_Stage_State( 4, D3DTSS_COLOROP, D3DTOP_MODULATE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 4, D3DTSS_TEXCOORDINDEX, 4);
DX8Wrapper::Set_DX8_Texture_Stage_State( 4, D3DTSS_COLORARG1, D3DTA_CURRENT);
DX8Wrapper::Set_DX8_Texture_Stage_State( 4, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 4, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 4, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
DX8Wrapper::Set_DX8_Texture_Stage_State( 4, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
DX8Wrapper::Set_DX8_Texture(5, NULL);
DX8Wrapper::Set_DX8_Texture_Stage_State( 5, D3DTSS_COLOROP, D3DTOP_ADD);
DX8Wrapper::Set_DX8_Texture_Stage_State( 5, D3DTSS_TEXCOORDINDEX, 5);
DX8Wrapper::Set_DX8_Texture_Stage_State( 5, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 5, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 5, D3DTSS_ALPHAOP, D3DTOP_ADD);
DX8Wrapper::Set_DX8_Texture_Stage_State( 5, D3DTSS_ALPHAARG1, D3DTA_TFACTOR | D3DTA_COMPLEMENT);
DX8Wrapper::Set_DX8_Texture_Stage_State( 5, D3DTSS_ALPHAARG2, D3DTA_TFACTOR);
DX8Wrapper::Set_DX8_Texture(6, NULL);
DX8Wrapper::Set_DX8_Texture_Stage_State( 6, D3DTSS_COLOROP, D3DTOP_MODULATE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 6, D3DTSS_TEXCOORDINDEX, 6);
DX8Wrapper::Set_DX8_Texture_Stage_State( 6, D3DTSS_COLORARG1, D3DTA_TFACTOR);
DX8Wrapper::Set_DX8_Texture_Stage_State( 6, D3DTSS_COLORARG2, D3DTA_TFACTOR);
DX8Wrapper::Set_DX8_Texture_Stage_State( 6, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 6, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
DX8Wrapper::Set_DX8_Texture_Stage_State( 6, D3DTSS_ALPHAARG2, D3DTA_TFACTOR);
DX8Wrapper::Set_DX8_Texture(7, NULL);
DX8Wrapper::Set_DX8_Texture_Stage_State( 7, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
DX8Wrapper::Set_DX8_Texture_Stage_State( 7, D3DTSS_TEXCOORDINDEX, 7);
DX8Wrapper::Set_DX8_Texture_Stage_State( 7, D3DTSS_COLORARG1, D3DTA_TFACTOR);
DX8Wrapper::Set_DX8_Texture_Stage_State( 7, D3DTSS_COLORARG2, D3DTA_TFACTOR);
DX8Wrapper::Set_DX8_Texture_Stage_State( 7, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
DX8Wrapper::Set_DX8_Texture_Stage_State( 7, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
DX8Wrapper::Set_DX8_Texture_Stage_State( 7, D3DTSS_ALPHAARG2, D3DTA_TFACTOR);
}
else
{ //setup cloud noise/pass
DX8Wrapper::Set_DX8_Texture_Stage_State( 2, D3DTSS_COLOROP, D3DTOP_DISABLE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 2, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 3, D3DTSS_COLOROP, D3DTOP_DISABLE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 3, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
DX8Wrapper::Invalidate_Cached_Render_States();
terrainShader2Stage.set(2);
}
return TRUE;
}
void TerrainShader8Stage::reset(void)
{
DX8Wrapper::Set_DX8_Texture_Stage_State( 2, D3DTSS_COLOROP, D3DTOP_DISABLE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 2, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 3, D3DTSS_COLOROP, D3DTOP_DISABLE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 3, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 4, D3DTSS_COLOROP, D3DTOP_DISABLE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 4, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
DX8Wrapper::_Get_D3D_Device8()->SetTexture(0, NULL);
DX8Wrapper::_Get_D3D_Device8()->SetTexture(1, NULL);
DX8Wrapper::Invalidate_Cached_Render_States();
}
Int TerrainShaderPixelShader::shutdown(void)
{
if (m_dwBasePixelShader)
DX8Wrapper::_Get_D3D_Device8()->DeletePixelShader(m_dwBasePixelShader);
if (m_dwBaseNoise1PixelShader)
DX8Wrapper::_Get_D3D_Device8()->DeletePixelShader(m_dwBaseNoise1PixelShader);
if (m_dwBaseNoise2PixelShader)
DX8Wrapper::_Get_D3D_Device8()->DeletePixelShader(m_dwBaseNoise2PixelShader);
m_dwBasePixelShader=NULL;
m_dwBaseNoise1PixelShader=NULL;
m_dwBaseNoise2PixelShader=NULL;
return TRUE;
}
Int TerrainShaderPixelShader::init( void )
{
Int res;
#ifdef DISABLE_PIXEL_SHADERS
return false;
#endif
//this shader will also use the 2Stage shader for some of the passes so initialize it too.
if (terrainShader2Stage.init() && (res=W3DShaderManager::getChipset()) >= DC_GENERIC_PIXEL_SHADER_1_1)
{
if (res >= DC_GENERIC_PIXEL_SHADER_1_1)
{
//this shader needs some assets that need to be loaded
//shader decleration
DWORD Declaration[]=
{
(D3DVSD_STREAM(0)),
(D3DVSD_REG(0, D3DVSDT_FLOAT3)), // Position
(D3DVSD_REG(1, D3DVSDT_D3DCOLOR)), // Diffuse
(D3DVSD_REG(2, D3DVSDT_FLOAT2)), // Texture Coordinates
(D3DVSD_REG(3, D3DVSDT_FLOAT2)), // Texture Coordinates
(D3DVSD_END())
};
//base version which doesn't apply any noise textures.
HRESULT hr = W3DShaderManager::LoadAndCreateD3DShader("shaders\\terrain.pso", &Declaration[0], 0, false, &m_dwBasePixelShader);
if (FAILED(hr))
return FALSE;
//version which blends 1 noise texture.
hr = W3DShaderManager::LoadAndCreateD3DShader("shaders\\terrainnoise.pso", &Declaration[0], 0, false, &m_dwBaseNoise1PixelShader);
if (FAILED(hr))
return FALSE;
//version which blends 2 noise textures.
hr = W3DShaderManager::LoadAndCreateD3DShader("shaders\\terrainnoise2.pso", &Declaration[0], 0, false, &m_dwBaseNoise2PixelShader);
if (FAILED(hr))
return FALSE;
W3DShaders[W3DShaderManager::ST_TERRAIN_BASE]=&terrainShaderPixelShader;
W3DShaders[W3DShaderManager::ST_TERRAIN_BASE_NOISE1]=&terrainShaderPixelShader;
W3DShaders[W3DShaderManager::ST_TERRAIN_BASE_NOISE2]=&terrainShaderPixelShader;
W3DShaders[W3DShaderManager::ST_TERRAIN_BASE_NOISE12]=&terrainShaderPixelShader;
W3DShadersPassCount[W3DShaderManager::ST_TERRAIN_BASE]=1;
W3DShadersPassCount[W3DShaderManager::ST_TERRAIN_BASE_NOISE1]=1;
W3DShadersPassCount[W3DShaderManager::ST_TERRAIN_BASE_NOISE2]=1;
W3DShadersPassCount[W3DShaderManager::ST_TERRAIN_BASE_NOISE12]=1;
return TRUE;
}
}
return FALSE;
}
Int TerrainShaderPixelShader::set(Int pass)
{
//force WW3D2 system to set it's states so it won't later overwrite our custom settings.
DX8Wrapper::Apply_Render_State_Changes();
//setup base pass
DX8Wrapper::_Get_D3D_Device8()->SetTexture(0, W3DShaderManager::getShaderTexture(0)->Peek_D3D_Texture());
DX8Wrapper::_Get_D3D_Device8()->SetTexture(1, W3DShaderManager::getShaderTexture(1)->Peek_D3D_Texture());
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
//tell pixel shader which UV set to use for each stage
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_TEXCOORDINDEX, 0 );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_TEXCOORDINDEX, 1 );
if (TheGlobalData && TheGlobalData->m_bilinearTerrainTex || TheGlobalData->m_trilinearTerrainTex) {
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
} else {
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MINFILTER, D3DTEXF_POINT);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MAGFILTER, D3DTEXF_POINT);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MINFILTER, D3DTEXF_POINT);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MAGFILTER, D3DTEXF_POINT);
}
if (TheGlobalData && TheGlobalData->m_trilinearTerrainTex) {
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
} else {
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MIPFILTER, D3DTEXF_POINT);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
}
if (W3DShaderManager::getCurrentShader() >= W3DShaderManager::ST_TERRAIN_BASE_NOISE1)
{
Matrix4x4 curView;
DX8Wrapper::_Get_DX8_Transform(D3DTS_VIEW, curView);
D3DXMATRIX inv;
float det;
D3DXMatrixInverse(&inv, &det, (D3DXMATRIX*)&curView);
DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
// Two output coordinates are used.
DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
if (W3DShaderManager::getCurrentShader() == W3DShaderManager::ST_TERRAIN_BASE_NOISE12)
{ //full shader
DX8Wrapper::Set_DX8_Texture_Stage_State(3, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
DX8Wrapper::Set_DX8_Texture_Stage_State(3, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
DX8Wrapper::_Get_D3D_Device8()->SetTexture(2, W3DShaderManager::getShaderTexture(2)->Peek_D3D_Texture());
DX8Wrapper::_Get_D3D_Device8()->SetTexture(3, W3DShaderManager::getShaderTexture(3)->Peek_D3D_Texture());
DX8Wrapper::_Get_D3D_Device8()->SetPixelShader(m_dwBaseNoise2PixelShader);
DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State(3, D3DTSS_MINFILTER, D3DTEXF_POINT);
DX8Wrapper::Set_DX8_Texture_Stage_State(3, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
terrainShader2Stage.updateNoise1(((D3DXMATRIX*)&curView),&inv); //update curView with texture matrix
DX8Wrapper::_Set_DX8_Transform(D3DTS_TEXTURE2, curView);
terrainShader2Stage.updateNoise2(((D3DXMATRIX*)&curView),&inv); //update curView with texture matrix
DX8Wrapper::_Set_DX8_Transform(D3DTS_TEXTURE3, curView);
DX8Wrapper::Set_DX8_Texture_Stage_State(3, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
// Two output coordinates are used.
DX8Wrapper::Set_DX8_Texture_Stage_State(3, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
}
else
{ //single noise texture shader
DX8Wrapper::_Get_D3D_Device8()->SetPixelShader(m_dwBaseNoise1PixelShader);
if (W3DShaderManager::getCurrentShader() == W3DShaderManager::ST_TERRAIN_BASE_NOISE1)
{ //cloud map
DX8Wrapper::_Get_D3D_Device8()->SetTexture(2, W3DShaderManager::getShaderTexture(2)->Peek_D3D_Texture());
terrainShader2Stage.updateNoise1(((D3DXMATRIX*)&curView),&inv); //update curView with texture matrix
DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
}
else
{ //light map
DX8Wrapper::_Get_D3D_Device8()->SetTexture(2, W3DShaderManager::getShaderTexture(3)->Peek_D3D_Texture());
terrainShader2Stage.updateNoise2(((D3DXMATRIX*)&curView),&inv); //update curView with texture matrix
DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_MINFILTER, D3DTEXF_POINT);
DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
}
DX8Wrapper::_Set_DX8_Transform(D3DTS_TEXTURE2, curView);
}
}
else
{ //just base texturing
DX8Wrapper::_Get_D3D_Device8()->SetPixelShader(m_dwBasePixelShader);
}
return TRUE;
}
void TerrainShaderPixelShader::reset(void)
{
DX8Wrapper::_Get_D3D_Device8()->SetTexture(2,NULL); //release reference to any texture
DX8Wrapper::_Get_D3D_Device8()->SetTexture(3,NULL); //release reference to any texture
DX8Wrapper::_Get_D3D_Device8()->SetPixelShader(0); //turn off pixel shader
DX8Wrapper::_Get_D3D_Device8()->SetTexture(0, NULL);
DX8Wrapper::_Get_D3D_Device8()->SetTexture(1, NULL);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU|0);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU|1);
DX8Wrapper::Set_DX8_Texture_Stage_State( 2, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 2, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU|2);
DX8Wrapper::Set_DX8_Texture_Stage_State( 3, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 3, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU|3);
DX8Wrapper::Invalidate_Cached_Render_States();
}
///Cloud layer rendering shader - used for objects similar to terrain which only need the cloud layer.
class CloudTextureShader : public W3DShaderInterface
{
virtual Int set(Int stage); ///SetTexture(stage, W3DShaderManager::getShaderTexture(stage)->Peek_D3D_Texture());
m_stageOfSet=stage;
return TRUE;
}
void CloudTextureShader::reset(void)
{
//Free reference to texture
DX8Wrapper::_Get_D3D_Device8()->SetTexture(m_stageOfSet, NULL);
//Turn off texture projection
DX8Wrapper::Set_DX8_Texture_Stage_State( m_stageOfSet, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
DX8Wrapper::Set_DX8_Texture_Stage_State( m_stageOfSet, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU|m_stageOfSet);
DX8Wrapper::Set_DX8_Texture_Stage_State( m_stageOfSet, D3DTSS_COLOROP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Texture_Stage_State( m_stageOfSet, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
}
/*===========================================================================================*/
/*========= Road Shaders =========================================================*/
/*===========================================================================================*/
class RoadShaderPixelShader : public W3DShaderInterface
{
DWORD m_dwBaseNoise2PixelShader; ///DeletePixelShader(m_dwBaseNoise2PixelShader);
m_dwBaseNoise2PixelShader=NULL;
return TRUE;
}
Int RoadShaderPixelShader::init( void )
{
Int res;
//this shader will also use the 2Stage shader for some of the passes so initialize it too.
if (roadShader2Stage.init() && (res=W3DShaderManager::getChipset()) >= DC_GENERIC_PIXEL_SHADER_1_1)
{
if (res >= DC_GENERIC_PIXEL_SHADER_1_1)
{
//this shader needs some assets that need to be loaded
//shader decleration
DWORD Declaration[]=
{
(D3DVSD_STREAM(0)),
(D3DVSD_REG(0, D3DVSDT_FLOAT3)), // Position
(D3DVSD_REG(1, D3DVSDT_D3DCOLOR)), // Diffuse
(D3DVSD_REG(2, D3DVSDT_FLOAT2)), // Texture Coordinates
(D3DVSD_END())
};
//version which blends 2 noise textures.
HRESULT hr = W3DShaderManager::LoadAndCreateD3DShader("shaders\\roadnoise2.pso", &Declaration[0], 0, false, &m_dwBaseNoise2PixelShader);
if (FAILED(hr))
return FALSE;
//Only set this shader for use in dual noise mode. The 2Stage shader will take care of
//all the other modes.
W3DShaders[W3DShaderManager::ST_ROAD_BASE_NOISE12]=&roadShaderPixelShader;
W3DShadersPassCount[W3DShaderManager::ST_ROAD_BASE_NOISE12]=1;
return TRUE;
}
}
return FALSE;
}
Int RoadShaderPixelShader::set(Int pass)
{
DX8Wrapper::Set_Texture(0,W3DShaderManager::getShaderTexture(0));
//force WW3D2 system to set it's states so it won't later overwrite our custom settings.
DX8Wrapper::Apply_Render_State_Changes();
//tell pixel shader which UV set to use for each stage
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_TEXCOORDINDEX, 0 );
DX8Wrapper::Set_DX8_Render_State(D3DRS_ZFUNC,D3DCMP_LESSEQUAL);
DX8Wrapper::Set_DX8_Render_State(D3DRS_ZWRITEENABLE,FALSE);
DX8Wrapper::Set_DX8_Render_State(D3DRS_LIGHTING, FALSE);
DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHABLENDENABLE,true); //blend roads into terrain
DX8Wrapper::Set_DX8_Render_State(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);
DX8Wrapper::Set_DX8_Render_State(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);
Matrix4x4 curView;
DX8Wrapper::_Get_DX8_Transform(D3DTS_VIEW, curView);
D3DXMATRIX inv;
float det;
D3DXMatrixInverse(&inv, &det, (D3DXMATRIX*)&curView);
if (TheGlobalData && TheGlobalData->m_trilinearTerrainTex)
{ DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
}
else
{ DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MIPFILTER, D3DTEXF_POINT);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MIPFILTER, D3DTEXF_POINT);
}
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
// Two output coordinates are used.
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
DX8Wrapper::Set_Texture(1,W3DShaderManager::getShaderTexture(1));
DX8Wrapper::Set_Texture(2,W3DShaderManager::getShaderTexture(2));
DX8Wrapper::_Get_D3D_Device8()->SetPixelShader(m_dwBaseNoise2PixelShader);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_MINFILTER, D3DTEXF_POINT);
DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
terrainShader2Stage.updateNoise1(((D3DXMATRIX*)&curView),&inv, false); //get texture projection matrix
DX8Wrapper::_Set_DX8_Transform(D3DTS_TEXTURE1, curView);
terrainShader2Stage.updateNoise2(((D3DXMATRIX*)&curView),&inv, false); //get texture projection matrix
DX8Wrapper::_Set_DX8_Transform(D3DTS_TEXTURE2, curView);
DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
// Two output coordinates are used.
DX8Wrapper::Set_DX8_Texture_Stage_State(2, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
return TRUE;
}
void RoadShaderPixelShader::reset(void)
{
DX8Wrapper::_Get_D3D_Device8()->SetPixelShader(0); //turn off pixel shader
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU|0);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU|1);
DX8Wrapper::Set_DX8_Texture_Stage_State( 2, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 2, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU|2);
DX8Wrapper::Set_DX8_Texture_Stage_State( 3, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 3, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU|3);
DX8Wrapper::Invalidate_Cached_Render_States();
}
Int RoadShader2Stage::init( void )
{
//no special device validation needed - anything in our min spec should handle this.
W3DShaders[W3DShaderManager::ST_ROAD_BASE]=&roadShader2Stage;
W3DShadersPassCount[W3DShaderManager::ST_ROAD_BASE]=1;
W3DShaders[W3DShaderManager::ST_ROAD_BASE_NOISE1]=&roadShader2Stage;
W3DShadersPassCount[W3DShaderManager::ST_ROAD_BASE_NOISE1]=1;
W3DShaders[W3DShaderManager::ST_ROAD_BASE_NOISE2]=&roadShader2Stage;
W3DShadersPassCount[W3DShaderManager::ST_ROAD_BASE_NOISE2]=1;
W3DShaders[W3DShaderManager::ST_ROAD_BASE_NOISE12]=&roadShader2Stage;
W3DShadersPassCount[W3DShaderManager::ST_ROAD_BASE_NOISE12]=2;
return TRUE;
}
Int RoadShader2Stage::set(Int pass)
{
//First stage always contains base texture.
DX8Wrapper::Set_Texture(0,W3DShaderManager::getShaderTexture(0));
//Force system to apply world/view transforms.
DX8Wrapper::Apply_Render_State_Changes();
DX8Wrapper::Set_DX8_Render_State(D3DRS_ZFUNC,D3DCMP_LESSEQUAL);
DX8Wrapper::Set_DX8_Render_State(D3DRS_ZWRITEENABLE,FALSE);
DX8Wrapper::Set_DX8_Render_State(D3DRS_LIGHTING, FALSE);
// Modulate the diffuse color with the texture as lighting comes from diffuse.
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_TEXCOORDINDEX, 0 );
DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHABLENDENABLE,true); //blend roads into terrain
if (pass == 0)
{
DX8Wrapper::Set_DX8_Render_State(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);
DX8Wrapper::Set_DX8_Render_State(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);
if (W3DShaderManager::getCurrentShader() >= W3DShaderManager::ST_ROAD_BASE_NOISE1)
{ //second texture unit will contain a noise pass
Matrix4x4 curView;
DX8Wrapper::_Get_DX8_Transform(D3DTS_VIEW, curView);
D3DXMATRIX inv;
float det;
D3DXMatrixInverse(&inv, &det, (D3DXMATRIX*)&curView);
if (TheGlobalData && TheGlobalData->m_trilinearTerrainTex)
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
else
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MIPFILTER, D3DTEXF_POINT);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
// Two output coordinates are used.
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_MODULATE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAARG2, D3DTA_CURRENT );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
if (W3DShaderManager::getCurrentShader() == W3DShaderManager::ST_ROAD_BASE_NOISE12)
{ //full shader, apply noise 1 in pass 0.
DX8Wrapper::Set_Texture(1,W3DShaderManager::getShaderTexture(1));
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
terrainShader2Stage.updateNoise1(((D3DXMATRIX*)&curView),&inv, false); //get texture projection matrix
DX8Wrapper::_Set_DX8_Transform(D3DTS_TEXTURE1, curView);
}
else
{ //single noise texture shader
if (W3DShaderManager::getCurrentShader() == W3DShaderManager::ST_ROAD_BASE_NOISE1)
{ //cloud map
DX8Wrapper::Set_Texture(1,W3DShaderManager::getShaderTexture(1));
terrainShader2Stage.updateNoise1(((D3DXMATRIX*)&curView),&inv, false); //update curView with texture matrix
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
}
else
{ //light map
DX8Wrapper::Set_Texture(1,W3DShaderManager::getShaderTexture(2));
terrainShader2Stage.updateNoise2(((D3DXMATRIX*)&curView),&inv, false); //update curView with texture matrix
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MINFILTER, D3DTEXF_POINT);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
}
DX8Wrapper::_Set_DX8_Transform(D3DTS_TEXTURE1, curView);
}
}
else
{ //just base texturing
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
}
} //pass 0
else
{ //pass 1, apply additional noise pass
Matrix4x4 curView;
DX8Wrapper::_Get_DX8_Transform(D3DTS_VIEW, curView);
D3DXMATRIX inv;
float det;
D3DXMatrixInverse(&inv, &det, (D3DXMATRIX*)&curView);
if (TheGlobalData && TheGlobalData->m_trilinearTerrainTex)
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
else
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MIPFILTER, D3DTEXF_POINT);
DX8Wrapper::Set_Texture(1,W3DShaderManager::getShaderTexture(2));
terrainShader2Stage.updateNoise2(((D3DXMATRIX*)&curView),&inv, false); //update curView with texture matrix
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MINFILTER, D3DTEXF_POINT);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
// Two output coordinates are used.
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
//Copy alpha channel into stage 1 but mask out color channel by replacing with white.
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
//Force color channel to white by copying the alpha into RGB
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE|D3DTA_ALPHAREPLICATE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG2);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_BLENDCURRENTALPHA);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAARG2, D3DTA_CURRENT );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
//Modulate into existing roads with clouds applied. - only apply where roads are transparent by
//using road texture as a mask.
DX8Wrapper::Set_DX8_Render_State(D3DRS_SRCBLEND,D3DBLEND_ZERO);
DX8Wrapper::Set_DX8_Render_State(D3DRS_DESTBLEND,D3DBLEND_SRCCOLOR);
DX8Wrapper::_Set_DX8_Transform(D3DTS_TEXTURE0, curView);
}
return TRUE;
}
void RoadShader2Stage::reset(void)
{
ShaderClass::Invalidate();
//Free references to textures
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU|0);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU|1);
}
/** List of all custom shader lists - each list in this list contains variations of the same
shader to allow it to work on different hardware configurations.
*/
W3DShaderInterface **MasterShaderList[]=
{
TerrainShaderList,
ShroudShaderList,
FlatShroudShaderList,
RoadShaderList,
MaskShaderList,
CloudShaderList,
FlatTerrainShaderList,
NULL
};
/** List of all custom filter lists - each list in this list contains variations of the same
filter to allow it to work on different hardware configurations.
*/
W3DFilterInterface **MasterFilterList[]=
{
ScreenDefaultFilterList,
ScreenBWFilterList,
ScreenMotionBlurFilterList,
ScreenCrossFadeFilterList,
NULL
};
// W3DShaderManager::W3DShaderManager =========================================
/** Constructor - just clears some variables */
//=============================================================================
W3DShaderManager::W3DShaderManager(void)
{
m_currentShader = ST_INVALID;
m_currentFilter = FT_NULL_FILTER;
m_oldRenderSurface = NULL;
m_renderTexture = NULL;
m_newRenderSurface = NULL;
m_oldDepthSurface = NULL;
m_renderingToTexture = false;
Int i;
for (i=0; iGetRenderTarget(&m_oldRenderSurface);
m_oldRenderSurface->GetDesc(&desc);
hr=DX8Wrapper::_Get_D3D_Device8()->CreateTexture(desc.Width,desc.Height,1,D3DUSAGE_RENDERTARGET,desc.Format,D3DPOOL_DEFAULT,&m_renderTexture);
if (hr != S_OK)
{
if (m_oldRenderSurface) m_oldRenderSurface->Release();
m_oldRenderSurface = NULL;
m_renderTexture = NULL;
} else {
hr = m_renderTexture->GetSurfaceLevel(0, &m_newRenderSurface);
if (hr != S_OK)
{
if (m_renderTexture) m_renderTexture->Release();
m_renderTexture = NULL;
m_newRenderSurface = NULL;
} else {
hr = DX8Wrapper::_Get_D3D_Device8()->GetDepthStencilSurface(&m_oldDepthSurface);
if (hr != S_OK)
{
if (m_newRenderSurface) m_newRenderSurface->Release();
if (m_renderTexture) m_renderTexture->Release();
m_renderTexture = NULL;
m_newRenderSurface = NULL;
m_oldDepthSurface = NULL;
}
}
}
}
W3DShaderInterface **shaders;
for (i=0; MasterShaderList[i] != NULL; i++)
{
shaders=MasterShaderList[i];
for (j=0; shaders[j] != NULL; j++)
{
if (shaders[j]->init())
break; //found a working shader
}
}
W3DFilterInterface **filters;
for (i=0; MasterFilterList[i] != NULL; i++)
{
filters=MasterFilterList[i];
for (j=0; filters[j] != NULL; j++)
{
if (filters[j]->init())
break; //found a working shader
}
}
DEBUG_LOG(("ShaderManager ChipsetID %d\n", res));
}
// W3DShaderManager::shutdown =======================================================
/** Any shaders which allocate resources will be allowed to free them */
//=============================================================================
void W3DShaderManager::shutdown(void)
{
if (m_newRenderSurface) m_newRenderSurface->Release();
if (m_renderTexture) m_renderTexture->Release();
if (m_oldRenderSurface) m_oldRenderSurface->Release();
if (m_oldDepthSurface) m_oldDepthSurface->Release();
m_renderTexture = NULL;
m_newRenderSurface = NULL;
m_oldDepthSurface = NULL;
m_oldRenderSurface = NULL;
m_currentShader = ST_INVALID;
m_currentFilter = FT_NULL_FILTER;
//release any assets associated with a shader (vertex/pixel shaders, textures, etc.)
for (Int i=0; ishutdown();
}
}
for (i=0; i < FT_MAX; i++)
{
if (W3DFilters[i])
{
W3DFilters[i]->shutdown();
}
}
}
// W3DShaderManager::getShaderPasses =======================================================
/** Return number of renderig passes required in perform the desired shader on current
hardware. App will need to re-render the polygons this many times to complete the
effect.
*/
//=============================================================================
Int W3DShaderManager::getShaderPasses(ShaderTypes shader)
{
return W3DShadersPassCount[shader];
}
// W3DShaderManager::setShader =======================================================
/** Must call this method before each rendering pass in order to perform proper D3D
setup for each shader.
*/
//=============================================================================
Int W3DShaderManager::setShader(ShaderTypes shader, Int pass)
{
if (shader == m_currentShader && pass == m_currentShaderPass)
return TRUE; //shader is already set
m_currentShader=shader;
m_currentShaderPass = pass;
if (W3DShaders[shader])
return W3DShaders[shader]->set(pass);
return FALSE;
}
// W3DShaderManager::resetShader =======================================================
/** Must call this method after all polygons and rendering passes have been submitted.
This method allows D3D to reset itself to a default state that doesn't conflict
with the WW3D2 Shader system.
*/
//=============================================================================
void W3DShaderManager::resetShader(ShaderTypes shader)
{
if (m_currentShader == ST_INVALID)
return; //last shader is already reset.
if (W3DShaders[shader])
W3DShaders[shader]->reset();
m_currentShader = ST_INVALID;
}
// W3DShaderManager::filterPreRender =======================================================
/** Call to view filter shaders before rendering starts.
*/
//=============================================================================
Bool W3DShaderManager::filterPreRender(FilterTypes filter, Bool &skipRender, CustomScenePassModes &scenePassMode)
{
if (W3DFilters[filter])
{ Bool result=W3DFilters[filter]->preRender(skipRender,scenePassMode);
if (result)
m_currentFilter = filter;
return result;
}
return FALSE;
}
// W3DShaderManager::filterPostRender =======================================================
/** Call to view filter shaders after rendering is complete.
*/
//=============================================================================
Bool W3DShaderManager::filterPostRender(FilterTypes filter, enum FilterModes mode, Coord2D &scrollDelta, Bool &doExtraRender)
{
if (W3DFilters[filter])
return W3DFilters[filter]->postRender(mode, scrollDelta,doExtraRender);
m_currentFilter = FT_NULL_FILTER;
return FALSE;
}
// W3DShaderManager::filterPostRender =======================================================
/** Call to view filter shaders after rendering is complete.
*/
//=============================================================================
static Bool filterSetup(FilterTypes filter, enum FilterModes mode);
Bool W3DShaderManager::filterSetup(FilterTypes filter, enum FilterModes mode)
{
if (W3DFilters[filter])
return W3DFilters[filter]->setup(mode);
return FALSE;
}
/*Draws 2 triangles covering the viewport given the current render states*/
void W3DShaderManager::drawViewport(Int color)
{
LPDIRECT3DDEVICE8 pDev=DX8Wrapper::_Get_D3D_Device8();
struct _TRANS_LIT_TEX_VERTEX {
D3DXVECTOR4 p;
DWORD color; // diffuse color
float u;
float v;
} v[4];
Int xpos, ypos, width, height;
TheTacticalView->getOrigin(&xpos,&ypos);
width=TheTacticalView->getWidth();
height=TheTacticalView->getHeight();
//bottom right
v[0].p = D3DXVECTOR4( xpos+width-0.5f, ypos+height-0.5f, 0.0f, 1.0f );
v[0].u = (Real)(xpos+width)/(Real)TheDisplay->getWidth(); v[0].v = (Real)(ypos+height)/(Real)TheDisplay->getHeight();
//top right
v[1].p = D3DXVECTOR4( xpos+width-0.5f, ypos-0.5f, 0.0f, 1.0f );
v[1].u = (Real)(xpos+width)/(Real)TheDisplay->getWidth(); v[1].v = (Real)(ypos)/(Real)TheDisplay->getHeight();
//bottom left
v[2].p = D3DXVECTOR4( xpos-0.5f, ypos+height-0.5f, 0.0f, 1.0f );
v[2].u = (Real)(xpos)/(Real)TheDisplay->getWidth(); v[2].v = (Real)(ypos+height)/(Real)TheDisplay->getHeight();
//top left
v[3].p = D3DXVECTOR4( xpos-0.5f, ypos-0.5f, 0.0f, 1.0f );
v[3].u = (Real)(xpos)/(Real)TheDisplay->getWidth(); v[3].v = (Real)(ypos)/(Real)TheDisplay->getHeight();
v[0].color = color;
v[1].color = color;
v[2].color = color;
v[3].color = color;
//draw polygons like this is very inefficient but for only 2 triangles, it's
//not worth bothering with index/vertex buffers.
pDev->SetVertexShader(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
pDev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v, sizeof(_TRANS_LIT_TEX_VERTEX));
}
// W3DShaderManager::startRenderToTexture =======================================================
/** Starts rendering to a texture.
*/
//=============================================================================
void W3DShaderManager::startRenderToTexture(void)
{
DEBUG_ASSERTCRASH(!m_renderingToTexture, ("Already rendering to texture - cannot nest calls."));
if (m_renderingToTexture || m_newRenderSurface==NULL || m_oldDepthSurface==NULL) return;
HRESULT hr = DX8Wrapper::_Get_D3D_Device8()->SetRenderTarget(m_newRenderSurface,m_oldDepthSurface);
DEBUG_ASSERTCRASH(hr==S_OK, ("Set target failed unexpectedly."));
if (hr != S_OK)
return;
m_renderingToTexture = true;
if (TheGlobalData->m_showSoftWaterEdge)
{ //Soft water edges use frame buffer destination alpha so we must clear it to a known value.
if (m_currentFilter == FT_VIEW_MOTION_BLUR_FILTER || m_currentFilter == FT_VIEW_CROSSFADE)
{ //these filters rely on the previous frame being visible so we must be careful about clearing
//frame buffer. Only clear the alpha channel
DX8Wrapper::Set_DX8_Render_State(D3DRS_COLORWRITEENABLE,D3DCOLORWRITEENABLE_ALPHA); //only clear alpha
ShaderClass shader=ShaderClass::_PresetOpaqueSolidShader;
shader.Set_Depth_Compare(ShaderClass::PASS_ALWAYS);
shader.Set_Depth_Mask(ShaderClass::DEPTH_WRITE_DISABLE);
DX8Wrapper::Set_Shader(shader);
VertexMaterialClass *vmat=VertexMaterialClass::Get_Preset(VertexMaterialClass::PRELIT_DIFFUSE);
DX8Wrapper::Set_Material(vmat);
REF_PTR_RELEASE(vmat); //no need to keep a reference since it's a preset.
drawViewport(0x00ffffff | (((Int)(TheWaterTransparency->m_minWaterOpacity*255.0f)) <<24));
DX8Wrapper::Set_DX8_Render_State(D3DRS_COLORWRITEENABLE,D3DCOLORWRITEENABLE_RED|D3DCOLORWRITEENABLE_GREEN|D3DCOLORWRITEENABLE_BLUE); //disable writes to alpha
}
else //normal clear that overwrites everything.
DX8Wrapper::Clear(true, false, Vector3( 0.0f, 0.0f, 0.0f ), TheWaterTransparency->m_minWaterOpacity);
}
}
// W3DShaderManager::startRenderToTexture =======================================================
/** Ends rendering to a texture.
*/
//=============================================================================
IDirect3DTexture8 *W3DShaderManager::endRenderToTexture(void)
{
DEBUG_ASSERTCRASH(m_renderingToTexture, ("Not rendering to texture."));
if (!m_renderingToTexture) return NULL;
HRESULT hr = DX8Wrapper::_Get_D3D_Device8()->SetRenderTarget(m_oldRenderSurface,m_oldDepthSurface); //restore original render target
DEBUG_ASSERTCRASH(hr==S_OK, ("Set target failed unexpectedly."));
if (hr == S_OK)
{
//assume render target texure will be in stage 0. Most hardware has "conditional" support for
//non-power-of-2 textures so we must force some required states:
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ADDRESSW, D3DTADDRESS_CLAMP);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_MIPFILTER, D3DTEXF_NONE);
m_renderingToTexture = false;
}
return m_renderTexture;
}
/**Returns texture containing the image that was last rendered using any of the effects requiring render target
textures. Used mostly for cross-fading effects that need an unmodified version of the view before the effect
was applied. NOTE: This texture does not survive device reset.. so quit effect on reset!*/
IDirect3DTexture8 *W3DShaderManager::getRenderTexture(void)
{
return m_renderTexture;
}
enum GraphicsVenderID
{
DC_NVIDIA_VENDOR_ID = 0x10DE,
DC_3DFX_VENDOR_ID = 0x121A,
DC_ATI_VENDOR_ID = 0x1002
};
// W3DShaderManager::ChipsetType =======================================================
/** Returns the chipset used by the currently active rendering device. Can be useful
for coding around specific driver bugs.
*/
//=============================================================================
ChipsetType W3DShaderManager::getChipset( void )
{
//check if globaldata has an override for current chipset
if (TheGlobalData && TheGlobalData->m_chipSetType != DC_UNKNOWN)
return (ChipsetType)TheGlobalData->m_chipSetType;
ChipsetType chip=DC_UNKNOWN;
IDirect3D8* d3d8Interface=DX8Wrapper::_Get_D3D8();
if (d3d8Interface && DX8Wrapper::_Get_D3D_Device8())
{
D3DADAPTER_IDENTIFIER8 did;
::ZeroMemory(&did, sizeof(D3DADAPTER_IDENTIFIER8));
/* HRESULT res = */ d3d8Interface->GetAdapterIdentifier(0,D3DENUM_NO_WHQL_LEVEL,&did);
*((LARGE_INTEGER*)&m_driverVersion) = did.DriverVersion;
if(did.VendorId == DC_NVIDIA_VENDOR_ID)
{
m_currentVendor = DC_NVIDIA_VENDOR_ID;
if (did.DeviceId == 0x20)
return DC_TNT;
if (did.DeviceId >= 0x28 && did.DeviceId < 0x100)
return DC_TNT2;
if ( (did.DeviceId >= 0x100 && did.DeviceId <= 0x103) || //GeForce
(did.DeviceId >= 0x110 && did.DeviceId <= 0x113) || //GeForce2 MX
(did.DeviceId >= 0x150 && did.DeviceId <= 0x153) ) //GeForce2
return DC_GEFORCE2;
if (did.DeviceId >= 0x200 && did.DeviceId < 0x250)
return DC_GEFORCE3;
if (did.DeviceId >= 0x250)
return DC_GEFORCE4;
}
else
if(did.VendorId == DC_3DFX_VENDOR_ID)
{
m_currentVendor = DC_3DFX_VENDOR_ID;
if (did.DeviceId == 0x0002)
return DC_VOODOO2;
if (did.DeviceId == 0x0005)
return DC_VOODOO3;
if (did.DeviceId == 0x0008) ///@todo: Just guessing on this one - find actual Voodoo4 deviceID.
return DC_VOODOO4;
if (did.DeviceId == 0x0009)
return DC_VOODOO5;
}
else
if(did.VendorId == DC_ATI_VENDOR_ID)
{
m_currentVendor = DC_ATI_VENDOR_ID;
if (did.DeviceId == 0x5144)
return DC_RADEON;
if (did.DeviceId == 0x514C)
return DC_RADEON_8500;
if (did.DeviceId == 0x4e44)
return DC_RADEON_9700;
}
//None of the vendor specific ID's matched so use generic means to classify the card
Int maxTextures=DX8Wrapper::Get_Current_Caps()->Get_Max_Simultaneous_Textures();
Real pixelShaderVersion;
char buf[256];
//Convert version to Real
sprintf(buf,"%d.%d",DX8Wrapper::Get_Current_Caps()->Get_Pixel_Shader_Major_Version(),DX8Wrapper::Get_Current_Caps()->Get_Pixel_Shader_Minor_Version());
sscanf(buf,"%f",&pixelShaderVersion);
if (maxTextures >= 4)
{ if (pixelShaderVersion >= 1.1f)
chip=DC_GENERIC_PIXEL_SHADER_1_1;
if (pixelShaderVersion >= 1.4f)
chip=DC_GENERIC_PIXEL_SHADER_1_4;
if (maxTextures >= 8 && pixelShaderVersion >= 2.0f)
chip=DC_GENERIC_PIXEL_SHADER_2_0;
}
} //D3D8 interface and device exist.
return chip;
}
//=============================================================================
// WaterRenderObjClass::LoadAndCreateShader
//=============================================================================
/** Loads and creates a D3D pixel or vertex shader.*/
//=============================================================================
HRESULT W3DShaderManager::LoadAndCreateD3DShader(char* strFilePath, const DWORD* pDeclaration, DWORD Usage, Bool ShaderType, DWORD* pHandle)
{
if (getChipset() < DC_GENERIC_PIXEL_SHADER_1_1)
return E_FAIL; //don't allow loading any shaders if hardware can't handle it.
try
{
File *file = NULL;
HRESULT hr;
file = TheFileSystem->openFile(strFilePath, File::READ | File::BINARY);
if (file == NULL)
{
OutputDebugString("Could not find file \n" );
return E_FAIL;
}
FileInfo fileInfo;
TheFileSystem->getFileInfo(AsciiString(strFilePath), &fileInfo);
DWORD dwFileSize = fileInfo.sizeLow;
const DWORD* pShader = (DWORD*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwFileSize);
if (!pShader)
{
OutputDebugString( "Failed to allocate memory to load shader\n " );
return E_FAIL;
}
file->read((void *)pShader, dwFileSize);
file->close();
file = NULL;
if (ShaderType == TRUE)//SHADERTYPE_VERTEX)
{
hr = DX8Wrapper::_Get_D3D_Device8()->CreateVertexShader(pDeclaration, pShader, pHandle, Usage);
}
else if (ShaderType == FALSE)//SHADERTYPE_PIXEL)
{
hr = DX8Wrapper::_Get_D3D_Device8()->CreatePixelShader(pShader, pHandle);
}
HeapFree(GetProcessHeap(), 0, (void*)pShader);
if (FAILED(hr))
{
OutputDebugString( "Failed to create shader\n ");
return E_FAIL;
}
}
catch(...)
{
OutputDebugString( "Error opening file \n" );
return E_FAIL;
}
return S_OK;
}
//For the MP test, we're enforcing high min-spec requirements that need to be verified.
#define MIN_INTEL_CPU_FREQ 1300
#define MIN_AMD_CPU_FREQ 1100
#define MIN_ACCEPTED_FREQUENCY 1300
#define MIN_ACCEPTED_MEMORY (1024*1024*256) //256 MB
#define MIN_ACCEPTED_TEXTURE_MEMORY (1024*1024*30) //30 MB
/**Hack to give gameengine access to this function*/
Bool testMinimumRequirements(ChipsetType *videoChipType, CpuType *cpuType, Int *cpuFreq, Int *numRAM, Real *intBenchIndex, Real *floatBenchIndex, Real *memBenchIndex)
{
return W3DShaderManager::testMinimumRequirements(videoChipType,cpuType,cpuFreq,numRAM,intBenchIndex,floatBenchIndex,memBenchIndex);
}
Bool W3DShaderManager::testMinimumRequirements(ChipsetType *videoChipType, CpuType *cpuType, Int *cpuFreq, Int *numRAM, Real *intBenchIndex, Real *floatBenchIndex, Real *memBenchIndex)
{
if (videoChipType)
*videoChipType = getChipset();
if (cpuType)
{
*cpuType = XX; //unknown
//Check if it's an Athlon
if (CPUDetectClass::Get_Processor_Manufacturer() == CPUDetectClass::MANUFACTURER_AMD &&
CPUDetectClass::Get_AMD_Processor() >= CPUDetectClass::AMD_PROCESSOR_ATHLON_025)
*cpuType = K7;
//Check if it's a P3
if (CPUDetectClass::Get_Processor_Manufacturer() == CPUDetectClass::MANUFACTURER_INTEL &&
CPUDetectClass::Get_Intel_Processor() >= CPUDetectClass::INTEL_PROCESSOR_PENTIUM_III_MODEL_7)
*cpuType = P3;
//Check if it's a P4
if (CPUDetectClass::Get_Processor_Manufacturer() == CPUDetectClass::MANUFACTURER_INTEL &&
CPUDetectClass::Get_Intel_Processor() >= CPUDetectClass::INTEL_PROCESSOR_PENTIUM4)
*cpuType = P4;
}
if (cpuFreq)
*cpuFreq=CPUDetectClass::Get_Processor_Speed();
if (numRAM)
*numRAM=CPUDetectClass::Get_Total_Physical_Memory();
if (intBenchIndex && floatBenchIndex && memBenchIndex)
{
RunBenchmark(0, NULL, floatBenchIndex, intBenchIndex, memBenchIndex);
}
return TRUE;
}
/**Try to guess how well the video card will handle the game assuming very fast CPU*/
StaticGameLODLevel W3DShaderManager::getGPUPerformanceIndex(void)
{
ChipsetType chipType;
StaticGameLODLevel detailSetting=STATIC_GAME_LOD_LOW; //assume lowest settings for now.
if ((chipType=getChipset()) != DC_UNKNOWN)
{ //a known video card so we can make some assumptions
if (chipType >= DC_GEFORCE2)
detailSetting=STATIC_GAME_LOD_LOW; //these cards need multiple terrain passes.
if (chipType >= DC_GENERIC_PIXEL_SHADER_1_1) //these cards can do terrain in single pass.
detailSetting=STATIC_GAME_LOD_HIGH;
}
return detailSetting;
}
/**We need a hardware independent method to compare different CPU's. For lack of anything better, we'll
use time to calculate PIE using a slow random number algorithm.*/
/**Used to test function call overhead*/
void add(float *sum,float *addend)
{
*sum = *sum + *addend;
}
/**Returns seconds needed to run the test*/
Real W3DShaderManager::GetCPUBenchTime(void)
{
float ztot, yran, ymult, ymod, x, y, z, pi, prod;
long int low, ixran, itot, j, iprod;
__int64 endTime64,freq64,startTime64;
QueryPerformanceFrequency((LARGE_INTEGER *)&freq64);
QueryPerformanceCounter((LARGE_INTEGER *)&startTime64);
ztot = 0.0;
low = 1;
ixran = 1907;
yran = 5813.0;
ymult = 1307.0;
ymod = 5471.0;
itot = 560000; //total iterations. This value ends up running at ~30 fps on our P4-2.2Ghz.
for(j=1; j<=itot; j++)
{
iprod = 27611 * ixran;
ixran = iprod - 74383*(long int)(iprod/74383);
x = (float)ixran / 74383.0;
prod = ymult * yran;
yran = (prod - ymod*(long int)(prod/ymod));
y = yran / ymod;
z = x*x + y*y;
add(&ztot,&z);
if ( z <= 1.0 )
{
low = low + 1;
}
}
pi = 4.0 * (float)low/(float)itot;
QueryPerformanceCounter((LARGE_INTEGER *)&endTime64);
return ((double)(endTime64-startTime64)/(double)(freq64));
}
// W3DShaderManager::setShroudTex =======================================================
/** Puts the shroud texture into a texture stage.
*/
//=============================================================================
Int W3DShaderManager::setShroudTex(Int stage)
{
//We need to scale so shroud texel stretches over one full terrain cell. Each texel
//is 1/128 the size of full texture. (assuming 128x128 vid-mem texture).
W3DShroud *shroud;
if ((shroud=TheTerrainRenderObject->getShroud()) != 0)
{
DX8Wrapper::Set_Texture(stage, shroud->getShroudTexture());
DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
DX8Wrapper::Set_DX8_Texture_Stage_State(stage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
DX8Wrapper::Set_DX8_Texture_Stage_State( stage, D3DTSS_COLORARG1, D3DTA_TEXTURE );
DX8Wrapper::Set_DX8_Texture_Stage_State( stage, D3DTSS_COLORARG2, D3DTA_CURRENT );
DX8Wrapper::Set_DX8_Texture_Stage_State( stage, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
DX8Wrapper::Set_DX8_Texture_Stage_State( stage, D3DTSS_ALPHAARG2, D3DTA_CURRENT );
DX8Wrapper::Set_DX8_Texture_Stage_State( stage, D3DTSS_COLOROP, D3DTOP_MODULATE );
DX8Wrapper::Set_DX8_Texture_Stage_State( stage, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );
D3DXMATRIX inv;
float det;
Matrix4x4 curView;
DX8Wrapper::_Get_DX8_Transform(D3DTS_VIEW, curView);
D3DXMatrixInverse(&inv, &det, (D3DXMATRIX*)&curView);
D3DXMATRIX scale,offset;
//We need to make all world coordinates be relative to the heightmap data origin since that
//is where the shroud begins.
float xoffset = 0;
float yoffset = 0;
Real width=shroud->getCellWidth();
Real height=shroud->getCellHeight();
if (TheTerrainRenderObject->getMap())
{ //subtract origin position from all coordinates. Origin is shifted by 1 cell width/height to allow for unused border texels.
xoffset = -(float)shroud->getDrawOriginX() + width;
yoffset = -(float)shroud->getDrawOriginY() + height;
}
D3DXMatrixTranslation(&offset, xoffset, yoffset,0);
width = 1.0f/(width*shroud->getTextureWidth());
height = 1.0f/(height*shroud->getTextureHeight());
D3DXMatrixScaling(&scale, width, height, 1);
*((D3DXMATRIX *)&curView) = (inv * offset) * scale;
DX8Wrapper::_Set_DX8_Transform((D3DTRANSFORMSTATETYPE )(D3DTS_TEXTURE0+stage), *((Matrix4x4*)&curView));
return TRUE;
}
return FALSE;
}
Int FlatTerrainShader2Stage::init( void )
{
//no special device validation needed - anything in our min spec should handle this.
W3DShaders[W3DShaderManager::ST_FLAT_TERRAIN_BASE]=&flatTerrainShader2Stage;
W3DShadersPassCount[W3DShaderManager::ST_FLAT_TERRAIN_BASE]=1;
W3DShaders[W3DShaderManager::ST_FLAT_TERRAIN_BASE_NOISE1]=&flatTerrainShader2Stage;
W3DShadersPassCount[W3DShaderManager::ST_FLAT_TERRAIN_BASE_NOISE1]=2;
W3DShaders[W3DShaderManager::ST_FLAT_TERRAIN_BASE_NOISE2]=&flatTerrainShader2Stage;
W3DShadersPassCount[W3DShaderManager::ST_FLAT_TERRAIN_BASE_NOISE2]=2;
W3DShaders[W3DShaderManager::ST_FLAT_TERRAIN_BASE_NOISE12]=&flatTerrainShader2Stage;
W3DShadersPassCount[W3DShaderManager::ST_FLAT_TERRAIN_BASE_NOISE12]=2;
return TRUE;
}
void FlatTerrainShader2Stage::reset(void)
{
ShaderClass::Invalidate();
//Free references to textures
DX8Wrapper::_Get_D3D_Device8()->SetTexture(0, NULL);
DX8Wrapper::_Get_D3D_Device8()->SetTexture(1, NULL);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU|0);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU|1);
}
Int FlatTerrainShader2Stage::set(Int pass)
{
//force WW3D2 system to set it's states so it won't later overwrite our custom settings.
DX8Wrapper::Apply_Render_State_Changes();
if (TheGlobalData && TheGlobalData->m_bilinearTerrainTex || TheGlobalData->m_trilinearTerrainTex) {
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
} else {
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MINFILTER, D3DTEXF_POINT);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MAGFILTER, D3DTEXF_POINT);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MINFILTER, D3DTEXF_POINT);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MAGFILTER, D3DTEXF_POINT);
}
if (TheGlobalData && TheGlobalData->m_trilinearTerrainTex) {
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
} else {
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MIPFILTER, D3DTEXF_POINT);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MIPFILTER, D3DTEXF_POINT);
}
switch (pass)
{
case 0:
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
// Modulate the diffuse color with the texture as lighting comes from diffuse.
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
if (W3DShaderManager::getShaderTexture(0)) {
DX8Wrapper::_Get_D3D_Device8()->SetTexture(0, W3DShaderManager::getShaderTexture(0)->Peek_D3D_Texture());
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG2, D3DTA_CURRENT );
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
//We need to scale so shroud texel stretches over one full terrain cell. Each texel
//is 1/128 the size of full texture. (assuming 128x128 vid-mem texture).
W3DShroud *shroud;
if ((shroud=TheTerrainRenderObject->getShroud()) != 0)
{
D3DXMATRIX inv;
float det;
Matrix4x4 curView;
DX8Wrapper::_Get_DX8_Transform(D3DTS_VIEW, curView);
D3DXMatrixInverse(&inv, &det, (D3DXMATRIX*)&curView);
D3DXMATRIX scale,offset;
//We need to make all world coordinates be relative to the heightmap data origin since that
//is where the shroud begins.
float xoffset = 0;
float yoffset = 0;
Real width=shroud->getCellWidth();
Real height=shroud->getCellHeight();
if (TheTerrainRenderObject->getMap())
{ //subtract origin position from all coordinates. Origin is shifted by 1 cell width/height to allow for unused border texels.
xoffset = -(float)shroud->getDrawOriginX() + width;
yoffset = -(float)shroud->getDrawOriginY() + height;
}
D3DXMatrixTranslation(&offset, xoffset, yoffset,0);
width = 1.0f/(width*shroud->getTextureWidth());
height = 1.0f/(height*shroud->getTextureHeight());
D3DXMatrixScaling(&scale, width, height, 1);
*((D3DXMATRIX *)&curView) = (inv * offset) * scale;
DX8Wrapper::_Set_DX8_Transform((D3DTRANSFORMSTATETYPE )(D3DTS_TEXTURE0), *((Matrix4x4*)&curView));
}
} else {
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG2 );
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_TEXCOORDINDEX, 0 );
}
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
// Modulate the diffuse color with the texture as lighting comes from diffuse.
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_MODULATE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_TEXCOORDINDEX, 0 );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU|0);
DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHABLENDENABLE,false);
break;
case 1:
// Noise/cloud pass
Matrix4x4 curView;
DX8Wrapper::_Get_DX8_Transform(D3DTS_VIEW, curView);
//these states apply to all noise/cloud combination passes
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
// Two output coordinates are used.
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
//blend into frame buffer
DX8Wrapper::Set_DX8_Render_State(D3DRS_ALPHABLENDENABLE,true);
DX8Wrapper::Set_DX8_Render_State(D3DRS_SRCBLEND,D3DBLEND_DESTCOLOR);
DX8Wrapper::Set_DX8_Render_State(D3DRS_DESTBLEND,D3DBLEND_ZERO);
D3DXMATRIX inv;
float det;
D3DXMatrixInverse(&inv, &det, (D3DXMATRIX*)&curView);
if (W3DShaderManager::getCurrentShader() == W3DShaderManager::ST_FLAT_TERRAIN_BASE_NOISE12)
{
//setup cloud pass
terrainShader2Stage.updateNoise1(((D3DXMATRIX*)&curView),&inv); //update curView with texture matrix
DX8Wrapper::_Set_DX8_Transform(D3DTS_TEXTURE0, curView);
//clouds always need bilinear filtering
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
DX8Wrapper::_Get_D3D_Device8()->SetTexture(0, W3DShaderManager::getShaderTexture(2)->Peek_D3D_Texture());
//setup noise pass
terrainShader2Stage.updateNoise2(((D3DXMATRIX*)&curView),&inv);
DX8Wrapper::_Set_DX8_Transform(D3DTS_TEXTURE1, curView);
//noise always needs point/linear filtering. Why point!?
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MINFILTER, D3DTEXF_POINT);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_MODULATE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
// Two output coordinates are used.
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
DX8Wrapper::_Get_D3D_Device8()->SetTexture(1, W3DShaderManager::getShaderTexture(3)->Peek_D3D_Texture());
} //ST_TERRAIN_BASE_NOISE12
else
{ //only 1 noise or cloud texture
// Now setup the texture pipeline.
if (W3DShaderManager::getCurrentShader() == W3DShaderManager::ST_FLAT_TERRAIN_BASE_NOISE1)
{ //setup cloud pass
DX8Wrapper::_Get_D3D_Device8()->SetTexture(0, W3DShaderManager::getShaderTexture(2)->Peek_D3D_Texture());
terrainShader2Stage.updateNoise1(((D3DXMATRIX*)&curView),&inv); //update curView with texture matrix
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
}
else
{
//setup noise pass
DX8Wrapper::_Get_D3D_Device8()->SetTexture(0, W3DShaderManager::getShaderTexture(3)->Peek_D3D_Texture());
terrainShader2Stage.updateNoise2(((D3DXMATRIX*)&curView),&inv); //update curView with texture matrix
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MINFILTER, D3DTEXF_POINT);
DX8Wrapper::Set_DX8_Texture_Stage_State(1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
}
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
DX8Wrapper::_Set_DX8_Transform(D3DTS_TEXTURE0, *((Matrix4x4*)&curView));
}
break;
}
return TRUE;
}
Int FlatTerrainShaderPixelShader::shutdown(void)
{
if (m_dwBasePixelShader)
DX8Wrapper::_Get_D3D_Device8()->DeletePixelShader(m_dwBasePixelShader);
if (m_dwBase0PixelShader)
DX8Wrapper::_Get_D3D_Device8()->DeletePixelShader(m_dwBase0PixelShader);
if (m_dwBaseNoise1PixelShader)
DX8Wrapper::_Get_D3D_Device8()->DeletePixelShader(m_dwBaseNoise1PixelShader);
if (m_dwBaseNoise2PixelShader)
DX8Wrapper::_Get_D3D_Device8()->DeletePixelShader(m_dwBaseNoise2PixelShader);
m_dwBasePixelShader=NULL;
m_dwBase0PixelShader=NULL;
m_dwBaseNoise1PixelShader=NULL;
m_dwBaseNoise2PixelShader=NULL;
return TRUE;
}
Int FlatTerrainShaderPixelShader::init( void )
{
Int res;
#ifdef DISABLE_PIXEL_SHADERS
return false;
#endif
//this shader will also use the 2Stage shader for some of the passes so initialize it too.
if ((res=W3DShaderManager::getChipset()) >= DC_GENERIC_PIXEL_SHADER_1_1)
{
if (res >= DC_GENERIC_PIXEL_SHADER_1_1)
{
//this shader needs some assets that need to be loaded
//shader decleration
DWORD Declaration[]=
{
(D3DVSD_STREAM(0)),
(D3DVSD_REG(0, D3DVSDT_FLOAT3)), // Position
(D3DVSD_REG(1, D3DVSDT_D3DCOLOR)), // Diffuse
(D3DVSD_REG(2, D3DVSDT_FLOAT2)), // Texture Coordinates
(D3DVSD_REG(3, D3DVSDT_FLOAT2)), // Texture Coordinates
(D3DVSD_END())
};
//base version which doesn't apply any noise textures.
HRESULT hr = W3DShaderManager::LoadAndCreateD3DShader("shaders\\fterrain.pso", &Declaration[0], 0, false, &m_dwBasePixelShader);
if (FAILED(hr))
return FALSE;
//base version which doesn't apply any shroud textures.
hr = W3DShaderManager::LoadAndCreateD3DShader("shaders\\fterrain0.pso", &Declaration[0], 0, false, &m_dwBase0PixelShader);
if (FAILED(hr))
return FALSE;
//version which blends 1 noise texture.
hr = W3DShaderManager::LoadAndCreateD3DShader("shaders\\fterrainnoise.pso", &Declaration[0], 0, false, &m_dwBaseNoise1PixelShader);
if (FAILED(hr))
return FALSE;
//version which blends 2 noise textures.
hr = W3DShaderManager::LoadAndCreateD3DShader("shaders\\fterrainnoise2.pso", &Declaration[0], 0, false, &m_dwBaseNoise2PixelShader);
if (FAILED(hr))
return FALSE;
W3DShaders[W3DShaderManager::ST_FLAT_TERRAIN_BASE]=&flatTerrainShaderPixelShader;
W3DShaders[W3DShaderManager::ST_FLAT_TERRAIN_BASE_NOISE1]=&flatTerrainShaderPixelShader;
W3DShaders[W3DShaderManager::ST_FLAT_TERRAIN_BASE_NOISE2]=&flatTerrainShaderPixelShader;
W3DShaders[W3DShaderManager::ST_FLAT_TERRAIN_BASE_NOISE12]=&flatTerrainShaderPixelShader;
W3DShadersPassCount[W3DShaderManager::ST_FLAT_TERRAIN_BASE]=1;
W3DShadersPassCount[W3DShaderManager::ST_FLAT_TERRAIN_BASE_NOISE1]=1;
W3DShadersPassCount[W3DShaderManager::ST_FLAT_TERRAIN_BASE_NOISE2]=1;
W3DShadersPassCount[W3DShaderManager::ST_FLAT_TERRAIN_BASE_NOISE12]=1;
return TRUE;
}
}
return FALSE;
}
Int FlatTerrainShaderPixelShader::set(Int pass)
{
//setup base pass
Int curStage = 1;
// setup terrain [3/31/2003]
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
DX8Wrapper::Set_Texture(0, W3DShaderManager::getShaderTexture(2));
DX8Wrapper::Set_Texture(1, W3DShaderManager::getShaderTexture(2));
//force WW3D2 system to set it's states so it won't later overwrite our custom settings.
DX8Wrapper::Apply_Render_State_Changes();
DX8Wrapper::Set_DX8_Texture_Stage_State( curStage, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
DX8Wrapper::Set_DX8_Texture_Stage_State( curStage, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
//tell pixel shader which UV set to use for each stage
DX8Wrapper::Set_DX8_Texture_Stage_State( curStage, D3DTSS_TEXCOORDINDEX, 0 );
DX8Wrapper::Set_DX8_Texture_Stage_State(curStage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
if (TheGlobalData && TheGlobalData->m_bilinearTerrainTex || TheGlobalData->m_trilinearTerrainTex) {
DX8Wrapper::Set_DX8_Texture_Stage_State(curStage, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State(curStage, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
} else {
DX8Wrapper::Set_DX8_Texture_Stage_State(curStage, D3DTSS_MINFILTER, D3DTEXF_POINT);
DX8Wrapper::Set_DX8_Texture_Stage_State(curStage, D3DTSS_MAGFILTER, D3DTEXF_POINT);
}
if (TheGlobalData && TheGlobalData->m_trilinearTerrainTex) {
DX8Wrapper::Set_DX8_Texture_Stage_State(curStage, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
} else {
DX8Wrapper::Set_DX8_Texture_Stage_State(curStage, D3DTSS_MIPFILTER, D3DTEXF_POINT);
}
curStage = 0;
W3DShroud *shroud = TheTerrainRenderObject->getShroud();
if (shroud) {
DX8Wrapper::Set_DX8_Texture_Stage_State(curStage, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
DX8Wrapper::Set_DX8_Texture_Stage_State(curStage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
//We need to scale so shroud texel stretches over one full terrain cell. Each texel
//is 1/128 the size of full texture. (assuming 128x128 vid-mem texture).
{
D3DXMATRIX inv;
float det;
Matrix4x4 curView;
DX8Wrapper::_Get_DX8_Transform(D3DTS_VIEW, curView);
D3DXMatrixInverse(&inv, &det, (D3DXMATRIX*)&curView);
D3DXMATRIX scale,offset;
//We need to make all world coordinates be relative to the heightmap data origin since that
//is where the shroud begins.
float xoffset = 0;
float yoffset = 0;
Real width=shroud->getCellWidth();
Real height=shroud->getCellHeight();
if (TheTerrainRenderObject->getMap())
{ //subtract origin position from all coordinates. Origin is shifted by 1 cell width/height to allow for unused border texels.
xoffset = -(float)shroud->getDrawOriginX() + width;
yoffset = -(float)shroud->getDrawOriginY() + height;
}
D3DXMatrixTranslation(&offset, xoffset, yoffset,0);
width = 1.0f/(width*shroud->getTextureWidth());
height = 1.0f/(height*shroud->getTextureHeight());
D3DXMatrixScaling(&scale, width, height, 1);
*((D3DXMATRIX *)&curView) = (inv * offset) * scale;
DX8Wrapper::_Set_DX8_Transform((D3DTRANSFORMSTATETYPE )(D3DTS_TEXTURE0+curStage), *((Matrix4x4*)&curView));
}
DX8Wrapper::Set_DX8_Texture_Stage_State( curStage, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
DX8Wrapper::Set_DX8_Texture_Stage_State( curStage, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
DX8Wrapper::Set_DX8_Texture_Stage_State( curStage, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State( curStage, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
DX8Wrapper::_Get_D3D_Device8()->SetTexture(curStage, shroud->getShroudTexture()->Peek_D3D_Texture());
curStage++;
if (curStage==1) curStage++;
}
Bool doNoise1 = (W3DShaderManager::getCurrentShader() == W3DShaderManager::ST_FLAT_TERRAIN_BASE_NOISE1 ||
W3DShaderManager::getCurrentShader() == W3DShaderManager::ST_FLAT_TERRAIN_BASE_NOISE12);
if (doNoise1) { // Cloud pass.
Matrix4x4 curView;
DX8Wrapper::_Get_DX8_Transform(D3DTS_VIEW, curView);
D3DXMATRIX inv;
float det;
D3DXMatrixInverse(&inv, &det, (D3DXMATRIX*)&curView);
DX8Wrapper::Set_DX8_Texture_Stage_State(curStage, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
// Two output coordinates are used.
DX8Wrapper::Set_DX8_Texture_Stage_State(curStage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
DX8Wrapper::Set_DX8_Texture_Stage_State(curStage, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
DX8Wrapper::Set_DX8_Texture_Stage_State(curStage, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
DX8Wrapper::_Get_D3D_Device8()->SetTexture(curStage, W3DShaderManager::getShaderTexture(2)->Peek_D3D_Texture());
terrainShader2Stage.updateNoise1(((D3DXMATRIX*)&curView),&inv); //update curView with texture matrix
DX8Wrapper::_Set_DX8_Transform((D3DTRANSFORMSTATETYPE )(D3DTS_TEXTURE0+curStage), *((Matrix4x4*)&curView));
DX8Wrapper::Set_DX8_Texture_Stage_State(curStage, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State(curStage, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
curStage++;
if (curStage==1) curStage++;
}
Bool doNoise2 = (W3DShaderManager::getCurrentShader() == W3DShaderManager::ST_FLAT_TERRAIN_BASE_NOISE2 ||
W3DShaderManager::getCurrentShader() == W3DShaderManager::ST_FLAT_TERRAIN_BASE_NOISE12);
if (doNoise2)
{
Matrix4x4 curView;
DX8Wrapper::_Get_DX8_Transform(D3DTS_VIEW, curView);
D3DXMATRIX inv;
float det;
D3DXMatrixInverse(&inv, &det, (D3DXMATRIX*)&curView);
DX8Wrapper::Set_DX8_Texture_Stage_State(curStage, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
// Two output coordinates are used.
DX8Wrapper::Set_DX8_Texture_Stage_State(curStage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
DX8Wrapper::Set_DX8_Texture_Stage_State(curStage, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
DX8Wrapper::Set_DX8_Texture_Stage_State(curStage, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
DX8Wrapper::_Get_D3D_Device8()->SetTexture(curStage, W3DShaderManager::getShaderTexture(3)->Peek_D3D_Texture());
terrainShader2Stage.updateNoise2(((D3DXMATRIX*)&curView),&inv); //update curView with texture matrix
DX8Wrapper::_Set_DX8_Transform((D3DTRANSFORMSTATETYPE )(D3DTS_TEXTURE0+curStage), *((Matrix4x4*)&curView));
DX8Wrapper::Set_DX8_Texture_Stage_State(curStage, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
DX8Wrapper::Set_DX8_Texture_Stage_State(curStage, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
curStage++;
if (curStage==1) curStage++;
}
if (curStage<2) {
DX8Wrapper::_Get_D3D_Device8()->SetPixelShader(m_dwBase0PixelShader);
} else if (curStage==2) {
DX8Wrapper::_Get_D3D_Device8()->SetPixelShader(m_dwBasePixelShader);
} else if (curStage==3) {
DX8Wrapper::_Get_D3D_Device8()->SetPixelShader(m_dwBaseNoise1PixelShader);
}else if (curStage==4) {
DX8Wrapper::_Get_D3D_Device8()->SetPixelShader(m_dwBaseNoise2PixelShader);
}
DX8Wrapper::_Get_D3D_Device8()->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
DX8Wrapper::Apply_Render_State_Changes();
DX8Wrapper::_Get_D3D_Device8()->SetTexture(curStage, W3DShaderManager::getShaderTexture(3)->Peek_D3D_Texture());
return TRUE;
}
void FlatTerrainShaderPixelShader::reset(void)
{
DX8Wrapper::_Get_D3D_Device8()->SetTexture(2,NULL); //release reference to any texture
DX8Wrapper::_Get_D3D_Device8()->SetTexture(3,NULL); //release reference to any texture
DX8Wrapper::_Get_D3D_Device8()->SetPixelShader(0); //turn off pixel shader
DX8Wrapper::_Get_D3D_Device8()->SetTexture(0, NULL);
DX8Wrapper::_Get_D3D_Device8()->SetTexture(1, NULL);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU|0);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU|1);
DX8Wrapper::Set_DX8_Texture_Stage_State( 2, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 2, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU|2);
DX8Wrapper::Set_DX8_Texture_Stage_State( 3, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
DX8Wrapper::Set_DX8_Texture_Stage_State( 3, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU|3);
DX8Wrapper::Invalidate_Cached_Render_States();
}