Bunch of stuff

BindlessTest
Cédric Mocquillon 2 months ago
parent 8545fb920e
commit 9c50fd3f44

@ -42,6 +42,10 @@ list (APPEND COMPONENT_FILES "${OpenMW_BINARY_DIR}/${VERSION_CPP_FILE}")
# source files
add_component_dir (bindlesstexture
bindlesstexture
)
add_component_dir (lua
luastate scriptscontainer asyncpackage utilpackage serialization configuration l10n storage utf8
shapes/box inputactions

@ -22,6 +22,7 @@
#include <components/nifosg/controller.hpp>
#include <components/nifosg/nifloader.hpp>
#include <components/nifosg/particle.hpp>
#include <components/nif/niffile.hpp>
@ -33,13 +34,16 @@
#include <components/vfs/manager.hpp>
#include <components/vfs/pathutil.hpp>
#include <components/vfs/recursivedirectoryiterator.hpp>
#include <components/sceneutil/clone.hpp>
#include <components/sceneutil/controller.hpp>
#include <components/sceneutil/depth.hpp>
#include <components/sceneutil/extradata.hpp>
#include <components/sceneutil/lightmanager.hpp>
#include <components/sceneutil/morphgeometry.hpp>
#include <components/sceneutil/optimizer.hpp>
#include <components/sceneutil/riggeometry.hpp>
#include <components/sceneutil/riggeometryosgaextension.hpp>
#include <components/sceneutil/util.hpp>
#include <components/sceneutil/visitor.hpp>
@ -352,6 +356,139 @@ namespace Resource
std::vector<osg::ref_ptr<SceneUtil::RigGeometryHolder>> mRigGeometryHolders;
};
class TextureAtlasVisitor : public osg::NodeVisitor
{
public:
/// default to traversing all children.
TextureAtlasVisitor()
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
{
}
void apply(osg::Node& node) override
{
bool pushedStateState = false;
osg::StateSet* ss = node.getStateSet();
if (ss)
pushedStateState = pushStateSet(ss);
traverse(node);
if (pushedStateState)
popStateSet();
}
void apply(osg::Drawable& node) override
{
if (auto rig = dynamic_cast<SceneUtil::RigGeometry*>(&node))
return apply(*rig->getSourceGeometry());
if (auto morph = dynamic_cast<SceneUtil::MorphGeometry*>(&node))
return apply(*morph->getSourceGeometry());
if (dynamic_cast<NifOsg::ParticleSystem*>(&node))
return;
//if (dynamic_cast<osgParticle::ParticleSystemUpdater*>(&node))
// toskip = true;
if (dynamic_cast<osgParticle::ParticleProcessor*>(&node))
return;
if (dynamic_cast<osgParticle::Particle*>(&node))
return;
bool pushedStateState = false;
osg::StateSet* ss = node.getStateSet();
if (ss)
pushedStateState = pushStateSet(ss);
[&] {
osg::Geometry* geom = node.asGeometry();
if (!geom || _statesetStack.empty())
return;
const osg::StateSet::TextureAttributeList& tal = _statesetStack.back()->getTextureAttributeList();
for (unsigned int unit = 0; unit < tal.size(); ++unit)
{
osg::ref_ptr<osg::Texture2D> texture = dynamic_cast<osg::Texture2D*>(
_statesetStack.back()->getTextureAttribute(unit, osg::StateAttribute::TEXTURE));
if (!texture)
continue;
auto it
= std::find(mTexture->_textureList.begin(), mTexture->_textureList.end(), texture->getImage());
if (it == mTexture->_textureList.end())
continue;
unsigned int d = std::distance(mTexture->_textureList.begin(), it);
auto indices = new osg::IntArray(geom->getVertexArray()->getNumElements());
for (unsigned int i = 0; i < geom->getVertexArray()->getNumElements(); ++i)
(*indices)[i] = d;
geom->setVertexAttribArray(7, indices, osg::Array::BIND_PER_VERTEX);
}
}();
if (pushedStateState)
popStateSet();
}
osg::ref_ptr<BindlessTexture> mTexture;
protected:
bool pushStateSet(osg::StateSet* stateset)
{
const osg::StateSet::TextureAttributeList& tal = stateset->getTextureAttributeList();
// if no textures ignore
if (tal.empty())
return false;
bool pushStateState = false;
// if already in stateset list ignore
if (_statesetMap.count(stateset) > 0)
{
pushStateState = true;
}
else
{
bool containsTexture2D = false;
for (unsigned int unit = 0; unit < tal.size(); ++unit)
{
osg::Texture2D* texture2D = dynamic_cast<osg::Texture2D*>(
stateset->getTextureAttribute(unit, osg::StateAttribute::TEXTURE));
if (texture2D)
{
containsTexture2D = true;
_textures.insert(texture2D);
}
}
if (containsTexture2D)
{
_statesetMap[stateset];
pushStateState = true;
}
}
if (pushStateState)
{
_statesetStack.push_back(stateset);
}
return pushStateState;
}
void popStateSet() { _statesetStack.pop_back(); }
typedef std::set<osg::Drawable*> Drawables;
typedef std::map<osg::StateSet*, Drawables> StateSetMap;
typedef std::set<osg::Texture2D*> Textures;
typedef std::vector<osg::StateSet*> StateSetStack;
StateSetMap _statesetMap;
StateSetStack _statesetStack;
Textures _textures;
};
SceneManager::SceneManager(const VFS::Manager* vfs, Resource::ImageManager* imageManager,
Resource::NifFileManager* nifFileManager, double expiryDelay)
: ResourceManager(vfs, expiryDelay)
@ -374,6 +511,17 @@ namespace Resource
, mUnRefImageDataAfterApply(false)
, mParticleSystemMask(~0u)
{
mBuffer = BindlessBuffer::Make(4800);
BindlessTexture::TextureList images;
images.reserve(4800);
for (auto const& tex : vfs->getRecursiveDirectoryIterator("textures/"))
{
auto image = imageManager->getImage(tex);
if (image->s() > 16 || image->t() > 16)
images.push_back(image);
}
mTexture = new BindlessTexture(mBuffer, images);
}
void SceneManager::setForceShaders(bool force)
@ -900,6 +1048,11 @@ namespace Resource
SceneUtil::ReplaceDepthVisitor replaceDepthVisitor;
loaded->accept(replaceDepthVisitor);
TextureAtlasVisitor tav;
tav.mTexture = mTexture;
loaded->accept(tav);
shareState(loaded);
osg::ref_ptr<Shader::ShaderVisitor> shaderVisitor(createShaderVisitor());
loaded->accept(*shaderVisitor);
@ -1134,6 +1287,10 @@ namespace Resource
shaderVisitor->setAdjustCoverageForAlphaTest(mAdjustCoverageForAlphaTest);
shaderVisitor->setSupportsNormalsRT(mSupportsNormalsRT);
shaderVisitor->setWeatherParticleOcclusion(mWeatherParticleOcclusion);
shaderVisitor->mBuffer = mBuffer;
shaderVisitor->mTexture = mTexture;
return shaderVisitor;
}
}

