mirror of
https://github.com/OpenMW/openmw.git
synced 2025-03-03 07:09:40 +00:00
initial reverse-z depth implementation
This commit is contained in:
parent
10d100f205
commit
70fac33940
46 changed files with 614 additions and 92 deletions
|
@ -161,7 +161,7 @@ namespace CSVRender
|
|||
}
|
||||
|
||||
mWaterGeometry = SceneUtil::createWaterGeometry(size, segments, textureRepeats);
|
||||
mWaterGeometry->setStateSet(SceneUtil::createSimpleWaterStateSet(Alpha, RenderBin));
|
||||
mWaterGeometry->setStateSet(SceneUtil::createSimpleWaterStateSet(Alpha, RenderBin, false));
|
||||
|
||||
// Add water texture
|
||||
std::string textureName = Fallback::Map::getString("Water_SurfaceTexture");
|
||||
|
|
|
@ -21,7 +21,7 @@ add_openmw_dir (mwrender
|
|||
actors objects renderingmanager animation rotatecontroller sky npcanimation vismask
|
||||
creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation screenshotmanager
|
||||
bulletdebugdraw globalmap characterpreview camera viewovershoulder localmap water terrainstorage ripplesimulation
|
||||
renderbin actoranimation landmanager navmesh actorspaths recastmesh fogmanager objectpaging groundcover
|
||||
renderbin actoranimation landmanager navmesh actorspaths recastmesh fogmanager objectpaging groundcover postprocessor
|
||||
)
|
||||
|
||||
add_openmw_dir (mwinput
|
||||
|
|
|
@ -8,7 +8,11 @@
|
|||
#include "MyGUI_FactoryManager.h"
|
||||
|
||||
#include <components/misc/utf8stream.hpp>
|
||||
#include <components/sceneutil/util.hpp>
|
||||
#include <components/resource/resourcesystem.hpp>
|
||||
#include <components/resource/scenemanager.hpp>
|
||||
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
|
||||
|
@ -1217,8 +1221,10 @@ public:
|
|||
|
||||
RenderXform renderXform (mCroppedParent, textFormat.mRenderItem->getRenderTarget()->getInfo());
|
||||
|
||||
float z = MWBase::Environment::get().getResourceSystem()->getSceneManager()->getReverseZ() ? 1.0 : -1.0;
|
||||
|
||||
GlyphStream glyphStream(textFormat.mFont, static_cast<float>(mCoord.left), static_cast<float>(mCoord.top - mViewTop),
|
||||
-1 /*mNode->getNodeDepth()*/, vertices, renderXform);
|
||||
z /*mNode->getNodeDepth()*/, vertices, renderXform);
|
||||
|
||||
int visit_top = (std::max) (mViewTop, mViewTop + int (renderXform.clipTop ));
|
||||
int visit_bottom = (std::min) (mViewBottom, mViewTop + int (renderXform.clipBottom));
|
||||
|
|
|
@ -741,7 +741,7 @@ namespace MWGui
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
MapWindow::MapWindow(CustomMarkerCollection &customMarkers, DragAndDrop* drag, MWRender::LocalMap* localMapRender, SceneUtil::WorkQueue* workQueue)
|
||||
MapWindow::MapWindow(CustomMarkerCollection &customMarkers, DragAndDrop* drag, MWRender::LocalMap* localMapRender, SceneUtil::WorkQueue* workQueue, bool reverseZ)
|
||||
: WindowPinnableBase("openmw_map_window.layout")
|
||||
, LocalMapBase(customMarkers, localMapRender)
|
||||
, NoDrop(drag, mMainWidget)
|
||||
|
@ -751,7 +751,7 @@ namespace MWGui
|
|||
, mGlobal(Settings::Manager::getBool("global", "Map"))
|
||||
, mEventBoxGlobal(nullptr)
|
||||
, mEventBoxLocal(nullptr)
|
||||
, mGlobalMapRender(new MWRender::GlobalMap(localMapRender->getRoot(), workQueue))
|
||||
, mGlobalMapRender(new MWRender::GlobalMap(localMapRender->getRoot(), workQueue, reverseZ))
|
||||
, mEditNoteDialog()
|
||||
{
|
||||
static bool registered = false;
|
||||
|
|
|
@ -222,7 +222,7 @@ namespace MWGui
|
|||
class MapWindow : public MWGui::WindowPinnableBase, public LocalMapBase, public NoDrop
|
||||
{
|
||||
public:
|
||||
MapWindow(CustomMarkerCollection& customMarkers, DragAndDrop* drag, MWRender::LocalMap* localMapRender, SceneUtil::WorkQueue* workQueue);
|
||||
MapWindow(CustomMarkerCollection& customMarkers, DragAndDrop* drag, MWRender::LocalMap* localMapRender, SceneUtil::WorkQueue* workQueue, bool reverseZ);
|
||||
virtual ~MapWindow();
|
||||
|
||||
void setCellName(const std::string& cellName);
|
||||
|
|
|
@ -305,8 +305,9 @@ namespace MWGui
|
|||
mGuiModeStates[GM_MainMenu] = GuiModeState(menu);
|
||||
mWindows.push_back(menu);
|
||||
|
||||
mLocalMapRender = new MWRender::LocalMap(mViewer->getSceneData()->asGroup());
|
||||
mMap = new MapWindow(mCustomMarkers, mDragAndDrop, mLocalMapRender, mWorkQueue);
|
||||
bool reverseZ = mResourceSystem->getSceneManager()->getReverseZ();
|
||||
mLocalMapRender = new MWRender::LocalMap(mViewer->getSceneData()->asGroup(), reverseZ);
|
||||
mMap = new MapWindow(mCustomMarkers, mDragAndDrop, mLocalMapRender, mWorkQueue, reverseZ);
|
||||
mWindows.push_back(mMap);
|
||||
mMap->renderGlobalMap();
|
||||
trackWindow(mMap, "map");
|
||||
|
|
|
@ -168,7 +168,7 @@ namespace MWRender
|
|||
mCamera->setRenderOrder(osg::Camera::PRE_RENDER);
|
||||
mCamera->attach(osg::Camera::COLOR_BUFFER, mTexture, 0, 0, false, Settings::Manager::getInt("antialiasing", "Video"));
|
||||
mCamera->setName("CharacterPreview");
|
||||
mCamera->setComputeNearFarMode(osg::Camera::COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES);
|
||||
mCamera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
|
||||
mCamera->setCullMask(~(Mask_UpdateVisitor));
|
||||
|
||||
mCamera->setNodeMask(Mask_RenderToTexture);
|
||||
|
@ -188,6 +188,9 @@ namespace MWRender
|
|||
defaultMat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4f(0.f, 0.f, 0.f, 0.f));
|
||||
stateset->setAttribute(defaultMat);
|
||||
|
||||
osg::ref_ptr<osg::Depth> depth = new osg::Depth;
|
||||
stateset->setAttributeAndModes(depth, osg::StateAttribute::ON);
|
||||
|
||||
SceneUtil::ShadowManager::disableShadowsForStateSet(stateset);
|
||||
|
||||
// assign large value to effectively turn off fog
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <components/debug/debuglog.hpp>
|
||||
|
||||
#include <components/sceneutil/workqueue.hpp>
|
||||
#include <components/sceneutil/util.hpp>
|
||||
|
||||
#include <components/esm/globalmap.hpp>
|
||||
|
||||
|
@ -219,13 +220,14 @@ namespace MWRender
|
|||
osg::ref_ptr<osg::Texture2D> mOverlayTexture;
|
||||
};
|
||||
|
||||
GlobalMap::GlobalMap(osg::Group* root, SceneUtil::WorkQueue* workQueue)
|
||||
GlobalMap::GlobalMap(osg::Group* root, SceneUtil::WorkQueue* workQueue, bool reverseZ)
|
||||
: mRoot(root)
|
||||
, mWorkQueue(workQueue)
|
||||
, mWidth(0)
|
||||
, mHeight(0)
|
||||
, mMinX(0), mMaxX(0)
|
||||
, mMinY(0), mMaxY(0)
|
||||
, mReverseZ(reverseZ)
|
||||
|
||||
{
|
||||
mCellSize = Settings::Manager::getInt("global map cell size", "Map");
|
||||
|
@ -323,7 +325,7 @@ namespace MWRender
|
|||
if (texture)
|
||||
{
|
||||
osg::ref_ptr<osg::Geometry> geom = createTexturedQuad(srcLeft, srcTop, srcRight, srcBottom);
|
||||
osg::ref_ptr<osg::Depth> depth = new osg::Depth;
|
||||
auto depth = SceneUtil::createDepth(mReverseZ);
|
||||
depth->setWriteMask(0);
|
||||
osg::StateSet* stateset = geom->getOrCreateStateSet();
|
||||
stateset->setAttribute(depth);
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace MWRender
|
|||
class GlobalMap
|
||||
{
|
||||
public:
|
||||
GlobalMap(osg::Group* root, SceneUtil::WorkQueue* workQueue);
|
||||
GlobalMap(osg::Group* root, SceneUtil::WorkQueue* workQueue, bool reverseZ);
|
||||
~GlobalMap();
|
||||
|
||||
void render();
|
||||
|
@ -126,6 +126,8 @@ namespace MWRender
|
|||
int mHeight;
|
||||
|
||||
int mMinX, mMaxX, mMinY, mMaxY;
|
||||
|
||||
bool mReverseZ;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -83,13 +83,14 @@ namespace
|
|||
namespace MWRender
|
||||
{
|
||||
|
||||
LocalMap::LocalMap(osg::Group* root)
|
||||
LocalMap::LocalMap(osg::Group* root, bool reverseZ)
|
||||
: mRoot(root)
|
||||
, mMapResolution(Settings::Manager::getInt("local map resolution", "Map"))
|
||||
, mMapWorldSize(Constants::CellSizeInUnits)
|
||||
, mCellDistance(Constants::CellGridRadius)
|
||||
, mAngle(0.f)
|
||||
, mInterior(false)
|
||||
, mReverseZ(reverseZ)
|
||||
{
|
||||
// Increase map resolution, if use UI scaling
|
||||
float uiScale = MWBase::Environment::get().getWindowManager()->getScalingFactor();
|
||||
|
@ -176,7 +177,12 @@ void LocalMap::saveFogOfWar(MWWorld::CellStore* cell)
|
|||
osg::ref_ptr<osg::Camera> LocalMap::createOrthographicCamera(float x, float y, float width, float height, const osg::Vec3d& upVector, float zmin, float zmax)
|
||||
{
|
||||
osg::ref_ptr<osg::Camera> camera (new osg::Camera);
|
||||
camera->setProjectionMatrixAsOrtho(-width/2, width/2, -height/2, height/2, 5, (zmax-zmin) + 10);
|
||||
|
||||
if (mReverseZ)
|
||||
camera->setProjectionMatrix(SceneUtil::getReversedZProjectionMatrixAsOrtho(-width/2, width/2, -height/2, height/2, 5, (zmax-zmin) + 10));
|
||||
else
|
||||
camera->setProjectionMatrixAsOrtho(-width/2, width/2, -height/2, height/2, 5, (zmax-zmin) + 10);
|
||||
|
||||
camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
|
||||
camera->setViewMatrixAsLookAt(osg::Vec3d(x, y, zmax + 5), osg::Vec3d(x, y, zmin), upVector);
|
||||
camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF_INHERIT_VIEWPOINT);
|
||||
|
@ -195,6 +201,13 @@ osg::ref_ptr<osg::Camera> LocalMap::createOrthographicCamera(float x, float y, f
|
|||
osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet;
|
||||
stateset->setAttribute(new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::FILL), osg::StateAttribute::OVERRIDE);
|
||||
|
||||
if (mReverseZ)
|
||||
{
|
||||
camera->setClearDepth(0.0);
|
||||
auto depth = SceneUtil::createDepth(mReverseZ);
|
||||
stateset->setAttributeAndModes(depth, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
|
||||
}
|
||||
|
||||
// assign large value to effectively turn off fog
|
||||
// shaders don't respect glDisable(GL_FOG)
|
||||
osg::ref_ptr<osg::Fog> fog (new osg::Fog);
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace MWRender
|
|||
class LocalMap
|
||||
{
|
||||
public:
|
||||
LocalMap(osg::Group* root);
|
||||
LocalMap(osg::Group* root, bool reverseZ);
|
||||
~LocalMap();
|
||||
|
||||
/**
|
||||
|
@ -156,6 +156,7 @@ namespace MWRender
|
|||
void setupRenderToTexture(osg::ref_ptr<osg::Camera> camera, int x, int y);
|
||||
|
||||
bool mInterior;
|
||||
bool mReverseZ;
|
||||
osg::BoundingBox mBounds;
|
||||
};
|
||||
|
||||
|
|
|
@ -370,9 +370,9 @@ void NpcAnimation::setViewMode(NpcAnimation::ViewMode viewMode)
|
|||
class DepthClearCallback : public osgUtil::RenderBin::DrawCallback
|
||||
{
|
||||
public:
|
||||
DepthClearCallback()
|
||||
DepthClearCallback(bool reverseZ)
|
||||
{
|
||||
mDepth = new osg::Depth;
|
||||
mDepth = SceneUtil::createDepth(reverseZ);
|
||||
mDepth->setWriteMask(true);
|
||||
}
|
||||
|
||||
|
@ -432,7 +432,7 @@ void NpcAnimation::setRenderBin()
|
|||
if (!prototypeAdded)
|
||||
{
|
||||
osg::ref_ptr<osgUtil::RenderBin> depthClearBin (new osgUtil::RenderBin);
|
||||
depthClearBin->setDrawCallback(new DepthClearCallback);
|
||||
depthClearBin->setDrawCallback(new DepthClearCallback(mResourceSystem->getSceneManager()->getReverseZ()));
|
||||
osgUtil::RenderBin::addRenderBinPrototype("DepthClear", depthClearBin);
|
||||
prototypeAdded = true;
|
||||
}
|
||||
|
|
|
@ -661,6 +661,7 @@ namespace MWRender
|
|||
if (mergeGroup->getNumChildren())
|
||||
{
|
||||
SceneUtil::Optimizer optimizer;
|
||||
optimizer.setReverseZ(mSceneManager->getReverseZ());
|
||||
if (size > 1/8.f)
|
||||
{
|
||||
optimizer.setViewPoint(relativeViewPoint);
|
||||
|
|
216
apps/openmw/mwrender/postprocessor.cpp
Normal file
216
apps/openmw/mwrender/postprocessor.cpp
Normal file
|
@ -0,0 +1,216 @@
|
|||
#include "postprocessor.hpp"
|
||||
|
||||
#include <osg/Group>
|
||||
#include <osg/Camera>
|
||||
#include <osg/Callback>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/FrameBufferObject>
|
||||
|
||||
#include <osgViewer/Viewer>
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
osg::ref_ptr<osg::Geometry> createFullScreenTri()
|
||||
{
|
||||
osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
|
||||
|
||||
osg::ref_ptr<osg::Vec3Array> verts = new osg::Vec3Array;
|
||||
verts->push_back(osg::Vec3f(-1, -1, 0));
|
||||
verts->push_back(osg::Vec3f(-1, 3, 0));
|
||||
verts->push_back(osg::Vec3f(3, -1, 0));
|
||||
|
||||
geom->setVertexArray(verts);
|
||||
|
||||
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES, 0, 3));
|
||||
|
||||
return geom;
|
||||
}
|
||||
|
||||
class CullCallback : public osg::NodeCallback
|
||||
{
|
||||
public:
|
||||
CullCallback(MWRender::PostProcessor* postProcessor)
|
||||
: mPostProcessor(postProcessor)
|
||||
, mLastFrameNumber(0)
|
||||
{}
|
||||
|
||||
void operator()(osg::Node* node, osg::NodeVisitor* nv) override
|
||||
{
|
||||
osgUtil::RenderStage* renderStage = nv->asCullVisitor()->getCurrentRenderStage();
|
||||
|
||||
unsigned int frame = nv->getTraversalNumber();
|
||||
if (frame != mLastFrameNumber)
|
||||
{
|
||||
mLastFrameNumber = frame;
|
||||
if (!mPostProcessor->getMsaaFbo())
|
||||
{
|
||||
renderStage->setFrameBufferObject(mPostProcessor->getFbo());
|
||||
}
|
||||
else
|
||||
{
|
||||
renderStage->setMultisampleResolveFramebufferObject(mPostProcessor->getFbo());
|
||||
renderStage->setFrameBufferObject(mPostProcessor->getMsaaFbo());
|
||||
}
|
||||
}
|
||||
|
||||
traverse(node, nv);
|
||||
}
|
||||
MWRender::PostProcessor* mPostProcessor;
|
||||
unsigned int mLastFrameNumber;
|
||||
};
|
||||
|
||||
struct ResizedCallback : osg::GraphicsContext::ResizedCallback
|
||||
{
|
||||
ResizedCallback(MWRender::PostProcessor* postProcessor)
|
||||
: mPostProcessor(postProcessor)
|
||||
{
|
||||
}
|
||||
|
||||
void resizedImplementation(osg::GraphicsContext* gc, int x, int y, int width, int height) override
|
||||
{
|
||||
mPostProcessor->resize(width, height);
|
||||
}
|
||||
|
||||
MWRender::PostProcessor* mPostProcessor;
|
||||
};
|
||||
}
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
PostProcessor::PostProcessor(osgViewer::Viewer* viewer, osg::Group* rootNode)
|
||||
: mViewer(viewer)
|
||||
, mRootNode(new osg::Group)
|
||||
{
|
||||
int width = viewer->getCamera()->getViewport()->width();
|
||||
int height = viewer->getCamera()->getViewport()->height();
|
||||
|
||||
createTexturesAndCamera(width, height);
|
||||
resize(width, height);
|
||||
|
||||
mRootNode->addChild(mHUDCamera);
|
||||
mRootNode->addChild(rootNode);
|
||||
mViewer->setSceneData(mRootNode);
|
||||
|
||||
// Main camera is treated specially, we need to manually set the FBO and
|
||||
// resolve FBO during the cull callback.
|
||||
mViewer->getCamera()->addCullCallback(new CullCallback(this));
|
||||
mViewer->getCamera()->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
|
||||
mViewer->getCamera()->attach(osg::Camera::COLOR_BUFFER0, mSceneTex);
|
||||
mViewer->getCamera()->attach(osg::Camera::DEPTH_BUFFER, mDepthTex);
|
||||
|
||||
mViewer->getCamera()->getGraphicsContext()->setResizedCallback(new ResizedCallback(this));
|
||||
}
|
||||
|
||||
void PostProcessor::resize(int width, int height)
|
||||
{
|
||||
mDepthTex->setTextureSize(width, height);
|
||||
mSceneTex->setTextureSize(width, height);
|
||||
mDepthTex->dirtyTextureObject();
|
||||
mSceneTex->dirtyTextureObject();
|
||||
|
||||
int samples = Settings::Manager::getInt("antialiasing", "Video");
|
||||
|
||||
mFbo = new osg::FrameBufferObject;
|
||||
mFbo->setAttachment(osg::Camera::COLOR_BUFFER0, osg::FrameBufferAttachment(mSceneTex));
|
||||
mFbo->setAttachment(osg::Camera::DEPTH_BUFFER, osg::FrameBufferAttachment(mDepthTex));
|
||||
|
||||
// When MSAA is enabled we must first render to a render buffer, then
|
||||
// blit the result to the FBO which is either passed to the main frame
|
||||
// buffer for display or used as the entry point for a post process chain.
|
||||
if (samples > 0)
|
||||
{
|
||||
mMsaaFbo = new osg::FrameBufferObject;
|
||||
osg::ref_ptr<osg::RenderBuffer> colorRB = new osg::RenderBuffer(width, height, mSceneTex->getInternalFormat(), samples);
|
||||
osg::ref_ptr<osg::RenderBuffer> depthRB = new osg::RenderBuffer(width, height, mDepthTex->getInternalFormat(), samples);
|
||||
mMsaaFbo->setAttachment(osg::Camera::COLOR_BUFFER0, osg::FrameBufferAttachment(colorRB));
|
||||
mMsaaFbo->setAttachment(osg::Camera::DEPTH_BUFFER, osg::FrameBufferAttachment(depthRB));
|
||||
}
|
||||
|
||||
double prevWidth = mViewer->getCamera()->getViewport()->width();
|
||||
double prevHeight = mViewer->getCamera()->getViewport()->height();
|
||||
double scaleX = prevWidth / width;
|
||||
double scaleY = prevHeight / height;
|
||||
|
||||
mViewer->getCamera()->resize(width,height);
|
||||
mHUDCamera->resize(width,height);
|
||||
|
||||
mViewer->getCamera()->getProjectionMatrix() *= osg::Matrix::scale(scaleX, scaleY, 1.0);
|
||||
}
|
||||
|
||||
void PostProcessor::createTexturesAndCamera(int width, int height)
|
||||
{
|
||||
mDepthTex = new osg::Texture2D;
|
||||
mDepthTex->setTextureSize(width, height);
|
||||
mDepthTex->setSourceFormat(GL_DEPTH_COMPONENT);
|
||||
mDepthTex->setSourceType(GL_FLOAT);
|
||||
mDepthTex->setInternalFormat(GL_DEPTH_COMPONENT32F);
|
||||
mDepthTex->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST);
|
||||
mDepthTex->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::NEAREST);
|
||||
mDepthTex->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
|
||||
mDepthTex->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
|
||||
mDepthTex->setResizeNonPowerOfTwoHint(false);
|
||||
|
||||
mSceneTex = new osg::Texture2D;
|
||||
mSceneTex->setTextureSize(width, height);
|
||||
mSceneTex->setSourceFormat(GL_RGB);
|
||||
mSceneTex->setSourceType(GL_UNSIGNED_BYTE);
|
||||
mSceneTex->setInternalFormat(GL_RGB);
|
||||
mSceneTex->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST);
|
||||
mSceneTex->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::NEAREST);
|
||||
mSceneTex->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
|
||||
mSceneTex->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
|
||||
mSceneTex->setResizeNonPowerOfTwoHint(false);
|
||||
|
||||
mHUDCamera = new osg::Camera;
|
||||
mHUDCamera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
|
||||
mHUDCamera->setRenderOrder(osg::Camera::POST_RENDER);
|
||||
mHUDCamera->setClearColor(osg::Vec4(0.45, 0.45, 0.14, 1.0));
|
||||
mHUDCamera->setProjectionMatrix(osg::Matrix::ortho2D(0, 1, 0, 1));
|
||||
mHUDCamera->setAllowEventFocus(false);
|
||||
mHUDCamera->setViewport(0, 0, width, height);
|
||||
|
||||
// Shaders calculate correct UV coordinates for our fullscreen triangle
|
||||
constexpr char vertSrc[] = R"GLSL(
|
||||
#version 120
|
||||
|
||||
varying vec2 uv;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(gl_Vertex.xy, 0.0, 1.0);
|
||||
uv = gl_Position.xy * 0.5 + 0.5;
|
||||
}
|
||||
)GLSL";
|
||||
|
||||
constexpr char fragSrc[] = R"GLSL(
|
||||
#version 120
|
||||
|
||||
varying vec2 uv;
|
||||
uniform sampler2D sceneTex;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragData[0] = texture2D(sceneTex, uv);
|
||||
}
|
||||
)GLSL";
|
||||
|
||||
osg::ref_ptr<osg::Shader> vertShader = new osg::Shader(osg::Shader::VERTEX, vertSrc);
|
||||
osg::ref_ptr<osg::Shader> fragShader = new osg::Shader(osg::Shader::FRAGMENT, fragSrc);
|
||||
|
||||
osg::ref_ptr<osg::Program> program = new osg::Program;
|
||||
program->addShader(vertShader);
|
||||
program->addShader(fragShader);
|
||||
|
||||
mHUDCamera->addChild(createFullScreenTri());
|
||||
|
||||
auto* stateset = mHUDCamera->getOrCreateStateSet();
|
||||
stateset->setTextureAttributeAndModes(0, mSceneTex, osg::StateAttribute::ON);
|
||||
stateset->setAttributeAndModes(program, osg::StateAttribute::ON);
|
||||
stateset->addUniform(new osg::Uniform("sceneTex", 0));
|
||||
stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||
stateset->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
|
||||
}
|
||||
|
||||
}
|
46
apps/openmw/mwrender/postprocessor.hpp
Normal file
46
apps/openmw/mwrender/postprocessor.hpp
Normal file
|
@ -0,0 +1,46 @@
|
|||
#ifndef OPENMW_MWRENDER_POSTPROCESSOR_H
|
||||
#define OPENMW_MWRENDER_POSTPROCESSOR_H
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
|
||||
namespace osg
|
||||
{
|
||||
class Texture2D;
|
||||
class Group;
|
||||
class FrameBufferObject;
|
||||
class Camera;
|
||||
}
|
||||
|
||||
namespace osgViewer
|
||||
{
|
||||
class Viewer;
|
||||
}
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
class PostProcessor
|
||||
{
|
||||
public:
|
||||
PostProcessor(osgViewer::Viewer* viewer, osg::Group* rootNode);
|
||||
|
||||
auto getMsaaFbo() { return mMsaaFbo; }
|
||||
auto getFbo() { return mFbo; }
|
||||
|
||||
void resize(int width, int height);
|
||||
|
||||
private:
|
||||
osgViewer::Viewer* mViewer;
|
||||
osg::ref_ptr<osg::Group> mRootNode;
|
||||
osg::ref_ptr<osg::Camera> mHUDCamera;
|
||||
|
||||
osg::ref_ptr<osg::FrameBufferObject> mMsaaFbo;
|
||||
osg::ref_ptr<osg::FrameBufferObject> mFbo;
|
||||
|
||||
osg::ref_ptr<osg::Texture2D> mSceneTex;
|
||||
osg::ref_ptr<osg::Texture2D> mDepthTex;
|
||||
|
||||
void createTexturesAndCamera(int width, int height);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -11,6 +11,8 @@
|
|||
#include <osg/Group>
|
||||
#include <osg/UserDataContainer>
|
||||
#include <osg/ComputeBoundsVisitor>
|
||||
#include <osg/Depth>
|
||||
#include <osg/ClipControl>
|
||||
|
||||
#include <osgUtil/LineSegmentIntersector>
|
||||
|
||||
|
@ -68,6 +70,7 @@
|
|||
#include "objectpaging.hpp"
|
||||
#include "screenshotmanager.hpp"
|
||||
#include "groundcover.hpp"
|
||||
#include "postprocessor.hpp"
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
|
@ -198,6 +201,17 @@ namespace MWRender
|
|||
, mFieldOfViewOverridden(false)
|
||||
, mFieldOfViewOverride(0.f)
|
||||
{
|
||||
auto ext = osg::GLExtensions::Get(0, false);
|
||||
bool reverseZ = ext && ext->isClipControlSupported;
|
||||
|
||||
if (getenv("OPENMW_DISABLE_REVERSEZ") != nullptr)
|
||||
reverseZ = false;
|
||||
|
||||
if (reverseZ)
|
||||
Log(Debug::Info) << "Using reverse-z depth buffer";
|
||||
else
|
||||
Log(Debug::Info) << "Using standard depth buffer";
|
||||
|
||||
auto lightingMethod = SceneUtil::LightManager::getLightingMethodFromString(Settings::Manager::getString("lighting method", "Shaders"));
|
||||
|
||||
resourceSystem->getSceneManager()->setParticleSystemMask(MWRender::Mask_ParticleSystem);
|
||||
|
@ -216,6 +230,7 @@ namespace MWRender
|
|||
resourceSystem->getSceneManager()->setSpecularMapPattern(Settings::Manager::getString("specular map pattern", "Shaders"));
|
||||
resourceSystem->getSceneManager()->setApplyLightingToEnvMaps(Settings::Manager::getBool("apply lighting to environment maps", "Shaders"));
|
||||
resourceSystem->getSceneManager()->setConvertAlphaTestToAlphaToCoverage(Settings::Manager::getBool("antialias alpha test", "Shaders") && Settings::Manager::getInt("antialiasing", "Video") > 1);
|
||||
resourceSystem->getSceneManager()->setReverseZ(reverseZ);
|
||||
|
||||
// Let LightManager choose which backend to use based on our hint. For methods besides legacy lighting, this depends on support for various OpenGL extensions.
|
||||
osg::ref_ptr<SceneUtil::LightManager> sceneRoot = new SceneUtil::LightManager(lightingMethod == SceneUtil::LightingMethod::FFP);
|
||||
|
@ -242,7 +257,7 @@ namespace MWRender
|
|||
if (Settings::Manager::getBool("object shadows", "Shadows"))
|
||||
shadowCastingTraversalMask |= (Mask_Object|Mask_Static);
|
||||
|
||||
mShadowManager.reset(new SceneUtil::ShadowManager(sceneRoot, mRootNode, shadowCastingTraversalMask, indoorShadowCastingTraversalMask, mResourceSystem->getSceneManager()->getShaderManager()));
|
||||
mShadowManager.reset(new SceneUtil::ShadowManager(sceneRoot, mRootNode, shadowCastingTraversalMask, indoorShadowCastingTraversalMask, mResourceSystem->getSceneManager()->getShaderManager(), reverseZ));
|
||||
|
||||
Shader::ShaderManager::DefineMap shadowDefines = mShadowManager->getShadowDefines();
|
||||
Shader::ShaderManager::DefineMap lightDefines = sceneRoot->getLightDefines();
|
||||
|
@ -267,6 +282,8 @@ namespace MWRender
|
|||
globalDefines["groundcoverStompMode"] = std::to_string(std::clamp(Settings::Manager::getInt("stomp mode", "Groundcover"), 0, 2));
|
||||
globalDefines["groundcoverStompIntensity"] = std::to_string(std::clamp(Settings::Manager::getInt("stomp intensity", "Groundcover"), 0, 2));
|
||||
|
||||
globalDefines["reverseZ"] = reverseZ ? "1" : "0";
|
||||
|
||||
// It is unnecessary to stop/start the viewer as no frames are being rendered yet.
|
||||
mResourceSystem->getSceneManager()->getShaderManager().setGlobalDefines(globalDefines);
|
||||
|
||||
|
@ -413,6 +430,7 @@ namespace MWRender
|
|||
mViewer->getCamera()->setCullMask(~(Mask_UpdateVisitor|Mask_SimpleWater));
|
||||
NifOsg::Loader::setHiddenNodeMask(Mask_UpdateVisitor);
|
||||
NifOsg::Loader::setIntersectionDisabledNodeMask(Mask_Effect);
|
||||
NifOsg::Loader::setReverseZ(reverseZ);
|
||||
Nif::NIFFile::setLoadUnsupportedFiles(Settings::Manager::getBool("load unsupported nif files", "Models"));
|
||||
|
||||
mNearClip = Settings::Manager::getFloat("near clip", "Camera");
|
||||
|
@ -434,6 +452,18 @@ namespace MWRender
|
|||
|
||||
mUniformNear = mRootNode->getOrCreateStateSet()->getUniform("near");
|
||||
mUniformFar = mRootNode->getOrCreateStateSet()->getUniform("far");
|
||||
|
||||
if (reverseZ)
|
||||
{
|
||||
auto depth = SceneUtil::createDepth(reverseZ);
|
||||
osg::ref_ptr<osg::ClipControl> clipcontrol = new osg::ClipControl(osg::ClipControl::LOWER_LEFT, osg::ClipControl::ZERO_TO_ONE);
|
||||
mViewer->getCamera()->setClearDepth(0.0);
|
||||
mRootNode->getOrCreateStateSet()->setAttributeAndModes(depth, osg::StateAttribute::ON);
|
||||
mRootNode->getOrCreateStateSet()->setAttributeAndModes(clipcontrol, osg::StateAttribute::ON);
|
||||
}
|
||||
|
||||
mPostProcessor.reset(new PostProcessor(viewer, mRootNode));
|
||||
|
||||
updateProjectionMatrix();
|
||||
}
|
||||
|
||||
|
@ -1066,7 +1096,20 @@ namespace MWRender
|
|||
float fov = mFieldOfView;
|
||||
if (mFieldOfViewOverridden)
|
||||
fov = mFieldOfViewOverride;
|
||||
mViewer->getCamera()->setProjectionMatrixAsPerspective(fov, aspect, mNearClip, mViewDistance);
|
||||
|
||||
if (mResourceSystem->getSceneManager()->getReverseZ())
|
||||
{
|
||||
mViewer->getCamera()->setProjectionMatrix(SceneUtil::getReversedZProjectionMatrixAsPerspectiveInf(fov, aspect, mNearClip));
|
||||
float linearFac = -mNearClip / (mViewDistance - mNearClip) - 1.0;
|
||||
mRootNode->getOrCreateStateSet()->getOrCreateUniform("linearFac", osg::Uniform::FLOAT, 1)->set(linearFac);
|
||||
|
||||
osg::Matrix shadowProj = osg::Matrix::perspective(fov, aspect, mNearClip, mViewDistance);
|
||||
mViewer->getCamera()->setUserValue("shadowProj", shadowProj);
|
||||
mViewer->getCamera()->setUserValue("near", static_cast<double>(mNearClip));
|
||||
mViewer->getCamera()->setUserValue("far", static_cast<double>(mViewDistance));
|
||||
}
|
||||
else
|
||||
mViewer->getCamera()->setProjectionMatrixAsPerspective(fov, aspect, mNearClip, mViewDistance);
|
||||
|
||||
mUniformNear->set(mNearClip);
|
||||
mUniformFar->set(mViewDistance);
|
||||
|
|
|
@ -89,6 +89,7 @@ namespace MWRender
|
|||
class RecastMesh;
|
||||
class ObjectPaging;
|
||||
class Groundcover;
|
||||
class PostProcessor;
|
||||
|
||||
class RenderingManager : public MWRender::RenderingInterface
|
||||
{
|
||||
|
@ -287,6 +288,7 @@ namespace MWRender
|
|||
std::unique_ptr<ScreenshotManager> mScreenshotManager;
|
||||
std::unique_ptr<EffectManager> mEffectManager;
|
||||
std::unique_ptr<SceneUtil::ShadowManager> mShadowManager;
|
||||
std::unique_ptr<PostProcessor> mPostProcessor;
|
||||
osg::ref_ptr<NpcAnimation> mPlayerAnimation;
|
||||
osg::ref_ptr<SceneUtil::PositionAttitudeTransform> mPlayerNode;
|
||||
std::unique_ptr<Camera> mCamera;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <components/resource/resourcesystem.hpp>
|
||||
#include <components/resource/scenemanager.hpp>
|
||||
#include <components/fallback/fallback.hpp>
|
||||
#include <components/sceneutil/util.hpp>
|
||||
|
||||
#include "vismask.hpp"
|
||||
|
||||
|
@ -55,7 +56,7 @@ namespace
|
|||
stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
|
||||
stateset->setTextureAttributeAndModes(0, textures[0], osg::StateAttribute::ON);
|
||||
|
||||
osg::ref_ptr<osg::Depth> depth (new osg::Depth);
|
||||
auto depth = SceneUtil::createDepth(resourceSystem->getSceneManager()->getReverseZ());
|
||||
depth->setWriteMask(false);
|
||||
stateset->setAttributeAndModes(depth, osg::StateAttribute::ON);
|
||||
|
||||
|
|
|
@ -473,7 +473,7 @@ const float CelestialBody::mDistance = 1000.0f;
|
|||
class Sun : public CelestialBody
|
||||
{
|
||||
public:
|
||||
Sun(osg::Group* parentNode, Resource::ImageManager& imageManager)
|
||||
Sun(osg::Group* parentNode, Resource::ImageManager& imageManager, bool reverseZ)
|
||||
: CelestialBody(parentNode, 1.0f, 1, Mask_Sun)
|
||||
, mUpdater(new Updater)
|
||||
{
|
||||
|
@ -502,8 +502,8 @@ public:
|
|||
|
||||
mTransform->addChild(queryNode);
|
||||
|
||||
mOcclusionQueryVisiblePixels = createOcclusionQueryNode(queryNode, true);
|
||||
mOcclusionQueryTotalPixels = createOcclusionQueryNode(queryNode, false);
|
||||
mOcclusionQueryVisiblePixels = createOcclusionQueryNode(queryNode, true, reverseZ);
|
||||
mOcclusionQueryTotalPixels = createOcclusionQueryNode(queryNode, false, reverseZ);
|
||||
|
||||
createSunFlash(imageManager);
|
||||
createSunGlare();
|
||||
|
@ -556,7 +556,7 @@ private:
|
|||
};
|
||||
|
||||
/// @param queryVisible If true, queries the amount of visible pixels. If false, queries the total amount of pixels.
|
||||
osg::ref_ptr<osg::OcclusionQueryNode> createOcclusionQueryNode(osg::Group* parent, bool queryVisible)
|
||||
osg::ref_ptr<osg::OcclusionQueryNode> createOcclusionQueryNode(osg::Group* parent, bool queryVisible, bool reverseZ)
|
||||
{
|
||||
osg::ref_ptr<osg::OcclusionQueryNode> oqn = new osg::OcclusionQueryNode;
|
||||
oqn->setQueriesEnabled(true);
|
||||
|
@ -594,13 +594,13 @@ private:
|
|||
osg::StateSet* queryStateSet = new osg::StateSet;
|
||||
if (queryVisible)
|
||||
{
|
||||
osg::ref_ptr<osg::Depth> depth (new osg::Depth);
|
||||
depth->setFunction(osg::Depth::LEQUAL);
|
||||
auto depth = SceneUtil::createDepth(reverseZ);
|
||||
// This is a trick to make fragments written by the query always use the maximum depth value,
|
||||
// without having to retrieve the current far clipping distance.
|
||||
// We want the sun glare to be "infinitely" far away.
|
||||
depth->setZNear(1.0);
|
||||
depth->setZFar(1.0);
|
||||
float far = reverseZ ? 0.0 : 1.0;
|
||||
depth->setZNear(far);
|
||||
depth->setZFar(far);
|
||||
depth->setWriteMask(false);
|
||||
queryStateSet->setAttributeAndModes(depth, osg::StateAttribute::ON);
|
||||
}
|
||||
|
@ -1188,7 +1188,8 @@ void SkyManager::create()
|
|||
mAtmosphereNightUpdater = new AtmosphereNightUpdater(mSceneManager->getImageManager());
|
||||
atmosphereNight->addUpdateCallback(mAtmosphereNightUpdater);
|
||||
|
||||
mSun.reset(new Sun(mEarlyRenderBinRoot, *mSceneManager->getImageManager()));
|
||||
bool reverseZ = mSceneManager->getReverseZ();
|
||||
mSun.reset(new Sun(mEarlyRenderBinRoot, *mSceneManager->getImageManager(), reverseZ));
|
||||
|
||||
mMasser.reset(new Moon(mEarlyRenderBinRoot, *mSceneManager->getImageManager(), Fallback::Map::getFloat("Moons_Masser_Size")/125, Moon::Type_Masser));
|
||||
mSecunda.reset(new Moon(mEarlyRenderBinRoot, *mSceneManager->getImageManager(), Fallback::Map::getFloat("Moons_Secunda_Size")/125, Moon::Type_Secunda));
|
||||
|
@ -1209,7 +1210,7 @@ void SkyManager::create()
|
|||
mCloudMesh2->addUpdateCallback(mCloudUpdater2);
|
||||
mCloudMesh2->setNodeMask(0);
|
||||
|
||||
osg::ref_ptr<osg::Depth> depth = new osg::Depth;
|
||||
auto depth = SceneUtil::createDepth(reverseZ);
|
||||
depth->setWriteMask(false);
|
||||
mEarlyRenderBinRoot->getOrCreateStateSet()->setAttributeAndModes(depth, osg::StateAttribute::ON);
|
||||
mEarlyRenderBinRoot->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
|
||||
|
|
|
@ -273,6 +273,7 @@ public:
|
|||
|
||||
void setDefaults(osg::Camera* camera) override
|
||||
{
|
||||
camera->setClearDepth(1.0);
|
||||
camera->setReferenceFrame(osg::Camera::RELATIVE_RF);
|
||||
camera->setSmallFeatureCullingPixelSize(Settings::Manager::getInt("small feature culling pixel size", "Water"));
|
||||
camera->setName("RefractionCamera");
|
||||
|
@ -338,6 +339,7 @@ public:
|
|||
|
||||
void setDefaults(osg::Camera* camera) override
|
||||
{
|
||||
camera->setClearDepth(1.0);
|
||||
camera->setReferenceFrame(osg::Camera::RELATIVE_RF);
|
||||
camera->setSmallFeatureCullingPixelSize(Settings::Manager::getInt("small feature culling pixel size", "Water"));
|
||||
camera->setName("ReflectionCamera");
|
||||
|
@ -544,7 +546,7 @@ osg::Node* Water::getRefractionNode()
|
|||
|
||||
void Water::createSimpleWaterStateSet(osg::Node* node, float alpha)
|
||||
{
|
||||
osg::ref_ptr<osg::StateSet> stateset = SceneUtil::createSimpleWaterStateSet(alpha, MWRender::RenderBin_Water);
|
||||
osg::ref_ptr<osg::StateSet> stateset = SceneUtil::createSimpleWaterStateSet(alpha, MWRender::RenderBin_Water, mResourceSystem->getSceneManager()->getReverseZ());
|
||||
|
||||
node->setStateSet(stateset);
|
||||
node->setUpdateCallback(nullptr);
|
||||
|
|
|
@ -226,6 +226,18 @@ namespace NifOsg
|
|||
return sIntersectionDisabledNodeMask;
|
||||
}
|
||||
|
||||
bool Loader::sReverseZ = false;
|
||||
|
||||
void Loader::setReverseZ(bool reverseZ)
|
||||
{
|
||||
sReverseZ = reverseZ;
|
||||
}
|
||||
|
||||
bool Loader::getReverseZ()
|
||||
{
|
||||
return sReverseZ;
|
||||
}
|
||||
|
||||
class LoaderImpl
|
||||
{
|
||||
public:
|
||||
|
@ -1823,7 +1835,7 @@ namespace NifOsg
|
|||
// Depth test flag
|
||||
stateset->setMode(GL_DEPTH_TEST, zprop->flags&1 ? osg::StateAttribute::ON
|
||||
: osg::StateAttribute::OFF);
|
||||
osg::ref_ptr<osg::Depth> depth = new osg::Depth;
|
||||
auto depth = SceneUtil::createDepth(Loader::getReverseZ());
|
||||
// Depth write flag
|
||||
depth->setWriteMask((zprop->flags>>1)&1);
|
||||
// Morrowind ignores depth test function
|
||||
|
|
|
@ -51,10 +51,14 @@ namespace NifOsg
|
|||
static void setIntersectionDisabledNodeMask(unsigned int mask);
|
||||
static unsigned int getIntersectionDisabledNodeMask();
|
||||
|
||||
static void setReverseZ(bool reverseZ);
|
||||
static bool getReverseZ();
|
||||
|
||||
private:
|
||||
static unsigned int sHiddenNodeMask;
|
||||
static unsigned int sIntersectionDisabledNodeMask;
|
||||
static bool sShowMarkers;
|
||||
static bool sReverseZ;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -275,6 +275,16 @@ namespace Resource
|
|||
return mClampLighting;
|
||||
}
|
||||
|
||||
void SceneManager::setReverseZ(bool reverseZ)
|
||||
{
|
||||
mReverseZ = reverseZ;
|
||||
}
|
||||
|
||||
bool SceneManager::getReverseZ() const
|
||||
{
|
||||
return mReverseZ;
|
||||
}
|
||||
|
||||
void SceneManager::setAutoUseNormalMaps(bool use)
|
||||
{
|
||||
mAutoUseNormalMaps = use;
|
||||
|
|
|
@ -92,6 +92,9 @@ namespace Resource
|
|||
void setClampLighting(bool clamp);
|
||||
bool getClampLighting() const;
|
||||
|
||||
void setReverseZ(bool reverseZ);
|
||||
bool getReverseZ() const;
|
||||
|
||||
/// @see ShaderVisitor::setAutoUseNormalMaps
|
||||
void setAutoUseNormalMaps(bool use);
|
||||
|
||||
|
@ -202,6 +205,7 @@ namespace Resource
|
|||
SceneUtil::LightingMethod mLightingMethod;
|
||||
SceneUtil::LightManager::SupportedMethods mSupportedLightingMethods;
|
||||
bool mConvertAlphaTestToAlphaToCoverage;
|
||||
bool mReverseZ;
|
||||
|
||||
osg::ref_ptr<MultiObjectCache> mInstanceCache;
|
||||
|
||||
|
|
|
@ -23,10 +23,13 @@
|
|||
#include <osg/Geometry>
|
||||
#include <osg/io_utils>
|
||||
#include <osg/Depth>
|
||||
#include <osg/ClipControl>
|
||||
|
||||
#include <sstream>
|
||||
#include "shadowsbin.hpp"
|
||||
|
||||
#include <components/sceneutil/util.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace osgShadow;
|
||||
|
@ -347,6 +350,11 @@ void VDSMCameraCullCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
|
|||
_projectionMatrix = cv->getProjectionMatrix();
|
||||
}
|
||||
|
||||
bool isOrthographicViewFrustum(const osg::Matrix& m)
|
||||
{
|
||||
return m(0,3)==0.0 && m(1,3)==0.0 && m(2,3)==0.0;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
MWShadowTechnique::ComputeLightSpaceBounds::ComputeLightSpaceBounds(osg::Viewport* viewport, const osg::Matrixd& projectionMatrix, osg::Matrixd& viewMatrix) :
|
||||
|
@ -890,6 +898,16 @@ void SceneUtil::MWShadowTechnique::disableFrontFaceCulling()
|
|||
}
|
||||
}
|
||||
|
||||
void SceneUtil::MWShadowTechnique::enableReverseZ()
|
||||
{
|
||||
_reverseZ = true;
|
||||
}
|
||||
|
||||
void SceneUtil::MWShadowTechnique::disableReverseZ()
|
||||
{
|
||||
_reverseZ = false;
|
||||
}
|
||||
|
||||
void SceneUtil::MWShadowTechnique::setupCastingShader(Shader::ShaderManager & shaderManager)
|
||||
{
|
||||
// This can't be part of the constructor as OSG mandates that there be a trivial constructor available
|
||||
|
@ -970,6 +988,9 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv)
|
|||
return;
|
||||
}
|
||||
|
||||
osg::Matrix shadowProj;
|
||||
cv.getCurrentCamera()->getUserValue("shadowProj", shadowProj);
|
||||
|
||||
ViewDependentData* vdd = getViewDependentData(&cv);
|
||||
|
||||
if (!vdd)
|
||||
|
@ -985,34 +1006,41 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv)
|
|||
|
||||
osg::CullSettings::ComputeNearFarMode cachedNearFarMode = cv.getComputeNearFarMode();
|
||||
|
||||
osg::RefMatrix& viewProjectionMatrix = *cv.getProjectionMatrix();
|
||||
|
||||
// check whether this main views projection is perspective or orthographic
|
||||
bool orthographicViewFrustum = viewProjectionMatrix(0,3)==0.0 &&
|
||||
viewProjectionMatrix(1,3)==0.0 &&
|
||||
viewProjectionMatrix(2,3)==0.0;
|
||||
|
||||
double minZNear = 0.0;
|
||||
double maxZFar = dbl_max;
|
||||
bool orthographicViewFrustum;
|
||||
|
||||
if (cachedNearFarMode==osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR)
|
||||
if (_reverseZ)
|
||||
{
|
||||
double left, right, top, bottom;
|
||||
if (orthographicViewFrustum)
|
||||
{
|
||||
viewProjectionMatrix.getOrtho(left, right, bottom, top, minZNear, maxZFar);
|
||||
}
|
||||
else
|
||||
{
|
||||
viewProjectionMatrix.getFrustum(left, right, bottom, top, minZNear, maxZFar);
|
||||
}
|
||||
OSG_INFO<<"minZNear="<<minZNear<<", maxZFar="<<maxZFar<<std::endl;
|
||||
cv.getCurrentCamera()->getUserValue("near", minZNear);
|
||||
cv.getCurrentCamera()->getUserValue("far", maxZFar);
|
||||
orthographicViewFrustum = isOrthographicViewFrustum(shadowProj);
|
||||
}
|
||||
|
||||
// set the compute near/far mode to the highest quality setting to ensure we push the near plan out as far as possible
|
||||
if (settings->getComputeNearFarModeOverride()!=osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR)
|
||||
else
|
||||
{
|
||||
cv.setComputeNearFarMode(settings->getComputeNearFarModeOverride());
|
||||
osg::RefMatrix& viewProjectionMatrix = *cv.getProjectionMatrix();
|
||||
|
||||
// check whether this main views projection is perspective or orthographic
|
||||
orthographicViewFrustum = isOrthographicViewFrustum(viewProjectionMatrix);
|
||||
|
||||
if (cachedNearFarMode==osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR)
|
||||
{
|
||||
double left, right, top, bottom;
|
||||
if (orthographicViewFrustum)
|
||||
{
|
||||
viewProjectionMatrix.getOrtho(left, right, bottom, top, minZNear, maxZFar);
|
||||
}
|
||||
else
|
||||
{
|
||||
viewProjectionMatrix.getFrustum(left, right, bottom, top, minZNear, maxZFar);
|
||||
}
|
||||
}
|
||||
|
||||
// set the compute near/far mode to the highest quality setting to ensure we push the near plan out as far as possible
|
||||
if (settings->getComputeNearFarModeOverride()!=osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR)
|
||||
{
|
||||
cv.setComputeNearFarMode(settings->getComputeNearFarModeOverride());
|
||||
}
|
||||
}
|
||||
|
||||
// 1. Traverse main scene graph
|
||||
|
@ -1024,6 +1052,9 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv)
|
|||
|
||||
cv.popStateSet();
|
||||
|
||||
if (_reverseZ)
|
||||
cv.pushProjectionMatrix(new osg::RefMatrix(shadowProj));
|
||||
|
||||
if (cv.getComputeNearFarMode()!=osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR)
|
||||
{
|
||||
OSG_INFO<<"Just done main subgraph traversak"<<std::endl;
|
||||
|
@ -1063,7 +1094,8 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv)
|
|||
}
|
||||
|
||||
// return compute near far mode back to it's original settings
|
||||
cv.setComputeNearFarMode(cachedNearFarMode);
|
||||
if (!_reverseZ)
|
||||
cv.setComputeNearFarMode(cachedNearFarMode);
|
||||
|
||||
OSG_INFO<<"frustum.eye="<<frustum.eye<<", frustum.centerNearPlane, "<<frustum.centerNearPlane<<" distance = "<<(frustum.eye-frustum.centerNearPlane).length()<<std::endl;
|
||||
|
||||
|
@ -1448,6 +1480,8 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv)
|
|||
prepareStateSetForRenderingShadow(*vdd, cv.getTraversalNumber());
|
||||
}
|
||||
|
||||
if (_reverseZ)
|
||||
cv.popProjectionMatrix();
|
||||
// OSG_NOTICE<<"End of shadow setup Projection matrix "<<*cv.getProjectionMatrix()<<std::endl;
|
||||
}
|
||||
|
||||
|
@ -1636,6 +1670,9 @@ void MWShadowTechnique::createShaders()
|
|||
_shadowCastingStateSet->addUniform(new osg::Uniform("alphaTestShadows", false));
|
||||
osg::ref_ptr<osg::Depth> depth = new osg::Depth;
|
||||
depth->setWriteMask(true);
|
||||
osg::ref_ptr<osg::ClipControl> clipcontrol = new osg::ClipControl(osg::ClipControl::LOWER_LEFT, osg::ClipControl::NEGATIVE_ONE_TO_ONE);
|
||||
if (_reverseZ)
|
||||
_shadowCastingStateSet->setAttribute(clipcontrol, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
|
||||
_shadowCastingStateSet->setAttribute(depth, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
|
||||
_shadowCastingStateSet->setMode(GL_DEPTH_CLAMP, osg::StateAttribute::ON);
|
||||
|
||||
|
|
|
@ -85,6 +85,10 @@ namespace SceneUtil {
|
|||
|
||||
virtual void disableFrontFaceCulling();
|
||||
|
||||
virtual void enableReverseZ();
|
||||
|
||||
virtual void disableReverseZ();
|
||||
|
||||
virtual void setupCastingShader(Shader::ShaderManager &shaderManager);
|
||||
|
||||
class ComputeLightSpaceBounds : public osg::NodeVisitor, public osg::CullStack
|
||||
|
@ -266,6 +270,8 @@ namespace SceneUtil {
|
|||
|
||||
float _shadowFadeStart = 0.0;
|
||||
|
||||
bool _reverseZ = false;
|
||||
|
||||
class DebugHUD final : public osg::Referenced
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
|
||||
#include <iterator>
|
||||
|
||||
#include <components/sceneutil/util.hpp>
|
||||
|
||||
using namespace osgUtil;
|
||||
|
||||
namespace SceneUtil
|
||||
|
@ -107,6 +109,7 @@ void Optimizer::optimize(osg::Node* node, unsigned int options)
|
|||
MergeGeometryVisitor mgv(this);
|
||||
mgv.setTargetMaximumNumberOfVertices(1000000);
|
||||
mgv.setMergeAlphaBlending(_mergeAlphaBlending);
|
||||
mgv.setReverseZ(_reverseZ);
|
||||
mgv.setViewPoint(_viewPoint);
|
||||
node->accept(mgv);
|
||||
|
||||
|
@ -1560,7 +1563,7 @@ bool Optimizer::MergeGeometryVisitor::mergeGroup(osg::Group& group)
|
|||
}
|
||||
if (_alphaBlendingActive && _mergeAlphaBlending && !geom->getStateSet())
|
||||
{
|
||||
osg::Depth* d = new osg::Depth;
|
||||
auto d = createDepth(_reverseZ);
|
||||
d->setWriteMask(0);
|
||||
geom->getOrCreateStateSet()->setAttribute(d);
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ class Optimizer
|
|||
|
||||
public:
|
||||
|
||||
Optimizer() : _mergeAlphaBlending(false) {}
|
||||
Optimizer() : _mergeAlphaBlending(false), _reverseZ(false) {}
|
||||
virtual ~Optimizer() {}
|
||||
|
||||
enum OptimizationOptions
|
||||
|
@ -119,6 +119,7 @@ class Optimizer
|
|||
};
|
||||
|
||||
void setMergeAlphaBlending(bool merge) { _mergeAlphaBlending = merge; }
|
||||
void setReverseZ(bool reverseZ) { _reverseZ = reverseZ; }
|
||||
void setViewPoint(const osg::Vec3f& viewPoint) { _viewPoint = viewPoint; }
|
||||
|
||||
/** Reset internal data to initial state - the getPermissibleOptionsMap is cleared.*/
|
||||
|
@ -257,6 +258,7 @@ class Optimizer
|
|||
|
||||
osg::Vec3f _viewPoint;
|
||||
bool _mergeAlphaBlending;
|
||||
bool _reverseZ;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -377,12 +379,18 @@ class Optimizer
|
|||
/// default to traversing all children.
|
||||
MergeGeometryVisitor(Optimizer* optimizer=0) :
|
||||
BaseOptimizerVisitor(optimizer, MERGE_GEOMETRY),
|
||||
_targetMaximumNumberOfVertices(10000), _alphaBlendingActive(false), _mergeAlphaBlending(false) {}
|
||||
_targetMaximumNumberOfVertices(10000), _alphaBlendingActive(false), _mergeAlphaBlending(false), _reverseZ(false) {}
|
||||
|
||||
void setMergeAlphaBlending(bool merge)
|
||||
{
|
||||
_mergeAlphaBlending = merge;
|
||||
}
|
||||
|
||||
void setReverseZ(bool reverseZ)
|
||||
{
|
||||
_reverseZ = reverseZ;
|
||||
}
|
||||
|
||||
void setViewPoint(const osg::Vec3f& viewPoint)
|
||||
{
|
||||
_viewPoint = viewPoint;
|
||||
|
@ -421,6 +429,7 @@ class Optimizer
|
|||
std::vector<osg::StateSet*> _stateSetStack;
|
||||
bool _alphaBlendingActive;
|
||||
bool _mergeAlphaBlending;
|
||||
bool _reverseZ;
|
||||
osg::Vec3f _viewPoint;
|
||||
};
|
||||
|
||||
|
|
|
@ -94,10 +94,12 @@ namespace SceneUtil
|
|||
}
|
||||
}
|
||||
|
||||
ShadowManager::ShadowManager(osg::ref_ptr<osg::Group> sceneRoot, osg::ref_ptr<osg::Group> rootNode, unsigned int outdoorShadowCastingMask, unsigned int indoorShadowCastingMask, Shader::ShaderManager &shaderManager) : mShadowedScene(new osgShadow::ShadowedScene),
|
||||
mShadowTechnique(new MWShadowTechnique),
|
||||
mOutdoorShadowCastingMask(outdoorShadowCastingMask),
|
||||
mIndoorShadowCastingMask(indoorShadowCastingMask)
|
||||
ShadowManager::ShadowManager(osg::ref_ptr<osg::Group> sceneRoot, osg::ref_ptr<osg::Group> rootNode, unsigned int outdoorShadowCastingMask, unsigned int indoorShadowCastingMask, Shader::ShaderManager &shaderManager, bool reverseZ)
|
||||
: mShadowedScene(new osgShadow::ShadowedScene)
|
||||
, mReverseZ(reverseZ)
|
||||
, mShadowTechnique(new MWShadowTechnique)
|
||||
, mOutdoorShadowCastingMask(outdoorShadowCastingMask)
|
||||
, mIndoorShadowCastingMask(indoorShadowCastingMask)
|
||||
{
|
||||
mShadowedScene->setShadowTechnique(mShadowTechnique);
|
||||
|
||||
|
@ -108,6 +110,9 @@ namespace SceneUtil
|
|||
mShadowSettings = mShadowedScene->getShadowSettings();
|
||||
setupShadowSettings();
|
||||
|
||||
if (mReverseZ)
|
||||
mShadowTechnique->enableReverseZ();
|
||||
|
||||
mShadowTechnique->setupCastingShader(shaderManager);
|
||||
|
||||
enableOutdoorMode();
|
||||
|
@ -180,4 +185,9 @@ namespace SceneUtil
|
|||
mShadowTechnique->enableShadows();
|
||||
mShadowSettings->setCastsShadowTraversalMask(mOutdoorShadowCastingMask);
|
||||
}
|
||||
|
||||
bool ShadowManager::getReverseZ() const
|
||||
{
|
||||
return mReverseZ;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace SceneUtil
|
|||
|
||||
static Shader::ShaderManager::DefineMap getShadowsDisabledDefines();
|
||||
|
||||
ShadowManager(osg::ref_ptr<osg::Group> sceneRoot, osg::ref_ptr<osg::Group> rootNode, unsigned int outdoorShadowCastingMask, unsigned int indoorShadowCastingMask, Shader::ShaderManager &shaderManager);
|
||||
ShadowManager(osg::ref_ptr<osg::Group> sceneRoot, osg::ref_ptr<osg::Group> rootNode, unsigned int outdoorShadowCastingMask, unsigned int indoorShadowCastingMask, Shader::ShaderManager &shaderManager, bool reverseZ);
|
||||
|
||||
void setupShadowSettings();
|
||||
|
||||
|
@ -26,8 +26,11 @@ namespace SceneUtil
|
|||
void enableIndoorMode();
|
||||
|
||||
void enableOutdoorMode();
|
||||
|
||||
bool getReverseZ() const;
|
||||
protected:
|
||||
bool mEnableShadows;
|
||||
bool mReverseZ;
|
||||
|
||||
osg::ref_ptr<osgShadow::ShadowedScene> mShadowedScene;
|
||||
osg::ref_ptr<osgShadow::ShadowSettings> mShadowSettings;
|
||||
|
|
|
@ -285,4 +285,43 @@ bool attachAlphaToCoverageFriendlyFramebufferToCamera(osg::Camera* camera, osg::
|
|||
return addMSAAIntermediateTarget;
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Depth> createDepth(bool reverseZ)
|
||||
{
|
||||
static osg::Depth::Function func = reverseZ ? osg::Depth::GEQUAL : osg::Depth::LEQUAL;
|
||||
return new osg::Depth(func);
|
||||
}
|
||||
|
||||
osg::Matrix getReversedZProjectionMatrixAsPerspectiveInf(double fov, double aspect, double near)
|
||||
{
|
||||
double A = 1.0/std::tan(osg::DegreesToRadians(fov)/2.0);
|
||||
return osg::Matrix(
|
||||
A/aspect, 0, 0, 0,
|
||||
0, A, 0, 0,
|
||||
0, 0, 0, -1,
|
||||
0, 0, near, 0
|
||||
);
|
||||
}
|
||||
|
||||
osg::Matrix getReversedZProjectionMatrixAsPerspective(double fov, double aspect, double near, double far)
|
||||
{
|
||||
double A = 1.0/std::tan(osg::DegreesToRadians(fov)/2.0);
|
||||
return osg::Matrix(
|
||||
A/aspect, 0, 0, 0,
|
||||
0, A, 0, 0,
|
||||
0, 0, far/(far-near)-1.0, -1,
|
||||
0, 0, -(far*near)/(far - near), 0
|
||||
);
|
||||
}
|
||||
|
||||
osg::Matrix getReversedZProjectionMatrixAsOrtho(double left, double right, double bottom, double top, double near, double far)
|
||||
{
|
||||
return osg::Matrix(
|
||||
2/(right-left), 0, 0, 0,
|
||||
0, 2/(top-bottom), 0, 0,
|
||||
0, 0, 1/(far-near), 0,
|
||||
(right+left)/(left-right), (top+bottom)/(bottom-top), far/(far-near), 1
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <osg/NodeCallback>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/Vec4f>
|
||||
#include <osg/Depth>
|
||||
|
||||
#include <components/resource/resourcesystem.hpp>
|
||||
|
||||
|
@ -64,6 +65,23 @@ namespace SceneUtil
|
|||
|
||||
// Alpha-to-coverage requires a multisampled framebuffer, so we need to set that up for RTTs
|
||||
bool attachAlphaToCoverageFriendlyFramebufferToCamera(osg::Camera* camera, osg::Camera::BufferComponent buffer, osg::Texture* texture, unsigned int level = 0, unsigned int face = 0, bool mipMapGeneration = false);
|
||||
|
||||
// Returns a suitable depth state attribute dependent on whether a reverse-z
|
||||
// depth buffer is in use.
|
||||
osg::ref_ptr<osg::Depth> createDepth(bool reverseZ);
|
||||
|
||||
// Returns a perspective projection matrix for use with a reversed z-buffer
|
||||
// and an infinite far plane. This is derived by mapping the default z-range
|
||||
// of [0,1] to [1,0], then taking the limit as far plane approaches
|
||||
// infinity.
|
||||
osg::Matrix getReversedZProjectionMatrixAsPerspectiveInf(double fov, double aspect, double near);
|
||||
|
||||
// Returns a perspective projection matrix for use with a reversed z-buffer.
|
||||
osg::Matrix getReversedZProjectionMatrixAsPerspective(double fov, double aspect, double near, double far);
|
||||
|
||||
// Returns an orthographic projection matrix for use with a reversed z-buffer.
|
||||
osg::Matrix getReversedZProjectionMatrixAsOrtho(double left, double right, double bottom, double top, double near, double far);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include <osg/Material>
|
||||
#include <osg/StateSet>
|
||||
|
||||
#include "util.hpp"
|
||||
|
||||
namespace SceneUtil
|
||||
{
|
||||
// disable nonsense test against a worldsize bb what will always pass
|
||||
|
@ -62,7 +64,7 @@ namespace SceneUtil
|
|||
return waterGeom;
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::StateSet> createSimpleWaterStateSet(float alpha, int renderBin)
|
||||
osg::ref_ptr<osg::StateSet> createSimpleWaterStateSet(float alpha, int renderBin, bool reverseZ)
|
||||
{
|
||||
osg::ref_ptr<osg::StateSet> stateset (new osg::StateSet);
|
||||
|
||||
|
@ -76,7 +78,7 @@ namespace SceneUtil
|
|||
stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
|
||||
stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
|
||||
|
||||
osg::ref_ptr<osg::Depth> depth (new osg::Depth);
|
||||
auto depth = createDepth(reverseZ);
|
||||
depth->setWriteMask(false);
|
||||
stateset->setAttributeAndModes(depth, osg::StateAttribute::ON);
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace SceneUtil
|
|||
{
|
||||
osg::ref_ptr<osg::Geometry> createWaterGeometry(float size, int segments, float textureRepeats);
|
||||
|
||||
osg::ref_ptr<osg::StateSet> createSimpleWaterStateSet(float alpha, int renderBin);
|
||||
osg::ref_ptr<osg::StateSet> createSimpleWaterStateSet(float alpha, int renderBin, bool reverseZ);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -163,7 +163,7 @@ std::vector<osg::ref_ptr<osg::StateSet> > ChunkManager::createPasses(float chunk
|
|||
|
||||
float blendmapScale = mStorage->getBlendmapScale(chunkSize);
|
||||
|
||||
return ::Terrain::createPasses(useShaders, &mSceneManager->getShaderManager(), layers, blendmapTextures, blendmapScale, blendmapScale);
|
||||
return ::Terrain::createPasses(useShaders, mSceneManager, layers, blendmapTextures, blendmapScale, blendmapScale);
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Node> ChunkManager::createChunk(float chunkSize, const osg::Vec2f &chunkCenter, unsigned char lod, unsigned int lodFlags, bool compile)
|
||||
|
@ -219,7 +219,7 @@ osg::ref_ptr<osg::Node> ChunkManager::createChunk(float chunkSize, const osg::Ve
|
|||
layer.mDiffuseMap = compositeMap->mTexture;
|
||||
layer.mParallax = false;
|
||||
layer.mSpecular = false;
|
||||
geometry->setPasses(::Terrain::createPasses(mSceneManager->getForceShaders() || !mSceneManager->getClampLighting(), &mSceneManager->getShaderManager(), std::vector<TextureLayer>(1, layer), std::vector<osg::ref_ptr<osg::Texture2D> >(), 1.f, 1.f));
|
||||
geometry->setPasses(::Terrain::createPasses(mSceneManager->getForceShaders() || !mSceneManager->getClampLighting(), mSceneManager, std::vector<TextureLayer>(1, layer), std::vector<osg::ref_ptr<osg::Texture2D> >(), 1.f, 1.f));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -7,7 +7,9 @@
|
|||
#include <osg/TexMat>
|
||||
#include <osg/BlendFunc>
|
||||
|
||||
#include <components/resource/scenemanager.hpp>
|
||||
#include <components/shader/shadermanager.hpp>
|
||||
#include <components/sceneutil/util.hpp>
|
||||
|
||||
#include <mutex>
|
||||
|
||||
|
@ -95,19 +97,18 @@ namespace
|
|||
class LequalDepth
|
||||
{
|
||||
public:
|
||||
static const osg::ref_ptr<osg::Depth>& value()
|
||||
static const osg::ref_ptr<osg::Depth>& value(bool reverseZ)
|
||||
{
|
||||
static LequalDepth instance;
|
||||
static LequalDepth instance(reverseZ);
|
||||
return instance.mValue;
|
||||
}
|
||||
|
||||
private:
|
||||
osg::ref_ptr<osg::Depth> mValue;
|
||||
|
||||
LequalDepth()
|
||||
: mValue(new osg::Depth)
|
||||
LequalDepth(bool reverseZ)
|
||||
: mValue(SceneUtil::createDepth(reverseZ))
|
||||
{
|
||||
mValue->setFunction(osg::Depth::LEQUAL);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -170,9 +171,10 @@ namespace
|
|||
|
||||
namespace Terrain
|
||||
{
|
||||
std::vector<osg::ref_ptr<osg::StateSet> > createPasses(bool useShaders, Shader::ShaderManager* shaderManager, const std::vector<TextureLayer> &layers,
|
||||
std::vector<osg::ref_ptr<osg::StateSet> > createPasses(bool useShaders, Resource::SceneManager* sceneManager, const std::vector<TextureLayer> &layers,
|
||||
const std::vector<osg::ref_ptr<osg::Texture2D> > &blendmaps, int blendmapScale, float layerTileSize)
|
||||
{
|
||||
Shader::ShaderManager* shaderManager = &sceneManager->getShaderManager();
|
||||
std::vector<osg::ref_ptr<osg::StateSet> > passes;
|
||||
|
||||
unsigned int blendmapIndex = 0;
|
||||
|
@ -195,7 +197,7 @@ namespace Terrain
|
|||
else
|
||||
{
|
||||
stateset->setAttributeAndModes(BlendFuncFirst::value(), osg::StateAttribute::ON);
|
||||
stateset->setAttributeAndModes(LequalDepth::value(), osg::StateAttribute::ON);
|
||||
stateset->setAttributeAndModes(LequalDepth::value(sceneManager->getReverseZ()), osg::StateAttribute::ON);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -238,7 +240,7 @@ namespace Terrain
|
|||
if (!vertexShader || !fragmentShader)
|
||||
{
|
||||
// Try again without shader. Error already logged by above
|
||||
return createPasses(false, shaderManager, layers, blendmaps, blendmapScale, layerTileSize);
|
||||
return createPasses(false, sceneManager, layers, blendmaps, blendmapScale, layerTileSize);
|
||||
}
|
||||
|
||||
stateset->setAttributeAndModes(shaderManager->getProgram(vertexShader, fragmentShader));
|
||||
|
|
|
@ -10,9 +10,9 @@ namespace osg
|
|||
class Texture2D;
|
||||
}
|
||||
|
||||
namespace Shader
|
||||
namespace Resource
|
||||
{
|
||||
class ShaderManager;
|
||||
class SceneManager;
|
||||
}
|
||||
|
||||
namespace Terrain
|
||||
|
@ -26,7 +26,7 @@ namespace Terrain
|
|||
bool mSpecular;
|
||||
};
|
||||
|
||||
std::vector<osg::ref_ptr<osg::StateSet> > createPasses(bool useShaders, Shader::ShaderManager* shaderManager,
|
||||
std::vector<osg::ref_ptr<osg::StateSet> > createPasses(bool useShaders, Resource::SceneManager* sceneManager,
|
||||
const std::vector<TextureLayer>& layers,
|
||||
const std::vector<osg::ref_ptr<osg::Texture2D> >& blendmaps, int blendmapScale, float layerTileSize);
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ set(SHADER_FILES
|
|||
water_fragment.glsl
|
||||
water_nm.png
|
||||
alpha.glsl
|
||||
depth.glsl
|
||||
objects_vertex.glsl
|
||||
objects_fragment.glsl
|
||||
terrain_vertex.glsl
|
||||
|
|
12
files/shaders/depth.glsl
Normal file
12
files/shaders/depth.glsl
Normal file
|
@ -0,0 +1,12 @@
|
|||
#if @reverseZ
|
||||
uniform float linearFac;
|
||||
#endif
|
||||
|
||||
float getLinearDepth(in vec4 viewPos)
|
||||
{
|
||||
#if @reverseZ
|
||||
return linearFac*viewPos.z;
|
||||
#else
|
||||
return gl_Position.z;
|
||||
#endif
|
||||
}
|
|
@ -39,6 +39,7 @@ centroid varying vec3 shadowDiffuseLighting;
|
|||
|
||||
#include "shadows_vertex.glsl"
|
||||
#include "lighting.glsl"
|
||||
#include "depth.glsl"
|
||||
|
||||
uniform float osg_SimulationTime;
|
||||
uniform mat4 osg_ViewMatrixInverse;
|
||||
|
@ -143,7 +144,7 @@ void main(void)
|
|||
else
|
||||
gl_Position = gl_ProjectionMatrix * viewPos;
|
||||
|
||||
linearDepth = gl_Position.z;
|
||||
linearDepth = getLinearDepth(viewPos);
|
||||
|
||||
#if (!PER_PIXEL_LIGHTING || @shadows_enabled)
|
||||
vec3 viewNormal = normalize((gl_NormalMatrix * rotation3(rotation) * gl_Normal).xyz);
|
||||
|
|
|
@ -32,6 +32,7 @@ varying vec3 passNormal;
|
|||
#include "vertexcolors.glsl"
|
||||
#include "shadows_vertex.glsl"
|
||||
#include "lighting.glsl"
|
||||
#include "depth.glsl"
|
||||
|
||||
void main(void)
|
||||
{
|
||||
|
@ -40,7 +41,7 @@ void main(void)
|
|||
vec4 viewPos = (gl_ModelViewMatrix * gl_Vertex);
|
||||
gl_ClipVertex = viewPos;
|
||||
euclideanDepth = length(viewPos.xyz);
|
||||
linearDepth = gl_Position.z;
|
||||
linearDepth = getLinearDepth(viewPos);
|
||||
|
||||
#if @diffuseMap
|
||||
diffuseMapUV = (gl_TextureMatrix[@diffuseMapUV] * gl_MultiTexCoord@diffuseMapUV).xy;
|
||||
|
|
|
@ -17,6 +17,7 @@ varying vec3 passViewPos;
|
|||
varying float passFalloff;
|
||||
|
||||
#include "vertexcolors.glsl"
|
||||
#include "depth.glsl"
|
||||
|
||||
void main(void)
|
||||
{
|
||||
|
@ -27,7 +28,7 @@ void main(void)
|
|||
#if @radialFog
|
||||
euclideanDepth = length(viewPos.xyz);
|
||||
#else
|
||||
linearDepth = gl_Position.z;
|
||||
linearDepth = getLinearDepth(viewPos);
|
||||
#endif
|
||||
|
||||
#if @diffuseMap
|
||||
|
|
|
@ -62,6 +62,7 @@ varying vec3 passNormal;
|
|||
#include "shadows_vertex.glsl"
|
||||
|
||||
#include "lighting.glsl"
|
||||
#include "depth.glsl"
|
||||
|
||||
void main(void)
|
||||
{
|
||||
|
@ -70,7 +71,7 @@ void main(void)
|
|||
vec4 viewPos = (gl_ModelViewMatrix * gl_Vertex);
|
||||
gl_ClipVertex = viewPos;
|
||||
euclideanDepth = length(viewPos.xyz);
|
||||
linearDepth = gl_Position.z;
|
||||
linearDepth = getLinearDepth(viewPos);
|
||||
|
||||
#if (@envMap || !PER_PIXEL_LIGHTING || @shadows_enabled)
|
||||
vec3 viewNormal = normalize((gl_NormalMatrix * gl_Normal).xyz);
|
||||
|
|
|
@ -25,6 +25,7 @@ varying vec3 passNormal;
|
|||
#include "shadows_vertex.glsl"
|
||||
|
||||
#include "lighting.glsl"
|
||||
#include "depth.glsl"
|
||||
|
||||
void main(void)
|
||||
{
|
||||
|
@ -33,7 +34,7 @@ void main(void)
|
|||
vec4 viewPos = (gl_ModelViewMatrix * gl_Vertex);
|
||||
gl_ClipVertex = viewPos;
|
||||
euclideanDepth = length(viewPos.xyz);
|
||||
linearDepth = gl_Position.z;
|
||||
linearDepth = getLinearDepth(viewPos);
|
||||
|
||||
#if (!PER_PIXEL_LIGHTING || @shadows_enabled)
|
||||
vec3 viewNormal = normalize((gl_NormalMatrix * gl_Normal).xyz);
|
||||
|
|
|
@ -158,11 +158,14 @@ uniform float rainIntensity;
|
|||
float frustumDepth;
|
||||
|
||||
float linearizeDepth(float depth)
|
||||
{
|
||||
float z_n = 2.0 * depth - 1.0;
|
||||
depth = 2.0 * near * far / (far + near - z_n * frustumDepth);
|
||||
return depth;
|
||||
}
|
||||
{
|
||||
#if @reverseZ
|
||||
depth = 1.0 - depth;
|
||||
#endif
|
||||
float z_n = 2.0 * depth - 1.0;
|
||||
depth = 2.0 * near * far / (far + near - z_n * frustumDepth);
|
||||
return depth;
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
|
|
|
@ -5,6 +5,7 @@ varying vec4 position;
|
|||
varying float linearDepth;
|
||||
|
||||
#include "shadows_vertex.glsl"
|
||||
#include "depth.glsl"
|
||||
|
||||
void main(void)
|
||||
{
|
||||
|
@ -20,7 +21,8 @@ void main(void)
|
|||
|
||||
position = gl_Vertex;
|
||||
|
||||
linearDepth = gl_Position.z;
|
||||
vec4 viewPos = gl_ModelViewMatrix * gl_Vertex;
|
||||
linearDepth = getLinearDepth(viewPos);
|
||||
|
||||
setupShadowCoords(gl_ModelViewMatrix * gl_Vertex, normalize((gl_NormalMatrix * gl_Normal).xyz));
|
||||
setupShadowCoords(viewPos, normalize((gl_NormalMatrix * gl_Normal).xyz));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue