mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 22:23:51 +00:00
Make better use of the available texture units (Bug #2702)
Nvidia drivers only support a maximum of 4 fixed function texture units. To resolve this problem, bind texture units in order instead of binding to the NiTexturingProperty::TextureType unit.
This commit is contained in:
parent
3ebfb4e0d9
commit
81a4a6da6b
1 changed files with 29 additions and 23 deletions
|
@ -344,7 +344,7 @@ namespace NifOsg
|
||||||
|
|
||||||
osg::ref_ptr<TextKeyMapHolder> textkeys (new TextKeyMapHolder);
|
osg::ref_ptr<TextKeyMapHolder> textkeys (new TextKeyMapHolder);
|
||||||
|
|
||||||
osg::ref_ptr<osg::Node> created = handleNode(nifNode, NULL, textureManager, std::map<int, int>(), 0, 0, false, &textkeys->mTextKeys);
|
osg::ref_ptr<osg::Node> created = handleNode(nifNode, NULL, textureManager, std::vector<int>(), 0, 0, false, &textkeys->mTextKeys);
|
||||||
|
|
||||||
if (nif->getUseSkinning())
|
if (nif->getUseSkinning())
|
||||||
{
|
{
|
||||||
|
@ -357,7 +357,7 @@ namespace NifOsg
|
||||||
return created;
|
return created;
|
||||||
}
|
}
|
||||||
|
|
||||||
void applyNodeProperties(const Nif::Node *nifNode, osg::Node *applyTo, SceneUtil::CompositeStateSetUpdater* composite, Resource::TextureManager* textureManager, std::map<int, int>& boundTextures, int animflags)
|
void applyNodeProperties(const Nif::Node *nifNode, osg::Node *applyTo, SceneUtil::CompositeStateSetUpdater* composite, Resource::TextureManager* textureManager, std::vector<int>& boundTextures, int animflags)
|
||||||
{
|
{
|
||||||
const Nif::PropertyList& props = nifNode->props;
|
const Nif::PropertyList& props = nifNode->props;
|
||||||
for (size_t i = 0; i <props.length();++i)
|
for (size_t i = 0; i <props.length();++i)
|
||||||
|
@ -412,7 +412,7 @@ namespace NifOsg
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::ref_ptr<osg::Node> handleNode(const Nif::Node* nifNode, osg::Group* parentNode, Resource::TextureManager* textureManager,
|
osg::ref_ptr<osg::Node> handleNode(const Nif::Node* nifNode, osg::Group* parentNode, Resource::TextureManager* textureManager,
|
||||||
std::map<int, int> boundTextures, int animflags, int particleflags, bool skipMeshes, TextKeyMap* textKeys, osg::Node* rootNode=NULL)
|
std::vector<int> boundTextures, int animflags, int particleflags, bool skipMeshes, TextKeyMap* textKeys, osg::Node* rootNode=NULL)
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::Group> node = new osg::MatrixTransform(nifNode->trafo.toMatrix());
|
osg::ref_ptr<osg::Group> node = new osg::MatrixTransform(nifNode->trafo.toMatrix());
|
||||||
|
|
||||||
|
@ -558,7 +558,7 @@ namespace NifOsg
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleMeshControllers(const Nif::Node *nifNode, SceneUtil::CompositeStateSetUpdater* composite, const std::map<int, int> &boundTextures, int animflags)
|
void handleMeshControllers(const Nif::Node *nifNode, SceneUtil::CompositeStateSetUpdater* composite, const std::vector<int> &boundTextures, int animflags)
|
||||||
{
|
{
|
||||||
for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next)
|
for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next)
|
||||||
{
|
{
|
||||||
|
@ -568,8 +568,8 @@ namespace NifOsg
|
||||||
{
|
{
|
||||||
const Nif::NiUVController *uvctrl = static_cast<const Nif::NiUVController*>(ctrl.getPtr());
|
const Nif::NiUVController *uvctrl = static_cast<const Nif::NiUVController*>(ctrl.getPtr());
|
||||||
std::set<int> texUnits;
|
std::set<int> texUnits;
|
||||||
for (std::map<int, int>::const_iterator it = boundTextures.begin(); it != boundTextures.end(); ++it)
|
for (unsigned int i=0; i<boundTextures.size(); ++i)
|
||||||
texUnits.insert(it->first);
|
texUnits.insert(i);
|
||||||
|
|
||||||
osg::ref_ptr<UVController> ctrl = new UVController(uvctrl->data.getPtr(), texUnits);
|
osg::ref_ptr<UVController> ctrl = new UVController(uvctrl->data.getPtr(), texUnits);
|
||||||
setupController(uvctrl, ctrl, animflags);
|
setupController(uvctrl, ctrl, animflags);
|
||||||
|
@ -888,7 +888,7 @@ namespace NifOsg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void triShapeToGeometry(const Nif::NiTriShape *triShape, osg::Geometry *geometry, osg::Node* parentNode, SceneUtil::CompositeStateSetUpdater* composite, const std::map<int, int>& boundTextures, int animflags)
|
void triShapeToGeometry(const Nif::NiTriShape *triShape, osg::Geometry *geometry, osg::Node* parentNode, SceneUtil::CompositeStateSetUpdater* composite, const std::vector<int>& boundTextures, int animflags)
|
||||||
{
|
{
|
||||||
const Nif::NiTriShapeData* data = triShape->data.getPtr();
|
const Nif::NiTriShapeData* data = triShape->data.getPtr();
|
||||||
|
|
||||||
|
@ -898,10 +898,10 @@ namespace NifOsg
|
||||||
geometry->setNormalArray(new osg::Vec3Array(data->normals.size(), &data->normals[0]), osg::Array::BIND_PER_VERTEX);
|
geometry->setNormalArray(new osg::Vec3Array(data->normals.size(), &data->normals[0]), osg::Array::BIND_PER_VERTEX);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (std::map<int, int>::const_iterator it = boundTextures.begin(); it != boundTextures.end(); ++it)
|
int textureStage = 0;
|
||||||
|
for (std::vector<int>::const_iterator it = boundTextures.begin(); it != boundTextures.end(); ++it,++textureStage)
|
||||||
{
|
{
|
||||||
int textureStage = it->first;
|
int uvSet = *it;
|
||||||
int uvSet = it->second;
|
|
||||||
if (uvSet >= (int)data->uvlist.size())
|
if (uvSet >= (int)data->uvlist.size())
|
||||||
{
|
{
|
||||||
// Occurred in "ascendedsleeper.nif", but only for hidden Shadow nodes, apparently
|
// Occurred in "ascendedsleeper.nif", but only for hidden Shadow nodes, apparently
|
||||||
|
@ -928,7 +928,7 @@ namespace NifOsg
|
||||||
applyMaterialProperties(parentNode, materialProps, composite, !data->colors.empty(), animflags);
|
applyMaterialProperties(parentNode, materialProps, composite, !data->colors.empty(), animflags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleTriShape(const Nif::NiTriShape* triShape, osg::Group* parentNode, SceneUtil::CompositeStateSetUpdater* composite, const std::map<int, int>& boundTextures, int animflags)
|
void handleTriShape(const Nif::NiTriShape* triShape, osg::Group* parentNode, SceneUtil::CompositeStateSetUpdater* composite, const std::vector<int>& boundTextures, int animflags)
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::Geometry> geometry;
|
osg::ref_ptr<osg::Geometry> geometry;
|
||||||
if(!triShape->controller.empty())
|
if(!triShape->controller.empty())
|
||||||
|
@ -1027,7 +1027,7 @@ namespace NifOsg
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleSkinnedTriShape(const Nif::NiTriShape *triShape, osg::Group *parentNode, SceneUtil::CompositeStateSetUpdater* composite,
|
void handleSkinnedTriShape(const Nif::NiTriShape *triShape, osg::Group *parentNode, SceneUtil::CompositeStateSetUpdater* composite,
|
||||||
const std::map<int, int>& boundTextures, int animflags)
|
const std::vector<int>& boundTextures, int animflags)
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
|
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
|
||||||
|
|
||||||
|
@ -1152,7 +1152,7 @@ namespace NifOsg
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleProperty(const Nif::Property *property,
|
void handleProperty(const Nif::Property *property,
|
||||||
osg::Node *node, SceneUtil::CompositeStateSetUpdater* composite, Resource::TextureManager* textureManager, std::map<int, int>& boundTextures, int animflags)
|
osg::Node *node, SceneUtil::CompositeStateSetUpdater* composite, Resource::TextureManager* textureManager, std::vector<int>& boundTextures, int animflags)
|
||||||
{
|
{
|
||||||
switch (property->recType)
|
switch (property->recType)
|
||||||
{
|
{
|
||||||
|
@ -1254,6 +1254,15 @@ namespace NifOsg
|
||||||
{
|
{
|
||||||
const Nif::NiTexturingProperty* texprop = static_cast<const Nif::NiTexturingProperty*>(property);
|
const Nif::NiTexturingProperty* texprop = static_cast<const Nif::NiTexturingProperty*>(property);
|
||||||
osg::StateSet* stateset = node->getOrCreateStateSet();
|
osg::StateSet* stateset = node->getOrCreateStateSet();
|
||||||
|
|
||||||
|
if (boundTextures.size())
|
||||||
|
{
|
||||||
|
// overriding a parent NiTexturingProperty, so remove what was previously bound
|
||||||
|
for (unsigned int i=0; i<boundTextures.size(); ++i)
|
||||||
|
stateset->setTextureMode(i, GL_TEXTURE_2D, osg::StateAttribute::OFF);
|
||||||
|
boundTextures.clear();
|
||||||
|
}
|
||||||
|
|
||||||
for (int i=0; i<Nif::NiTexturingProperty::NumTextures; ++i)
|
for (int i=0; i<Nif::NiTexturingProperty::NumTextures; ++i)
|
||||||
{
|
{
|
||||||
if (texprop->textures[i].inUse)
|
if (texprop->textures[i].inUse)
|
||||||
|
@ -1290,19 +1299,21 @@ namespace NifOsg
|
||||||
wrapS ? osg::Texture::REPEAT : osg::Texture::CLAMP,
|
wrapS ? osg::Texture::REPEAT : osg::Texture::CLAMP,
|
||||||
wrapT ? osg::Texture::REPEAT : osg::Texture::CLAMP);
|
wrapT ? osg::Texture::REPEAT : osg::Texture::CLAMP);
|
||||||
|
|
||||||
stateset->setTextureAttributeAndModes(i, texture2d, osg::StateAttribute::ON);
|
int texUnit = boundTextures.size();
|
||||||
|
|
||||||
|
stateset->setTextureAttributeAndModes(texUnit, texture2d, osg::StateAttribute::ON);
|
||||||
|
|
||||||
if (i == Nif::NiTexturingProperty::GlowTexture)
|
if (i == Nif::NiTexturingProperty::GlowTexture)
|
||||||
{
|
{
|
||||||
osg::TexEnv* texEnv = new osg::TexEnv;
|
osg::TexEnv* texEnv = new osg::TexEnv;
|
||||||
texEnv->setMode(osg::TexEnv::ADD);
|
texEnv->setMode(osg::TexEnv::ADD);
|
||||||
stateset->setTextureAttributeAndModes(i, texEnv, osg::StateAttribute::ON);
|
stateset->setTextureAttributeAndModes(texUnit, texEnv, osg::StateAttribute::ON);
|
||||||
}
|
}
|
||||||
else if (i == Nif::NiTexturingProperty::DarkTexture)
|
else if (i == Nif::NiTexturingProperty::DarkTexture)
|
||||||
{
|
{
|
||||||
osg::TexEnv* texEnv = new osg::TexEnv;
|
osg::TexEnv* texEnv = new osg::TexEnv;
|
||||||
texEnv->setMode(osg::TexEnv::MODULATE);
|
texEnv->setMode(osg::TexEnv::MODULATE);
|
||||||
stateset->setTextureAttributeAndModes(i, texEnv, osg::StateAttribute::ON);
|
stateset->setTextureAttributeAndModes(texUnit, texEnv, osg::StateAttribute::ON);
|
||||||
}
|
}
|
||||||
else if (i == Nif::NiTexturingProperty::DetailTexture)
|
else if (i == Nif::NiTexturingProperty::DetailTexture)
|
||||||
{
|
{
|
||||||
|
@ -1318,15 +1329,10 @@ namespace NifOsg
|
||||||
texEnv->setOperand1_RGB(GL_SRC_COLOR);
|
texEnv->setOperand1_RGB(GL_SRC_COLOR);
|
||||||
texEnv->setSource0_RGB(GL_PREVIOUS_ARB);
|
texEnv->setSource0_RGB(GL_PREVIOUS_ARB);
|
||||||
texEnv->setSource1_RGB(GL_TEXTURE);
|
texEnv->setSource1_RGB(GL_TEXTURE);
|
||||||
stateset->setTextureAttributeAndModes(i, texEnv, osg::StateAttribute::ON);
|
stateset->setTextureAttributeAndModes(texUnit, texEnv, osg::StateAttribute::ON);
|
||||||
}
|
}
|
||||||
|
|
||||||
boundTextures[i] = tex.uvSet;
|
boundTextures.push_back(tex.uvSet);
|
||||||
}
|
|
||||||
else if (boundTextures.find(i) != boundTextures.end())
|
|
||||||
{
|
|
||||||
stateset->setTextureAttributeAndModes(i, new osg::Texture2D, osg::StateAttribute::OFF);
|
|
||||||
boundTextures.erase(i);
|
|
||||||
}
|
}
|
||||||
handleTextureControllers(texprop, composite, textureManager, stateset, animflags);
|
handleTextureControllers(texprop, composite, textureManager, stateset, animflags);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue