diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c3d34e1f0..1736ae1766 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/apps/openmw/mwrender/skyutil.cpp b/apps/openmw/mwrender/skyutil.cpp index 53baf36416..faa0566016 100644 --- a/apps/openmw/mwrender/skyutil.cpp +++ b/apps/openmw/mwrender/skyutil.cpp @@ -28,6 +28,7 @@ #include #include +#include #include @@ -768,9 +769,10 @@ namespace MWRender osg::ref_ptr 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(Pass::Sun))); osg::ref_ptr 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(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 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); diff --git a/apps/openmw/mwrender/util.cpp b/apps/openmw/mwrender/util.cpp index f1a1177f85..019484eebd 100644 --- a/apps/openmw/mwrender/util.cpp +++ b/apps/openmw/mwrender/util.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -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 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); } diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index ce0bd9673b..509b1feafe 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -47,6 +47,7 @@ #include #include +#include #include #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(type)->getName(), fileName); + else + mTextures.emplace_back(texture->getName(), fileName); } } diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index e8f275ff39..3245f8c4a2 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -57,6 +57,7 @@ #include #include #include +#include #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; } diff --git a/components/sceneutil/serialize.cpp b/components/sceneutil/serialize.cpp index fa239e692f..90f0e7e7a6 100644 --- a/components/sceneutil/serialize.cpp +++ b/components/sceneutil/serialize.cpp @@ -11,6 +11,7 @@ #include #include #include +#include namespace SceneUtil { @@ -137,6 +138,19 @@ namespace SceneUtil } }; + class TextureTypeSerializer : public osgDB::ObjectWrapper + { + public: + TextureTypeSerializer() + : osgDB::ObjectWrapper(createInstanceFunc, "SceneUtil::TextureType", + "osg::Object osg::StateAttribute SceneUtil::TextureType") + { + addSerializer(new osgDB::StringSerializer( + "Name", {}, &SceneUtil::TextureType::getName, &SceneUtil::TextureType::setName), + osgDB::BaseSerializer::RW_STRING); + } + }; + osgDB::ObjectWrapper* makeDummySerializer(const std::string& classname) { return new osgDB::ObjectWrapper(createInstanceFunc, 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. diff --git a/components/sceneutil/texturetype.hpp b/components/sceneutil/texturetype.hpp new file mode 100644 index 0000000000..648fa6f80e --- /dev/null +++ b/components/sceneutil/texturetype.hpp @@ -0,0 +1,44 @@ +#ifndef OPENMW_COMPONENTS_SCENEUTIL_TEXTURETYPE_H +#define OPENMW_COMPONENTS_SCENEUTIL_TEXTURETYPE_H + +#include + +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(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 diff --git a/components/sceneutil/util.cpp b/components/sceneutil/util.cpp index 21a753df12..8d7c585d94 100644 --- a/components/sceneutil/util.cpp +++ b/components/sceneutil/util.cpp @@ -15,6 +15,7 @@ #include #include +#include namespace SceneUtil { @@ -222,7 +223,6 @@ namespace SceneUtil { osg::ref_ptr image = resourceSystem->getImageManager()->getImage(name); osg::ref_ptr 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)); diff --git a/components/shader/shadervisitor.cpp b/components/shader/shadervisitor.cpp index 2676ea3168..263ca0f2bb 100644 --- a/components/shader/shadervisitor.cpp +++ b/components/shader/shadervisitor.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -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(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; }