@ -12,6 +12,7 @@
#include "resourcemanager.hpp"
#include <components/sceneutil/lightmanager.hpp>
#include <components/bindlesstexture/bindlesstexture.hpp>
#include <filesystem>
namespace VFS
@ -230,6 +231,9 @@ namespace Resource
void setWeatherParticleOcclusion(bool value) { mWeatherParticleOcclusion = value; }
private:
osg::ref_ptr<BindlessBuffer> mBuffer;
osg::ref_ptr <BindlessTexture> mTexture;
osg::ref_ptr<Shader::ShaderVisitor> createShaderVisitor(const std::string& shaderPrefix = "objects");
osg::ref_ptr<osg::Node> loadErrorMarker();
osg::ref_ptr<osg::Node> cloneErrorMarker();

@ -361,6 +361,10 @@ namespace Shader
mRequirements.back().mTexStageRequiringTangents = unit;
}
diffuseMap = texture;
if (!writableStateSet)
writableStateSet = getWritableStateSet(node);
writableStateSet->setTextureAttribute(unit, mTexture, osg::StateAttribute::ON);
writableStateSet->setAttributeAndModes(mBuffer->Binding(), osg::StateAttribute::ON);
}
else if (texName == "specularMap")
specularMap = texture;
@ -739,6 +743,7 @@ namespace Shader
shaderPrefix = mDefaultShaderPrefix;
auto program = mShaderManager.getProgram(shaderPrefix, defineMap, mProgramTemplate);
program->addBindAttribLocation("index", 7);
writableStateSet->setAttributeAndModes(program, osg::StateAttribute::ON);
addedState->setAttributeAndModes(std::move(program));

