Use named uniform indices for lighted vertex program

This commit is contained in:
kaetemi 2013-09-13 21:31:47 +02:00
parent a0fbb152ee
commit edec14807f
11 changed files with 81 additions and 55 deletions

View file

@ -1191,6 +1191,7 @@ public:
virtual void setUniform4ui(TProgram program, uint index, uint32 ui0, uint32 ui1, uint32 ui2, uint32 ui3) = 0;
virtual void setUniform3f(TProgram program, uint index, const NLMISC::CVector& v) = 0;
virtual void setUniform4f(TProgram program, uint index, const NLMISC::CVector& v, float f3) = 0;
virtual void setUniform4f(TProgram program, uint index, const NLMISC::CRGBAF& rgba) = 0;
virtual void setUniform4x4f(TProgram program, uint index, const NLMISC::CMatrix& m) = 0;
virtual void setUniform4fv(TProgram program, uint index, size_t num, const float *src) = 0;
virtual void setUniform4iv(TProgram program, uint index, size_t num, const sint32 *src) = 0;

View file

@ -88,6 +88,8 @@ private:
//
enum { NumVp = 8};
static NLMISC::CSmartPtr<CVertexProgramPerPixelLight> _VertexProgram[NumVp];
NLMISC::CRefPtr<CVertexProgramPerPixelLight> _ActiveVertexProgram;
};
} // NL3D

View file

@ -116,6 +116,8 @@ private:
*/
static NLMISC::CSmartPtr<CVertexProgramWindTree> _VertexProgram[NumVp];
NLMISC::CRefPtr<CVertexProgramWindTree> _ActiveVertexProgram;
// WindTree Time for this mesh param setup. Stored in mesh because same for all instances.
float _CurrentTime[HrcDepth];
double _LastSceneTime;

View file

