Support defining the texture type with a state attribute (#6240)

Named textures are still supported for easier native format compatibility (and so that I don't have to edit the documentation)
esm4-texture
Alexei Kotov 8 months ago
parent c3d02c0b41
commit 84f4ba4ca1

@ -37,6 +37,7 @@
Bug #6156: 1ft Charm or Sound magic effect vfx doesn't work properly
Bug #6190: Unintuitive sun specularity time of day dependence
Bug #6222: global map cell size can crash openmw if set to too high a value
Bug #6240: State sharing sometimes prevents the use of the same texture file for different purposes in shaders
Bug #6313: Followers with high Fight can turn hostile
Bug #6402: The sound of a thunderstorm does not stop playing after entering the premises
Bug #6427: Enemy health bar disappears before damaging effect ends

@ -28,6 +28,7 @@
#include <components/resource/scenemanager.hpp>
#include <components/sceneutil/depth.hpp>
#include <components/sceneutil/texturetype.hpp>
#include <components/fallback/fallback.hpp>
@ -768,9 +769,10 @@ namespace MWRender
osg::ref_ptr<osg::Texture2D> sunTex = new osg::Texture2D(imageManager.getImage("textures/tx_sun_05.dds"));
sunTex->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
sunTex->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
sunTex->setName("diffuseMap");
mGeom->getOrCreateStateSet()->setTextureAttributeAndModes(0, sunTex);
mGeom->getOrCreateStateSet()->setTextureAttributeAndModes(
0, new SceneUtil::TextureType("diffuseMap"), osg::StateAttribute::ON);
mGeom->getOrCreateStateSet()->addUniform(new osg::Uniform("pass", static_cast<int>(Pass::Sun)));
osg::ref_ptr<osg::Group> queryNode = new osg::Group;
@ -787,6 +789,7 @@ namespace MWRender
stateset->setAttributeAndModes(alphaFunc);
}
stateset->setTextureAttributeAndModes(0, sunTex);
stateset->setTextureAttributeAndModes(0, new SceneUtil::TextureType("diffuseMap"), osg::StateAttribute::ON);
stateset->setAttributeAndModes(createUnlitMaterial());
stateset->addUniform(new osg::Uniform("pass", static_cast<int>(Pass::Sunflash_Query)));
@ -908,7 +911,6 @@ namespace MWRender
= new osg::Texture2D(imageManager.getImage("textures/tx_sun_flash_grey_05.dds"));
tex->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
tex->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
tex->setName("diffuseMap");
osg::ref_ptr<osg::Group> group(new osg::Group);
@ -921,6 +923,7 @@ namespace MWRender
osg::StateSet* stateset = geom->getOrCreateStateSet();
stateset->setTextureAttributeAndModes(0, tex);
stateset->setTextureAttributeAndModes(0, new SceneUtil::TextureType("diffuseMap"), osg::StateAttribute::ON);
stateset->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
stateset->setRenderBinDetails(RenderBin_SunGlare, "RenderBin");
stateset->setNestRenderBins(false);

@ -6,6 +6,7 @@
#include <components/misc/resourcehelpers.hpp>
#include <components/resource/imagemanager.hpp>
#include <components/resource/resourcesystem.hpp>
#include <components/sceneutil/texturetype.hpp>
#include <components/sceneutil/visitor.hpp>
#include <components/settings/values.hpp>
@ -54,7 +55,6 @@ namespace MWRender
= new osg::Texture2D(resourceSystem->getImageManager()->getImage(correctedTexture));
tex->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
tex->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
tex->setName("diffuseMap");
osg::ref_ptr<osg::StateSet> stateset;
if (const osg::StateSet* const src = node.getStateSet())
@ -63,6 +63,7 @@ namespace MWRender
stateset = new osg::StateSet;
stateset->setTextureAttribute(0, tex, osg::StateAttribute::OVERRIDE);
stateset->setTextureAttribute(0, new SceneUtil::TextureType("diffuseMap"), osg::StateAttribute::OVERRIDE);
node.setStateSet(stateset);
}

