khanat-opennel-code/code/nel/src/3d/driver/direct3d/driver_direct3d_shader.cpp

3919 lines
132 KiB
C++
Raw Normal View History

2010-05-06 00:08:41 +00:00
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stddirect3d.h"
#include "driver_direct3d.h"
using namespace std;
using namespace NLMISC;
namespace NL3D
{
// mem allocator for state records
std::allocator<uint8> CStateRecord::Allocator;
// ***************************************************************************
// The state manager with cache
// ***************************************************************************
HRESULT CDriverD3D::QueryInterface(REFIID /* riid */, LPVOID * /* ppvObj */)
{
H_AUTO_D3D(CDriverD3D_QueryInterface)
return D3D_OK;
}
// ***************************************************************************
ULONG CDriverD3D::AddRef(VOID)
{
H_AUTO_D3D(CDriverD3D_AddRef)
return 0;
}
// ***************************************************************************
ULONG CDriverD3D::Release(VOID)
{
H_AUTO_D3D(CDriverD3D_Release)
return 0;
}
// ***************************************************************************
HRESULT CDriverD3D::LightEnable(DWORD Index, BOOL Enable)
{
H_AUTO_D3D(CDriverD3D_LightEnable)
enableLight ((uint8)Index, Enable!=FALSE);
return D3D_OK;
}
// ***************************************************************************
HRESULT CDriverD3D::SetFVF(DWORD /* FVF */)
{
H_AUTO_D3D(CDriverD3D_SetFVF)
// Not implemented
return D3D_OK;
}
// ***************************************************************************
HRESULT CDriverD3D::SetLight(DWORD Index, CONST D3DLIGHT9* pLight)
{
H_AUTO_D3D(CDriverD3D_SetLight)
_LightCache[Index].Light = *pLight;
touchRenderVariable (&_LightCache[Index]);
return D3D_OK;
}
// ***************************************************************************
HRESULT CDriverD3D::SetMaterial(CONST D3DMATERIAL9* pMaterial)
{
H_AUTO_D3D(CDriverD3D_SetMaterial)
setMaterialState( *pMaterial );
return D3D_OK;
}
// ***************************************************************************
HRESULT CDriverD3D::SetNPatchMode(FLOAT /* nSegments */)
{
H_AUTO_D3D(CDriverD3D_SetNPatchMode)
// Not implemented
return D3D_OK;
}
// ***************************************************************************
HRESULT CDriverD3D::SetPixelShader(LPDIRECT3DPIXELSHADER9 pShader)
{
H_AUTO_D3D(CDriverD3D_SetPixelShader)
setPixelShader (pShader);
return D3D_OK;
}
// ***************************************************************************
HRESULT CDriverD3D::SetPixelShaderConstantB(UINT StartRegister, CONST BOOL* pConstantData, UINT RegisterCount)
{
H_AUTO_D3D(CDriverD3D_SetPixelShaderConstantB)
uint i;
for (i=0; i<RegisterCount; i++)
setPixelShaderConstant (i+StartRegister, (int*)(pConstantData+i*4));
return D3D_OK;
}
// ***************************************************************************
HRESULT CDriverD3D::SetPixelShaderConstantF(UINT StartRegister, CONST FLOAT* pConstantData, UINT RegisterCount)
{
H_AUTO_D3D(CDriverD3D_SetPixelShaderConstantF)
uint i;
for (i=0; i<RegisterCount; i++)
setPixelShaderConstant (i+StartRegister, pConstantData+i*4);
return D3D_OK;
}
// ***************************************************************************
HRESULT CDriverD3D::SetPixelShaderConstantI(UINT StartRegister, CONST INT* pConstantData, UINT RegisterCount)
{
H_AUTO_D3D(CDriverD3D_SetPixelShaderConstantI)
uint i;
for (i=0; i<RegisterCount; i++)
setPixelShaderConstant (i+StartRegister, pConstantData+i*4);
return D3D_OK;
}
// ***************************************************************************
HRESULT CDriverD3D::SetRenderState(D3DRENDERSTATETYPE State, DWORD Value)
{
H_AUTO_D3D(CDriverD3D_SetRenderState)
setRenderState (State, Value);
return D3D_OK;
}
// ***************************************************************************
HRESULT CDriverD3D::SetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value)
{
H_AUTO_D3D(CDriverD3D_SetSamplerState)
setSamplerState (Sampler, Type, Value);
return D3D_OK;
}
// ***************************************************************************
HRESULT CDriverD3D::SetTexture (DWORD Stage, LPDIRECT3DBASETEXTURE9 pTexture)
{
H_AUTO_D3D(CDriverD3D_SetTexture )
// Look for the current texture
uint i;
const uint count = _CurrentShaderTextures.size();
for (i=0; i<count; i++)
{
const CTextureRef &ref = _CurrentShaderTextures[i];
if (ref.D3DTexture == pTexture)
{
// Set the additionnal stage set by NeL texture (D3DSAMP_ADDRESSU, D3DSAMP_ADDRESSV, D3DSAMP_MAGFILTER, D3DSAMP_MINFILTER and D3DSAMP_MIPFILTER)
setTexture (Stage, ref.NeLTexture);
break;
}
}
if (i == count)
setTexture (Stage, pTexture);
return D3D_OK;
}
// ***************************************************************************
HRESULT CDriverD3D::SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value)
{
H_AUTO_D3D(CDriverD3D_SetTextureStageState)
if (Type == D3DTSS_TEXCOORDINDEX)
setTextureIndexUV (Stage, Value);
else
setTextureState (Stage, Type, Value);
return D3D_OK;
}
// ***************************************************************************
HRESULT CDriverD3D::SetTransform(D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix)
{
H_AUTO_D3D(CDriverD3D_SetTransform)
setMatrix (State, *pMatrix);
return D3D_OK;
}
// ***************************************************************************
HRESULT CDriverD3D::SetVertexShader(LPDIRECT3DVERTEXSHADER9 pShader)
{
H_AUTO_D3D(CDriverD3D_SetVertexShader)
setVertexProgram (pShader, NULL);
return D3D_OK;
}
// ***************************************************************************
HRESULT CDriverD3D::SetVertexShaderConstantB(UINT StartRegister, CONST BOOL* pConstantData, UINT RegisterCount)
{
H_AUTO_D3D(CDriverD3D_SetVertexShaderConstantB)
uint i;
for (i=0; i<RegisterCount; i++)
setVertexProgramConstant (i+StartRegister, (int*)(pConstantData+i*4));
return D3D_OK;
}
// ***************************************************************************
HRESULT CDriverD3D::SetVertexShaderConstantF(UINT StartRegister, CONST FLOAT* pConstantData, UINT RegisterCount)
{
H_AUTO_D3D(CDriverD3D_SetVertexShaderConstantF)
uint i;
for (i=0; i<RegisterCount; i++)
setVertexProgramConstant (i+StartRegister, pConstantData+i*4);
return D3D_OK;
}
// ***************************************************************************
HRESULT CDriverD3D::SetVertexShaderConstantI(UINT StartRegister, CONST INT* pConstantData, UINT RegisterCount)
{
H_AUTO_D3D(CDriverD3D_SetVertexShaderConstantI)
uint i;
for (i=0; i<RegisterCount; i++)
setVertexProgramConstant (i+StartRegister, pConstantData+i*4);
return D3D_OK;
}
// ***************************************************************************
CShaderDrvInfosD3D::CShaderDrvInfosD3D(IDriver *drv, ItShaderDrvInfoPtrList it) : IShaderDrvInfos(drv, it)
{
H_AUTO_D3D(CShaderDrvInfosD3D_CShaderDrvInfosD3D)
Validated = false;
}
// ***************************************************************************
CShaderDrvInfosD3D::~CShaderDrvInfosD3D()
{
H_AUTO_D3D(CShaderDrvInfosD3D_CShaderDrvInfosD3DDtor)
Effect->Release();
}
// ***************************************************************************
bool CDriverD3D::validateShader(CShader *shader)
{
H_AUTO_D3D(CDriverD3D_validateShader)
CShaderDrvInfosD3D *shaderInfo = static_cast<CShaderDrvInfosD3D*>((IShaderDrvInfos*)shader->_DrvInfo);
if (!shaderInfo->Validated)
{
// Choose the good method
D3DXHANDLE hTechnique = NULL;
D3DXHANDLE hCurrentTechnique = NULL;
while (hTechnique == NULL)
{
if (shaderInfo->Effect->FindNextValidTechnique(hCurrentTechnique, &hCurrentTechnique) != D3D_OK)
return false;
// Info
#ifdef NL_FORCE_TEXTURE_STAGE_COUNT
D3DXTECHNIQUE_DESC desc;
nlverify (shaderInfo->Effect->GetTechniqueDesc(hCurrentTechnique, &desc) == D3D_OK);
// Check this is compatible
const uint len = strlen(desc.Name);
if (len)
{
char shaderStageCount = desc.Name[len-1];
if ((shaderStageCount>='0') && (shaderStageCount<='9'))
{
uint stageCount = NL_FORCE_TEXTURE_STAGE_COUNT;
if ((uint)(shaderStageCount-'0')<=stageCount)
// The good technique
hTechnique = hCurrentTechnique;
}
}
#else // NL_FORCE_TEXTURE_STAGE_COUNT
hTechnique = hCurrentTechnique;
#endif // NL_FORCE_TEXTURE_STAGE_COUNT
#ifdef NL_DEBUG_D3D
{
D3DXTECHNIQUE_DESC desc;
nlverify (shaderInfo->Effect->GetTechniqueDesc(hCurrentTechnique, &desc) == D3D_OK);
if (hTechnique)
nlinfo ("Shader \"%s\" : use technique \"%s\" with %d passes.", shader->getName(), desc.Name, desc.Passes);
}
#endif // NL_DEBUG_D3D
}
// Set the technique
shaderInfo->Effect->SetTechnique(hTechnique);
// Set the state manager
shaderInfo->Effect->SetStateManager (this);
shaderInfo->Validated = true;
}
return true;
}
// ***************************************************************************
bool CDriverD3D::activeShader(CShader *shd)
{
H_AUTO_D3D(CDriverD3D_activeShader)
if (_DisableHardwarePixelShader)
return false;
// Clear current textures
_CurrentShaderTextures.clear();
// Shader has been changed ?
if (shd && shd->_ShaderChanged)
{
// Remove old shader
shd->_DrvInfo.kill();
// Already setuped ?
CShaderDrvInfosD3D *shaderInfo = static_cast<CShaderDrvInfosD3D*>((IShaderDrvInfos*)shd->_DrvInfo);
if ( !shd->_DrvInfo )
{
// insert into driver list. (so it is deleted when driver is deleted).
ItShaderDrvInfoPtrList it= _ShaderDrvInfos.insert(_ShaderDrvInfos.end(), NULL);
// create and set iterator, for future deletion.
shaderInfo = new CShaderDrvInfosD3D(this, it);
*it= shd->_DrvInfo = shaderInfo;
}
// Assemble the shader
LPD3DXBUFFER pErrorMsgs;
if (D3DXCreateEffect(_DeviceInterface, shd->getText(), strlen(shd->getText())+1, NULL, NULL, 0, NULL, &(shaderInfo->Effect), &pErrorMsgs)
== D3D_OK)
{
// Get the texture handle
uint i;
for (i=0; i<CShaderDrvInfosD3D::MaxShaderTexture; i++)
{
string name = "texture" + toString (i);
shaderInfo->TextureHandle[i] = shaderInfo->Effect->GetParameterByName(NULL, name.c_str());
name = "color" + toString (i);
shaderInfo->ColorHandle[i] = shaderInfo->Effect->GetParameterByName(NULL, name.c_str());
name = "factor" + toString (i);
shaderInfo->FactorHandle[i] = shaderInfo->Effect->GetParameterByName(NULL, name.c_str());
name = "scalarFloat" + toString (i);
shaderInfo->ScalarFloatHandle[i] = shaderInfo->Effect->GetParameterByName(NULL, name.c_str());
}
}
else
{
nlwarning ("Can't create shader '%s':", shd->getText());
if (pErrorMsgs)
nlwarning ((const char*)pErrorMsgs->GetBufferPointer());
shd->_ShaderChanged = false;
_CurrentShader = NULL;
return false;
}
// Done
shd->_ShaderChanged = false;
}
// Set the shader
_CurrentShader = shd;
return true;
}
static void setFX(CShader &s, const char *name, const char *prog, CDriverD3D *drv)
{
H_AUTO_D3D(setFX)
s.setName(name);
s.setText(prog);
nlverify (drv->activeShader (&s));
}
#define setFx(a,b,c) { setFX(a, b, c, this); }
static const char *CloudFx =
" \n\
texture texture0; \n\
texture texture1; \n\
float4 factor0; \n\
\n\
pixelshader two_stages_ps = asm \n\
{ \n\
ps_1_1; \n\
tex t0; \n\
tex t1; \n\
lrp r0.w, v0, t0, t1; \n\
mov r0.xyz, c0; \n\
+mul r0.w, c0, r0; \n\
}; \n\
\n\
technique two_stages_2 \n\
{ \n\
pass p0 \n\
{ \n\
Texture[0] = <texture0>; \n\
Texture[1] = <texture1>; \n\
PixelShaderConstant[0] = <factor0>; \n\
PixelShader = (two_stages_ps); \n\
} \n\
}; \n\
\n\
";
static const char *Lightmap0Fx =
" \n\
texture texture0; \n\
\n\
float4 g_black = { 0.0f, 0.0f, 0.0f, 1.0f }; \n\
float4 g_dyn_factor = { 1.0f, 1.0f, 1.0f, 1.0f }; \n\
\n\
technique one_stage_1 \n\
{ \n\
pass p0 \n\
{ \n\
// do a standard lighting with the first light \n\
Lighting = true; \n\
MaterialEmissive= <g_black>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = false; \n\
\n\
Texture[0] = <texture0>; \n\
ColorOp[0] = MODULATE; \n\
ColorArg1[0] = TEXTURE; \n\
ColorArg2[0] = DIFFUSE; \n\
AlphaOp[0] = SELECTARG1; // for alpha test \n\
AlphaArg1[0] = TEXTURE; \n\
} \n\
}; \n\
\n\
";
static const char *Lightmap0blendFx =
" \n\
texture texture0; \n\
\n\
float4 g_black = { 0.0f, 0.0f, 0.0f, 1.0f }; \n\
float4 g_dyn_factor = { 1.0f, 1.0f, 1.0f, 1.0f }; \n\
\n\
technique one_stage_1 \n\
{ \n\
pass p0 \n\
{ \n\
// do a standard lighting with the first light \n\
Lighting = true; \n\
MaterialEmissive= <g_black>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = true; \n\
SrcBlend = SRCALPHA; \n\
DestBlend = INVSRCALPHA; \n\
\n\
Texture[0] = <texture0>; \n\
ColorOp[0] = MODULATE; \n\
ColorArg1[0] = TEXTURE; \n\
ColorArg2[0] = DIFFUSE; \n\
AlphaOp[0] = SELECTARG1; \n\
AlphaArg1[0] = TEXTURE; \n\
} \n\
}; \n\
\n\
";
static const char *Lightmap0blend_x2Fx =
" \n\
texture texture0; \n\
\n\
float4 g_black = { 0.0f, 0.0f, 0.0f, 1.0f }; \n\
float4 g_dyn_factor = { 1.0f, 1.0f, 1.0f, 1.0f }; \n\
\n\
technique one_stage_1 \n\
{ \n\
pass p0 \n\
{ \n\
// do a standard lighting with the first light \n\
Lighting = true; \n\
MaterialEmissive= <g_black>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = true; \n\
SrcBlend = SRCALPHA; \n\
DestBlend = INVSRCALPHA; \n\
\n\
Texture[0] = <texture0>; \n\
ColorOp[0] = MODULATE; \n\
ColorArg1[0] = TEXTURE; \n\
ColorArg2[0] = DIFFUSE; \n\
AlphaOp[0] = SELECTARG1; \n\
AlphaArg1[0] = TEXTURE; \n\
} \n\
}; \n\
\n\
";
static const char *Lightmap0_x2Fx =
" \n\
texture texture0; \n\
\n\
float4 g_black = { 0.0f, 0.0f, 0.0f, 1.0f }; \n\
float4 g_dyn_factor = { 1.0f, 1.0f, 1.0f, 1.0f }; \n\
\n\
technique one_stage_1 \n\
{ \n\
pass p0 \n\
{ \n\
// do a standard lighting with the first light \n\
Lighting = true; \n\
MaterialEmissive= <g_black>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = false; \n\
\n\
Texture[0] = <texture0>; \n\
ColorOp[0] = MODULATE; \n\
ColorArg1[0] = TEXTURE; \n\
ColorArg2[0] = DIFFUSE; \n\
AlphaOp[0] = SELECTARG1; // for alpha test \n\
AlphaArg1[0] = TEXTURE; \n\
} \n\
}; \n\
\n\
";
static const char *Lightmap1Fx =
" \n\
texture texture0; \n\
texture texture1; \n\
// Color0 is the Ambient Added to the lightmap (for Lightmap 8 bit compression)\n\
// Other colors are the lightmap Factors for each lightmap \n\
dword color0; \n\
dword color1; \n\
float4 factor0; \n\
float4 factor1; \n\
\n\
float4 g_black = { 0.0f, 0.0f, 0.0f, 1.0f }; \n\
float4 g_dyn_factor = { 1.0f, 1.0f, 1.0f, 1.0f }; \n\
\n\
technique two_stages_2 \n\
{ \n\
pass p0 \n\
{ \n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = false; \n\
\n\
// the DiffuseTexture texture 0 is in last stage \n\
TexCoordIndex[0] = 1; \n\
TexCoordIndex[1] = 0; \n\
Texture[0] = <texture1>; \n\
Texture[1] = <texture0>; \n\
TextureFactor = <color1>; \n\
ColorOp[0] = MULTIPLYADD; \n\
ColorArg0[0] = DIFFUSE; \n\
ColorArg1[0] = TFACTOR; \n\
ColorArg2[0] = TEXTURE; \n\
ColorOp[1] = MODULATE; \n\
ColorArg1[1] = CURRENT; \n\
ColorArg2[1] = TEXTURE; \n\
AlphaOp[0] = SELECTARG1; \n\
AlphaArg1[0] = TFACTOR; \n\
AlphaOp[1] = SELECTARG1; // for alpha test \n\
AlphaArg1[1] = TEXTURE; \n\
} \n\
}; \n\
\n\
";
static const char *Lightmap1blendFx =
" \n\
texture texture0; \n\
texture texture1; \n\
// Color0 is the Ambient Added to the lightmap (for Lightmap 8 bit compression)\n\
// Other colors are the lightmap Factors for each lightmap \n\
dword color0; \n\
dword color1; \n\
float4 factor0; \n\
float4 factor1; \n\
\n\
float4 g_black = { 0.0f, 0.0f, 0.0f, 1.0f }; \n\
float4 g_dyn_factor = { 1.0f, 1.0f, 1.0f, 1.0f }; \n\
\n\
technique two_stages_2 \n\
{ \n\
pass p0 \n\
{ \n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = true; \n\
SrcBlend = SRCALPHA; \n\
DestBlend = INVSRCALPHA; \n\
\n\
// the DiffuseTexture texture 0 is in last stage \n\
TexCoordIndex[0] = 1; \n\
TexCoordIndex[1] = 0; \n\
Texture[0] = <texture1>; \n\
Texture[1] = <texture0>; \n\
TextureFactor = <color1>; \n\
ColorOp[0] = MULTIPLYADD; \n\
ColorArg0[0] = DIFFUSE; \n\
ColorArg1[0] = TFACTOR; \n\
ColorArg2[0] = TEXTURE; \n\
ColorOp[1] = MODULATE; \n\
ColorArg1[1] = CURRENT; \n\
ColorArg2[1] = TEXTURE; \n\
// Alpha stage 0 unused \n\
AlphaOp[0] = SELECTARG1; \n\
AlphaArg1[0] = TFACTOR; \n\
AlphaOp[1] = SELECTARG1; \n\
AlphaArg1[1] = TEXTURE; \n\
} \n\
}; \n\
\n\
";
static const char *Lightmap1blend_x2Fx =
" \n\
texture texture0; \n\
texture texture1; \n\
// Color0 is the Ambient Added to the lightmap (for Lightmap 8 bit compression)\n\
// Other colors are the lightmap Factors for each lightmap \n\
dword color0; \n\
dword color1; \n\
float4 factor0; \n\
float4 factor1; \n\
\n\
float4 g_black = { 0.0f, 0.0f, 0.0f, 1.0f }; \n\
// modulate the dyn light by 0.5, because of MODULATE2X \n\
float4 g_dyn_factor = { 0.5f, 0.5f, 0.5f, 1.0f }; \n\
\n\
technique two_stages_2 \n\
{ \n\
pass p0 \n\
{ \n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = true; \n\
SrcBlend = SRCALPHA; \n\
DestBlend = INVSRCALPHA; \n\
\n\
// the DiffuseTexture texture 0 is in last stage \n\
TexCoordIndex[0] = 1; \n\
TexCoordIndex[1] = 0; \n\
Texture[0] = <texture1>; \n\
Texture[1] = <texture0>; \n\
TextureFactor = <color1>; \n\
ColorOp[0] = MULTIPLYADD; \n\
ColorArg0[0] = DIFFUSE; \n\
ColorArg1[0] = TFACTOR; \n\
ColorArg2[0] = TEXTURE; \n\
ColorOp[1] = MODULATE2X; \n\
ColorArg1[1] = CURRENT; \n\
ColorArg2[1] = TEXTURE; \n\
// Alpha stage 0 unused \n\
AlphaOp[0] = SELECTARG1; \n\
AlphaArg1[0] = TFACTOR; \n\
AlphaOp[1] = SELECTARG1; \n\
AlphaArg1[1] = TEXTURE; \n\
} \n\
}; \n\
\n\
";
static const char *Lightmap1_x2Fx =
" \n\
texture texture0; \n\
texture texture1; \n\
// Color0 is the Ambient Added to the lightmap (for Lightmap 8 bit compression)\n\
// Other colors are the lightmap Factors for each lightmap \n\
dword color0; \n\
dword color1; \n\
float4 factor0; \n\
float4 factor1; \n\
\n\
float4 g_black = { 0.0f, 0.0f, 0.0f, 1.0f }; \n\
// modulate the dyn light by 0.5, because of MODULATE2X \n\
float4 g_dyn_factor = { 0.5f, 0.5f, 0.5f, 1.0f }; \n\
\n\
technique two_stages_2 \n\
{ \n\
pass p0 \n\
{ \n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = false; \n\
\n\
// the DiffuseTexture texture 0 is in last stage \n\
TexCoordIndex[0] = 1; \n\
TexCoordIndex[1] = 0; \n\
Texture[0] = <texture1>; \n\
Texture[1] = <texture0>; \n\
TextureFactor = <color1>; \n\
ColorOp[0] = MULTIPLYADD; \n\
ColorArg0[0] = DIFFUSE; \n\
ColorArg1[0] = TFACTOR; \n\
ColorArg2[0] = TEXTURE; \n\
ColorOp[1] = MODULATE2X; \n\
ColorArg1[1] = CURRENT; \n\
ColorArg2[1] = TEXTURE; \n\
AlphaOp[0] = SELECTARG1; \n\
AlphaArg1[0] = TFACTOR; \n\
AlphaOp[1] = SELECTARG1; // for alpha test \n\
AlphaArg1[1] = TEXTURE; \n\
} \n\
}; \n\
\n\
";
static const char *Lightmap2Fx =
" \n\
texture texture0; \n\
texture texture1; \n\
texture texture2; \n\
// Color0 is the Ambient Added to the lightmap (for Lightmap 8 bit compression)\n\
// Other colors are the lightmap Factors for each lightmap \n\
dword color0; \n\
dword color1; \n\
dword color2; \n\
float4 factor0; \n\
float4 factor1; \n\
float4 factor2; \n\
\n\
float4 g_black = { 0.0f, 0.0f, 0.0f, 1.0f }; \n\
float4 g_dyn_factor = { 1.0f, 1.0f, 1.0f, 1.0f }; \n\
\n\
\n\
// **** 3 stages technique \n\
pixelshader three_stages_ps = asm \n\
{ \n\
ps_1_1; \n\
tex t0; \n\
tex t1; \n\
tex t2; \n\
// multiply lightmap with factor, and add with LMCAmbient+DynamicLight term\n\
mad r0.xyz, c1, t1, v0; \n\
mad r0.xyz, c2, t2, r0; \n\
mul r0.xyz, r0, t0; \n\
+mov r0.w, t0; \n\
}; \n\
\n\
technique three_stages_3 \n\
{ \n\
pass p0 \n\
{ \n\
TexCoordIndex[2] = 1; \n\
\n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = false; \n\
\n\
Texture[0] = <texture0>; \n\
Texture[1] = <texture1>; \n\
Texture[2] = <texture2>; \n\
PixelShaderConstant[1] = <factor1>; \n\
PixelShaderConstant[2] = <factor2>; \n\
PixelShader = (three_stages_ps); \n\
} \n\
} \n\
\n\
// **** 2 stages, no pixel shader technique \n\
technique two_stages_2 \n\
{ \n\
pass p0 \n\
{ \n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = false; \n\
\n\
// the DiffuseTexture texture 0 is in last stage \n\
TexCoordIndex[0] = 1; \n\
TexCoordIndex[1] = 0; \n\
Texture[0] = <texture1>; \n\
Texture[1] = <texture0>; \n\
TextureFactor = <color1>; \n\
ColorOp[0] = MULTIPLYADD; \n\
ColorArg0[0] = DIFFUSE; \n\
ColorArg1[0] = TFACTOR; \n\
ColorArg2[0] = TEXTURE; \n\
ColorOp[1] = MODULATE; \n\
ColorArg1[1] = CURRENT; \n\
ColorArg2[1] = TEXTURE; \n\
// Alpha stage 0 unused \n\
AlphaOp[0] = SELECTARG1; \n\
AlphaArg1[0] = TFACTOR; \n\
AlphaOp[1] = SELECTARG1; // for alpha test \n\
AlphaArg1[1] = TEXTURE; \n\
} \n\
pass p1 \n\
{ \n\
FogColor = 0x00000000; // don't accumulate fog several times\n\
Lighting = false; \n\
AlphaBlendEnable = true; \n\
SrcBlend = one; \n\
DestBlend = one; \n\
Texture[0] = <texture2>; \n\
TextureFactor = <color2>; \n\
ColorOp[0] = MODULATE; \n\
} \n\
} \n\
\n\
";
static const char *Lightmap2blendFx =
" \n\
texture texture0; \n\
texture texture1; \n\
texture texture2; \n\
// Color0 is the Ambient Added to the lightmap (for Lightmap 8 bit compression)\n\
// Other colors are the lightmap Factors for each lightmap \n\
dword color0; \n\
dword color1; \n\
dword color2; \n\
float4 factor0; \n\
float4 factor1; \n\
float4 factor2; \n\
\n\
float4 g_black = { 0.0f, 0.0f, 0.0f, 1.0f }; \n\
float4 g_dyn_factor = { 1.0f, 1.0f, 1.0f, 1.0f }; \n\
\n\
\n\
// **** 3 stages technique \n\
pixelshader three_stages_ps = asm \n\
{ \n\
ps_1_1; \n\
tex t0; \n\
tex t1; \n\
tex t2; \n\
// multiply lightmap with factor, and add with LMCAmbient+DynamicLight term\n\
mad r0.xyz, c1, t1, v0; \n\
mad r0.xyz, c2, t2, r0; \n\
mul r0.xyz, r0, t0; \n\
+mov r0.w, t0; \n\
}; \n\
\n\
technique three_stages_3 \n\
{ \n\
pass p0 \n\
{ \n\
TexCoordIndex[2] = 1; \n\
\n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = true; \n\
SrcBlend = srcalpha; \n\
DestBlend = invsrcalpha; \n\
\n\
Texture[0] = <texture0>; \n\
Texture[1] = <texture1>; \n\
Texture[2] = <texture2>; \n\
PixelShaderConstant[1] = <factor1>; \n\
PixelShaderConstant[2] = <factor2>; \n\
PixelShader = (three_stages_ps); \n\
} \n\
} \n\
\n\
// **** 2 stages, no pixel shader technique \n\
technique two_stages_2 \n\
{ \n\
pass p0 \n\
{ \n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = true; \n\
SrcBlend = srcalpha; \n\
DestBlend = invsrcalpha; \n\
\n\
// the DiffuseTexture texture 0 is in last stage \n\
TexCoordIndex[0] = 1; \n\
TexCoordIndex[1] = 0; \n\
Texture[0] = <texture1>; \n\
Texture[1] = <texture0>; \n\
TextureFactor = <color1>; \n\
ColorOp[0] = MULTIPLYADD; \n\
ColorArg0[0] = DIFFUSE; \n\
ColorArg1[0] = TFACTOR; \n\
ColorArg2[0] = TEXTURE; \n\
ColorOp[1] = MODULATE; \n\
ColorArg1[1] = CURRENT; \n\
ColorArg2[1] = TEXTURE; \n\
// Alpha stage 0 unused \n\
AlphaOp[0] = SELECTARG1; \n\
AlphaArg1[0] = TFACTOR; \n\
AlphaOp[1] = SELECTARG1; \n\
AlphaArg1[1] = TEXTURE; \n\
} \n\
pass p1 \n\
{ \n\
FogColor = 0x00000000; // don't accumulate fog several times\n\
Lighting = false; \n\
DestBlend = one; \n\
Texture[0] = <texture2>; \n\
TextureFactor = <color2>; \n\
ColorOp[0] = MODULATE; \n\
} \n\
} \n\
\n\
\n\
";
static const char *Lightmap2blend_x2Fx =
" \n\
texture texture0; \n\
texture texture1; \n\
texture texture2; \n\
// Color0 is the Ambient Added to the lightmap (for Lightmap 8 bit compression)\n\
// Other colors are the lightmap Factors for each lightmap \n\
dword color0; \n\
dword color1; \n\
dword color2; \n\
float4 factor0; \n\
float4 factor1; \n\
float4 factor2; \n\
\n\
float4 g_black = { 0.0f, 0.0f, 0.0f, 1.0f }; \n\
// modulate the dyn light by 0.5, because of MODULATE2X \n\
float4 g_dyn_factor = { 0.5f, 0.5f, 0.5f, 1.0f }; \n\
\n\
\n\
// **** 3 stages technique \n\
pixelshader three_stages_ps = asm \n\
{ \n\
ps_1_1; \n\
tex t0; \n\
tex t1; \n\
tex t2; \n\
// multiply lightmap with factor, and add with LMCAmbient+DynamicLight term\n\
mad r0.xyz, c1, t1, v0; \n\
mad r0.xyz, c2, t2, r0; \n\
mul_x2 r0.xyz, r0, t0; \n\
mov r0.w, t0; \n\
}; \n\
\n\
technique three_stages_3 \n\
{ \n\
pass p0 \n\
{ \n\
TexCoordIndex[2] = 1; \n\
\n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = true; \n\
SrcBlend = srcalpha; \n\
DestBlend = invsrcalpha; \n\
\n\
Texture[0] = <texture0>; \n\
Texture[1] = <texture1>; \n\
Texture[2] = <texture2>; \n\
PixelShaderConstant[1] = <factor1>; \n\
PixelShaderConstant[2] = <factor2>; \n\
PixelShader = (three_stages_ps); \n\
} \n\
} \n\
\n\
// **** 2 stages, no pixel shader technique \n\
technique two_stages_2 \n\
{ \n\
pass p0 \n\
{ \n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = true; \n\
SrcBlend = srcalpha; \n\
DestBlend = invsrcalpha; \n\
\n\
// the DiffuseTexture texture 0 is in last stage \n\
TexCoordIndex[0] = 1; \n\
TexCoordIndex[1] = 0; \n\
Texture[0] = <texture1>; \n\
Texture[1] = <texture0>; \n\
TextureFactor = <color1>; \n\
ColorOp[0] = MULTIPLYADD; \n\
ColorArg0[0] = DIFFUSE; \n\
ColorArg1[0] = TFACTOR; \n\
ColorArg2[0] = TEXTURE; \n\
ColorOp[1] = MODULATE2X; \n\
ColorArg1[1] = CURRENT; \n\
ColorArg2[1] = TEXTURE; \n\
// Alpha stage 0 unused \n\
AlphaOp[0] = SELECTARG1; \n\
AlphaArg1[0] = TFACTOR; \n\
AlphaOp[1] = SELECTARG1; \n\
AlphaArg1[1] = TEXTURE; \n\
} \n\
pass p1 \n\
{ \n\
FogColor = 0x00000000; // don't accumulate fog several times\n\
Lighting = false; \n\
DestBlend = one; \n\
Texture[0] = <texture2>; \n\
TextureFactor = <color2>; \n\
ColorOp[0] = MODULATE; \n\
} \n\
} \n\
\n\
\n\
";
static const char *Lightmap2_x2Fx =
" \n\
texture texture0; \n\
texture texture1; \n\
texture texture2; \n\
// Color0 is the Ambient Added to the lightmap (for Lightmap 8 bit compression)\n\
// Other colors are the lightmap Factors for each lightmap \n\
dword color0; \n\
dword color1; \n\
dword color2; \n\
float4 factor0; \n\
float4 factor1; \n\
float4 factor2; \n\
\n\
float4 g_black = { 0.0f, 0.0f, 0.0f, 1.0f }; \n\
// modulate the dyn light by 0.5, because of MODULATE2X \n\
float4 g_dyn_factor = { 0.5f, 0.5f, 0.5f, 1.0f }; \n\
\n\
\n\
// **** 3 stages technique \n\
pixelshader three_stages_ps = asm \n\
{ \n\
ps_1_1; \n\
tex t0; \n\
tex t1; \n\
tex t2; \n\
// multiply lightmap with factor, and add with LMCAmbient+DynamicLight term\n\
mad r0.xyz, c1, t1, v0; \n\
mad r0.xyz, c2, t2, r0; \n\
mul_x2 r0.xyz, r0, t0; \n\
+mov r0.w, t0; \n\
}; \n\
\n\
technique three_stages_3 \n\
{ \n\
pass p0 \n\
{ \n\
TexCoordIndex[2] = 1; \n\
\n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = false; \n\
\n\
Texture[0] = <texture0>; \n\
Texture[1] = <texture1>; \n\
Texture[2] = <texture2>; \n\
PixelShaderConstant[1] = <factor1>; \n\
PixelShaderConstant[2] = <factor2>; \n\
PixelShader = (three_stages_ps); \n\
} \n\
} \n\
\n\
// **** 2 stages, no pixel shader technique \n\
technique two_stages_2 \n\
{ \n\
pass p0 \n\
{ \n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = false; \n\
\n\
// the DiffuseTexture texture 0 is in last stage \n\
TexCoordIndex[0] = 1; \n\
TexCoordIndex[1] = 0; \n\
Texture[0] = <texture1>; \n\
Texture[1] = <texture0>; \n\
TextureFactor = <color1>; \n\
ColorOp[0] = MULTIPLYADD; \n\
ColorArg0[0] = DIFFUSE; \n\
ColorArg1[0] = TFACTOR; \n\
ColorArg2[0] = TEXTURE; \n\
ColorOp[1] = MODULATE2X; \n\
ColorArg1[1] = CURRENT; \n\
ColorArg2[1] = TEXTURE; \n\
// Alpha stage 0 unused \n\
AlphaOp[0] = SELECTARG1; \n\
AlphaArg1[0] = TFACTOR; \n\
AlphaOp[1] = SELECTARG1; // for alpha test if enabled \n\
AlphaArg1[1] = TEXTURE; \n\
} \n\
pass p1 \n\
{ \n\
FogColor = 0x00000000; // don't accumulate fog several times\n\
Lighting = false; \n\
AlphaBlendEnable = true; \n\
SrcBlend = one; \n\
DestBlend = one; \n\
Texture[0] = <texture2>; \n\
TextureFactor = <color2>; \n\
ColorOp[0] = MODULATE; \n\
} \n\
} \n\
\n\
";
static const char *Lightmap3Fx =
" \n\
texture texture0; \n\
texture texture1; \n\
texture texture2; \n\
texture texture3; \n\
// Color0 is the Ambient Added to the lightmap (for Lightmap 8 bit compression)\n\
// Other colors are the lightmap Factors for each lightmap \n\
dword color0; \n\
dword color1; \n\
dword color2; \n\
dword color3; \n\
float4 factor0; \n\
float4 factor1; \n\
float4 factor2; \n\
float4 factor3; \n\
\n\
float4 g_black = { 0.0f, 0.0f, 0.0f, 1.0f }; \n\
float4 g_dyn_factor = { 1.0f, 1.0f, 1.0f, 1.0f }; \n\
\n\
\n\
// **** 4 stages technique \n\
pixelshader four_stages_ps = asm \n\
{ \n\
ps_1_1; \n\
tex t0; \n\
tex t1; \n\
tex t2; \n\
tex t3; \n\
// multiply lightmap with factor, and add with LMCAmbient+DynamicLight term\n\
mad r0.xyz, c1, t1, v0; \n\
mad r0.xyz, c2, t2, r0; \n\
mad r0.xyz, c3, t3, r0; \n\
mul r0.xyz, r0, t0; \n\
+mov r0.w, t0; \n\
}; \n\
\n\
technique four_stages_4 \n\
{ \n\
pass p0 \n\
{ \n\
TexCoordIndex[2] = 1; \n\
TexCoordIndex[3] = 1; \n\
\n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = false; \n\
\n\
Texture[0] = <texture0>; \n\
Texture[1] = <texture1>; \n\
Texture[2] = <texture2>; \n\
Texture[3] = <texture3>; \n\
PixelShaderConstant[1] = <factor1>; \n\
PixelShaderConstant[2] = <factor2>; \n\
PixelShaderConstant[3] = <factor3>; \n\
PixelShader = (four_stages_ps); \n\
} \n\
} \n\
\n\
// **** 3 stages technique \n\
pixelshader three_stages_0_ps = asm \n\
{ \n\
ps_1_1; \n\
tex t0; \n\
tex t1; \n\
tex t2; \n\
// multiply lightmap with factor, and add with LMCAmbient+DynamicLight term\n\
mad r0.xyz, c1, t1, v0; \n\
mad r0.xyz, c2, t2, r0; \n\
mul r0.xyz, r0, t0; \n\
+mov r0.w, t0; \n\
}; \n\
\n\
technique three_stages_3 \n\
{ \n\
pass p0 \n\
{ \n\
TexCoordIndex[2] = 1; \n\
\n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = false; \n\
\n\
Texture[0] = <texture0>; \n\
Texture[1] = <texture1>; \n\
Texture[2] = <texture2>; \n\
PixelShaderConstant[1] = <factor1>; \n\
PixelShaderConstant[2] = <factor2>; \n\
PixelShader = (three_stages_0_ps); \n\
} \n\
pass p1 \n\
{ \n\
FogColor = 0x00000000; // don't accumulate fog several times\n\
AlphaBlendEnable = true; \n\
SrcBlend = one; \n\
DestBlend = one; \n\
Lighting = false; \n\
\n\
// the DiffuseTexture texture 0 is in last stage \n\
TexCoordIndex[0] = 1; \n\
TexCoordIndex[1] = 0; \n\
Texture[0] = <texture3>; \n\
Texture[1] = <texture0>; \n\
TextureFactor = <color3>; \n\
ColorOp[0] = MODULATE; \n\
ColorArg1[0] = TFACTOR; \n\
ColorArg2[0] = TEXTURE; \n\
ColorOp[1] = MODULATE; \n\
ColorArg1[1] = CURRENT; \n\
ColorArg2[1] = TEXTURE; \n\
ColorOp[2] = DISABLE; \n\
// Alpha stage 0 unused \n\
AlphaOp[0] = SELECTARG1; \n\
AlphaArg1[0] = TFACTOR; \n\
AlphaOp[1] = SELECTARG1; \n\
AlphaArg1[1] = TEXTURE; // for case when there's alpha test \n\
AlphaOp[2] = DISABLE; \n\
PixelShader = NULL; \n\
} \n\
} \n\
\n\
// **** 2 stages, no pixel shader technique \n\
technique two_stages_2 \n\
{ \n\
pass p0 \n\
{ \n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = false; \n\
\n\
// the DiffuseTexture texture 0 is in last stage \n\
TexCoordIndex[0] = 1; \n\
TexCoordIndex[1] = 0; \n\
Texture[0] = <texture1>; \n\
Texture[1] = <texture0>; \n\
TextureFactor = <color1>; \n\
ColorOp[0] = MULTIPLYADD; \n\
ColorArg0[0] = DIFFUSE; \n\
ColorArg1[0] = TFACTOR; \n\
ColorArg2[0] = TEXTURE; \n\
ColorOp[1] = MODULATE; \n\
ColorArg1[1] = CURRENT; \n\
ColorArg2[1] = TEXTURE; \n\
// Alpha stage 0 unused \n\
AlphaOp[0] = SELECTARG1; \n\
AlphaArg1[0] = TFACTOR; \n\
AlphaOp[1] = SELECTARG1; // alpha in case were alpha test is used\n\
AlphaArg1[1] = TEXTURE; \n\
} \n\
pass p1 \n\
{ \n\
FogColor = 0x00000000; // don't accumulate fog several times\n\
Lighting = false; \n\
AlphaBlendEnable = true; \n\
SrcBlend = one; \n\
DestBlend = one; \n\
Texture[0] = <texture2>; \n\
TextureFactor = <color2>; \n\
ColorOp[0] = MODULATE; \n\
} \n\
pass p2 \n\
{ \n\
Texture[0] = <texture3>; \n\
TextureFactor = <color3>; \n\
} \n\
} \n\
\n\
\n\
\n\
";
static const char *Lightmap3blendFx =
" \n\
texture texture0; \n\
texture texture1; \n\
texture texture2; \n\
texture texture3; \n\
// Color0 is the Ambient Added to the lightmap (for Lightmap 8 bit compression)\n\
// Other colors are the lightmap Factors for each lightmap \n\
dword color0; \n\
dword color1; \n\
dword color2; \n\
dword color3; \n\
float4 factor0; \n\
float4 factor1; \n\
float4 factor2; \n\
float4 factor3; \n\
\n\
float4 g_black = { 0.0f, 0.0f, 0.0f, 1.0f }; \n\
float4 g_dyn_factor = { 1.0f, 1.0f, 1.0f, 1.0f }; \n\
\n\
\n\
// **** 4 stages technique \n\
pixelshader four_stages_ps = asm \n\
{ \n\
ps_1_1; \n\
tex t0; \n\
tex t1; \n\
tex t2; \n\
tex t3; \n\
// multiply lightmap with factor, and add with LMCAmbient+DynamicLight term\n\
mad r0.xyz, c1, t1, v0; \n\
mad r0.xyz, c2, t2, r0; \n\
mad r0.xyz, c3, t3, r0; \n\
mul r0.xyz, r0, t0; \n\
+mov r0.w, t0; \n\
}; \n\
\n\
technique four_stages_4 \n\
{ \n\
pass p0 \n\
{ \n\
TexCoordIndex[2] = 1; \n\
TexCoordIndex[3] = 1; \n\
\n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = true; \n\
SrcBlend = srcalpha; \n\
DestBlend = invsrcalpha; \n\
\n\
Texture[0] = <texture0>; \n\
Texture[1] = <texture1>; \n\
Texture[2] = <texture2>; \n\
Texture[3] = <texture3>; \n\
PixelShaderConstant[1] = <factor1>; \n\
PixelShaderConstant[2] = <factor2>; \n\
PixelShaderConstant[3] = <factor3>; \n\
PixelShader = (four_stages_ps); \n\
} \n\
} \n\
\n\
// **** 3 stages technique \n\
pixelshader three_stages_0_ps = asm \n\
{ \n\
ps_1_1; \n\
tex t0; \n\
tex t1; \n\
tex t2; \n\
// multiply lightmap with factor, and add with LMCAmbient+DynamicLight term\n\
mad r0.xyz, c1, t1, v0; \n\
mad r0.xyz, c2, t2, r0; \n\
mul r0.xyz, r0, t0; \n\
+mov r0.w, t0; \n\
}; \n\
\n\
technique three_stages_3 \n\
{ \n\
pass p0 \n\
{ \n\
TexCoordIndex[2] = 1; \n\
\n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = true; \n\
SrcBlend = srcalpha; \n\
DestBlend = invsrcalpha; \n\
\n\
Texture[0] = <texture0>; \n\
Texture[1] = <texture1>; \n\
Texture[2] = <texture2>; \n\
PixelShaderConstant[1] = <factor1>; \n\
PixelShaderConstant[2] = <factor2>; \n\
PixelShader = (three_stages_0_ps); \n\
} \n\
pass p1 \n\
{ \n\
FogColor = 0x00000000; // don't accumulate fog several times\n\
DestBlend = one; \n\
Lighting = false; \n\
\n\
// the DiffuseTexture texture 0 is in last stage \n\
TexCoordIndex[0] = 1; \n\
TexCoordIndex[1] = 0; \n\
Texture[0] = <texture3>; \n\
Texture[1] = <texture0>; \n\
TextureFactor = <color3>; \n\
ColorOp[0] = MODULATE; \n\
ColorArg1[0] = TFACTOR; \n\
ColorArg2[0] = TEXTURE; \n\
ColorOp[1] = MODULATE; \n\
ColorArg1[1] = CURRENT; \n\
ColorArg2[1] = TEXTURE; \n\
ColorOp[2] = DISABLE; \n\
// Alpha stage 0 unused \n\
AlphaOp[0] = SELECTARG1; \n\
AlphaArg1[0] = TFACTOR; \n\
AlphaOp[1] = SELECTARG1; \n\
AlphaArg1[1] = TEXTURE; \n\
AlphaOp[2] = DISABLE; \n\
PixelShader = NULL; \n\
} \n\
} \n\
\n\
// **** 2 stages, no pixel shader technique \n\
technique two_stages_2 \n\
{ \n\
pass p0 \n\
{ \n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = true; \n\
SrcBlend = srcalpha; \n\
DestBlend = invsrcalpha; \n\
\n\
// the DiffuseTexture texture 0 is in last stage \n\
TexCoordIndex[0] = 1; \n\
TexCoordIndex[1] = 0; \n\
Texture[0] = <texture1>; \n\
Texture[1] = <texture0>; \n\
TextureFactor = <color1>; \n\
ColorOp[0] = MULTIPLYADD; \n\
ColorArg0[0] = DIFFUSE; \n\
ColorArg1[0] = TFACTOR; \n\
ColorArg2[0] = TEXTURE; \n\
ColorOp[1] = MODULATE; \n\
ColorArg1[1] = CURRENT; \n\
ColorArg2[1] = TEXTURE; \n\
// Alpha stage 0 unused \n\
AlphaOp[0] = SELECTARG1; \n\
AlphaArg1[0] = TFACTOR; \n\
AlphaOp[1] = SELECTARG1; \n\
AlphaArg1[1] = TEXTURE; \n\
} \n\
pass p1 \n\
{ \n\
FogColor = 0x00000000; // don't accumulate fog several times\n\
Lighting = false; \n\
DestBlend = one; \n\
Texture[0] = <texture2>; \n\
TextureFactor = <color2>; \n\
ColorOp[0] = MODULATE; \n\
} \n\
pass p2 \n\
{ \n\
Texture[0] = <texture3>; \n\
TextureFactor = <color3>; \n\
} \n\
} \n\
\n\
";
static const char *Lightmap3blend_x2Fx =
" \n\
texture texture0; \n\
texture texture1; \n\
texture texture2; \n\
texture texture3; \n\
// Color0 is the Ambient Added to the lightmap (for Lightmap 8 bit compression)\n\
// Other colors are the lightmap Factors for each lightmap \n\
dword color0; \n\
dword color1; \n\
dword color2; \n\
dword color3; \n\
float4 factor0; \n\
float4 factor1; \n\
float4 factor2; \n\
float4 factor3; \n\
\n\
float4 g_black = { 0.0f, 0.0f, 0.0f, 1.0f }; \n\
// modulate the dyn light by 0.5, because of MODULATE2X \n\
float4 g_dyn_factor = { 0.5f, 0.5f, 0.5f, 1.0f }; \n\
\n\
\n\
// **** 4 stages technique \n\
pixelshader four_stages_ps = asm \n\
{ \n\
ps_1_1; \n\
tex t0; \n\
tex t1; \n\
tex t2; \n\
tex t3; \n\
// multiply lightmap with factor, and add with LMCAmbient+DynamicLight term\n\
mad r0.xyz, c1, t1, v0; \n\
mad r0.xyz, c2, t2, r0; \n\
mad r0.xyz, c3, t3, r0; \n\
mul_x2 r0.xyz, r0, t0; \n\
+mov r0.w, t0; \n\
}; \n\
\n\
technique four_stages_4 \n\
{ \n\
pass p0 \n\
{ \n\
TexCoordIndex[2] = 1; \n\
TexCoordIndex[3] = 1; \n\
\n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = true; \n\
SrcBlend = srcalpha; \n\
DestBlend = invsrcalpha; \n\
\n\
Texture[0] = <texture0>; \n\
Texture[1] = <texture1>; \n\
Texture[2] = <texture2>; \n\
Texture[3] = <texture3>; \n\
PixelShaderConstant[1] = <factor1>; \n\
PixelShaderConstant[2] = <factor2>; \n\
PixelShaderConstant[3] = <factor3>; \n\
PixelShader = (four_stages_ps); \n\
} \n\
} \n\
\n\
// **** 3 stages technique \n\
pixelshader three_stages_0_ps = asm \n\
{ \n\
ps_1_1; \n\
tex t0; \n\
tex t1; \n\
tex t2; \n\
// multiply lightmap with factor, and add with LMCAmbient+DynamicLight term\n\
mad r0.xyz, c1, t1, v0; \n\
mad r0.xyz, c2, t2, r0; \n\
mul_x2 r0.xyz, r0, t0; \n\
+mov r0.w, t0; \n\
}; \n\
\n\
technique three_stages_3 \n\
{ \n\
pass p0 \n\
{ \n\
TexCoordIndex[2] = 1; \n\
\n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = true; \n\
SrcBlend = srcalpha; \n\
DestBlend = invsrcalpha; \n\
\n\
Texture[0] = <texture0>; \n\
Texture[1] = <texture1>; \n\
Texture[2] = <texture2>; \n\
PixelShaderConstant[1] = <factor1>; \n\
PixelShaderConstant[2] = <factor2>; \n\
PixelShader = (three_stages_0_ps); \n\
} \n\
pass p1 \n\
{ \n\
FogColor = 0x00000000; // don't accumulate fog several times\n\
DestBlend = one; \n\
Lighting = false; \n\
\n\
// the DiffuseTexture texture 0 is in last stage \n\
TexCoordIndex[0] = 1; \n\
TexCoordIndex[1] = 0; \n\
Texture[0] = <texture3>; \n\
Texture[1] = <texture0>; \n\
TextureFactor = <color3>; \n\
ColorOp[0] = MODULATE; \n\
ColorArg1[0] = TFACTOR; \n\
ColorArg2[0] = TEXTURE; \n\
ColorOp[1] = MODULATE2X; \n\
ColorArg1[1] = CURRENT; \n\
ColorArg2[1] = TEXTURE; \n\
ColorOp[2] = DISABLE; \n\
// Alpha stage 0 unused \n\
AlphaOp[0] = SELECTARG1; \n\
AlphaArg1[0] = TFACTOR; \n\
AlphaOp[1] = SELECTARG1; \n\
AlphaArg1[1] = TEXTURE; \n\
AlphaOp[2] = DISABLE; \n\
PixelShader = NULL; \n\
} \n\
} \n\
\n\
// **** 2 stages, no pixel shader technique \n\
technique two_stages_2 \n\
{ \n\
pass p0 \n\
{ \n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = true; \n\
SrcBlend = srcalpha; \n\
DestBlend = invsrcalpha; \n\
\n\
// the DiffuseTexture texture 0 is in last stage \n\
TexCoordIndex[0] = 1; \n\
TexCoordIndex[1] = 0; \n\
Texture[0] = <texture1>; \n\
Texture[1] = <texture0>; \n\
TextureFactor = <color1>; \n\
ColorOp[0] = MULTIPLYADD; \n\
ColorArg0[0] = DIFFUSE; \n\
ColorArg1[0] = TFACTOR; \n\
ColorArg2[0] = TEXTURE; \n\
ColorOp[1] = MODULATE2X; \n\
ColorArg1[1] = CURRENT; \n\
ColorArg2[1] = TEXTURE; \n\
// Alpha stage 0 unused \n\
AlphaOp[0] = SELECTARG1; \n\
AlphaArg1[0] = TFACTOR; \n\
AlphaOp[1] = SELECTARG1; \n\
AlphaArg1[1] = TEXTURE; \n\
} \n\
pass p1 \n\
{ \n\
FogColor = 0x00000000; // don't accumulate fog several times\n\
Lighting = false; \n\
DestBlend = one; \n\
Texture[0] = <texture2>; \n\
TextureFactor = <color2>; \n\
ColorOp[0] = MODULATE; \n\
} \n\
pass p2 \n\
{ \n\
Texture[0] = <texture3>; \n\
TextureFactor = <color3>; \n\
} \n\
} \n\
\n\
";
static const char *Lightmap3_x2Fx =
" \n\
texture texture0; \n\
texture texture1; \n\
texture texture2; \n\
texture texture3; \n\
// Color0 is the Ambient Added to the lightmap (for Lightmap 8 bit compression)\n\
// Other colors are the lightmap Factors for each lightmap \n\
dword color0; \n\
dword color1; \n\
dword color2; \n\
dword color3; \n\
float4 factor0; \n\
float4 factor1; \n\
float4 factor2; \n\
float4 factor3; \n\
\n\
float4 g_black = { 0.0f, 0.0f, 0.0f, 1.0f }; \n\
// modulate the dyn light by 0.5, because of MODULATE2X \n\
float4 g_dyn_factor = { 0.5f, 0.5f, 0.5f, 1.0f }; \n\
\n\
\n\
// **** 4 stages technique \n\
pixelshader four_stages_ps = asm \n\
{ \n\
ps_1_1; \n\
tex t0; \n\
tex t1; \n\
tex t2; \n\
tex t3; \n\
// multiply lightmap with factor, and add with LMCAmbient+DynamicLight term\n\
mad r0.xyz, c1, t1, v0; \n\
mad r0.xyz, c2, t2, r0; \n\
mad r0.xyz, c3, t3, r0; \n\
mul_x2 r0.xyz, r0, t0; \n\
+mov r0.w, t0; \n\
}; \n\
\n\
technique four_stages_4 \n\
{ \n\
pass p0 \n\
{ \n\
TexCoordIndex[2] = 1; \n\
TexCoordIndex[3] = 1; \n\
\n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = false; \n\
\n\
Texture[0] = <texture0>; \n\
Texture[1] = <texture1>; \n\
Texture[2] = <texture2>; \n\
Texture[3] = <texture3>; \n\
PixelShaderConstant[1] = <factor1>; \n\
PixelShaderConstant[2] = <factor2>; \n\
PixelShaderConstant[3] = <factor3>; \n\
PixelShader = (four_stages_ps); \n\
} \n\
} \n\
\n\
// **** 3 stages technique \n\
pixelshader three_stages_0_ps = asm \n\
{ \n\
ps_1_1; \n\
tex t0; \n\
tex t1; \n\
tex t2; \n\
// multiply lightmap with factor, and add with LMCAmbient+DynamicLight term\n\
mad r0.xyz, c1, t1, v0; \n\
mad r0.xyz, c2, t2, r0; \n\
mul_x2 r0.xyz, r0, t0; \n\
+mov r0.w, t0; \n\
}; \n\
\n\
technique three_stages_3 \n\
{ \n\
pass p0 \n\
{ \n\
TexCoordIndex[2] = 1; \n\
\n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = false; \n\
\n\
Texture[0] = <texture0>; \n\
Texture[1] = <texture1>; \n\
Texture[2] = <texture2>; \n\
PixelShaderConstant[1] = <factor1>; \n\
PixelShaderConstant[2] = <factor2>; \n\
PixelShader = (three_stages_0_ps); \n\
} \n\
pass p1 \n\
{ \n\
FogColor = 0x00000000; // don't accumulate fog several times\n\
AlphaBlendEnable = true; \n\
SrcBlend = one; \n\
DestBlend = one; \n\
Lighting = false; \n\
\n\
// the DiffuseTexture texture 0 is in last stage \n\
TexCoordIndex[0] = 1; \n\
TexCoordIndex[1] = 0; \n\
Texture[0] = <texture3>; \n\
Texture[1] = <texture0>; \n\
TextureFactor = <color3>; \n\
ColorOp[0] = MODULATE; \n\
ColorArg1[0] = TFACTOR; \n\
ColorArg2[0] = TEXTURE; \n\
ColorOp[1] = MODULATE2X; \n\
ColorArg1[1] = CURRENT; \n\
ColorArg2[1] = TEXTURE; \n\
ColorOp[2] = DISABLE; \n\
// Alpha stage 0 unused \n\
AlphaOp[0] = SELECTARG1; \n\
AlphaArg1[0] = TFACTOR; \n\
AlphaOp[1] = SELECTARG1; \n\
AlphaArg1[1] = TEXTURE; // for case when there's alpha test \n\
AlphaOp[2] = DISABLE; \n\
PixelShader = NULL; \n\
} \n\
} \n\
\n\
// **** 2 stages, no pixel shader technique \n\
technique two_stages_2 \n\
{ \n\
pass p0 \n\
{ \n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = false; \n\
\n\
// the DiffuseTexture texture 0 is in last stage \n\
TexCoordIndex[0] = 1; \n\
TexCoordIndex[1] = 0; \n\
Texture[0] = <texture1>; \n\
Texture[1] = <texture0>; \n\
TextureFactor = <color1>; \n\
ColorOp[0] = MULTIPLYADD; \n\
ColorArg0[0] = DIFFUSE; \n\
ColorArg1[0] = TFACTOR; \n\
ColorArg2[0] = TEXTURE; \n\
ColorOp[1] = MODULATE2X; \n\
ColorArg1[1] = CURRENT; \n\
ColorArg2[1] = TEXTURE; \n\
// Alpha stage 0 unused \n\
AlphaOp[0] = SELECTARG1; \n\
AlphaArg1[0] = TFACTOR; \n\
AlphaOp[1] = SELECTARG1; // alpha in case were alpha test is used\n\
AlphaArg1[1] = TEXTURE; \n\
} \n\
pass p1 \n\
{ \n\
FogColor = 0x00000000; // don't accumulate fog several times\n\
Lighting = false; \n\
AlphaBlendEnable = true; \n\
SrcBlend = one; \n\
DestBlend = one; \n\
Texture[0] = <texture2>; \n\
TextureFactor = <color2>; \n\
ColorOp[0] = MODULATE; \n\
} \n\
pass p2 \n\
{ \n\
Texture[0] = <texture3>; \n\
TextureFactor = <color3>; \n\
} \n\
} \n\
\n\
\n\
\n\
";
static const char *Lightmap4Fx =
" \n\
texture texture0; \n\
texture texture1; \n\
texture texture2; \n\
texture texture3; \n\
texture texture4; \n\
// Color0 is the Ambient Added to the lightmap (for Lightmap 8 bit compression)\n\
// Other colors are the lightmap Factors for each lightmap \n\
dword color0; \n\
dword color1; \n\
dword color2; \n\
dword color3; \n\
dword color4; \n\
float4 factor0; \n\
float4 factor1; \n\
float4 factor2; \n\
float4 factor3; \n\
float4 factor4; \n\
\n\
float4 g_black = { 0.0f, 0.0f, 0.0f, 1.0f }; \n\
float4 g_dyn_factor = { 1.0f, 1.0f, 1.0f, 1.0f }; \n\
\n\
\n\
// **** 5 stages technique \n\
pixelshader five_stages_ps = asm \n\
{ \n\
ps_1_4; \n\
texld r0, t0; \n\
texld r1, t1; \n\
texld r2, t2; \n\
texld r3, t3; \n\
texld r4, t4; \n\
// multiply lightmap with factor, and add with LMCAmbient+DynamicLight term\n\
mad r1.xyz, c1, r1, v0; \n\
mad r1.xyz, c2, r2, r1; \n\
mad r1.xyz, c3, r3, r1; \n\
mad r1.xyz, c4, r4, r1; \n\
mul r0.xyz, r1, r0; \n\
}; \n\
\n\
technique five_stages_5 \n\
{ \n\
pass p0 \n\
{ \n\
TexCoordIndex[2] = 1; \n\
TexCoordIndex[3] = 1; \n\
TexCoordIndex[4] = 1; \n\
\n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = false; \n\
\n\
Texture[0] = <texture0>; \n\
Texture[1] = <texture1>; \n\
Texture[2] = <texture2>; \n\
Texture[3] = <texture3>; \n\
Texture[4] = <texture4>; \n\
PixelShaderConstant[1] = <factor1>; \n\
PixelShaderConstant[2] = <factor2>; \n\
PixelShaderConstant[3] = <factor3>; \n\
PixelShaderConstant[4] = <factor4>; \n\
PixelShader = (five_stages_ps); \n\
} \n\
} \n\
\n\
// **** 4 stages technique \n\
pixelshader four_stages_ps = asm \n\
{ \n\
ps_1_1; \n\
tex t0; \n\
tex t1; \n\
tex t2; \n\
tex t3; \n\
// multiply lightmap with factor, and add with LMCAmbient+DynamicLight term\n\
mad r0.xyz, c1, t1, v0; \n\
mad r0.xyz, c2, t2, r0; \n\
mad r0.xyz, c3, t3, r0; \n\
mul r0.xyz, r0, t0; \n\
+mov r0.w, t0; \n\
}; \n\
\n\
technique four_stages_4 \n\
{ \n\
pass p0 \n\
{ \n\
TexCoordIndex[2] = 1; \n\
TexCoordIndex[3] = 1; \n\
\n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = false; \n\
\n\
Texture[0] = <texture0>; \n\
Texture[1] = <texture1>; \n\
Texture[2] = <texture2>; \n\
Texture[3] = <texture3>; \n\
PixelShaderConstant[1] = <factor1>; \n\
PixelShaderConstant[2] = <factor2>; \n\
PixelShaderConstant[3] = <factor3>; \n\
PixelShader = (four_stages_ps); \n\
} \n\
pass p1 \n\
{ \n\
FogColor = 0x00000000; // don't accumulate fog several times\n\
Lighting = false; \n\
AlphaBlendEnable = true; \n\
SrcBlend = one; \n\
DestBlend = one; \n\
\n\
// the DiffuseTexture texture 0 is in last stage \n\
TexCoordIndex[0] = 1; \n\
TexCoordIndex[1] = 0; \n\
Texture[0] = <texture4>; \n\
Texture[1] = <texture0>; \n\
TextureFactor = <color4>; \n\
ColorOp[0] = MODULATE; \n\
ColorArg1[0] = TFACTOR; \n\
ColorArg2[0] = TEXTURE; \n\
ColorOp[1] = MODULATE; \n\
ColorArg1[1] = CURRENT; \n\
ColorArg2[1] = TEXTURE; \n\
ColorOp[2] = DISABLE; \n\
ColorOp[3] = DISABLE; \n\
// Alpha stage 0 unused \n\
AlphaOp[0] = SELECTARG1; \n\
AlphaArg1[0] = TFACTOR; \n\
AlphaOp[1] = SELECTARG1; \n\
AlphaArg1[1] = TEXTURE; \n\
AlphaOp[2] = DISABLE; \n\
AlphaOp[3] = DISABLE; \n\
PixelShader = NULL; \n\
} \n\
} \n\
\n\
// **** 3 stages technique \n\
pixelshader three_stages_0_ps = asm \n\
{ \n\
ps_1_1; \n\
tex t0; \n\
tex t1; \n\
tex t2; \n\
// multiply lightmap with factor, and add with LMCAmbient+DynamicLight term\n\
mad r0.xyz, c1, t1, v0; \n\
mad r0.xyz, c2, t2, r0; \n\
mul r0.xyz, r0, t0; \n\
+mov r0.w, t0; \n\
}; \n\
\n\
technique three_stages_3 \n\
{ \n\
// 2 pass with the same pixel shader \n\
pass p0 \n\
{ \n\
TexCoordIndex[2] = 1; \n\
\n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = false; \n\
\n\
Texture[0] = <texture0>; \n\
Texture[1] = <texture1>; \n\
Texture[2] = <texture2>; \n\
PixelShaderConstant[1] = <factor1>; \n\
PixelShaderConstant[2] = <factor2>; \n\
PixelShader = (three_stages_0_ps); \n\
} \n\
pass p1 \n\
{ \n\
FogColor = 0x00000000; // don't accumulate fog several times\n\
// second pass: shut down all lighting (lmc ambient term and dynamic lighting already added in first pass)\n\
MaterialEmissive= <g_black>; \n\
MaterialDiffuse= <g_black>; \n\
\n\
AlphaBlendEnable = true; \n\
SrcBlend = one; \n\
DestBlend = one; \n\
Texture[1] = <texture3>; \n\
Texture[2] = <texture4>; \n\
PixelShaderConstant[1] = <factor3>; \n\
PixelShaderConstant[2] = <factor4>; \n\
} \n\
} \n\
\n\
// **** 2 stages, no pixel shader technique \n\
technique two_stages_2 \n\
{ \n\
pass p0 \n\
{ \n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = false; \n\
\n\
// the DiffuseTexture texture 0 is in last stage \n\
TexCoordIndex[0] = 1; \n\
TexCoordIndex[1] = 0; \n\
Texture[0] = <texture1>; \n\
Texture[1] = <texture0>; \n\
TextureFactor = <color1>; \n\
ColorOp[0] = MULTIPLYADD; \n\
ColorArg0[0] = DIFFUSE; \n\
ColorArg1[0] = TFACTOR; \n\
ColorArg2[0] = TEXTURE; \n\
ColorOp[1] = MODULATE; \n\
ColorArg1[1] = CURRENT; \n\
ColorArg2[1] = TEXTURE; \n\
// Alpha stage 0 unused \n\
AlphaOp[0] = SELECTARG1; \n\
AlphaArg1[0] = TFACTOR; \n\
AlphaOp[1] = SELECTARG1; \n\
AlphaArg1[1] = TEXTURE; \n\
} \n\
pass p1 \n\
{ \n\
FogColor = 0x00000000; // don't accumulate fog several times\n\
Lighting = false; \n\
AlphaBlendEnable = true; \n\
SrcBlend = one; \n\
DestBlend = one; \n\
Texture[0] = <texture2>; \n\
TextureFactor = <color2>; \n\
ColorOp[0] = MODULATE; \n\
} \n\
pass p2 \n\
{ \n\
Texture[0] = <texture3>; \n\
TextureFactor = <color3>; \n\
} \n\
pass p3 \n\
{ \n\
Texture[0] = <texture4>; \n\
TextureFactor = <color4>; \n\
} \n\
} \n\
\n\
\n\
";
static const char *Lightmap4blendFx =
" \n\
texture texture0; \n\
texture texture1; \n\
texture texture2; \n\
texture texture3; \n\
texture texture4; \n\
// Color0 is the Ambient Added to the lightmap (for Lightmap 8 bit compression)\n\
// Other colors are the lightmap Factors for each lightmap \n\
dword color0; \n\
dword color1; \n\
dword color2; \n\
dword color3; \n\
dword color4; \n\
float4 factor0; \n\
float4 factor1; \n\
float4 factor2; \n\
float4 factor3; \n\
float4 factor4; \n\
\n\
float4 g_black = { 0.0f, 0.0f, 0.0f, 1.0f }; \n\
float4 g_dyn_factor = { 1.0f, 1.0f, 1.0f, 1.0f }; \n\
\n\
\n\
// **** 5 stages technique \n\
pixelshader five_stages_ps = asm \n\
{ \n\
ps_1_4; \n\
texld r0, t0; \n\
texld r1, t1; \n\
texld r2, t2; \n\
texld r3, t3; \n\
texld r4, t4; \n\
// multiply lightmap with factor, and add with LMCAmbient+DynamicLight term\n\
mad r1.xyz, c1, r1, v0; \n\
mad r1.xyz, c2, r2, r1; \n\
mad r1.xyz, c3, r3, r1; \n\
mad r1.xyz, c4, r4, r1; \n\
mul r0.xyz, r1, r0; \n\
mov r0.w, r0; \n\
}; \n\
\n\
technique five_stages_5 \n\
{ \n\
pass p0 \n\
{ \n\
TexCoordIndex[2] = 1; \n\
TexCoordIndex[3] = 1; \n\
TexCoordIndex[4] = 1; \n\
\n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = true; \n\
SrcBlend = srcalpha; \n\
DestBlend = invsrcalpha; \n\
\n\
Texture[0] = <texture0>; \n\
Texture[1] = <texture1>; \n\
Texture[2] = <texture2>; \n\
Texture[3] = <texture3>; \n\
Texture[4] = <texture4>; \n\
PixelShaderConstant[1] = <factor1>; \n\
PixelShaderConstant[2] = <factor2>; \n\
PixelShaderConstant[3] = <factor3>; \n\
PixelShaderConstant[4] = <factor4>; \n\
PixelShader = (five_stages_ps); \n\
} \n\
} \n\
\n\
// **** 4 stages technique \n\
pixelshader four_stages_ps = asm \n\
{ \n\
ps_1_1; \n\
tex t0; \n\
tex t1; \n\
tex t2; \n\
tex t3; \n\
// multiply lightmap with factor, and add with LMCAmbient+DynamicLight term\n\
mad r0.xyz, c1, t1, v0; \n\
mad r0.xyz, c2, t2, r0; \n\
mad r0.xyz, c3, t3, r0; \n\
mul r0.xyz, r0, t0; \n\
mov r0.w, t0; \n\
}; \n\
\n\
technique four_stages_4 \n\
{ \n\
pass p0 \n\
{ \n\
TexCoordIndex[2] = 1; \n\
TexCoordIndex[3] = 1; \n\
\n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = true; \n\
SrcBlend = srcalpha; \n\
DestBlend = invsrcalpha; \n\
\n\
Texture[0] = <texture0>; \n\
Texture[1] = <texture1>; \n\
Texture[2] = <texture2>; \n\
Texture[3] = <texture3>; \n\
PixelShaderConstant[1] = <factor1>; \n\
PixelShaderConstant[2] = <factor2>; \n\
PixelShaderConstant[3] = <factor3>; \n\
PixelShader = (four_stages_ps); \n\
} \n\
pass p1 \n\
{ \n\
FogColor = 0x00000000; // don't accumulate fog several times\n\
Lighting = false; \n\
DestBlend = one; \n\
\n\
// the DiffuseTexture texture 0 is in last stage \n\
TexCoordIndex[0] = 1; \n\
TexCoordIndex[1] = 0; \n\
Texture[0] = <texture4>; \n\
Texture[1] = <texture0>; \n\
TextureFactor = <color4>; \n\
ColorOp[0] = MODULATE; \n\
ColorArg1[0] = TFACTOR; \n\
ColorArg2[0] = TEXTURE; \n\
ColorOp[1] = MODULATE; \n\
ColorArg1[1] = CURRENT; \n\
ColorArg2[1] = TEXTURE; \n\
ColorOp[2] = DISABLE; \n\
ColorOp[3] = DISABLE; \n\
// Alpha stage 0 unused \n\
AlphaOp[0] = SELECTARG1; \n\
AlphaArg1[0] = TFACTOR; \n\
AlphaOp[1] = SELECTARG1; \n\
AlphaArg1[1] = TEXTURE; \n\
AlphaOp[2] = DISABLE; \n\
AlphaOp[3] = DISABLE; \n\
PixelShader = NULL; \n\
} \n\
} \n\
\n\
// **** 3 stages technique \n\
pixelshader three_stages_0_ps = asm \n\
{ \n\
ps_1_1; \n\
tex t0; \n\
tex t1; \n\
tex t2; \n\
// multiply lightmap with factor, and add with LMCAmbient+DynamicLight term\n\
mad r0.xyz, c1, t1, v0; \n\
mad r0.xyz, c2, t2, r0; \n\
mul r0.xyz, r0, t0; \n\
mov r0.w, t0; \n\
}; \n\
\n\
technique three_stages_3 \n\
{ \n\
// 2 pass with the same pixel shader \n\
pass p0 \n\
{ \n\
TexCoordIndex[2] = 1; \n\
\n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = true; \n\
SrcBlend = srcalpha; \n\
DestBlend = invsrcalpha; \n\
\n\
Texture[0] = <texture0>; \n\
Texture[1] = <texture1>; \n\
Texture[2] = <texture2>; \n\
PixelShaderConstant[1] = <factor1>; \n\
PixelShaderConstant[2] = <factor2>; \n\
PixelShader = (three_stages_0_ps); \n\
} \n\
pass p1 \n\
{ \n\
FogColor = 0x00000000; // don't accumulate fog several times\n\
// second pass: shut down all lighting (lmc ambient term and dynamic lighting already added in first pass)\n\
MaterialEmissive= <g_black>; \n\
MaterialDiffuse= <g_black>; \n\
\n\
DestBlend = one; \n\
Texture[1] = <texture3>; \n\
Texture[2] = <texture4>; \n\
PixelShaderConstant[1] = <factor3>; \n\
PixelShaderConstant[2] = <factor4>; \n\
} \n\
} \n\
\n\
// **** 2 stages, no pixel shader technique \n\
technique two_stages_2 \n\
{ \n\
pass p0 \n\
{ \n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = true; \n\
SrcBlend = srcalpha; \n\
DestBlend = invsrcalpha; \n\
\n\
// the DiffuseTexture texture 0 is in last stage \n\
TexCoordIndex[0] = 1; \n\
TexCoordIndex[1] = 0; \n\
Texture[0] = <texture1>; \n\
Texture[1] = <texture0>; \n\
TextureFactor = <color1>; \n\
ColorOp[0] = MULTIPLYADD; \n\
ColorArg0[0] = DIFFUSE; \n\
ColorArg1[0] = TFACTOR; \n\
ColorArg2[0] = TEXTURE; \n\
ColorOp[1] = MODULATE; \n\
ColorArg1[1] = CURRENT; \n\
ColorArg2[1] = TEXTURE; \n\
// Alpha stage 0 unused \n\
AlphaOp[0] = SELECTARG1; \n\
AlphaArg1[0] = TFACTOR; \n\
AlphaOp[1] = SELECTARG1; \n\
AlphaArg1[1] = TEXTURE; \n\
} \n\
pass p1 \n\
{ \n\
FogColor = 0x00000000; // don't accumulate fog several times\n\
Lighting = false; \n\
DestBlend = one; \n\
Texture[0] = <texture2>; \n\
TextureFactor = <color2>; \n\
ColorOp[0] = MODULATE; \n\
} \n\
pass p2 \n\
{ \n\
Texture[0] = <texture3>; \n\
TextureFactor = <color3>; \n\
} \n\
pass p3 \n\
{ \n\
Texture[0] = <texture4>; \n\
TextureFactor = <color4>; \n\
} \n\
} \n\
\n\
\n\
\n\
";
static const char *Lightmap4blend_x2Fx =
" \n\
texture texture0; \n\
texture texture1; \n\
texture texture2; \n\
texture texture3; \n\
texture texture4; \n\
// Color0 is the Ambient Added to the lightmap (for Lightmap 8 bit compression)\n\
// Other colors are the lightmap Factors for each lightmap \n\
dword color0; \n\
dword color1; \n\
dword color2; \n\
dword color3; \n\
dword color4; \n\
float4 factor0; \n\
float4 factor1; \n\
float4 factor2; \n\
float4 factor3; \n\
float4 factor4; \n\
\n\
float4 g_black = { 0.0f, 0.0f, 0.0f, 1.0f }; \n\
// modulate the dyn light by 0.5, because of MODULATE2X \n\
float4 g_dyn_factor = { 0.5f, 0.5f, 0.5f, 1.0f }; \n\
\n\
\n\
// **** 5 stages technique \n\
pixelshader five_stages_ps = asm \n\
{ \n\
ps_1_4; \n\
texld r0, t0; \n\
texld r1, t1; \n\
texld r2, t2; \n\
texld r3, t3; \n\
texld r4, t4; \n\
// multiply lightmap with factor, and add with LMCAmbient+DynamicLight term\n\
mad r1.xyz, c1, r1, v0; \n\
mad r1.xyz, c2, r2, r1; \n\
mad r1.xyz, c3, r3, r1; \n\
mad r1.xyz, c4, r4, r1; \n\
mul_x2 r0.xyz, r1, r0; \n\
}; \n\
\n\
technique five_stages_5 \n\
{ \n\
pass p0 \n\
{ \n\
TexCoordIndex[2] = 1; \n\
TexCoordIndex[3] = 1; \n\
TexCoordIndex[4] = 1; \n\
\n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = true; \n\
SrcBlend = srcalpha; \n\
DestBlend = invsrcalpha; \n\
\n\
Texture[0] = <texture0>; \n\
Texture[1] = <texture1>; \n\
Texture[2] = <texture2>; \n\
Texture[3] = <texture3>; \n\
Texture[4] = <texture4>; \n\
PixelShaderConstant[1] = <factor1>; \n\
PixelShaderConstant[2] = <factor2>; \n\
PixelShaderConstant[3] = <factor3>; \n\
PixelShaderConstant[4] = <factor4>; \n\
PixelShader = (five_stages_ps); \n\
} \n\
} \n\
\n\
// **** 4 stages technique \n\
pixelshader four_stages_ps = asm \n\
{ \n\
ps_1_1; \n\
tex t0; \n\
tex t1; \n\
tex t2; \n\
tex t3; \n\
// multiply lightmap with factor, and add with LMCAmbient+DynamicLight term\n\
mad r0.xyz, c1, t1, v0; \n\
mad r0.xyz, c2, t2, r0; \n\
mad r0.xyz, c3, t3, r0; \n\
mul_x2 r0.xyz, r0, t0; \n\
+mov r0.w, t0; \n\
}; \n\
\n\
technique four_stages_4 \n\
{ \n\
pass p0 \n\
{ \n\
TexCoordIndex[2] = 1; \n\
TexCoordIndex[3] = 1; \n\
\n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = true; \n\
SrcBlend = srcalpha; \n\
DestBlend = invsrcalpha; \n\
\n\
Texture[0] = <texture0>; \n\
Texture[1] = <texture1>; \n\
Texture[2] = <texture2>; \n\
Texture[3] = <texture3>; \n\
PixelShaderConstant[1] = <factor1>; \n\
PixelShaderConstant[2] = <factor2>; \n\
PixelShaderConstant[3] = <factor3>; \n\
PixelShader = (four_stages_ps); \n\
} \n\
pass p1 \n\
{ \n\
FogColor = 0x00000000; // don't accumulate fog several times\n\
Lighting = false; \n\
DestBlend = one; \n\
\n\
// the DiffuseTexture texture 0 is in last stage \n\
TexCoordIndex[0] = 1; \n\
TexCoordIndex[1] = 0; \n\
Texture[0] = <texture4>; \n\
Texture[1] = <texture0>; \n\
TextureFactor = <color4>; \n\
ColorOp[0] = MODULATE; \n\
ColorArg1[0] = TFACTOR; \n\
ColorArg2[0] = TEXTURE; \n\
ColorOp[1] = MODULATE2X; \n\
ColorArg1[1] = CURRENT; \n\
ColorArg2[1] = TEXTURE; \n\
ColorOp[2] = DISABLE; \n\
ColorOp[3] = DISABLE; \n\
// Alpha stage 0 unused \n\
AlphaOp[0] = SELECTARG1; \n\
AlphaArg1[0] = TFACTOR; \n\
AlphaOp[1] = SELECTARG1; \n\
AlphaArg1[1] = TEXTURE; \n\
AlphaOp[2] = DISABLE; \n\
AlphaOp[3] = DISABLE; \n\
PixelShader = NULL; \n\
} \n\
} \n\
\n\
// **** 3 stages technique \n\
pixelshader three_stages_0_ps = asm \n\
{ \n\
ps_1_1; \n\
tex t0; \n\
tex t1; \n\
tex t2; \n\
// multiply lightmap with factor, and add with LMCAmbient+DynamicLight term\n\
mad r0.xyz, c1, t1, v0; \n\
mad r0.xyz, c2, t2, r0; \n\
mul_x2 r0.xyz, r0, t0; \n\
+mov r0.w, t0; \n\
}; \n\
\n\
technique three_stages_3 \n\
{ \n\
// 2 pass with the same pixel shader \n\
pass p0 \n\
{ \n\
TexCoordIndex[2] = 1; \n\
\n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = true; \n\
SrcBlend = srcalpha; \n\
DestBlend = invsrcalpha; \n\
\n\
Texture[0] = <texture0>; \n\
Texture[1] = <texture1>; \n\
Texture[2] = <texture2>; \n\
PixelShaderConstant[1] = <factor1>; \n\
PixelShaderConstant[2] = <factor2>; \n\
PixelShader = (three_stages_0_ps); \n\
} \n\
pass p1 \n\
{ \n\
FogColor = 0x00000000; // don't accumulate fog several times\n\
// second pass: shut down all lighting (lmc ambient term and dynamic lighting already added in first pass)\n\
MaterialEmissive= <g_black>; \n\
MaterialDiffuse= <g_black>; \n\
\n\
DestBlend = one; \n\
Texture[1] = <texture3>; \n\
Texture[2] = <texture4>; \n\
PixelShaderConstant[1] = <factor3>; \n\
PixelShaderConstant[2] = <factor4>; \n\
} \n\
} \n\
\n\
// **** 2 stages, no pixel shader technique \n\
technique two_stages_2 \n\
{ \n\
pass p0 \n\
{ \n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = true; \n\
SrcBlend = srcalpha; \n\
DestBlend = invsrcalpha; \n\
\n\
// the DiffuseTexture texture 0 is in last stage \n\
TexCoordIndex[0] = 1; \n\
TexCoordIndex[1] = 0; \n\
Texture[0] = <texture1>; \n\
Texture[1] = <texture0>; \n\
TextureFactor = <color1>; \n\
ColorOp[0] = MULTIPLYADD; \n\
ColorArg0[0] = DIFFUSE; \n\
ColorArg1[0] = TFACTOR; \n\
ColorArg2[0] = TEXTURE; \n\
ColorOp[1] = MODULATE2X; \n\
ColorArg1[1] = CURRENT; \n\
ColorArg2[1] = TEXTURE; \n\
// Alpha stage 0 unused \n\
AlphaOp[0] = SELECTARG1; \n\
AlphaArg1[0] = TFACTOR; \n\
AlphaOp[1] = SELECTARG1; \n\
AlphaArg1[1] = TEXTURE; \n\
} \n\
pass p1 \n\
{ \n\
FogColor = 0x00000000; // don't accumulate fog several times\n\
Lighting = false; \n\
DestBlend = one; \n\
Texture[0] = <texture2>; \n\
TextureFactor = <color2>; \n\
ColorOp[0] = MODULATE; \n\
} \n\
pass p2 \n\
{ \n\
Texture[0] = <texture3>; \n\
TextureFactor = <color3>; \n\
} \n\
pass p3 \n\
{ \n\
Texture[0] = <texture4>; \n\
TextureFactor = <color4>; \n\
} \n\
} \n\
\n\
\n\
\n\
";
static const char *Lightmap4_x2Fx =
" \n\
texture texture0; \n\
texture texture1; \n\
texture texture2; \n\
texture texture3; \n\
texture texture4; \n\
// Color0 is the Ambient Added to the lightmap (for Lightmap 8 bit compression)\n\
// Other colors are the lightmap Factors for each lightmap \n\
dword color0; \n\
dword color1; \n\
dword color2; \n\
dword color3; \n\
dword color4; \n\
float4 factor0; \n\
float4 factor1; \n\
float4 factor2; \n\
float4 factor3; \n\
float4 factor4; \n\
\n\
float4 g_black = { 0.0f, 0.0f, 0.0f, 1.0f }; \n\
// modulate the dyn light by 0.5, because of MODULATE2X \n\
float4 g_dyn_factor = { 0.5f, 0.5f, 0.5f, 1.0f }; \n\
\n\
\n\
// **** 5 stages technique \n\
pixelshader five_stages_ps = asm \n\
{ \n\
ps_1_4; \n\
texld r0, t0; \n\
texld r1, t1; \n\
texld r2, t2; \n\
texld r3, t3; \n\
texld r4, t4; \n\
// multiply lightmap with factor, and add with LMCAmbient+DynamicLight term\n\
mad r1.xyz, c1, r1, v0; \n\
mad r1.xyz, c2, r2, r1; \n\
mad r1.xyz, c3, r3, r1; \n\
mad r1.xyz, c4, r4, r1; \n\
mul_x2 r0.xyz, r1, r0; \n\
}; \n\
\n\
technique five_stages_5 \n\
{ \n\
pass p0 \n\
{ \n\
TexCoordIndex[2] = 1; \n\
TexCoordIndex[3] = 1; \n\
TexCoordIndex[4] = 1; \n\
\n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = false; \n\
\n\
Texture[0] = <texture0>; \n\
Texture[1] = <texture1>; \n\
Texture[2] = <texture2>; \n\
Texture[3] = <texture3>; \n\
Texture[4] = <texture4>; \n\
PixelShaderConstant[1] = <factor1>; \n\
PixelShaderConstant[2] = <factor2>; \n\
PixelShaderConstant[3] = <factor3>; \n\
PixelShaderConstant[4] = <factor4>; \n\
PixelShader = (five_stages_ps); \n\
} \n\
} \n\
\n\
// **** 4 stages technique \n\
pixelshader four_stages_ps = asm \n\
{ \n\
ps_1_1; \n\
tex t0; \n\
tex t1; \n\
tex t2; \n\
tex t3; \n\
// multiply lightmap with factor, and add with LMCAmbient+DynamicLight term\n\
mad r0.xyz, c1, t1, v0; \n\
mad r0.xyz, c2, t2, r0; \n\
mad r0.xyz, c3, t3, r0; \n\
mul_x2 r0.xyz, r0, t0; \n\
+mov r0.w, t0; \n\
}; \n\
\n\
technique four_stages_4 \n\
{ \n\
pass p0 \n\
{ \n\
TexCoordIndex[2] = 1; \n\
TexCoordIndex[3] = 1; \n\
\n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = false; \n\
\n\
Texture[0] = <texture0>; \n\
Texture[1] = <texture1>; \n\
Texture[2] = <texture2>; \n\
Texture[3] = <texture3>; \n\
PixelShaderConstant[1] = <factor1>; \n\
PixelShaderConstant[2] = <factor2>; \n\
PixelShaderConstant[3] = <factor3>; \n\
PixelShader = (four_stages_ps); \n\
} \n\
pass p1 \n\
{ \n\
FogColor = 0x00000000; // don't accumulate fog several times\n\
Lighting = false; \n\
AlphaBlendEnable = true; \n\
SrcBlend = one; \n\
DestBlend = one; \n\
\n\
// the DiffuseTexture texture 0 is in last stage \n\
TexCoordIndex[0] = 1; \n\
TexCoordIndex[1] = 0; \n\
Texture[0] = <texture4>; \n\
Texture[1] = <texture0>; \n\
TextureFactor = <color4>; \n\
ColorOp[0] = MODULATE; \n\
ColorArg1[0] = TFACTOR; \n\
ColorArg2[0] = TEXTURE; \n\
ColorOp[1] = MODULATE2X; \n\
ColorArg1[1] = CURRENT; \n\
ColorArg2[1] = TEXTURE; \n\
ColorOp[2] = DISABLE; \n\
ColorOp[3] = DISABLE; \n\
// Alpha stage 0 unused \n\
AlphaOp[0] = SELECTARG1; \n\
AlphaArg1[0] = TFACTOR; \n\
AlphaOp[1] = SELECTARG1; \n\
AlphaArg1[1] = TEXTURE; \n\
AlphaOp[2] = DISABLE; \n\
AlphaOp[3] = DISABLE; \n\
PixelShader = NULL; \n\
} \n\
} \n\
\n\
// **** 3 stages technique \n\
pixelshader three_stages_0_ps = asm \n\
{ \n\
ps_1_1; \n\
tex t0; \n\
tex t1; \n\
tex t2; \n\
// multiply lightmap with factor, and add with LMCAmbient+DynamicLight term\n\
mad r0.xyz, c1, t1, v0; \n\
mad r0.xyz, c2, t2, r0; \n\
mul_x2 r0.xyz, r0, t0; \n\
+mov r0.w, t0; \n\
}; \n\
\n\
technique three_stages_3 \n\
{ \n\
// 2 pass with the same pixel shader \n\
pass p0 \n\
{ \n\
TexCoordIndex[2] = 1; \n\
\n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = false; \n\
\n\
Texture[0] = <texture0>; \n\
Texture[1] = <texture1>; \n\
Texture[2] = <texture2>; \n\
PixelShaderConstant[1] = <factor1>; \n\
PixelShaderConstant[2] = <factor2>; \n\
PixelShader = (three_stages_0_ps); \n\
} \n\
pass p1 \n\
{ \n\
FogColor = 0x00000000; // don't accumulate fog several times\n\
// second pass: shut down all lighting (lmc ambient term and dynamic lighting already added in first pass)\n\
MaterialEmissive= <g_black>; \n\
MaterialDiffuse= <g_black>; \n\
\n\
AlphaBlendEnable = true; \n\
SrcBlend = one; \n\
DestBlend = one; \n\
Texture[1] = <texture3>; \n\
Texture[2] = <texture4>; \n\
PixelShaderConstant[1] = <factor3>; \n\
PixelShaderConstant[2] = <factor4>; \n\
} \n\
} \n\
\n\
// **** 2 stages, no pixel shader technique \n\
technique two_stages_2 \n\
{ \n\
pass p0 \n\
{ \n\
// Use Emissive For LMCAmbient, and diffuse for per vertex dynamic lighting\n\
Lighting = true; \n\
MaterialEmissive= <factor0>; \n\
MaterialAmbient= <g_black>; \n\
MaterialDiffuse= <g_dyn_factor>; \n\
MaterialSpecular= <g_black>; \n\
AlphaBlendEnable = false; \n\
\n\
// the DiffuseTexture texture 0 is in last stage \n\
TexCoordIndex[0] = 1; \n\
TexCoordIndex[1] = 0; \n\
Texture[0] = <texture1>; \n\
Texture[1] = <texture0>; \n\
TextureFactor = <color1>; \n\
ColorOp[0] = MULTIPLYADD; \n\
ColorArg0[0] = DIFFUSE; \n\
ColorArg1[0] = TFACTOR; \n\
ColorArg2[0] = TEXTURE; \n\
ColorOp[1] = MODULATE2X; \n\
ColorArg1[1] = CURRENT; \n\
ColorArg2[1] = TEXTURE; \n\
// Alpha stage 0 unused \n\
AlphaOp[0] = SELECTARG1; \n\
AlphaArg1[0] = TFACTOR; \n\
AlphaOp[1] = SELECTARG1; \n\
AlphaArg1[1] = TEXTURE; \n\
} \n\
pass p1 \n\
{ \n\
FogColor = 0x00000000; // don't accumulate fog several times\n\
Lighting = false; \n\
AlphaBlendEnable = true; \n\
SrcBlend = one; \n\
DestBlend = one; \n\
Texture[0] = <texture2>; \n\
TextureFactor = <color2>; \n\
ColorOp[0] = MODULATE; \n\
} \n\
pass p2 \n\
{ \n\
Texture[0] = <texture3>; \n\
TextureFactor = <color3>; \n\
} \n\
pass p3 \n\
{ \n\
Texture[0] = <texture4>; \n\
TextureFactor = <color4>; \n\
} \n\
} \n\
\n\
\n\
";
static const char *Water_diffuseFx =
" \n\
texture texture0; // bumpmap0 \n\
texture texture1; // bumpmap1 \n\
texture texture2; // envmap \n\
texture texture3; // diffuse \n\
\n\
float4 factor0; // bumpmap0 scale \n\
float4 factor1; // bumpmap1 scale \n\
float scalarFloat0; // bump scale for 1_1 version \n\
\n\
pixelshader water_diffuse_2_0 = asm \n\
{ \n\
ps_2_0; \n\
dcl t0.xy; \n\
dcl t1.xy; \n\
dcl t2.xy; \n\
dcl t3.xy; \n\
dcl_2d s0; \n\
dcl_2d s1; \n\
dcl_2d s2; \n\
dcl_2d s3; \n\
//read bump map 0 \n\
texld r0, t0, s0; \n\
//bias result (include scaling) \n\
mad r0.xy, r0, c0.z, c0; \n\
add r0.xy, r0, t1; \n\
//read bump map 1 \n\
texld r0, r0, s1; \n\
//bias result (include scaling) \n\
mad r0.xy, r0, c1.z, c1; \n\
//add envmap coord \n\
add r0.xy, r0, t2; \n\
// read envmap \n\
texld r0, r0, s2; \n\
// read diffuse \n\
texld r1, t3, s3; \n\
mul r0, r0, r1; \n\
mov oC0, r0 \n\
}; \n\
\n\
technique technique_water_diffuse_2_0 \n\
{ \n\
pass p0 \n\
{ \n\
Texture[0] = <texture0>; \n\
Texture[1] = <texture1>; \n\
Texture[2] = <texture2>; \n\
Texture[3] = <texture3>; \n\
PixelShaderConstant[0] = <factor0>; \n\
PixelShaderConstant[1] = <factor1>; \n\
PixelShader = (water_diffuse_2_0); \n\
} \n\
}; \n\
\n\
pixelshader water_diffuse_1_4 = asm \n\
{ \n\
ps_1_4; \n\
texld r0, t0; \n\
texld r1, t1; \n\
texcrd r2.xyz, t2; \n\
mad r2.xy, r0_bx2, c0, r2; \n\
mad r2.xy, r1_bx2, c1, r2; \n\
phase \n\
texld r2, r2; \n\
texld r3, t3; \n\
mul r0, r2, r3; \n\
}; \n\
\n\
technique technique_water_diffuse_1_4 \n\
{ \n\
pass p0 \n\
{ \n\
Texture[0] = <texture0>; \n\
Texture[1] = <texture1>; \n\
Texture[2] = <texture2>; \n\
Texture[3] = <texture3>; \n\
PixelShaderConstant[0] = <factor0>; \n\
PixelShaderConstant[1] = <factor1>; \n\
PixelShader = (water_diffuse_1_4); \n\
} \n\
}; \n\
\n\
pixelshader water_diffuse_1_1 = asm \n\
{ \n\
// note in OpenGL on nVidia cards, it is permitted to chain 2 texbem so the effect is less nice there (no bumpmap animation)\n\
ps_1_1; \n\
tex t1; \n\
texbem t2, t1; \n\
tex t3; \n\
mul r0, t3, t2; \n\
}; \n\
\n\
technique technique_water_diffuse_1_1 \n\
{ \n\
pass p0 \n\
{ \n\
Texture[1] = <texture1>; \n\
Texture[2] = <texture2>; \n\
Texture[3] = <texture3>; \n\
PixelShaderConstant[0] = <factor0>; \n\
PixelShaderConstant[1] = <factor1>; \n\
PixelShader = (water_diffuse_1_1); \n\
BumpEnvMat00[2] = <scalarFloat0>; \n\
BumpEnvMat01[0] = 0; \n\
BumpEnvMat10[0] = 0; \n\
BumpEnvMat11[2] = <scalarFloat0>; \n\
} \n\
}; \n\
\n\
";
static const char *Water_no_diffuseFx =
" \n\
texture texture0; // bumpmap0 \n\
texture texture1; // bumpmap1 \n\
texture texture2; // envmap \n\
\n\
float4 factor0; // bumpmap0 scale \n\
float4 factor1; // bumpmap1 scale \n\
float scalarFloat0; // bump scale for 1_1 version \n\
\n\
pixelshader water_no_diffuse_2_0 = asm \n\
{ \n\
ps_2_0; \n\
dcl t0.xy; \n\
dcl t1.xy; \n\
dcl t2.xy; \n\
dcl_2d s0; \n\
dcl_2d s1; \n\
dcl_2d s2; \n\
//read bump map 0 \n\
texld r0, t0, s0; \n\
//bias result (include scaling) \n\
mad r0.xy, r0, c0.z, c0; \n\
add r0.xy, r0, t1; \n\
//read bump map 1 \n\
texld r0, r0, s1; \n\
//bias result (include scaling) \n\
mad r0.xy, r0, c1.z, c1; \n\
//add envmap coord \n\
add r0.xy, r0, t2; \n\
//read envmap \n\
texld r0, r0, s2; \n\
mov oC0, r0; \n\
}; \n\
\n\
technique technique_water_no_diffuse_2_0 \n\
{ \n\
pass p0 \n\
{ \n\
Texture[0] = <texture0>; \n\
Texture[1] = <texture1>; \n\
Texture[2] = <texture2>; \n\
PixelShaderConstant[0] = <factor0>; \n\
PixelShaderConstant[1] = <factor1>; \n\
PixelShader = (water_no_diffuse_2_0); \n\
} \n\
}; \n\
\n\
pixelshader water_no_diffuse_1_4 = asm \n\
{ \n\
ps_1_4; \n\
texld r0, t0; \n\
texld r1, t1; \n\
texcrd r2.xyz, t2; \n\
mad r2.xy, r0_bx2, c0, r2; \n\
mad r2.xy, r1_bx2, c1, r2; \n\
phase \n\
texld r2, r2; \n\
mov r0, r2; \n\
}; \n\
\n\
technique technique_water_no_diffuse_1_4 \n\
{ \n\
pass p0 \n\
{ \n\
Texture[0] = <texture0>; \n\
Texture[1] = <texture1>; \n\
Texture[2] = <texture2>; \n\
PixelShaderConstant[0] = <factor0>; \n\
PixelShaderConstant[1] = <factor1>; \n\
PixelShader = (water_no_diffuse_1_4); \n\
} \n\
}; \n\
\n\
pixelshader water_no_diffuse_1_1 = asm \n\
{ \n\
// note in OpenGL on nVidia cards, it is permitted to chain 2 texbem so the effect is less nice there (no bumpmap animation)\n\
ps_1_1; \n\
tex t1; \n\
texbem t2, t1; \n\
mov r0, t2; \n\
}; \n\
\n\
technique technique_water_no_diffuse_1_1 \n\
{ \n\
pass p0 \n\
{ \n\
Texture[1] = <texture1>; \n\
Texture[2] = <texture2>; \n\
PixelShaderConstant[0] = <factor0>; \n\
PixelShaderConstant[1] = <factor1>; \n\
PixelShader = (water_no_diffuse_1_1); \n\
BumpEnvMat00[2] = <scalarFloat0>; \n\
BumpEnvMat01[0] = 0; \n\
BumpEnvMat10[0] = 0; \n\
BumpEnvMat11[2] = <scalarFloat0>; \n\
} \n\
}; \n\
\n\
";
void CDriverD3D::initInternalShaders()
{
H_AUTO_D3D(CDriverD3D_initInternalShaders)
setFx(_ShaderLightmap0,"lightmap0Fx", Lightmap0Fx);
setFx(_ShaderLightmap1,"lightmap1Fx", Lightmap1Fx);
setFx(_ShaderLightmap2,"lightmap2Fx", Lightmap2Fx);
setFx(_ShaderLightmap3,"lightmap3Fx", Lightmap3Fx);
setFx(_ShaderLightmap4,"lightmap4Fx", Lightmap4Fx);
setFx(_ShaderLightmap0Blend,"lightmap0blendFx", Lightmap0blendFx);
setFx(_ShaderLightmap1Blend,"lightmap1blendFx", Lightmap1blendFx);
setFx(_ShaderLightmap2Blend,"lightmap2blendFx", Lightmap2blendFx);
setFx(_ShaderLightmap3Blend,"lightmap3blendFx", Lightmap3blendFx);
setFx(_ShaderLightmap4Blend,"lightmap4blendFx", Lightmap4blendFx);
setFx(_ShaderLightmap0X2,"lightmap0_x2Fx", Lightmap0_x2Fx);
setFx(_ShaderLightmap1X2,"lightmap1_x2Fx", Lightmap1_x2Fx);
setFx(_ShaderLightmap2X2,"lightmap2_x2Fx", Lightmap2_x2Fx);
setFx(_ShaderLightmap3X2,"lightmap3_x2Fx", Lightmap3_x2Fx);
setFx(_ShaderLightmap4X2,"lightmap4_x2Fx", Lightmap4_x2Fx);
setFx(_ShaderLightmap0BlendX2,"lightmap0blend_x2Fx", Lightmap0blend_x2Fx);
setFx(_ShaderLightmap1BlendX2,"lightmap1blend_x2Fx", Lightmap1blend_x2Fx);
setFx(_ShaderLightmap2BlendX2,"lightmap2blend_x2Fx", Lightmap2blend_x2Fx);
setFx(_ShaderLightmap3BlendX2,"lightmap3blend_x2Fx", Lightmap3blend_x2Fx);
setFx(_ShaderLightmap4BlendX2,"lightmap4blend_x2Fx", Lightmap4blend_x2Fx);
setFx(_ShaderCloud, "cloudFx", CloudFx);
setFx(_ShaderWaterNoDiffuse,"water_no_diffuseFx", Water_no_diffuseFx);
setFx(_ShaderWaterDiffuse, "water_diffuseFx", Water_diffuseFx);
}
// ***************************************************************************
void CDriverD3D::releaseInternalShaders()
{
H_AUTO_D3D(CDriverD3D_releaseInternalShaders)
_ShaderLightmap0._DrvInfo.kill();
_ShaderLightmap1._DrvInfo.kill();
_ShaderLightmap2._DrvInfo.kill();
_ShaderLightmap3._DrvInfo.kill();
_ShaderLightmap4._DrvInfo.kill();
_ShaderLightmap0Blend._DrvInfo.kill();
_ShaderLightmap1Blend._DrvInfo.kill();
_ShaderLightmap2Blend._DrvInfo.kill();
_ShaderLightmap3Blend._DrvInfo.kill();
_ShaderLightmap4Blend._DrvInfo.kill();
_ShaderLightmap0X2._DrvInfo.kill();
_ShaderLightmap1X2._DrvInfo.kill();
_ShaderLightmap2X2._DrvInfo.kill();
_ShaderLightmap3X2._DrvInfo.kill();
_ShaderLightmap4X2._DrvInfo.kill();
_ShaderLightmap0BlendX2._DrvInfo.kill();
_ShaderLightmap1BlendX2._DrvInfo.kill();
_ShaderLightmap2BlendX2._DrvInfo.kill();
_ShaderLightmap3BlendX2._DrvInfo.kill();
_ShaderLightmap4BlendX2._DrvInfo.kill();
_ShaderCloud._DrvInfo.kill();
_ShaderWaterNoDiffuse._DrvInfo.kill();
_ShaderWaterDiffuse._DrvInfo.kill();
}
// ***************************************************************************
bool CDriverD3D::setShaderTexture (uint textureHandle, ITexture *texture, CFXCache *cache)
{
H_AUTO_D3D(CDriverD3D_setShaderTexture )
// Setup the texture
if (!setupTexture(*texture))
return false;
// Set the main texture
nlassert (_CurrentShader);
CShaderDrvInfosD3D *shaderInfo = static_cast<CShaderDrvInfosD3D*>((IShaderDrvInfos*)_CurrentShader->_DrvInfo);
nlassert (shaderInfo);
ID3DXEffect *effect = shaderInfo->Effect;
CTextureDrvInfosD3D *d3dtext = getTextureD3D (*texture);
if (texture)
{
if (cache)
{
cache->Params.setTexture(textureHandle, d3dtext->Texture);
}
else
{
effect->SetTexture (shaderInfo->TextureHandle[textureHandle], d3dtext->Texture);
}
}
// Add a ref on this texture
_CurrentShaderTextures.push_back (CTextureRef());
CTextureRef &ref = _CurrentShaderTextures.back();
ref.NeLTexture = texture;
ref.D3DTexture = d3dtext->Texture;
return true;
}
// ***************************************************************************
void CDriverD3D::disableHardwareTextureShader()
{
// cannot disable pixel shader under DX, because it crashes with lightmap
// => no-op
/*
_DisableHardwarePixelShader = true;
_PixelShader = false;
*/
}
// ***************************************************************************
void CDriverD3D::notifyAllShaderDrvOfLostDevice()
{
for(TShaderDrvInfoPtrList::iterator it = _ShaderDrvInfos.begin(); it != _ShaderDrvInfos.end(); ++it)
{
nlassert(*it);
CShaderDrvInfosD3D *drvInfo = NLMISC::safe_cast<CShaderDrvInfosD3D *>(*it);
if (drvInfo->Effect)
{
nlverify(drvInfo->Effect->OnLostDevice() == D3D_OK);
}
}
}
// ***************************************************************************
void CDriverD3D::notifyAllShaderDrvOfResetDevice()
{
for(TShaderDrvInfoPtrList::iterator it = _ShaderDrvInfos.begin(); it != _ShaderDrvInfos.end(); ++it)
{
nlassert(*it);
CShaderDrvInfosD3D *drvInfo = NLMISC::safe_cast<CShaderDrvInfosD3D *>(*it);
if (drvInfo->Effect)
{
//nlverify(
drvInfo->Effect->OnResetDevice();
//== D3D_OK);
}
}
}
// ***************************************************************************
// state records (for .fx caching)
// ***************************************************************************
class CStateRecordLightEnable : public CStateRecord
{
public:
DWORD Index;
BOOL Enable;
public:
CStateRecordLightEnable(DWORD index, BOOL enable) : Index(index), Enable(enable) {}
virtual void apply(class CDriverD3D &drv)
{
drv.enableLight ((uint8)Index, Enable!=FALSE);
}
};
//
class CStateRecordLight : public CStateRecord
{
public:
DWORD Index;
D3DLIGHT9 Light;
public:
CStateRecordLight(DWORD index, const D3DLIGHT9 *pLight) : Index(index), Light(*pLight) {}
virtual void apply(class CDriverD3D &drv)
{
drv._LightCache[Index].Light = Light;
drv.touchRenderVariable (&drv._LightCache[Index]);
}
};
//
class CStateRecordMaterial : public CStateRecord
{
public:
D3DMATERIAL9 Material;
public:
CStateRecordMaterial(const D3DMATERIAL9 *pMaterial) : Material(*pMaterial) {}
virtual void apply(class CDriverD3D &drv)
{
drv.setMaterialState(Material);
}
};
//
class CStateRecordPixelShader : public CStateRecord
{
public:
LPDIRECT3DPIXELSHADER9 PixelShader;
public:
CStateRecordPixelShader(LPDIRECT3DPIXELSHADER9 pixelShader) : PixelShader(pixelShader) {}
virtual void apply(class CDriverD3D &drv)
{
drv.setPixelShader(PixelShader);
}
};
//
class CStateRecordPixelShaderConstantB : public CStateRecord
{
public:
std::vector<BOOL> Values;
uint StartRegister;
public:
CStateRecordPixelShaderConstantB(DWORD startRegister, const BOOL *values, DWORD countVec4) : StartRegister(startRegister)
{
Values.resize(countVec4 * 4);
std::copy(values, values + countVec4 * 4, Values.begin());
}
virtual void apply(class CDriverD3D &drv)
{
const BOOL *curr = &Values[0];
const BOOL *last = &Values[0] + Values.size();
uint i = StartRegister;
while (curr != last)
{
drv.setPixelShaderConstant (i, curr);
curr += 4;
++ i;
}
}
};
//
class CStateRecordPixelShaderConstantF : public CStateRecord
{
public:
std::vector<FLOAT> Values;
uint StartRegister;
public:
CStateRecordPixelShaderConstantF(DWORD startRegister, const FLOAT *values, DWORD countVec4) : StartRegister(startRegister)
{
Values.resize(countVec4 * 4);
std::copy(values, values + countVec4 * 4, Values.begin());
}
virtual void apply(class CDriverD3D &drv)
{
const FLOAT *curr = &Values[0];
const FLOAT *last = &Values[0] + Values.size();
uint i = StartRegister;
while (curr != last)
{
drv.setPixelShaderConstant (i, curr);
curr += 4;
++ i;
}
}
};
//
class CStateRecordPixelShaderConstantI : public CStateRecord
{
public:
std::vector<INT> Values;
uint StartRegister;
public:
CStateRecordPixelShaderConstantI(DWORD startRegister, const INT *values, DWORD countVec4) : StartRegister(startRegister)
{
Values.resize(countVec4 * 4);
std::copy(values, values + countVec4 * 4, Values.begin());
}
virtual void apply(class CDriverD3D &drv)
{
const INT *curr = &Values[0];
const INT *last = &Values[0] + Values.size();
uint i = StartRegister;
while (curr != last)
{
drv.setPixelShaderConstant (i, curr);
curr += 4;
++ i;
}
}
};
//
class CStateRecordRenderState : public CStateRecord
{
public:
D3DRENDERSTATETYPE State;
DWORD Value;
public:
CStateRecordRenderState(D3DRENDERSTATETYPE state, DWORD value) : State(state), Value(value) {}
virtual void apply(class CDriverD3D &drv)
{
drv.setRenderState(State, Value);
}
};
//
class CStateRecordSamplerState : public CStateRecord
{
public:
DWORD Sampler;
D3DSAMPLERSTATETYPE Type;
DWORD Value;
public:
CStateRecordSamplerState(DWORD sampler, D3DSAMPLERSTATETYPE type, DWORD value) : Sampler(sampler), Type(type), Value(value) {}
virtual void apply(class CDriverD3D &drv)
{
drv.setSamplerState(Sampler, Type, Value);
}
};
//
class CStateRecordTexture : public CStateRecord
{
public:
DWORD Stage;
CRefPtr<ITexture> TexRef;
LPDIRECT3DBASETEXTURE9 Texture;
BOOL IsNelTexture;
public:
CStateRecordTexture(DWORD stage, LPDIRECT3DBASETEXTURE9 texture, ITexture *nelTexture) : Stage(stage), Texture(texture)
{
nlassert(Texture);
H_AUTO_D3D(CDriverD3D_SetTexture )
// if not a NeL texture, should add a reference on texture, else use refptr instead
IsNelTexture = nelTexture != NULL;
TexRef = nelTexture;
if (!IsNelTexture)
{
HRESULT r = Texture->AddRef();
nlassert(r == D3D_OK);
}
}
~CStateRecordTexture()
{
nlassert(Texture); // no default ctor, so texture should have been set
if (!IsNelTexture)
{
nlassert(TexRef == NULL);
HRESULT r = Texture->Release();
nlassert(r == D3D_OK);
}
}
virtual void apply(class CDriverD3D &drv)
{
nlassert(Texture);
if (TexRef)
{
drv.setTexture(Stage, TexRef);
}
else
{
drv.setTexture(Stage, Texture);
}
}
};
//
class CStateRecordTextureStageState : public CStateRecord
{
public:
DWORD Stage;
D3DTEXTURESTAGESTATETYPE Type;
DWORD Value;
public:
CStateRecordTextureStageState(DWORD stage, D3DTEXTURESTAGESTATETYPE type, DWORD value) : Stage(stage), Type(type), Value(value) {}
virtual void apply(class CDriverD3D &drv)
{
if (Type == D3DTSS_TEXCOORDINDEX)
drv.setTextureIndexUV (Stage, Value);
else
drv.setTextureState (Stage, Type, Value);
}
};
//
class CStateRecordTransform : public CStateRecord
{
public:
D3DTRANSFORMSTATETYPE State;
D3DMATRIX Matrix;
public:
CStateRecordTransform(D3DTRANSFORMSTATETYPE state, const D3DMATRIX *pMatrix) : State(state), Matrix(*pMatrix) {}
virtual void apply(class CDriverD3D &drv)
{
drv.setMatrix(State, Matrix);
}
};
//
class CStateRecordVertexShader : public CStateRecord
{
public:
LPDIRECT3DVERTEXSHADER9 Shader;
public:
CStateRecordVertexShader(LPDIRECT3DVERTEXSHADER9 shader) : Shader(shader) {}
virtual void apply(class CDriverD3D &/* drv */)
{
nlassert(0); // not supported
//drv.setVertexProgram(Shader);
}
};
//
class CStateRecordVertexShaderConstantB : public CStateRecord
{
public:
std::vector<BOOL> Values;
uint StartRegister;
public:
CStateRecordVertexShaderConstantB(DWORD startRegister, const BOOL *values, DWORD countVec4) : StartRegister(startRegister)
{
Values.resize(countVec4 * 4);
std::copy(values, values + countVec4 * 4, Values.begin());
}
virtual void apply(class CDriverD3D &drv)
{
const BOOL *curr = &Values[0];
const BOOL *last = &Values[0] + Values.size();
uint i = StartRegister;
while (curr != last)
{
drv.setVertexProgramConstant(i, curr);
curr += 4;
++ i;
}
}
};
class CStateRecordVertexShaderConstantF : public CStateRecord
{
public:
std::vector<FLOAT> Values;
uint StartRegister;
public:
CStateRecordVertexShaderConstantF(DWORD startRegister, const FLOAT *values, DWORD countVec4) : StartRegister(startRegister)
{
Values.resize(countVec4 * 4);
std::copy(values, values + countVec4 * 4, Values.begin());
}
virtual void apply(class CDriverD3D &drv)
{
const FLOAT *curr = &Values[0];
const FLOAT *last = &Values[0] + Values.size();
uint i = StartRegister;
while (curr != last)
{
drv.setVertexProgramConstant(i, curr);
curr += 4;
++ i;
}
}
};
class CStateRecordVertexShaderConstantI : public CStateRecord
{
public:
std::vector<INT> Values;
uint StartRegister;
public:
CStateRecordVertexShaderConstantI(DWORD startRegister, const INT *values, DWORD countVec4) : StartRegister(startRegister)
{
Values.resize(countVec4 * 4);
std::copy(values, values + countVec4 * 4, Values.begin());
}
virtual void apply(class CDriverD3D &drv)
{
const INT *curr = &Values[0];
const INT *last = &Values[0] + Values.size();
uint i = StartRegister;
while (curr != last)
{
drv.setVertexProgramConstant(i, curr);
curr += 4;
++ i;
}
}
};
// state recorder
HRESULT STDMETHODCALLTYPE CFXPassRecorder::QueryInterface(REFIID riid, LPVOID *ppvObj)
{
nlassert(Driver);
return Driver->QueryInterface(riid, ppvObj);
}
ULONG STDMETHODCALLTYPE CFXPassRecorder::AddRef(VOID)
{
nlassert(Driver);
return Driver->AddRef();
}
ULONG STDMETHODCALLTYPE CFXPassRecorder::Release(VOID)
{
nlassert(Driver);
return Driver->Release();
}
HRESULT STDMETHODCALLTYPE CFXPassRecorder::LightEnable(DWORD Index, BOOL Enable)
{
nlassert(Driver);
nlassert(Target);
Target->States.push_back(new CStateRecordLightEnable(Index, Enable));
return D3D_OK;
}
HRESULT STDMETHODCALLTYPE CFXPassRecorder::SetFVF(DWORD /* FVF */)
{
nlassert(0); // not managed
return D3D_OK;
}
HRESULT STDMETHODCALLTYPE CFXPassRecorder::SetLight(DWORD Index, CONST D3DLIGHT9* pLight)
{
nlassert(Driver);
nlassert(Target);
Target->States.push_back(new CStateRecordLight(Index, pLight));
return D3D_OK;
}
HRESULT STDMETHODCALLTYPE CFXPassRecorder::SetMaterial(CONST D3DMATERIAL9* pMaterial)
{
nlassert(Driver);
nlassert(Target);
Target->States.push_back(new CStateRecordMaterial(pMaterial));
return D3D_OK;
}
HRESULT STDMETHODCALLTYPE CFXPassRecorder::SetNPatchMode(FLOAT /* nSegments */)
{
nlassert(0); // not managed
return D3D_OK;
}
HRESULT STDMETHODCALLTYPE CFXPassRecorder::SetPixelShader(LPDIRECT3DPIXELSHADER9 pShader)
{
nlassert(Driver);
nlassert(Target);
Target->States.push_back(new CStateRecordPixelShader(pShader));
return D3D_OK;
}
HRESULT STDMETHODCALLTYPE CFXPassRecorder::SetPixelShaderConstantB(UINT StartRegister, CONST BOOL* pConstantData, UINT RegisterCount)
{
nlassert(Driver);
nlassert(Target);
Target->States.push_back(new CStateRecordPixelShaderConstantB(StartRegister, pConstantData, RegisterCount));
return D3D_OK;
}
HRESULT STDMETHODCALLTYPE CFXPassRecorder::SetPixelShaderConstantF(UINT StartRegister, CONST FLOAT* pConstantData, UINT RegisterCount)
{
nlassert(Driver);
nlassert(Target);
Target->States.push_back(new CStateRecordPixelShaderConstantF(StartRegister, pConstantData, RegisterCount));
return D3D_OK;
}
HRESULT STDMETHODCALLTYPE CFXPassRecorder::SetPixelShaderConstantI(UINT StartRegister, CONST INT* pConstantData, UINT RegisterCount)
{
nlassert(Driver);
nlassert(Target);
Target->States.push_back(new CStateRecordPixelShaderConstantI(StartRegister, pConstantData, RegisterCount));
return D3D_OK;
}
HRESULT STDMETHODCALLTYPE CFXPassRecorder::SetRenderState(D3DRENDERSTATETYPE State, DWORD Value)
{
nlassert(Driver);
nlassert(Target);
Target->States.push_back(new CStateRecordRenderState(State, Value));
return D3D_OK;
}
HRESULT STDMETHODCALLTYPE CFXPassRecorder::SetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value)
{
nlassert(Driver);
nlassert(Target);
Target->States.push_back(new CStateRecordSamplerState(Sampler, Type, Value));
return D3D_OK;
}
HRESULT STDMETHODCALLTYPE CFXPassRecorder::SetTexture(DWORD Stage, LPDIRECT3DBASETEXTURE9 pTexture)
{
nlassert(Driver);
nlassert(Target);
// Look for the current texture
uint i;
const uint count = Driver->getCurrentShaderTextures().size();
for (i=0; i<count; i++)
{
const CDriverD3D::CTextureRef &ref = Driver->getCurrentShaderTextures()[i];
if (ref.D3DTexture == pTexture)
{
// Set the additionnal stage set by NeL texture (D3DSAMP_ADDRESSU, D3DSAMP_ADDRESSV, D3DSAMP_MAGFILTER, D3DSAMP_MINFILTER and D3DSAMP_MIPFILTER)
Target->States.push_back(new CStateRecordTexture(Stage, pTexture, ref.NeLTexture));
break;
}
}
if (i == count)
{
// The texture isn't a NeL texture (was created inside driver)
Target->States.push_back(new CStateRecordTexture(Stage, pTexture, NULL));
}
return D3D_OK;
}
HRESULT STDMETHODCALLTYPE CFXPassRecorder::SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value)
{
nlassert(Driver);
nlassert(Target);
Target->States.push_back(new CStateRecordTextureStageState(Stage, Type, Value));
return D3D_OK;
}
HRESULT STDMETHODCALLTYPE CFXPassRecorder::SetTransform(D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix)
{
nlassert(Driver);
nlassert(Target);
Target->States.push_back(new CStateRecordTransform(State, pMatrix));
return D3D_OK;
}
HRESULT STDMETHODCALLTYPE CFXPassRecorder::SetVertexShader(LPDIRECT3DVERTEXSHADER9 pShader)
{
nlassert(Driver);
nlassert(Target);
Target->States.push_back(new CStateRecordVertexShader(pShader));
return D3D_OK;
}
HRESULT STDMETHODCALLTYPE CFXPassRecorder::SetVertexShaderConstantB(UINT StartRegister, CONST BOOL* pConstantData, UINT RegisterCount)
{
nlassert(Driver);
nlassert(Target);
Target->States.push_back(new CStateRecordVertexShaderConstantB(StartRegister, pConstantData, RegisterCount));
return D3D_OK;
}
HRESULT STDMETHODCALLTYPE CFXPassRecorder::SetVertexShaderConstantF(UINT StartRegister, CONST FLOAT* pConstantData, UINT RegisterCount)
{
nlassert(Driver);
nlassert(Target);
Target->States.push_back(new CStateRecordVertexShaderConstantF(StartRegister, pConstantData, RegisterCount));
return D3D_OK;
}
HRESULT STDMETHODCALLTYPE CFXPassRecorder::SetVertexShaderConstantI(UINT StartRegister, CONST INT* pConstantData, UINT RegisterCount)
{
nlassert(Driver);
nlassert(Target);
Target->States.push_back(new CStateRecordVertexShaderConstantI(StartRegister, pConstantData, RegisterCount));
return D3D_OK;
}
//===================================================================================
CFXPassRecord::~CFXPassRecord()
{
for(std::vector<CStateRecord *>::iterator it = States.begin(); it != States.end(); ++it)
{
delete *it;
}
}
void CFXPassRecord::apply(CDriverD3D &drv)
{
for(std::vector<CStateRecord *>::iterator it = States.begin(); it != States.end(); ++it)
{
(*it)->apply(drv);
}
}
const uint NL_D3D_NUM_RENDER_FOR_FX_CACHING = 4;
//===================================================================================
void CFXCache::setConstants(CShaderDrvInfosD3D *si)
{
nlassert(si);
nlassert(si->Effect);
for(uint k = 0; k < CFXInputParams::MaxNumParams; ++k)
{
if (Params.Textures[k].Set) si->Effect->SetTexture(si->TextureHandle[k], Params.Textures[k].Value);
if (Params.Vectors[k].Set) si->Effect->SetFloatArray(si->FactorHandle[k], (CONST FLOAT *) &(Params.Vectors[k].Value), 4);
if (Params.Colors[k].Set) si->Effect->SetInt(si->ColorHandle[k], Params.Colors[k].Value);
if (Params.Floats[k].Set) si->Effect->SetFloat(si->ScalarFloatHandle[k], Params.Floats[k].Value);
}
}
void CFXCache::begin(CShaderDrvInfosD3D *si, CDriverD3D *driver)
{
nlassert(driver);
// amortize cost of caching for animated material -> ensure that the parameters don't change for
// a few number of display before doing caching
if (Params.Touched)
{
Steadyness = 0;
Passes.clear();
NumPasses = 0;
Params.Touched = false;
return;
}
if (!Params.Touched)
{
++ Steadyness;
}
if (Steadyness < NL_D3D_NUM_RENDER_FOR_FX_CACHING)
{
NumPasses = 0;
Passes.clear();
return;
}
if (Passes.empty()) // must record shader ?
{
Passes.clear();
UINT numPasses;
CFXPassRecorder pr;
pr.Driver = driver;
si->Effect->SetStateManager(&pr);
// Set constants
setConstants(si);
//
HRESULT r = si->Effect->Begin(&numPasses, D3DXFX_DONOTSAVESTATE|D3DXFX_DONOTSAVESHADERSTATE);
nlassert(r == D3D_OK);
Passes.resize(numPasses);
for(uint k = 0; k < numPasses; ++k)
{
pr.Target = &Passes[k];
#if (DIRECT3D_VERSION >= 0x0900) && (D3D_SDK_VERSION >= 32)
si->Effect->BeginPass(k);
si->Effect->EndPass();
#else
si->Effect->Pass(k);
#endif
}
r = si->Effect->End();
nlassert(r == D3D_OK);
NumPasses = numPasses;
si->Effect->SetStateManager(driver);
}
}
void CFXCache::applyPass(class CDriverD3D &drv, CShaderDrvInfosD3D *si, uint passIndex)
{
if (Passes.empty() && NumPasses == 0)
{
// the shader has not been cached yet (maybe animated)
// so uses the standard path
UINT numPasses;
setConstants(si);
HRESULT r = si->Effect->Begin(&numPasses, D3DXFX_DONOTSAVESTATE|D3DXFX_DONOTSAVESHADERSTATE);
nlassert(r == D3D_OK);
NumPasses = numPasses;
}
nlassert(passIndex < NumPasses);
if (Passes.empty())
{
#if (DIRECT3D_VERSION >= 0x0900) && (D3D_SDK_VERSION >= 32)
HRESULT r = si->Effect->BeginPass(passIndex);
si->Effect->EndPass ();
#else
HRESULT r = si->Effect->Pass(passIndex);
#endif
nlassert(r == D3D_OK);
}
else
{
Passes[passIndex].apply(drv);
}
}
void CFXCache::end(CShaderDrvInfosD3D *si)
{
if (Passes.empty())
{
HRESULT r = si->Effect->End();
nlassert(r == D3D_OK);
}
}
void CFXCache::reset()
{
Params.reset();
Passes.clear();
Steadyness = 0;
}
} // NL3D