Initial commit

Multiview shaders.

Refactor Frustum management

Rewrite shared shadow map

cull mask should respect stereo

Stereo savegame screencap

LocalMap refactoring

use the vertex buffer hint instead of the display list patch to enable/disable display lists

Character preview fixes
This commit is contained in:
madsbuvi 2022-04-04 22:51:23 +02:00
parent 2061a0b66e
commit dd5901d351
69 changed files with 3567 additions and 435 deletions

View file

@ -4,11 +4,16 @@
#include <osg/Node>
#include <osg/NodeVisitor>
#include <osg/Texture2D>
#include <osg/Texture2DArray>
#include <osgUtil/CullVisitor>
#include <components/sceneutil/nodecallback.hpp>
#include <components/settings/settings.hpp>
#include <components/sceneutil/depth.hpp>
#include <components/sceneutil/color.hpp>
#include <components/stereo/multiview.hpp>
#include <components/debug/debuglog.hpp>
#include <components/stereo/stereomanager.hpp>
namespace SceneUtil
{
@ -22,11 +27,15 @@ namespace SceneUtil
}
};
RTTNode::RTTNode(uint32_t textureWidth, uint32_t textureHeight, int renderOrderNum, bool doPerViewMapping)
RTTNode::RTTNode(uint32_t textureWidth, uint32_t textureHeight, uint32_t samples, bool generateMipmaps, int renderOrderNum, StereoAwareness stereoAwareness)
: mTextureWidth(textureWidth)
, mTextureHeight(textureHeight)
, mSamples(samples)
, mGenerateMipmaps(generateMipmaps)
, mColorBufferInternalFormat(Color::colorInternalFormat())
, mDepthBufferInternalFormat(AutoDepth::depthInternalFormat())
, mRenderOrderNum(renderOrderNum)
, mDoPerViewMapping(doPerViewMapping)
, mStereoAwareness(stereoAwareness)
{
addCullCallback(new CullCallback);
setCullingActive(false);
@ -34,28 +43,139 @@ namespace SceneUtil
RTTNode::~RTTNode()
{
for (auto& vdd : mViewDependentDataMap)
{
auto* camera = vdd.second->mCamera.get();
if (camera)
{
camera->removeChildren(0, camera->getNumChildren());
}
}
mViewDependentDataMap.clear();
}
void RTTNode::cull(osgUtil::CullVisitor* cv)
{
auto frameNumber = cv->getFrameStamp()->getFrameNumber();
auto* vdd = getViewDependentData(cv);
apply(vdd->mCamera);
vdd->mCamera->accept(*cv);
if (frameNumber > vdd->mFrameNumber)
{
apply(vdd->mCamera);
auto& sm = Stereo::Manager::instance();
if (sm.getEye(cv) == Stereo::Eye::Left)
applyLeft(vdd->mCamera);
if (sm.getEye(cv) == Stereo::Eye::Right)
applyRight(vdd->mCamera);
vdd->mCamera->accept(*cv);
}
vdd->mFrameNumber = frameNumber;
}
void RTTNode::setColorBufferInternalFormat(GLint internalFormat)
{
mColorBufferInternalFormat = internalFormat;
}
void RTTNode::setDepthBufferInternalFormat(GLint internalFormat)
{
mDepthBufferInternalFormat = internalFormat;
}
bool RTTNode::shouldDoPerViewMapping()
{
if(mStereoAwareness != StereoAwareness::Aware)
return false;
if (!Stereo::getMultiview())
return true;
return false;
}
bool RTTNode::shouldDoTextureArray()
{
if (mStereoAwareness == StereoAwareness::Unaware)
return false;
if (Stereo::getMultiview())
return true;
return false;
}
bool RTTNode::shouldDoTextureView()
{
if (mStereoAwareness != StereoAwareness::Unaware_MultiViewShaders)
return false;
if (Stereo::getMultiview())
return true;
return false;
}
osg::Texture2DArray* RTTNode::createTextureArray(GLint internalFormat)
{
osg::Texture2DArray* textureArray = new osg::Texture2DArray;
textureArray->setTextureSize(mTextureWidth, mTextureHeight, 2);
textureArray->setInternalFormat(internalFormat);
GLenum sourceFormat = 0;
GLenum sourceType = 0;
if (SceneUtil::isDepthFormat(internalFormat))
{
SceneUtil::getDepthFormatSourceFormatAndType(internalFormat, sourceFormat, sourceType);
}
else
{
SceneUtil::getColorFormatSourceFormatAndType(internalFormat, sourceFormat, sourceType);
}
textureArray->setSourceFormat(sourceFormat);
textureArray->setSourceType(sourceType);
textureArray->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
textureArray->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
textureArray->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
textureArray->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
textureArray->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE);
return textureArray;
}
osg::Texture2D* RTTNode::createTexture(GLint internalFormat)
{
osg::Texture2D* texture = new osg::Texture2D;
texture->setTextureSize(mTextureWidth, mTextureHeight);
texture->setInternalFormat(internalFormat);
GLenum sourceFormat = 0;
GLenum sourceType = 0;
if (SceneUtil::isDepthFormat(internalFormat))
{
SceneUtil::getDepthFormatSourceFormatAndType(internalFormat, sourceFormat, sourceType);
}
else
{
SceneUtil::getColorFormatSourceFormatAndType(internalFormat, sourceFormat, sourceType);
}
texture->setSourceFormat(sourceFormat);
texture->setSourceType(sourceType);
texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
texture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
texture->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE);
return texture;
}
osg::Texture* RTTNode::getColorTexture(osgUtil::CullVisitor* cv)
{
return getViewDependentData(cv)->mCamera->getBufferAttachmentMap()[osg::Camera::COLOR_BUFFER]._texture;
return getViewDependentData(cv)->mColorTexture;
}
osg::Texture* RTTNode::getDepthTexture(osgUtil::CullVisitor* cv)
{
return getViewDependentData(cv)->mCamera->getBufferAttachmentMap()[osg::Camera::PACKED_DEPTH_STENCIL_BUFFER]._texture;
return getViewDependentData(cv)->mDepthTexture;
}
osg::Camera* RTTNode::getCamera(osgUtil::CullVisitor* cv)
{
return getViewDependentData(cv)->mCamera;
}
RTTNode::ViewDependentData* RTTNode::getViewDependentData(osgUtil::CullVisitor* cv)
{
if (!mDoPerViewMapping)
if (!shouldDoPerViewMapping())
// Always setting it to null is an easy way to disable per-view mapping when mDoPerViewMapping is false.
// This is safe since the visitor is never dereferenced.
cv = nullptr;
@ -63,7 +183,8 @@ namespace SceneUtil
if (mViewDependentDataMap.count(cv) == 0)
{
auto camera = new osg::Camera();
mViewDependentDataMap[cv].reset(new ViewDependentData);
auto vdd = std::make_shared<ViewDependentData>();
mViewDependentDataMap[cv] = vdd;
mViewDependentDataMap[cv]->mCamera = camera;
camera->setRenderOrder(osg::Camera::PRE_RENDER, mRenderOrderNum);
@ -72,34 +193,63 @@ namespace SceneUtil
camera->setViewport(0, 0, mTextureWidth, mTextureHeight);
SceneUtil::setCameraClearDepth(camera);
setDefaults(mViewDependentDataMap[cv]->mCamera.get());
setDefaults(camera);
// Create any buffer attachments not added in setDefaults
if (camera->getBufferAttachmentMap().count(osg::Camera::COLOR_BUFFER) == 0)
if (camera->getBufferAttachmentMap().count(osg::Camera::COLOR_BUFFER))
vdd->mColorTexture = camera->getBufferAttachmentMap()[osg::Camera::COLOR_BUFFER]._texture;
if (camera->getBufferAttachmentMap().count(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER))
vdd->mDepthTexture = camera->getBufferAttachmentMap()[osg::Camera::PACKED_DEPTH_STENCIL_BUFFER]._texture;
#ifdef OSG_HAS_MULTIVIEW
if (shouldDoTextureArray())
{
auto colorBuffer = new osg::Texture2D;
colorBuffer->setTextureSize(mTextureWidth, mTextureHeight);
colorBuffer->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
colorBuffer->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
colorBuffer->setInternalFormat(GL_RGB);
colorBuffer->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
colorBuffer->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
camera->attach(osg::Camera::COLOR_BUFFER, colorBuffer);
SceneUtil::attachAlphaToCoverageFriendlyFramebufferToCamera(camera, osg::Camera::COLOR_BUFFER, colorBuffer);
// Create any buffer attachments not added in setDefaults
if (camera->getBufferAttachmentMap().count(osg::Camera::COLOR_BUFFER) == 0)
{
vdd->mColorTexture = createTextureArray(mColorBufferInternalFormat);
camera->attach(osg::Camera::COLOR_BUFFER, vdd->mColorTexture, 0, osg::Camera::FACE_CONTROLLED_BY_MULTIVIEW_SHADER, mGenerateMipmaps, mSamples);
SceneUtil::attachAlphaToCoverageFriendlyFramebufferToCamera(camera, osg::Camera::COLOR_BUFFER, vdd->mColorTexture, 0, osg::Camera::FACE_CONTROLLED_BY_MULTIVIEW_SHADER, mGenerateMipmaps);
}
if (camera->getBufferAttachmentMap().count(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER) == 0)
{
vdd->mDepthTexture = createTextureArray(mDepthBufferInternalFormat);
camera->attach(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER, vdd->mDepthTexture, 0, osg::Camera::FACE_CONTROLLED_BY_MULTIVIEW_SHADER, false, mSamples);
}
if (shouldDoTextureView())
{
// In this case, shaders being set to multiview forces us to render to a multiview framebuffer even though we don't need that.
// This forces us to make Texture2DArray. To make this possible to sample as a Texture2D, make a Texture2D view into the texture array.
vdd->mColorTexture = Stereo::createTextureView_Texture2DFromTexture2DArray(static_cast<osg::Texture2DArray*>(vdd->mColorTexture.get()), 0);
vdd->mDepthTexture = Stereo::createTextureView_Texture2DFromTexture2DArray(static_cast<osg::Texture2DArray*>(vdd->mDepthTexture.get()), 0);
}
}
else
#endif
{
// Create any buffer attachments not added in setDefaults
if (camera->getBufferAttachmentMap().count(osg::Camera::COLOR_BUFFER) == 0)
{
vdd->mColorTexture = createTexture(mColorBufferInternalFormat);
camera->attach(osg::Camera::COLOR_BUFFER, vdd->mColorTexture, 0, 0, mGenerateMipmaps, mSamples);
SceneUtil::attachAlphaToCoverageFriendlyFramebufferToCamera(camera, osg::Camera::COLOR_BUFFER, vdd->mColorTexture, 0, 0, mGenerateMipmaps);
}
if (camera->getBufferAttachmentMap().count(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER) == 0)
{
vdd->mDepthTexture = createTexture(mDepthBufferInternalFormat);
camera->attach(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER, vdd->mDepthTexture, 0, 0, false, mSamples);
}
}
if (camera->getBufferAttachmentMap().count(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER) == 0)
// OSG appears not to properly initialize this metadata. So when multisampling is enabled, OSG will use incorrect formats for the resolve buffers.
if (mSamples > 1)
{
auto depthBuffer = new osg::Texture2D;
depthBuffer->setTextureSize(mTextureWidth, mTextureHeight);
depthBuffer->setSourceFormat(GL_DEPTH_STENCIL_EXT);
depthBuffer->setInternalFormat(GL_DEPTH24_STENCIL8_EXT);
depthBuffer->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
depthBuffer->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
depthBuffer->setSourceType(GL_UNSIGNED_INT_24_8_EXT);
depthBuffer->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
depthBuffer->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
camera->attach(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER, depthBuffer);
camera->getBufferAttachmentMap()[osg::Camera::COLOR_BUFFER]._internalFormat = mColorBufferInternalFormat;
camera->getBufferAttachmentMap()[osg::Camera::COLOR_BUFFER]._mipMapGeneration = mGenerateMipmaps;
camera->getBufferAttachmentMap()[osg::Camera::PACKED_DEPTH_STENCIL_BUFFER]._internalFormat = mDepthBufferInternalFormat;
camera->getBufferAttachmentMap()[osg::Camera::PACKED_DEPTH_STENCIL_BUFFER]._mipMapGeneration = mGenerateMipmaps;
}
}