@ -47,6 +47,7 @@
#include <components/files/conversion.hpp>
#include <components/misc/strings/conversion.hpp>
#include <components/sceneutil/texturetype.hpp>
#include <components/vfs/manager.hpp>
#include "../mwbase/environment.hpp"
@ -106,7 +107,12 @@ namespace
std::string fileName;
if (image)
fileName = image->getFileName();
mTextures.emplace_back(texture->getName(), fileName);
const osg::StateAttribute* type
= stateset->getTextureAttribute(i, SceneUtil::TextureType::AttributeType);
if (type)
mTextures.emplace_back(static_cast<const SceneUtil::TextureType*>(type)->getName(), fileName);
else
mTextures.emplace_back(texture->getName(), fileName);
}
}

@ -57,6 +57,7 @@
#include <components/sceneutil/morphgeometry.hpp>
#include <components/sceneutil/riggeometry.hpp>
#include <components/sceneutil/skeleton.hpp>
#include <components/sceneutil/texturetype.hpp>
#include "fog.hpp"
#include "matrixtransform.hpp"
@ -1031,8 +1032,11 @@ namespace NifOsg
texture2d->setWrap(osg::Texture::WRAP_T, wrapT ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE);
unsigned int texUnit = boundTextures.size();
if (stateset)
{
stateset->setTextureAttributeAndModes(texUnit, texture2d, osg::StateAttribute::ON);
texture2d->setName(name);
stateset->setTextureAttributeAndModes(
texUnit, new SceneUtil::TextureType(name), osg::StateAttribute::ON);
}
boundTextures.emplace_back(uvSet);
return texture2d;
}