@ -3,6 +3,7 @@
#include <osg/NodeVisitor>
#include <osg/Program>
#include <components/bindlesstexture/bindlesstexture.hpp>
namespace Resource
{
@ -63,6 +64,9 @@ namespace Shader
void pushRequirements(osg::Node& node);
void popRequirements();
osg::ref_ptr<BindlessBuffer> mBuffer;
osg::ref_ptr<BindlessTexture> mTexture;
private:
bool mForceShaders;
bool mAllowedToModifyStateSets;

@ -1,4 +1,6 @@
#version 120
#version 450 compatibility
#extension GL_ARB_bindless_texture : require
#extension GL_NV_gpu_shader5 : require // uint64_t
#pragma import_defines(FORCE_OPAQUE, DISTORTION)
#if @useUBO
@ -14,6 +16,13 @@ uniform sampler2D diffuseMap;
varying vec2 diffuseMapUV;
#endif
flat in int textureIndex;
layout (binding = 0, std140) uniform TEXTURE_BLOCK
{
uint64_t tex[4096];
};
#if @darkMap
uniform sampler2D darkMap;
varying vec2 darkMapUV;
@ -124,12 +133,15 @@ void main()
// only offset diffuse and normal maps for now, other textures are more likely to be using a completely different UV set
vec2 offset = vec2(0.0);
int tIndex = (int)(textureIndex);
sampler2D myText = sampler2D(tex[tIndex]);
#if @parallax || @diffuseParallax
#if @parallax
float height = texture2D(normalMap, normalMapUV).a;
float flipY = (passTangent.w > 0.0) ? -1.f : 1.f;
#else
float height = texture2D(diffuseMap, diffuseMapUV).a;
float height = texture2D(myText, diffuseMapUV).a;
// FIXME: shouldn't be necessary, but in this path false-positives are common
float flipY = -1.f;
#endif
@ -139,7 +151,7 @@ void main()
vec2 screenCoords = gl_FragCoord.xy / screenRes;
#if @diffuseMap
gl_FragData[0] = texture2D(diffuseMap, diffuseMapUV + offset);
gl_FragData[0] = texture2D(myText, diffuseMapUV + offset);
#if defined(DISTORTION) && DISTORTION
gl_FragData[0].a = getDiffuseColor().a;
@ -150,7 +162,7 @@ vec2 screenCoords = gl_FragCoord.xy / screenRes;
#if @diffuseParallax
gl_FragData[0].a = 1.0;
#else
gl_FragData[0].a *= coveragePreservingAlphaScale(diffuseMap, diffuseMapUV + offset);
gl_FragData[0].a *= coveragePreservingAlphaScale(myText, diffuseMapUV + offset);
#endif
#else
gl_FragData[0] = vec4(1.0);

@ -1,4 +1,6 @@
#version 120
#version 450 compatibility
#extension GL_ARB_bindless_texture : require
#extension GL_NV_gpu_shader5 : require // uint64_t
#if @useUBO
#extension GL_ARB_uniform_buffer_object : require
@ -8,6 +10,9 @@
#extension GL_EXT_gpu_shader4: require
#endif
attribute float index;
flat out int textureIndex;
#include "lib/core/vertex.h.glsl"
#if @diffuseMap
varying vec2 diffuseMapUV;
@ -94,6 +99,7 @@ void main(void)
passViewPos = viewPos.xyz;
passNormal = gl_Normal.xyz;
normalToViewMatrix = gl_NormalMatrix;
textureIndex = (int)(index + 0.5);
#if @normalMap || @diffuseParallax
passTangent = gl_MultiTexCoord7.xyzw;

Loading…
Cancel
Save