@ -289,7 +289,7 @@ public:
* \param supportSpecular asitsounds. PointLights and dirLight are localViewer
* \param invObjectWM the inverse of object matrix: lights are mul by this. Vp compute in object space.
*/
void beginVPLightSetup(uint ctStart, bool supportSpecular, const CMatrix &invObjectWM);
void beginVPLightSetup(CVertexProgramLighted *program, const CMatrix &invObjectWM);
/** change the driver VP LightSetup constants which depends on material.
* \param excludeStrongest This remove the strongest light from the setup. The typical use is to have it computed by using perpixel lighting.
@ -418,12 +418,14 @@ private:
mutable uint _StrongestLightIndex;
mutable bool _StrongestLightTouched;
// Current vp setuped with beginVPLightSetup()
NLMISC::CRefPtr<CVertexProgramLighted> _VPCurrent;
// Current ctStart setuped with beginVPLightSetup()
uint _VPCurrentCtStart;
//uint _VPCurrentCtStart;
// Current num of VP lights enabled.
uint _VPNumLights;
// Current support of specular
bool _VPSupportSpecular;
//bool _VPSupportSpecular;
// Sum of all ambiant of all lights + ambiantGlobal.
NLMISC::CRGBAF _VPFinalAmbient;
// Diffuse/Spec comp of all light / 255.

View file

@ -1200,6 +1200,7 @@ public:
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 setUniform4f(TProgram program, uint index, const NLMISC::CRGBAF& rgba);
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);

View file

@ -138,6 +138,11 @@ void CDriverD3D::setUniform4f(TProgram program, uint index, const NLMISC::CVecto
CDriverD3D::setUniform4f(program, index, v.x, v.y, v.z, f3);
}
void CDriverD3D::setUniform4f(TProgram program, uint index, const NLMISC::CRGBAF& rgba)
{
CDriverD3D::setUniform4fv(program, index, 1, &rgba.R);
}
void CDriverD3D::setUniform4x4f(TProgram program, uint index, const NLMISC::CMatrix& m)
{
H_AUTO_D3D(CDriverD3D_setUniform4x4f);

View file

@ -1406,6 +1406,7 @@ private:
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 setUniform4f(TProgram program, uint index, const NLMISC::CRGBAF& rgba);
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);

View file

@ -169,6 +169,11 @@ void CDriverGL::setUniform4f(TProgram program, uint index, const NLMISC::CVector
CDriverGL::setUniform4f(program, index, v.x, v.y, v.z, f3);
}
void CDriverGL::setUniform4f(TProgram program, uint index, const NLMISC::CRGBAF& rgba)
{
CDriverGL::setUniform4fv(program, index, 1, &rgba.R);
}
void CDriverGL::setUniform4x4f(TProgram program, uint index, const NLMISC::CMatrix& m)
{
H_AUTO_OGL(CDriverGL_setUniform4x4f);

View file

@ -488,9 +488,7 @@ bool CMeshVPPerPixelLight::begin(IDriver *drv,
//
CRenderTrav *renderTrav= &scene->getRenderTrav();
/// Setup for gouraud lighting
renderTrav->beginVPLightSetup(VPLightConstantStart,
SpecularLighting,
invertedModelMat);
renderTrav->beginVPLightSetup(_ActiveVertexProgram, invertedModelMat);
//
sint strongestLightIndex = renderTrav->getStrongestLightIndex();
if (strongestLightIndex == -1) return false; // if no strongest light, disable this vertex program
@ -569,10 +567,12 @@ void CMeshVPPerPixelLight::enable(bool enabled, IDriver *drv)
| (_IsPointLight ? 1 : 0);
//
drv->activeVertexProgram((CVertexProgramPerPixelLight *)_VertexProgram[idVP]);
_ActiveVertexProgram = _VertexProgram[idVP];
}
else
{
drv->activeVertexProgram(NULL);
_ActiveVertexProgram = NULL;
}
_Enabled = enabled;
}

View file

@ -354,6 +354,7 @@ bool CMeshVPWindTree::begin(IDriver *driver, CScene *scene, CMeshBaseInstance *m
idVP= numPls*4 + idVP;
// activate VP.
driver->activeVertexProgram(_VertexProgram[idVP]);
_ActiveVertexProgram = _VertexProgram[idVP];
// precompute mesh
@ -373,6 +374,7 @@ void CMeshVPWindTree::end(IDriver *driver)
{
// Disable the VertexProgram
driver->activeVertexProgram(NULL);
_ActiveVertexProgram = NULL;
}
// ***************************************************************************
@ -398,7 +400,8 @@ void CMeshVPWindTree::setupLighting(CScene *scene, CMeshBaseInstance *mbi, const
nlassert(scene != NULL);
CRenderTrav *renderTrav= &scene->getRenderTrav();
// setup cte for lighting
renderTrav->beginVPLightSetup(VPLightConstantStart, SpecularLighting, invertedModelMat);
CVertexProgramWindTree *program = _ActiveVertexProgram;
renderTrav->beginVPLightSetup(program, invertedModelMat);
}
@ -431,6 +434,7 @@ void CMeshVPWindTree::beginMBRMesh(IDriver *driver, CScene *scene)
// activate VP.
driver->activeVertexProgram(_VertexProgram[_LastMBRIdVP]);
_ActiveVertexProgram = _VertexProgram[_LastMBRIdVP];
// precompute mesh
setupPerMesh(driver, scene);
@ -456,6 +460,7 @@ void CMeshVPWindTree::beginMBRInstance(IDriver *driver, CScene *scene, CMeshBase
{
_LastMBRIdVP= idVP;
driver->activeVertexProgram(_VertexProgram[_LastMBRIdVP]);
_ActiveVertexProgram = _VertexProgram[_LastMBRIdVP];
if (!_VertexProgram[_LastMBRIdVP]->PerMeshSetup)
{
@ -474,6 +479,7 @@ void CMeshVPWindTree::endMBRMesh(IDriver *driver)
{
// Disable the VertexProgram
driver->activeVertexProgram(NULL);
_ActiveVertexProgram = NULL;
}
// ***************************************************************************

View file

@ -762,13 +762,15 @@ void CRenderTrav::changeLightSetup(CLightContribution *lightContribution, bool
// ***************************************************************************
void CRenderTrav::beginVPLightSetup(uint ctStart, bool supportSpecular, const CMatrix &invObjectWM)
void CRenderTrav::beginVPLightSetup(CVertexProgramLighted *program, const CMatrix &invObjectWM)
{
uint i;
nlassert(MaxVPLight==4);
_VPNumLights= min(_NumLightEnabled, (uint)MaxVPLight);
_VPCurrentCtStart= ctStart;
_VPSupportSpecular= supportSpecular;
// _VPCurrentCtStart= ctStart;
// _VPSupportSpecular= supportSpecular;
_VPCurrent = program;
bool supportSpecular = program->featuresLighted().SupportSpecular;
// Prepare Colors (to be multiplied by material)
//================
@ -786,8 +788,11 @@ void CRenderTrav::beginVPLightSetup(uint ctStart, bool supportSpecular, const C
// reset other to 0.
for(; i<MaxVPLight; i++)
{
_VPLightDiffuse[i]= CRGBA::Black;
Driver->setConstant(_VPCurrentCtStart+1+i, 0.f, 0.f, 0.f, 0.f);
_VPLightDiffuse[i] = CRGBA::Black;
if (program->idxLighted().Diffuse[i] != ~0)
{
Driver->setUniform4f(IDriver::VertexProgram, program->idxLighted().Diffuse[i], 0.f, 0.f, 0.f, 0.f);
}
}
// Specular. _VPCurrentCtStart+5 to 8 (only if supportSpecular)
if(supportSpecular)
@ -800,7 +805,10 @@ void CRenderTrav::beginVPLightSetup(uint ctStart, bool supportSpecular, const C
for(; i<MaxVPLight; i++)
{
_VPLightSpecular[i]= CRGBA::Black;
Driver->setConstant(_VPCurrentCtStart+5+i, 0.f, 0.f, 0.f, 0.f);
if (program->idxLighted().Specular[i] != ~0)
{
Driver->setUniform4f(IDriver::VertexProgram, program->idxLighted().Specular[i], 0.f, 0.f, 0.f, 0.f);
}
}
}
@ -816,40 +824,24 @@ void CRenderTrav::beginVPLightSetup(uint ctStart, bool supportSpecular, const C
lightDir= invObjectWM.mulVector(_DriverLight[0].getDirection());
lightDir.normalize();
lightDir= -lightDir;
if(supportSpecular)
{
// Setup lightDir.
Driver->setConstant(_VPCurrentCtStart+9, lightDir);
}
else
{
// Setup lightDir. NB: no specular color!
Driver->setConstant(_VPCurrentCtStart+5, lightDir);
}
Driver->setUniform3f(IDriver::VertexProgram, program->idxLighted().DirOrPos[0], lightDir); // The sun is the same for every instance.
// Setup PointLights
//================
uint startPLPos;
if(supportSpecular)
if (supportSpecular)
{
// Setup eye in objectSpace for localViewer
Driver->setConstant(_VPCurrentCtStart+11, eye);
// Start at 12.
startPLPos= 12;
}
else
{
// Start at 6.
startPLPos= 6;
Driver->setUniform3f(IDriver::VertexProgram, program->idxLighted().EyePosition, eye);
}
// For all pointLight enabled (other are black: don't matter)
for(i=1; i<_VPNumLights; i++)
{
// Setup position of light.
CVector lightPos;
lightPos= invObjectWM * _DriverLight[i].getPosition();
Driver->setConstant(_VPCurrentCtStart+startPLPos+(i-1), lightPos);
lightPos = invObjectWM * _DriverLight[i].getPosition();
Driver->setUniform3f(IDriver::VertexProgram, program->idxLighted().DirOrPos[i], lightPos);
}
@ -860,6 +852,9 @@ void CRenderTrav::beginVPLightSetup(uint ctStart, bool supportSpecular, const C
// ***************************************************************************
void CRenderTrav::changeVPLightSetupMaterial(const CMaterial &mat, bool excludeStrongest)
{
CVertexProgramLighted *program = _VPCurrent;
nlassert(program);
// Must test if at least done one time.
if(!_VPMaterialCacheDirty)
{
@ -869,7 +864,7 @@ void CRenderTrav::changeVPLightSetupMaterial(const CMaterial &mat, bool exclude
_VPMaterialCacheDiffuse == mat.getDiffuse().getPacked() )
{
// Same Diffuse part, test if same specular if necessary
if( !_VPSupportSpecular ||
if( !program->featuresLighted().SupportSpecular ||
( _VPMaterialCacheSpecular == mat.getSpecular().getPacked() &&
_VPMaterialCacheShininess == mat.getShininess() ) )
{
@ -899,7 +894,7 @@ void CRenderTrav::changeVPLightSetupMaterial(const CMaterial &mat, bool exclude
// setup Ambient + Emissive
color= _VPFinalAmbient * mat.getAmbient();
color+= mat.getEmissive();
Driver->setConstant(_VPCurrentCtStart+0, 1, &color.R);
Driver->setUniform4f(IDriver::VertexProgram, program->idxLighted().Ambient, color);
// is the strongest light is not excluded, its index should have been setup to _VPNumLights
@ -908,7 +903,7 @@ void CRenderTrav::changeVPLightSetupMaterial(const CMaterial &mat, bool exclude
for(i = 0; i < strongestLightIndex; ++i)
{
color= _VPLightDiffuse[i] * matDiff;
Driver->setConstant(_VPCurrentCtStart+1+i, 1, &color.R);
Driver->setUniform4f(IDriver::VertexProgram, program->idxLighted().Diffuse[i], color);
}
@ -917,24 +912,24 @@ void CRenderTrav::changeVPLightSetupMaterial(const CMaterial &mat, bool exclude
color= _VPLightDiffuse[i] * matDiff;
_StrongestLightDiffuse.set((uint8) (255.f * color.R), (uint8) (255.f * color.G), (uint8) (255.f * color.B), (uint8) (255.f * color.A));
// setup strongest light to black for the gouraud part
Driver->setConstant(_VPCurrentCtStart + 1 + i, 0.f, 0.f, 0.f, 0.f);
Driver->setUniform4f(IDriver::VertexProgram, program->idxLighted().Diffuse[i], 0.f, 0.f, 0.f, 0.f);
++i;
// setup other lights
for(; i < _VPNumLights; i++)
{
color= _VPLightDiffuse[i] * matDiff;
Driver->setConstant(_VPCurrentCtStart + 1 + i, 1, &color.R);
Driver->setUniform4f(IDriver::VertexProgram, program->idxLighted().Diffuse[i], color);
}
}
// setup Specular
if(_VPSupportSpecular)
if (program->featuresLighted().SupportSpecular)
{
for(i = 0; i < strongestLightIndex; ++i)
{
color= _VPLightSpecular[i] * matSpec;
color.A= specExp;
Driver->setConstant(_VPCurrentCtStart+5+i, 1, &color.R);
Driver->setUniform4f(IDriver::VertexProgram, program->idxLighted().Specular[i], color);
}
if (i != _VPNumLights)
@ -943,14 +938,14 @@ void CRenderTrav::changeVPLightSetupMaterial(const CMaterial &mat, bool exclude
_StrongestLightSpecular.set((uint8) (255.f * color.R), (uint8) (255.f * color.G), (uint8) (255.f * color.B), (uint8) (255.f * color.A));
// setup strongest light to black (for gouraud part)
Driver->setConstant(_VPCurrentCtStart + 5 + i, 0.f, 0.f, 0.f, 0.f);
Driver->setUniform4f(IDriver::VertexProgram, program->idxLighted().Specular[i], 0.f, 0.f, 0.f, 0.f);
++i;
// setup other lights
for(; i < _VPNumLights; i++)
{
color= _VPLightSpecular[i] * matSpec;
color.A= specExp;
Driver->setConstant(_VPCurrentCtStart + 5 + i, 1, &color.R);
Driver->setUniform4f(IDriver::VertexProgram, program->idxLighted().Specular[i], color);
}
}
}
@ -959,10 +954,7 @@ void CRenderTrav::changeVPLightSetupMaterial(const CMaterial &mat, bool exclude
static float alphaCte[4]= {0,0,1,0};
alphaCte[3]= matDiff.A;
// setup at good place
if(_VPSupportSpecular)
Driver->setConstant(_VPCurrentCtStart+10, 1, alphaCte);
else
Driver->setConstant(_VPCurrentCtStart+9, 1, alphaCte);
Driver->setUniform4fv(IDriver::VertexProgram, program->idxLighted().DiffuseAlpha, 1, alphaCte);
}
// ***************************************************************************
@ -1174,24 +1166,24 @@ void CVertexProgramLighted::buildInfo()
if (profile() == nelvp)
{
// Fixed uniform locations
m_IdxLighted.Ambient = 0;
m_IdxLighted.Ambient = m_FeaturesLighted.CtStartNeLVP + 0;
for (uint i = 0; i < MaxLight; ++i)
{
m_IdxLighted.Diffuse[i] = 1 + i;
m_IdxLighted.Diffuse[i] = m_FeaturesLighted.CtStartNeLVP + 1 + i;
}
if (m_FeaturesLighted.SupportSpecular)
{
for (uint i = 0; i < MaxLight; ++i)
{
m_IdxLighted.Specular[i] = 5 + i;
m_IdxLighted.Specular[i] = m_FeaturesLighted.CtStartNeLVP + 5 + i;
}
m_IdxLighted.DirOrPos[0] = 9;
for (uint i = 1; i < MaxLight; ++i)
{
m_IdxLighted.DirOrPos[i] = (12 - 1) + i;
m_IdxLighted.DirOrPos[i] = m_FeaturesLighted.CtStartNeLVP + (12 - 1) + i;
}
m_IdxLighted.DiffuseAlpha = 10;
m_IdxLighted.EyePosition = 11;
m_IdxLighted.DiffuseAlpha = m_FeaturesLighted.CtStartNeLVP + 10;
m_IdxLighted.EyePosition = m_FeaturesLighted.CtStartNeLVP + 11;
}
else
{
@ -1201,9 +1193,9 @@ void CVertexProgramLighted::buildInfo()
}
for (uint i = 0; i < MaxLight; ++i)
{
m_IdxLighted.DirOrPos[i] = 5 + i;
m_IdxLighted.DirOrPos[i] = m_FeaturesLighted.CtStartNeLVP + 5 + i;
}
m_IdxLighted.DiffuseAlpha = 9;
m_IdxLighted.DiffuseAlpha = m_FeaturesLighted.CtStartNeLVP + 9;
m_IdxLighted.EyePosition = ~0;
}
}
@ -1214,6 +1206,15 @@ void CVertexProgramLighted::buildInfo()
// m_IdxLighted.Ambient = getUniformIndex("ambient");
// etc
}
nlassert(m_IdxLighted.Diffuse[0] != ~0);
if (m_FeaturesLighted.SupportSpecular)
{
nlassert(m_IdxLighted.Specular[0] != ~0);
nlassert(m_IdxLighted.EyePosition != ~0);
}
nlassert(m_IdxLighted.DirOrPos[0] != ~0);
nlassert(m_IdxLighted.DiffuseAlpha != ~0);
}
// generates the lighting part of a vertex program, nelvp profile