@ -11,6 +11,7 @@
#include <components/sceneutil/riggeometry.hpp>
#include <components/sceneutil/riggeometryosgaextension.hpp>
#include <components/sceneutil/skeleton.hpp>
#include <components/sceneutil/texturetype.hpp>
namespace SceneUtil
{
@ -137,6 +138,19 @@ namespace SceneUtil
}
};
class TextureTypeSerializer : public osgDB::ObjectWrapper
{
public:
TextureTypeSerializer()
: osgDB::ObjectWrapper(createInstanceFunc<SceneUtil::TextureType>, "SceneUtil::TextureType",
"osg::Object osg::StateAttribute SceneUtil::TextureType")
{
addSerializer(new osgDB::StringSerializer<SceneUtil::TextureType>(
"Name", {}, &SceneUtil::TextureType::getName, &SceneUtil::TextureType::setName),
osgDB::BaseSerializer::RW_STRING);
}
};
osgDB::ObjectWrapper* makeDummySerializer(const std::string& classname)
{
return new osgDB::ObjectWrapper(createInstanceFunc<osg::DummyObject>, classname, "osg::Object");
@ -168,6 +182,7 @@ namespace SceneUtil
mgr->addWrapper(new CameraRelativeTransformSerializer);
mgr->addWrapper(new MatrixTransformSerializer);
mgr->addWrapper(new FogSerializer);
mgr->addWrapper(new TextureTypeSerializer);
// Don't serialize Geometry data as we are more interested in the overall structure rather than tons of
// vertex data that would make the file large and hard to read.

@ -0,0 +1,44 @@
#ifndef OPENMW_COMPONENTS_SCENEUTIL_TEXTURETYPE_H
#define OPENMW_COMPONENTS_SCENEUTIL_TEXTURETYPE_H
#include <osg/StateAttribute>
namespace SceneUtil
{
// The type bound to the given texture used by the ShaderVisitor to distinguish between them
class TextureType : public osg::StateAttribute
{
public:
TextureType() = default;
TextureType(const std::string& name)
: mName(name)
{
}
TextureType(const TextureType& copy, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY)
: StateAttribute(copy, copyop)
, mName(copy.mName)
{
}
static const osg::StateAttribute::Type AttributeType = static_cast<osg::StateAttribute::Type>(69420);
META_StateAttribute(SceneUtil, TextureType, AttributeType)
bool isTextureAttribute() const override { return true; }
int compare(const osg::StateAttribute& sa) const override
{
COMPARE_StateAttribute_Types(TextureType, sa);
COMPARE_StateAttribute_Parameter(mName);
return 0;
}
void setName(const std::string& name) { mName = name; }
const std::string& getName() const { return mName; }
private:
std::string mName;
};
}
#endif

@ -15,6 +15,7 @@
#include <components/resource/imagemanager.hpp>
#include <components/resource/scenemanager.hpp>
#include <components/sceneutil/texturetype.hpp>
namespace SceneUtil
{
@ -222,7 +223,6 @@ namespace SceneUtil
{
osg::ref_ptr<osg::Image> image = resourceSystem->getImageManager()->getImage(name);
osg::ref_ptr<osg::Texture2D> tex(new osg::Texture2D(image));
tex->setName("envMap");
tex->setWrap(osg::Texture::WRAP_S, osg::Texture2D::REPEAT);
tex->setWrap(osg::Texture::WRAP_T, osg::Texture2D::REPEAT);
resourceSystem->getSceneManager()->applyFilterSettings(tex);
@ -247,6 +247,7 @@ namespace SceneUtil
node->setStateSet(writableStateSet);
}
writableStateSet->setTextureAttributeAndModes(texUnit, textures.front(), osg::StateAttribute::ON);
writableStateSet->setTextureAttributeAndModes(texUnit, new TextureType("envMap"), osg::StateAttribute::ON);
writableStateSet->addUniform(new osg::Uniform("envMapColor", glowColor));
resourceSystem->getSceneManager()->recreateShaders(std::move(node));

@ -26,6 +26,7 @@
#include <components/sceneutil/morphgeometry.hpp>
#include <components/sceneutil/riggeometry.hpp>
#include <components/sceneutil/riggeometryosgaextension.hpp>
#include <components/sceneutil/texturetype.hpp>
#include <components/sceneutil/util.hpp>
#include <components/settings/settings.hpp>
#include <components/stereo/stereomanager.hpp>
@ -329,7 +330,14 @@ namespace Shader
const osg::Texture* texture = attr->asTexture();
if (texture)
{
std::string texName = texture->getName();
std::string texName;
const osg::StateAttribute* type
= stateset->getTextureAttribute(unit, SceneUtil::TextureType::AttributeType);
if (type)
texName = static_cast<const SceneUtil::TextureType*>(type)->getName();
else
texName = texture->getName();
if ((texName.empty() || !isTextureNameRecognized(texName)) && unit == 0)
texName = "diffuseMap";
@ -430,13 +438,14 @@ namespace Shader
normalMapTex->setFilter(osg::Texture::MIN_FILTER, diffuseMap->getFilter(osg::Texture::MIN_FILTER));
normalMapTex->setFilter(osg::Texture::MAG_FILTER, diffuseMap->getFilter(osg::Texture::MAG_FILTER));
normalMapTex->setMaxAnisotropy(diffuseMap->getMaxAnisotropy());
normalMapTex->setName("normalMap");
normalMap = normalMapTex;
int unit = texAttributes.size();
if (!writableStateSet)
writableStateSet = getWritableStateSet(node);
writableStateSet->setTextureAttributeAndModes(unit, normalMapTex, osg::StateAttribute::ON);
writableStateSet->setTextureAttributeAndModes(
unit, new SceneUtil::TextureType("normalMap"), osg::StateAttribute::ON);
mRequirements.back().mTextures[unit] = "normalMap";
mRequirements.back().mTexStageRequiringTangents = unit;
mRequirements.back().mShaderRequired = true;
@ -474,12 +483,13 @@ namespace Shader
specularMapTex->setFilter(
osg::Texture::MAG_FILTER, diffuseMap->getFilter(osg::Texture::MAG_FILTER));
specularMapTex->setMaxAnisotropy(diffuseMap->getMaxAnisotropy());
specularMapTex->setName("specularMap");
int unit = texAttributes.size();
if (!writableStateSet)
writableStateSet = getWritableStateSet(node);
writableStateSet->setTextureAttributeAndModes(unit, specularMapTex, osg::StateAttribute::ON);
writableStateSet->setTextureAttributeAndModes(
unit, new SceneUtil::TextureType("specularMap"), osg::StateAttribute::ON);
mRequirements.back().mTextures[unit] = "specularMap";
mRequirements.back().mShaderRequired = true;
}

Loading…
Cancel
Save