Implement new driver interface in Direct3D driver
This commit is contained in:
parent
99a48d5511
commit
fcb0ee720e
5 changed files with 482 additions and 517 deletions
|
@ -3634,7 +3634,7 @@ void CDriverD3D::CVertexProgramPtrState::apply(CDriverD3D *driver)
|
|||
void CDriverD3D::CPixelShaderPtrState::apply(CDriverD3D *driver)
|
||||
{
|
||||
H_AUTO_D3D(CDriverD3D_CPixelShaderPtrState);
|
||||
if (!driver->supportPixelProgram()) return;
|
||||
if (!driver->_PixelProgram) return;
|
||||
driver->_DeviceInterface->SetPixelShader(PixelShader);
|
||||
}
|
||||
|
||||
|
|
|
@ -1092,33 +1092,103 @@ public:
|
|||
virtual void setupMaterialPass(uint pass);
|
||||
virtual void endMaterialMultiPass();
|
||||
|
||||
// Vertex program
|
||||
virtual bool supportVertexProgram () const;
|
||||
virtual bool supportPixelProgram () const;
|
||||
virtual bool supportPixelProgram (CPixelProgram::TProfile profile) const;
|
||||
virtual bool isVertexProgramEmulated () const;
|
||||
virtual bool activeVertexProgram (CVertexProgram *program);
|
||||
virtual bool activePixelProgram (CPixelProgram *program);
|
||||
virtual void setConstant (uint index, float, float, float, float);
|
||||
virtual void setConstant (uint index, double, double, double, double);
|
||||
virtual void setConstant (uint index, const NLMISC::CVector& value);
|
||||
virtual void setConstant (uint index, const NLMISC::CVectorD& value);
|
||||
virtual void setConstant (uint index, uint num, const float *src);
|
||||
virtual void setConstant (uint index, uint num, const double *src);
|
||||
virtual void setConstantMatrix (uint index, IDriver::TMatrix matrix, IDriver::TTransform transform);
|
||||
virtual void setConstantFog (uint index);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// \name Vertex Program
|
||||
// @{
|
||||
|
||||
// Order of preference
|
||||
// - activeVertexProgram
|
||||
// - CMaterial pass[n] VP (uses activeVertexProgram, but does not override if one already set by code)
|
||||
// - default generic VP that mimics fixed pipeline / no VP with fixed pipeline
|
||||
|
||||
/**
|
||||
* Does the driver supports vertex program, but emulated by CPU ?
|
||||
*/
|
||||
virtual bool isVertexProgramEmulated() const;
|
||||
|
||||
/** Return true if the driver supports the specified vertex program profile.
|
||||
*/
|
||||
virtual bool supportVertexProgram(CVertexProgram::TProfile profile = CVertexProgram::nelvp) const;
|
||||
|
||||
/** Compile the given vertex program, return if successful.
|
||||
* If a vertex program was set active before compilation,
|
||||
* the state of the active vertex program is undefined behaviour afterwards.
|
||||
*/
|
||||
virtual bool compileVertexProgram(CVertexProgram *program);
|
||||
|
||||
/** Set the active vertex program. This will override vertex programs specified in CMaterial render calls.
|
||||
* Also used internally by setupMaterial(CMaterial) when getVertexProgram returns NULL.
|
||||
* The vertex program is activated immediately.
|
||||
*/
|
||||
virtual bool activeVertexProgram(CVertexProgram *program);
|
||||
// @}
|
||||
|
||||
|
||||
|
||||
/// \name Pixel Program
|
||||
// @{
|
||||
|
||||
// Order of preference
|
||||
// - activePixelProgram
|
||||
// - CMaterial pass[n] PP (uses activePixelProgram, but does not override if one already set by code)
|
||||
// - PP generated from CMaterial (uses activePixelProgram, but does not override if one already set by code)
|
||||
|
||||
/** Return true if the driver supports the specified pixel program profile.
|
||||
*/
|
||||
virtual bool supportPixelProgram(CPixelProgram::TProfile profile) const;
|
||||
|
||||
/** Compile the given pixel program, return if successful.
|
||||
* If a pixel program was set active before compilation,
|
||||
* the state of the active pixel program is undefined behaviour afterwards.
|
||||
*/
|
||||
virtual bool compilePixelProgram(CPixelProgram *program);
|
||||
|
||||
/** Set the active pixel program. This will override pixel programs specified in CMaterial render calls.
|
||||
* Also used internally by setupMaterial(CMaterial) when getPixelProgram returns NULL.
|
||||
* The pixel program is activated immediately.
|
||||
*/
|
||||
virtual bool activePixelProgram(CPixelProgram *program);
|
||||
// @}
|
||||
|
||||
|
||||
|
||||
/// \name Program parameters
|
||||
// @{
|
||||
// Set parameters
|
||||
virtual void setUniform1f(TProgram program, uint index, float f0);
|
||||
virtual void setUniform2f(TProgram program, uint index, float f0, float f1);
|
||||
virtual void setUniform3f(TProgram program, uint index, float f0, float f1, float f2);
|
||||
virtual void setUniform4f(TProgram program, uint index, float f0, float f1, float f2, float f3);
|
||||
virtual void setUniform1i(TProgram program, uint index, sint32 i0);
|
||||
virtual void setUniform2i(TProgram program, uint index, sint32 i0, sint32 i1);
|
||||
virtual void setUniform3i(TProgram program, uint index, sint32 i0, sint32 i1, sint32 i2);
|
||||
virtual void setUniform4i(TProgram program, uint index, sint32 i0, sint32 i1, sint32 i2, sint32 i3);
|
||||
virtual void setUniform1ui(TProgram program, uint index, uint32 ui0);
|
||||
virtual void setUniform2ui(TProgram program, uint index, uint32 ui0, uint32 ui1);
|
||||
virtual void setUniform3ui(TProgram program, uint index, uint32 ui0, uint32 ui1, uint32 ui2);
|
||||
virtual void setUniform4ui(TProgram program, uint index, uint32 ui0, uint32 ui1, uint32 ui2, uint32 ui3);
|
||||
virtual void setUniform3f(TProgram program, uint index, const NLMISC::CVector& v);
|
||||
virtual void setUniform4f(TProgram program, uint index, const NLMISC::CVector& v, float f3);
|
||||
virtual void setUniform4x4f(TProgram program, uint index, const NLMISC::CMatrix& m);
|
||||
virtual void setUniform4fv(TProgram program, uint index, size_t num, const float *src);
|
||||
virtual void setUniform4iv(TProgram program, uint index, size_t num, const sint32 *src);
|
||||
virtual void setUniform4uiv(TProgram program, uint index, size_t num, const uint32 *src);
|
||||
// Set builtin parameters
|
||||
virtual void setUniformMatrix(TProgram program, uint index, TMatrix matrix, TTransform transform);
|
||||
virtual void setUniformFog(TProgram program, uint index);
|
||||
// @}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual void enableVertexProgramDoubleSidedColor(bool doubleSided);
|
||||
virtual bool supportVertexProgramDoubleSidedColor() const;
|
||||
|
||||
// Pixel program
|
||||
virtual void setPixelProgramConstant (uint index, float, float, float, float);
|
||||
virtual void setPixelProgramConstant (uint index, double, double, double, double);
|
||||
virtual void setPixelProgramConstant (uint index, const NLMISC::CVector& value);
|
||||
virtual void setPixelProgramConstant (uint index, const NLMISC::CVectorD& value);
|
||||
virtual void setPixelProgramConstant (uint index, uint num, const float *src);
|
||||
virtual void setPixelProgramConstant (uint index, uint num, const double *src);
|
||||
virtual void setPixelProgramConstantMatrix (uint index, IDriver::TMatrix matrix, IDriver::TTransform transform);
|
||||
|
||||
// Occlusion query
|
||||
virtual bool supportOcclusionQuery() const;
|
||||
virtual IOcclusionQuery *createOcclusionQuery();
|
||||
|
|
|
@ -54,12 +54,6 @@ CPixelProgramDrvInfosD3D::~CPixelProgramDrvInfosD3D()
|
|||
|
||||
// ***************************************************************************
|
||||
|
||||
bool CDriverD3D::supportPixelProgram () const
|
||||
{
|
||||
H_AUTO_D3D(CDriverD3D_supportPixelProgram)
|
||||
return _PixelProgram;
|
||||
}
|
||||
|
||||
bool CDriverD3D::supportPixelProgram (CPixelProgram::TProfile profile) const
|
||||
{
|
||||
H_AUTO_D3D(CDriverD3D_supportPixelProgram_profile)
|
||||
|
@ -69,81 +63,77 @@ bool CDriverD3D::supportPixelProgram (CPixelProgram::TProfile profile) const
|
|||
|
||||
// ***************************************************************************
|
||||
|
||||
bool CDriverD3D::compilePixelProgram(CPixelProgram *program)
|
||||
{
|
||||
// Program setuped ?
|
||||
if (program->_DrvInfo==NULL)
|
||||
{
|
||||
// Find a supported pixel program profile
|
||||
CGPUProgramSource *source = NULL;
|
||||
for (uint i = 0; i < program->getProgramSource()->Sources.size(); ++i)
|
||||
{
|
||||
if (supportPixelProgram(program->getProgramSource()->Sources[i]->Profile))
|
||||
{
|
||||
source = program->getProgramSource()->Sources[i];
|
||||
}
|
||||
}
|
||||
if (!source)
|
||||
{
|
||||
nlwarning("No supported source profile for pixel program");
|
||||
return false;
|
||||
}
|
||||
|
||||
_GPUPrgDrvInfos.push_front (NULL);
|
||||
ItGPUPrgDrvInfoPtrList itPix = _GPUPrgDrvInfos.begin();
|
||||
CPixelProgramDrvInfosD3D *drvInfo;
|
||||
*itPix = drvInfo = new CPixelProgramDrvInfosD3D(this, itPix);
|
||||
|
||||
// Create a driver info structure
|
||||
program->_DrvInfo = *itPix;
|
||||
|
||||
LPD3DXBUFFER pShader;
|
||||
LPD3DXBUFFER pErrorMsgs;
|
||||
if (D3DXAssembleShader(source->SourcePtr, source->SourceLen, NULL, NULL, 0, &pShader, &pErrorMsgs) == D3D_OK)
|
||||
{
|
||||
if (_DeviceInterface->CreatePixelShader((DWORD*)pShader->GetBufferPointer(), &(getPixelProgramD3D(*program)->Shader)) != D3D_OK)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
nlwarning ("Can't assemble pixel program:");
|
||||
nlwarning ((const char*)pErrorMsgs->GetBufferPointer());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set parameters for assembly programs
|
||||
drvInfo->ParamIndices = source->ParamIndices;
|
||||
|
||||
// Build the feature info
|
||||
program->buildInfo(source->DisplayName.c_str(), source->Features);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
|
||||
bool CDriverD3D::activePixelProgram(CPixelProgram *program)
|
||||
{
|
||||
H_AUTO_D3D(CDriverD3D_activePixelProgram )
|
||||
if (_DisableHardwarePixelProgram)
|
||||
return false;
|
||||
|
||||
// Setup or unsetup ?
|
||||
if (program)
|
||||
{
|
||||
// Program setuped ?
|
||||
if (program->_DrvInfo==NULL)
|
||||
{
|
||||
// Find a supported pixel program profile
|
||||
CGPUProgramSource *source = NULL;
|
||||
for (uint i = 0; i < program->getProgramSource()->Sources.size(); ++i)
|
||||
{
|
||||
if (supportPixelProgram(program->getProgramSource()->Sources[i]->Profile))
|
||||
{
|
||||
source = program->getProgramSource()->Sources[i];
|
||||
}
|
||||
}
|
||||
if (!source)
|
||||
{
|
||||
nlwarning("No supported source profile for pixel program");
|
||||
return false;
|
||||
}
|
||||
|
||||
_GPUPrgDrvInfos.push_front (NULL);
|
||||
ItGPUPrgDrvInfoPtrList itPix = _GPUPrgDrvInfos.begin();
|
||||
CPixelProgramDrvInfosD3D *drvInfo;
|
||||
*itPix = drvInfo = new CPixelProgramDrvInfosD3D(this, itPix);
|
||||
|
||||
// Create a driver info structure
|
||||
program->_DrvInfo = *itPix;
|
||||
|
||||
LPD3DXBUFFER pShader;
|
||||
LPD3DXBUFFER pErrorMsgs;
|
||||
if (D3DXAssembleShader(source->SourcePtr, source->SourceLen, NULL, NULL, 0, &pShader, &pErrorMsgs) == D3D_OK)
|
||||
{
|
||||
if (_DeviceInterface->CreatePixelShader((DWORD*)pShader->GetBufferPointer(), &(getPixelProgramD3D(*program)->Shader)) != D3D_OK)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
nlwarning ("Can't assemble pixel program:");
|
||||
nlwarning ((const char*)pErrorMsgs->GetBufferPointer());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set parameters for assembly programs
|
||||
drvInfo->ParamIndices = source->ParamIndices;
|
||||
|
||||
// Build the feature info
|
||||
program->buildInfo(source->DisplayName.c_str(), source->Features);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the pixel program
|
||||
if (program)
|
||||
{
|
||||
CPixelProgramDrvInfosD3D *info = static_cast<CPixelProgramDrvInfosD3D *>((IGPUProgramDrvInfos*)program->_DrvInfo);
|
||||
setPixelShader (info->Shader);
|
||||
if (!CDriverD3D::compilePixelProgram(program)) return false;
|
||||
|
||||
float z = 0;
|
||||
float o = 1;
|
||||
setRenderState (D3DRS_FOGSTART, *((DWORD*) (&o)));
|
||||
setRenderState (D3DRS_FOGEND, *((DWORD*) (&z)));
|
||||
CPixelProgramDrvInfosD3D *info = static_cast<CPixelProgramDrvInfosD3D *>((IGPUProgramDrvInfos*)program->_DrvInfo);
|
||||
setPixelShader(info->Shader);
|
||||
}
|
||||
else
|
||||
{
|
||||
setPixelShader (NULL);
|
||||
|
||||
// Set the old fog range
|
||||
setRenderState (D3DRS_FOGSTART, *((DWORD*) (&_FogStart)));
|
||||
setRenderState (D3DRS_FOGEND, *((DWORD*) (&_FogEnd)));
|
||||
setPixelShader(NULL);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -151,160 +141,6 @@ bool CDriverD3D::activePixelProgram(CPixelProgram *program)
|
|||
|
||||
// ***************************************************************************
|
||||
|
||||
void CDriverD3D::setPixelProgramConstant (uint index, float f0, float f1, float f2, float f3)
|
||||
{
|
||||
H_AUTO_D3D(CDriverD3D_setPixelProgramConstant)
|
||||
if (!_PixelProgram)
|
||||
{
|
||||
#ifdef NL_DEBUG
|
||||
nlwarning("No pixel programs available!!");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
const float tabl[4] = {f0, f1, f2, f3};
|
||||
setPixelShaderConstant (index, tabl);
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
|
||||
void CDriverD3D::setPixelProgramConstant (uint index, double d0, double d1, double d2, double d3)
|
||||
{
|
||||
H_AUTO_D3D(CDriverD3D_setPixelProgramConstant )
|
||||
if (!_PixelProgram)
|
||||
{
|
||||
#ifdef NL_DEBUG
|
||||
nlwarning("No pixel programs available!!");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
const float tabl[4] = {(float)d0, (float)d1, (float)d2, (float)d3};
|
||||
setPixelShaderConstant (index, tabl);
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
|
||||
void CDriverD3D::setPixelProgramConstant (uint index, const NLMISC::CVector& value)
|
||||
{
|
||||
H_AUTO_D3D(CDriverD3D_setPixelProgramConstant )
|
||||
if (!_PixelProgram)
|
||||
{
|
||||
#ifdef NL_DEBUG
|
||||
nlwarning("No pixel programs available!!");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
const float tabl[4] = {value.x, value.y, value.z, 0};
|
||||
setPixelShaderConstant (index, tabl);
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
|
||||
void CDriverD3D::setPixelProgramConstant (uint index, const NLMISC::CVectorD& value)
|
||||
{
|
||||
H_AUTO_D3D(CDriverD3D_setPixelProgramConstant )
|
||||
if (!_PixelProgram)
|
||||
{
|
||||
#ifdef NL_DEBUG
|
||||
nlwarning("No pixel programs available!!");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
const float tabl[4] = {(float)value.x, (float)value.y, (float)value.z, 0};
|
||||
setPixelShaderConstant (index, tabl);
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
|
||||
void CDriverD3D::setPixelProgramConstant (uint index, uint num, const float *src)
|
||||
{
|
||||
H_AUTO_D3D(CDriverD3D_setPixelProgramConstant )
|
||||
if (!_PixelProgram)
|
||||
{
|
||||
#ifdef NL_DEBUG
|
||||
nlwarning("No pixel programs available!!");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
uint i;
|
||||
for (i=0; i<num; i++)
|
||||
setPixelShaderConstant (index+i, src+i*4);
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
|
||||
void CDriverD3D::setPixelProgramConstant (uint index, uint num, const double *src)
|
||||
{
|
||||
H_AUTO_D3D(CDriverD3D_setPixelProgramConstant )
|
||||
if (!_PixelProgram)
|
||||
{
|
||||
#ifdef NL_DEBUG
|
||||
nlwarning("No pixel programs available!!");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
uint i;
|
||||
for (i=0; i<num; i++)
|
||||
{
|
||||
const float tabl[4] = {(float)src[0], (float)src[1], (float)src[2], (float)src[3]};
|
||||
setPixelShaderConstant (index+i, tabl);
|
||||
src += 4;
|
||||
}
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
|
||||
void CDriverD3D::setPixelProgramConstantMatrix (uint index, IDriver::TMatrix matrix, IDriver::TTransform transform)
|
||||
{
|
||||
H_AUTO_D3D(CDriverD3D_setPixelProgramConstantMatrix)
|
||||
if (!_PixelProgram)
|
||||
{
|
||||
#ifdef NL_DEBUG
|
||||
nlwarning("No pixel programs available!!");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
D3DXMATRIX mat;
|
||||
D3DXMATRIX *matPtr;
|
||||
switch (matrix)
|
||||
{
|
||||
case IDriver::ModelView:
|
||||
matPtr = &_D3DModelView;
|
||||
break;
|
||||
case IDriver::Projection:
|
||||
matPtr = &(_MatrixCache[remapMatrixIndex (D3DTS_PROJECTION)].Matrix);
|
||||
break;
|
||||
case IDriver::ModelViewProjection:
|
||||
matPtr = &_D3DModelViewProjection;
|
||||
break;
|
||||
}
|
||||
|
||||
if (transform != IDriver::Identity)
|
||||
{
|
||||
mat = *matPtr;
|
||||
matPtr = &mat;
|
||||
switch(transform)
|
||||
{
|
||||
case IDriver::Inverse:
|
||||
D3DXMatrixInverse (&mat, NULL, &mat);
|
||||
break;
|
||||
case IDriver::Transpose:
|
||||
D3DXMatrixTranspose (&mat, &mat);
|
||||
break;
|
||||
case IDriver::InverseTranspose:
|
||||
D3DXMatrixInverse (&mat, NULL, &mat);
|
||||
D3DXMatrixTranspose (&mat, &mat);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
setPixelProgramConstant (index, matPtr->_11, matPtr->_21, matPtr->_31, matPtr->_41);
|
||||
setPixelProgramConstant (index+1, matPtr->_12, matPtr->_22, matPtr->_32, matPtr->_42);
|
||||
setPixelProgramConstant (index+2, matPtr->_13, matPtr->_23, matPtr->_33, matPtr->_43);
|
||||
setPixelProgramConstant (index+3, matPtr->_14, matPtr->_24, matPtr->_34, matPtr->_44);
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
|
||||
void CDriverD3D::disableHardwarePixelProgram()
|
||||
{
|
||||
H_AUTO_D3D(CDriverD3D_disableHardwarePixelProgram)
|
||||
|
|
218
code/nel/src/3d/driver/direct3d/driver_direct3d_uniform.cpp
Normal file
218
code/nel/src/3d/driver/direct3d/driver_direct3d_uniform.cpp
Normal file
|
@ -0,0 +1,218 @@
|
|||
// 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
|
||||
{
|
||||
|
||||
void CDriverD3D::setUniform4f(TProgram program, uint index, float f0, float f1, float f2, float f3)
|
||||
{
|
||||
H_AUTO_D3D(CDriverD3D_setUniform4f);
|
||||
|
||||
const float tabl[4] = { f0, f1, f2, f3 };
|
||||
switch (program)
|
||||
{
|
||||
case VertexProgram:
|
||||
if (_VertexProgram)
|
||||
{
|
||||
setVertexProgramConstant(index, tabl);
|
||||
}
|
||||
break;
|
||||
case PixelProgram:
|
||||
if (_PixelProgram)
|
||||
{
|
||||
setPixelShaderConstant(index, tabl);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CDriverD3D::setUniform4fv(TProgram program, uint index, size_t num, const float *src)
|
||||
{
|
||||
H_AUTO_D3D(CDriverD3D_setUniform4fv);
|
||||
|
||||
switch (program)
|
||||
{
|
||||
case VertexProgram:
|
||||
if (_VertexProgram)
|
||||
{
|
||||
for (uint i = 0; i < num; ++i)
|
||||
{
|
||||
setVertexProgramConstant(index + i, src + (i * 4));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PixelProgram:
|
||||
if (_PixelProgram)
|
||||
{
|
||||
for (uint i = 0; i < num; ++i)
|
||||
{
|
||||
setPixelShaderConstant(index + i, src + (i * 4));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CDriverD3D::setUniform1f(TProgram program, uint index, float f0)
|
||||
{
|
||||
CDriverD3D::setUniform4f(program, index, f0, 0.f, 0.f, 0.f);
|
||||
}
|
||||
|
||||
void CDriverD3D::setUniform2f(TProgram program, uint index, float f0, float f1)
|
||||
{
|
||||
CDriverD3D::setUniform4f(program, index, f0, f1, 0.f, 0.f);
|
||||
}
|
||||
|
||||
void CDriverD3D::setUniform3f(TProgram program, uint index, float f0, float f1, float f2)
|
||||
{
|
||||
CDriverD3D::setUniform4f(program, index, f0, f1, f2, 0.0f);
|
||||
}
|
||||
|
||||
void CDriverD3D::setUniform1i(TProgram program, uint index, sint32 i0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CDriverD3D::setUniform2i(TProgram program, uint index, sint32 i0, sint32 i1)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CDriverD3D::setUniform3i(TProgram program, uint index, sint32 i0, sint32 i1, sint32 i2)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CDriverD3D::setUniform4i(TProgram program, uint index, sint32 i0, sint32 i1, sint32 i2, sint32 i3)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CDriverD3D::setUniform1ui(TProgram program, uint index, uint32 ui0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CDriverD3D::setUniform2ui(TProgram program, uint index, uint32 ui0, uint32 ui1)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CDriverD3D::setUniform3ui(TProgram program, uint index, uint32 ui0, uint32 ui1, uint32 ui2)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CDriverD3D::setUniform4ui(TProgram program, uint index, uint32 ui0, uint32 ui1, uint32 ui2, uint32 ui3)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CDriverD3D::setUniform3f(TProgram program, uint index, const NLMISC::CVector& v)
|
||||
{
|
||||
CDriverD3D::setUniform4f(program, index, v.x, v.y, v.z, 0.f);
|
||||
}
|
||||
|
||||
void CDriverD3D::setUniform4f(TProgram program, uint index, const NLMISC::CVector& v, float f3)
|
||||
{
|
||||
CDriverD3D::setUniform4f(program, index, v.x, v.y, v.z, f3);
|
||||
}
|
||||
|
||||
void CDriverD3D::setUniform4x4f(TProgram program, uint index, const NLMISC::CMatrix& m)
|
||||
{
|
||||
H_AUTO_D3D(CDriverD3D_setUniform4x4f);
|
||||
|
||||
// TODO: Verify this!
|
||||
NLMISC::CMatrix mat = m;
|
||||
mat.transpose();
|
||||
const float *md = mat.get();
|
||||
|
||||
CDriverD3D::setUniform4fv(program, index, 4, md);
|
||||
}
|
||||
|
||||
void CDriverD3D::setUniform4iv(TProgram program, uint index, size_t num, const sint32 *src)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CDriverD3D::setUniform4uiv(TProgram program, uint index, size_t num, const uint32 *src)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CDriverD3D::setUniformMatrix(NL3D::IDriver::TProgram program, uint index, NL3D::IDriver::TMatrix matrix, NL3D::IDriver::TTransform transform)
|
||||
{
|
||||
H_AUTO_D3D(CDriverD3D_setUniformMatrix);
|
||||
|
||||
D3DXMATRIX mat;
|
||||
D3DXMATRIX *matPtr = NULL;
|
||||
switch (matrix)
|
||||
{
|
||||
case IDriver::ModelView:
|
||||
matPtr = &_D3DModelView;
|
||||
break;
|
||||
case IDriver::Projection:
|
||||
matPtr = &(_MatrixCache[remapMatrixIndex(D3DTS_PROJECTION)].Matrix);
|
||||
break;
|
||||
case IDriver::ModelViewProjection:
|
||||
matPtr = &_D3DModelViewProjection;
|
||||
break;
|
||||
}
|
||||
if (transform != IDriver::Identity)
|
||||
{
|
||||
switch (transform)
|
||||
{
|
||||
case IDriver::Inverse:
|
||||
D3DXMatrixInverse(&mat, NULL, matPtr);
|
||||
break;
|
||||
case IDriver::Transpose:
|
||||
D3DXMatrixTranspose(&mat, matPtr);
|
||||
break;
|
||||
case IDriver::InverseTranspose:
|
||||
D3DXMatrixInverse(&mat, NULL, matPtr);
|
||||
D3DXMatrixTranspose(&mat, &mat);
|
||||
break;
|
||||
}
|
||||
matPtr = &mat;
|
||||
}
|
||||
|
||||
D3DXMatrixTranspose(&mat, matPtr);
|
||||
|
||||
CDriverD3D::setUniform4fv(program, index, 4, &mat.m[0][0]);
|
||||
}
|
||||
|
||||
void CDriverD3D::setUniformFog(NL3D::IDriver::TProgram program, uint index)
|
||||
{
|
||||
H_AUTO_D3D(CDriverD3D_setUniformFog)
|
||||
|
||||
/* "oFog" must always be between [1, 0] what ever you set in D3DRS_FOGSTART and D3DRS_FOGEND (1 for no fog, 0 for full fog).
|
||||
The Geforce4 TI 4200 (drivers 53.03 and 45.23) doesn't accept other values for "oFog". */
|
||||
const float delta = _FogEnd - _FogStart;
|
||||
CDriverD3D::setUniform4f(program, index,
|
||||
-_D3DModelView._13 / delta,
|
||||
-_D3DModelView._23 / delta,
|
||||
-_D3DModelView._33 / delta,
|
||||
1 - (_D3DModelView._43 - _FogStart) / delta);
|
||||
}
|
||||
|
||||
} // NL3D
|
|
@ -43,10 +43,10 @@ CVertexProgamDrvInfosD3D::~CVertexProgamDrvInfosD3D()
|
|||
|
||||
// ***************************************************************************
|
||||
|
||||
bool CDriverD3D::supportVertexProgram () const
|
||||
bool CDriverD3D::supportVertexProgram (CVertexProgram::TProfile profile) const
|
||||
{
|
||||
H_AUTO_D3D(CDriverD3D_supportVertexProgram )
|
||||
return _VertexProgram;
|
||||
return (profile == CVertexProgram::nelvp) && _VertexProgram;
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
|
@ -262,123 +262,129 @@ void dump(const CVPParser::TProgram &prg, std::string &dest)
|
|||
|
||||
// ***************************************************************************
|
||||
|
||||
bool CDriverD3D::compileVertexProgram(NL3D::CVertexProgram *program)
|
||||
{
|
||||
// Program setuped ?
|
||||
if (program->_DrvInfo == NULL)
|
||||
{
|
||||
// Find nelvp
|
||||
CGPUProgramSource *source = NULL;
|
||||
for (uint i = 0; i < program->getProgramSource()->Sources.size(); ++i)
|
||||
{
|
||||
if (program->getProgramSource()->Sources[i]->Profile == CVertexProgram::nelvp)
|
||||
{
|
||||
source = program->getProgramSource()->Sources[i];
|
||||
}
|
||||
}
|
||||
if (!source)
|
||||
{
|
||||
nlwarning("Direct3D driver only supports 'nelvp' profile, vertex program cannot be used");
|
||||
return false;
|
||||
}
|
||||
|
||||
_GPUPrgDrvInfos.push_front (NULL);
|
||||
ItGPUPrgDrvInfoPtrList itTex = _GPUPrgDrvInfos.begin();
|
||||
CVertexProgamDrvInfosD3D *drvInfo;
|
||||
*itTex = drvInfo = new CVertexProgamDrvInfosD3D(this, itTex);
|
||||
|
||||
// Create a driver info structure
|
||||
program->_DrvInfo = *itTex;
|
||||
|
||||
/** Check with our parser if the program will works with other implemented extensions, too. (EXT_vertex_shader ..).
|
||||
* There are some incompatibilities.
|
||||
*/
|
||||
CVPParser parser;
|
||||
CVPParser::TProgram parsedProgram;
|
||||
std::string errorOutput;
|
||||
bool result = parser.parse(source->SourcePtr, parsedProgram, errorOutput);
|
||||
if (!result)
|
||||
{
|
||||
nlwarning("Unable to parse a vertex program :");
|
||||
nlwarning(errorOutput.c_str());
|
||||
#ifdef NL_DEBUG_D3D
|
||||
nlassert(0);
|
||||
#endif // NL_DEBUG_D3D
|
||||
return false;
|
||||
}
|
||||
|
||||
// tmp fix for Radeon 8500/9000/9200
|
||||
// Currently they hang when PaletteSkin / SkinWeight are present in the vertex declaration, but not used
|
||||
// so disable them in the vertex declaration
|
||||
// We don't use these component in vertex programs currently..
|
||||
#ifdef NL_DEBUG
|
||||
for(uint k = 0; k < parsedProgram.size(); ++k)
|
||||
{
|
||||
for(uint l = 0; l < parsedProgram[k].getNumUsedSrc(); ++l)
|
||||
{
|
||||
const CVPOperand &op = parsedProgram[k].getSrc(l);
|
||||
if (op.Type == CVPOperand::InputRegister)
|
||||
{
|
||||
nlassert(op.Value.InputRegisterValue != CVPOperand::IWeight);
|
||||
nlassert(op.Value.InputRegisterValue != CVPOperand::IPaletteSkin);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Dump the vertex program
|
||||
std::string dest;
|
||||
dump(parsedProgram, dest);
|
||||
#ifdef NL_DEBUG_D3D
|
||||
nlinfo("Assemble Vertex Shader : ");
|
||||
string::size_type lineBegin = 0;
|
||||
string::size_type lineEnd;
|
||||
while ((lineEnd = dest.find('\n', lineBegin)) != string::npos)
|
||||
{
|
||||
nlinfo(dest.substr (lineBegin, lineEnd-lineBegin).c_str());
|
||||
lineBegin = lineEnd+1;
|
||||
}
|
||||
nlinfo(dest.substr (lineBegin, lineEnd-lineBegin).c_str());
|
||||
#endif // NL_DEBUG_D3D
|
||||
|
||||
LPD3DXBUFFER pShader;
|
||||
LPD3DXBUFFER pErrorMsgs;
|
||||
if (D3DXAssembleShader (dest.c_str(), (UINT)dest.size(), NULL, NULL, 0, &pShader, &pErrorMsgs) == D3D_OK)
|
||||
{
|
||||
if (_DeviceInterface->CreateVertexShader((DWORD*)pShader->GetBufferPointer(), &(getVertexProgramD3D(*program)->Shader)) != D3D_OK)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
nlwarning ("Can't assemble vertex program:");
|
||||
nlwarning ((const char*)pErrorMsgs->GetBufferPointer());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set parameters for assembly programs
|
||||
drvInfo->ParamIndices = source->ParamIndices;
|
||||
|
||||
// Build the feature info
|
||||
program->buildInfo(source->DisplayName.c_str(), source->Features);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
|
||||
bool CDriverD3D::activeVertexProgram (CVertexProgram *program)
|
||||
{
|
||||
H_AUTO_D3D(CDriverD3D_activeVertexProgram )
|
||||
if (_DisableHardwareVertexProgram)
|
||||
return false;
|
||||
|
||||
// Setup or unsetup ?
|
||||
if (program)
|
||||
{
|
||||
// Program setuped ?
|
||||
if (program->_DrvInfo==NULL)
|
||||
{
|
||||
// Find nelvp
|
||||
CGPUProgramSource *source = NULL;
|
||||
for (uint i = 0; i < program->getProgramSource()->Sources.size(); ++i)
|
||||
{
|
||||
if (program->getProgramSource()->Sources[i]->Profile == CVertexProgram::nelvp)
|
||||
{
|
||||
source = program->getProgramSource()->Sources[i];
|
||||
}
|
||||
}
|
||||
if (!source)
|
||||
{
|
||||
nlwarning("Direct3D driver only supports 'nelvp' profile, vertex program cannot be used");
|
||||
return false;
|
||||
}
|
||||
|
||||
_GPUPrgDrvInfos.push_front (NULL);
|
||||
ItGPUPrgDrvInfoPtrList itTex = _GPUPrgDrvInfos.begin();
|
||||
CVertexProgamDrvInfosD3D *drvInfo;
|
||||
*itTex = drvInfo = new CVertexProgamDrvInfosD3D(this, itTex);
|
||||
|
||||
// Create a driver info structure
|
||||
program->_DrvInfo = *itTex;
|
||||
|
||||
/** Check with our parser if the program will works with other implemented extensions, too. (EXT_vertex_shader ..).
|
||||
* There are some incompatibilities.
|
||||
*/
|
||||
CVPParser parser;
|
||||
CVPParser::TProgram parsedProgram;
|
||||
std::string errorOutput;
|
||||
bool result = parser.parse(source->SourcePtr, parsedProgram, errorOutput);
|
||||
if (!result)
|
||||
{
|
||||
nlwarning("Unable to parse a vertex program :");
|
||||
nlwarning(errorOutput.c_str());
|
||||
#ifdef NL_DEBUG_D3D
|
||||
nlassert(0);
|
||||
#endif // NL_DEBUG_D3D
|
||||
return false;
|
||||
}
|
||||
|
||||
// tmp fix for Radeon 8500/9000/9200
|
||||
// Currently they hang when PaletteSkin / SkinWeight are present in the vertex declaration, but not used
|
||||
// so disable them in the vertex declaration
|
||||
// We don't use these component in vertex programs currently..
|
||||
#ifdef NL_DEBUG
|
||||
for(uint k = 0; k < parsedProgram.size(); ++k)
|
||||
{
|
||||
for(uint l = 0; l < parsedProgram[k].getNumUsedSrc(); ++l)
|
||||
{
|
||||
const CVPOperand &op = parsedProgram[k].getSrc(l);
|
||||
if (op.Type == CVPOperand::InputRegister)
|
||||
{
|
||||
nlassert(op.Value.InputRegisterValue != CVPOperand::IWeight);
|
||||
nlassert(op.Value.InputRegisterValue != CVPOperand::IPaletteSkin);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Dump the vertex program
|
||||
std::string dest;
|
||||
dump(parsedProgram, dest);
|
||||
#ifdef NL_DEBUG_D3D
|
||||
nlinfo("Assemble Vertex Shader : ");
|
||||
string::size_type lineBegin = 0;
|
||||
string::size_type lineEnd;
|
||||
while ((lineEnd = dest.find('\n', lineBegin)) != string::npos)
|
||||
{
|
||||
nlinfo(dest.substr (lineBegin, lineEnd-lineBegin).c_str());
|
||||
lineBegin = lineEnd+1;
|
||||
}
|
||||
nlinfo(dest.substr (lineBegin, lineEnd-lineBegin).c_str());
|
||||
#endif // NL_DEBUG_D3D
|
||||
|
||||
LPD3DXBUFFER pShader;
|
||||
LPD3DXBUFFER pErrorMsgs;
|
||||
if (D3DXAssembleShader (dest.c_str(), (UINT)dest.size(), NULL, NULL, 0, &pShader, &pErrorMsgs) == D3D_OK)
|
||||
{
|
||||
if (_DeviceInterface->CreateVertexShader((DWORD*)pShader->GetBufferPointer(), &(getVertexProgramD3D(*program)->Shader)) != D3D_OK)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
nlwarning ("Can't assemble vertex program:");
|
||||
nlwarning ((const char*)pErrorMsgs->GetBufferPointer());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set parameters for assembly programs
|
||||
drvInfo->ParamIndices = source->ParamIndices;
|
||||
|
||||
// Build the feature info
|
||||
program->buildInfo(source->DisplayName.c_str(), source->Features);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the vertex program
|
||||
if (program)
|
||||
{
|
||||
CVertexProgamDrvInfosD3D *info = static_cast<CVertexProgamDrvInfosD3D *>((IGPUProgramDrvInfos*)program->_DrvInfo);
|
||||
if (!CDriverD3D::compileVertexProgram(program)) return false;
|
||||
|
||||
CVertexProgamDrvInfosD3D *info = NLMISC::safe_cast<CVertexProgamDrvInfosD3D *>((IGPUProgramDrvInfos*)program->_DrvInfo);
|
||||
setVertexProgram (info->Shader, program);
|
||||
|
||||
/* D3DRS_FOGSTART and D3DRS_FOGEND must be set with [1, 0] else the fog doesn't work properly on VertexShader and non-VertexShader objects
|
||||
(random fog flicking) with Geforce4 TI 4200 (drivers 53.03 and 45.23). The other cards seam to interpret the "oFog"'s values using D3DRS_FOGSTART,
|
||||
D3DRS_FOGEND.
|
||||
Related to setUniformFog().
|
||||
*/
|
||||
float z = 0;
|
||||
float o = 1;
|
||||
|
@ -399,171 +405,6 @@ bool CDriverD3D::activeVertexProgram (CVertexProgram *program)
|
|||
|
||||
// ***************************************************************************
|
||||
|
||||
void CDriverD3D::setConstant (uint index, float f0, float f1, float f2, float f3)
|
||||
{
|
||||
H_AUTO_D3D(CDriverD3D_setConstant )
|
||||
if (!_VertexProgram)
|
||||
{
|
||||
#ifdef NL_DEBUG
|
||||
nlwarning("No vertex programs available!!");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
const float tabl[4] = {f0, f1, f2, f3};
|
||||
setVertexProgramConstant (index, tabl);
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
|
||||
void CDriverD3D::setConstant (uint index, double d0, double d1, double d2, double d3)
|
||||
{
|
||||
H_AUTO_D3D(CDriverD3D_setConstant )
|
||||
if (!_VertexProgram)
|
||||
{
|
||||
#ifdef NL_DEBUG
|
||||
nlwarning("No vertex programs available!!");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
const float tabl[4] = {(float)d0, (float)d1, (float)d2, (float)d3};
|
||||
setVertexProgramConstant (index, tabl);
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
|
||||
void CDriverD3D::setConstant (uint index, const NLMISC::CVector& value)
|
||||
{
|
||||
H_AUTO_D3D(CDriverD3D_setConstant )
|
||||
if (!_VertexProgram)
|
||||
{
|
||||
#ifdef NL_DEBUG
|
||||
nlwarning("No vertex programs available!!");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
const float tabl[4] = {value.x, value.y, value.z, 0};
|
||||
setVertexProgramConstant (index, tabl);
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
|
||||
void CDriverD3D::setConstant (uint index, const NLMISC::CVectorD& value)
|
||||
{
|
||||
H_AUTO_D3D(CDriverD3D_setConstant )
|
||||
if (!_VertexProgram)
|
||||
{
|
||||
#ifdef NL_DEBUG
|
||||
nlwarning("No vertex programs available!!");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
const float tabl[4] = {(float)value.x, (float)value.y, (float)value.z, 0};
|
||||
setVertexProgramConstant (index, tabl);
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
|
||||
void CDriverD3D::setConstant (uint index, uint num, const float *src)
|
||||
{
|
||||
H_AUTO_D3D(CDriverD3D_setConstant )
|
||||
if (!_VertexProgram)
|
||||
{
|
||||
#ifdef NL_DEBUG
|
||||
nlwarning("No vertex programs available!!");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
uint i;
|
||||
for (i=0; i<num; i++)
|
||||
setVertexProgramConstant (index+i, src+i*4);
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
|
||||
void CDriverD3D::setConstant (uint index, uint num, const double *src)
|
||||
{
|
||||
H_AUTO_D3D(CDriverD3D_setConstant )
|
||||
if (!_VertexProgram)
|
||||
{
|
||||
#ifdef NL_DEBUG
|
||||
nlwarning("No vertex programs available!!");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
uint i;
|
||||
for (i=0; i<num; i++)
|
||||
{
|
||||
const float tabl[4] = {(float)src[0], (float)src[1], (float)src[2], (float)src[3]};
|
||||
setVertexProgramConstant (index+i, tabl);
|
||||
src += 4;
|
||||
}
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
|
||||
void CDriverD3D::setConstantMatrix (uint index, IDriver::TMatrix matrix, IDriver::TTransform transform)
|
||||
{
|
||||
H_AUTO_D3D(CDriverD3D_setConstantMatrix )
|
||||
if (!_VertexProgram)
|
||||
{
|
||||
#ifdef NL_DEBUG
|
||||
nlwarning("No vertex programs available!!");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
D3DXMATRIX mat;
|
||||
D3DXMATRIX *matPtr = NULL;
|
||||
switch (matrix)
|
||||
{
|
||||
case IDriver::ModelView:
|
||||
matPtr = &_D3DModelView;
|
||||
break;
|
||||
case IDriver::Projection:
|
||||
matPtr = &(_MatrixCache[remapMatrixIndex (D3DTS_PROJECTION)].Matrix);
|
||||
break;
|
||||
case IDriver::ModelViewProjection:
|
||||
matPtr = &_D3DModelViewProjection;
|
||||
break;
|
||||
}
|
||||
|
||||
if (transform != IDriver::Identity)
|
||||
{
|
||||
mat = *matPtr;
|
||||
matPtr = &mat;
|
||||
switch(transform)
|
||||
{
|
||||
case IDriver::Inverse:
|
||||
D3DXMatrixInverse (&mat, NULL, &mat);
|
||||
break;
|
||||
case IDriver::Transpose:
|
||||
D3DXMatrixTranspose (&mat, &mat);
|
||||
break;
|
||||
case IDriver::InverseTranspose:
|
||||
D3DXMatrixInverse (&mat, NULL, &mat);
|
||||
D3DXMatrixTranspose (&mat, &mat);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
setConstant (index, matPtr->_11, matPtr->_21, matPtr->_31, matPtr->_41);
|
||||
setConstant (index+1, matPtr->_12, matPtr->_22, matPtr->_32, matPtr->_42);
|
||||
setConstant (index+2, matPtr->_13, matPtr->_23, matPtr->_33, matPtr->_43);
|
||||
setConstant (index+3, matPtr->_14, matPtr->_24, matPtr->_34, matPtr->_44);
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
|
||||
void CDriverD3D::setConstantFog (uint index)
|
||||
{
|
||||
H_AUTO_D3D(CDriverD3D_setConstantFog )
|
||||
/* "oFog" must always be between [1, 0] what ever you set in D3DRS_FOGSTART and D3DRS_FOGEND (1 for no fog, 0 for full fog).
|
||||
The Geforce4 TI 4200 (drivers 53.03 and 45.23) doesn't accept other values for "oFog". */
|
||||
const float delta = _FogEnd-_FogStart;
|
||||
setConstant (index, - _D3DModelView._13/delta, -_D3DModelView._23/delta, -_D3DModelView._33/delta, 1-(_D3DModelView._43-_FogStart)/delta);
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
|
||||
void CDriverD3D::enableVertexProgramDoubleSidedColor(bool /* doubleSided */)
|
||||
{
|
||||
H_AUTO_D3D(CDriverD3D_enableVertexProgramDoubleSidedColor)
|
||||
|
|
Loading…
Reference in a new issue