mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-03-26 02:38:04 +00:00
Merge branch 'baby_it_is_occluded_outside' into 'master'
Weather Particle Occlusion (#5492) Closes #5492 See merge request OpenMW/openmw!1328
This commit is contained in:
commit
6a250c5900
@ -220,6 +220,7 @@
|
|||||||
Feature #5198: Implement "Magic effect expired" event
|
Feature #5198: Implement "Magic effect expired" event
|
||||||
Feature #5454: Clear active spells from actor when he disappears from scene
|
Feature #5454: Clear active spells from actor when he disappears from scene
|
||||||
Feature #5489: MCP: Telekinesis fix for activators
|
Feature #5489: MCP: Telekinesis fix for activators
|
||||||
|
Feature #5492: Let rain and snow collide with statics
|
||||||
Feature #5701: Convert osgAnimation::RigGeometry to double-buffered custom version
|
Feature #5701: Convert osgAnimation::RigGeometry to double-buffered custom version
|
||||||
Feature #5737: OpenMW-CS: Handle instance move from one cell to another
|
Feature #5737: OpenMW-CS: Handle instance move from one cell to another
|
||||||
Feature #5928: Allow Glow in the Dahrk to be disabled
|
Feature #5928: Allow Glow in the Dahrk to be disabled
|
||||||
|
@ -126,6 +126,7 @@ bool Launcher::AdvancedPage::loadSettings()
|
|||||||
antialiasAlphaTestCheckBox->setCheckState(Qt::Unchecked);
|
antialiasAlphaTestCheckBox->setCheckState(Qt::Unchecked);
|
||||||
}
|
}
|
||||||
loadSettingBool(adjustCoverageForAlphaTestCheckBox, "adjust coverage for alpha test", "Shaders");
|
loadSettingBool(adjustCoverageForAlphaTestCheckBox, "adjust coverage for alpha test", "Shaders");
|
||||||
|
loadSettingBool(weatherParticleOcclusionCheckBox, "weather particle occlusion", "Shaders");
|
||||||
loadSettingBool(magicItemAnimationsCheckBox, "use magic item animations", "Game");
|
loadSettingBool(magicItemAnimationsCheckBox, "use magic item animations", "Game");
|
||||||
connect(animSourcesCheckBox, &QCheckBox::toggled, this, &AdvancedPage::slotAnimSourcesToggled);
|
connect(animSourcesCheckBox, &QCheckBox::toggled, this, &AdvancedPage::slotAnimSourcesToggled);
|
||||||
loadSettingBool(animSourcesCheckBox, "use additional anim sources", "Game");
|
loadSettingBool(animSourcesCheckBox, "use additional anim sources", "Game");
|
||||||
@ -285,6 +286,7 @@ void Launcher::AdvancedPage::saveSettings()
|
|||||||
saveSettingBool(softParticlesCheckBox, "soft particles", "Shaders");
|
saveSettingBool(softParticlesCheckBox, "soft particles", "Shaders");
|
||||||
saveSettingBool(antialiasAlphaTestCheckBox, "antialias alpha test", "Shaders");
|
saveSettingBool(antialiasAlphaTestCheckBox, "antialias alpha test", "Shaders");
|
||||||
saveSettingBool(adjustCoverageForAlphaTestCheckBox, "adjust coverage for alpha test", "Shaders");
|
saveSettingBool(adjustCoverageForAlphaTestCheckBox, "adjust coverage for alpha test", "Shaders");
|
||||||
|
saveSettingBool(weatherParticleOcclusionCheckBox, "weather particle occlusion", "Shaders");
|
||||||
saveSettingBool(magicItemAnimationsCheckBox, "use magic item animations", "Game");
|
saveSettingBool(magicItemAnimationsCheckBox, "use magic item animations", "Game");
|
||||||
saveSettingBool(animSourcesCheckBox, "use additional anim sources", "Game");
|
saveSettingBool(animSourcesCheckBox, "use additional anim sources", "Game");
|
||||||
saveSettingBool(weaponSheathingCheckBox, "weapon sheathing", "Game");
|
saveSettingBool(weaponSheathingCheckBox, "weapon sheathing", "Game");
|
||||||
|
@ -23,7 +23,7 @@ add_openmw_dir (mwrender
|
|||||||
creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation screenshotmanager
|
creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation screenshotmanager
|
||||||
bulletdebugdraw globalmap characterpreview camera localmap water terrainstorage ripplesimulation
|
bulletdebugdraw globalmap characterpreview camera localmap water terrainstorage ripplesimulation
|
||||||
renderbin actoranimation landmanager navmesh actorspaths recastmesh fogmanager objectpaging groundcover
|
renderbin actoranimation landmanager navmesh actorspaths recastmesh fogmanager objectpaging groundcover
|
||||||
postprocessor pingpongcull luminancecalculator pingpongcanvas transparentpass navmeshmode
|
postprocessor pingpongcull luminancecalculator pingpongcanvas transparentpass navmeshmode precipitationocclusion
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwinput
|
add_openmw_dir (mwinput
|
||||||
|
170
apps/openmw/mwrender/precipitationocclusion.cpp
Normal file
170
apps/openmw/mwrender/precipitationocclusion.cpp
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
#include "precipitationocclusion.hpp"
|
||||||
|
|
||||||
|
#include <osgUtil/CullVisitor>
|
||||||
|
|
||||||
|
#include <components/misc/constants.hpp>
|
||||||
|
#include <components/resource/resourcesystem.hpp>
|
||||||
|
#include <components/resource/scenemanager.hpp>
|
||||||
|
#include <components/sceneutil/depth.hpp>
|
||||||
|
#include <components/sceneutil/positionattitudetransform.hpp>
|
||||||
|
#include <components/sceneutil/util.hpp>
|
||||||
|
#include <components/shader/shadermanager.hpp>
|
||||||
|
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
|
||||||
|
#include "vismask.hpp"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
class PrecipitationOcclusionUpdater : public SceneUtil::StateSetUpdater
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PrecipitationOcclusionUpdater(osg::ref_ptr<osg::Texture2D> depthTexture)
|
||||||
|
: mDepthTexture(depthTexture)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setDefaults(osg::StateSet* stateset) override
|
||||||
|
{
|
||||||
|
stateset->setTextureAttributeAndModes(3, mDepthTexture);
|
||||||
|
stateset->addUniform(new osg::Uniform("orthoDepthMap", 3));
|
||||||
|
stateset->addUniform(new osg::Uniform("depthSpaceMatrix", mDepthSpaceMatrix));
|
||||||
|
}
|
||||||
|
void apply(osg::StateSet* stateset, osg::NodeVisitor* nv) override
|
||||||
|
{
|
||||||
|
osg::Camera* camera = nv->asCullVisitor()->getCurrentCamera();
|
||||||
|
stateset->getUniform("depthSpaceMatrix")->set(camera->getViewMatrix() * camera->getProjectionMatrix());
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::Matrixf mDepthSpaceMatrix;
|
||||||
|
osg::ref_ptr<osg::Texture2D> mDepthTexture;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DepthCameraUpdater : public SceneUtil::StateSetUpdater
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DepthCameraUpdater()
|
||||||
|
: mDummyTexture(new osg::Texture2D)
|
||||||
|
{
|
||||||
|
mDummyTexture->setInternalFormat(GL_RGB);
|
||||||
|
mDummyTexture->setTextureSize(1, 1);
|
||||||
|
|
||||||
|
Shader::ShaderManager& shaderMgr
|
||||||
|
= MWBase::Environment::get().getResourceSystem()->getSceneManager()->getShaderManager();
|
||||||
|
osg::ref_ptr<osg::Shader> vertex
|
||||||
|
= shaderMgr.getShader("precipitationdepth_vertex.glsl", {}, osg::Shader::VERTEX);
|
||||||
|
osg::ref_ptr<osg::Shader> fragment
|
||||||
|
= shaderMgr.getShader("precipitationdepth_fragment.glsl", {}, osg::Shader::FRAGMENT);
|
||||||
|
mProgram = shaderMgr.getProgram(vertex, fragment);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setDefaults(osg::StateSet* stateset) override
|
||||||
|
{
|
||||||
|
stateset->addUniform(new osg::Uniform("projectionMatrix", osg::Matrixf()));
|
||||||
|
stateset->setAttributeAndModes(mProgram, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
|
||||||
|
stateset->setTextureAttributeAndModes(0, mDummyTexture);
|
||||||
|
stateset->setRenderBinDetails(
|
||||||
|
osg::StateSet::OPAQUE_BIN, "RenderBin", osg::StateSet::OVERRIDE_PROTECTED_RENDERBIN_DETAILS);
|
||||||
|
}
|
||||||
|
void apply(osg::StateSet* stateset, osg::NodeVisitor* nv) override
|
||||||
|
{
|
||||||
|
osg::Camera* camera = nv->asCullVisitor()->getCurrentCamera();
|
||||||
|
stateset->getUniform("projectionMatrix")->set(camera->getProjectionMatrix());
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::Matrixf mProjectionMatrix;
|
||||||
|
osg::ref_ptr<osg::Texture2D> mDummyTexture;
|
||||||
|
osg::ref_ptr<osg::Program> mProgram;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWRender
|
||||||
|
{
|
||||||
|
PrecipitationOccluder::PrecipitationOccluder(
|
||||||
|
osg::Group* skyNode, osg::Group* sceneNode, osg::Group* rootNode, osg::Camera* camera)
|
||||||
|
: mSkyNode(skyNode)
|
||||||
|
, mSceneNode(sceneNode)
|
||||||
|
, mRootNode(rootNode)
|
||||||
|
, mSceneCamera(camera)
|
||||||
|
{
|
||||||
|
constexpr int rttSize = 256;
|
||||||
|
|
||||||
|
mDepthTexture = new osg::Texture2D;
|
||||||
|
mDepthTexture->setTextureSize(rttSize, rttSize);
|
||||||
|
mDepthTexture->setSourceFormat(GL_DEPTH_COMPONENT);
|
||||||
|
mDepthTexture->setInternalFormat(GL_DEPTH_COMPONENT24);
|
||||||
|
mDepthTexture->setSourceType(GL_UNSIGNED_INT);
|
||||||
|
mDepthTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_BORDER);
|
||||||
|
mDepthTexture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_BORDER);
|
||||||
|
mDepthTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
|
||||||
|
mDepthTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
|
||||||
|
mDepthTexture->setBorderColor(
|
||||||
|
SceneUtil::AutoDepth::isReversed() ? osg::Vec4(0, 0, 0, 0) : osg::Vec4(1, 1, 1, 1));
|
||||||
|
|
||||||
|
mCamera = new osg::Camera;
|
||||||
|
mCamera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
|
||||||
|
mCamera->setRenderOrder(osg::Camera::PRE_RENDER);
|
||||||
|
mCamera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
|
||||||
|
mCamera->setReferenceFrame(osg::Camera::ABSOLUTE_RF_INHERIT_VIEWPOINT);
|
||||||
|
mCamera->setNodeMask(Mask_RenderToTexture);
|
||||||
|
mCamera->setCullMask(Mask_Scene | Mask_Object | Mask_Static);
|
||||||
|
mCamera->setViewport(0, 0, rttSize, rttSize);
|
||||||
|
mCamera->attach(osg::Camera::DEPTH_BUFFER, mDepthTexture);
|
||||||
|
mCamera->addChild(mSceneNode);
|
||||||
|
|
||||||
|
SceneUtil::setCameraClearDepth(mCamera);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrecipitationOccluder::update()
|
||||||
|
{
|
||||||
|
const osg::Vec3 pos = mSceneCamera->getInverseViewMatrix().getTrans();
|
||||||
|
|
||||||
|
const float zmin = pos.z() - mRange.z() - Constants::CellSizeInUnits;
|
||||||
|
const float zmax = pos.z() + mRange.z() + Constants::CellSizeInUnits;
|
||||||
|
const float near = 0;
|
||||||
|
const float far = zmax - zmin;
|
||||||
|
|
||||||
|
const float left = -mRange.x() / 2;
|
||||||
|
const float right = -left;
|
||||||
|
const float top = mRange.y() / 2;
|
||||||
|
const float bottom = -top;
|
||||||
|
|
||||||
|
if (SceneUtil::AutoDepth::isReversed())
|
||||||
|
{
|
||||||
|
mCamera->setProjectionMatrix(
|
||||||
|
SceneUtil::getReversedZProjectionMatrixAsOrtho(left, right, bottom, top, near, far));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mCamera->setProjectionMatrix(osg::Matrixf::ortho(left, right, bottom, top, near, far));
|
||||||
|
}
|
||||||
|
|
||||||
|
mCamera->setViewMatrixAsLookAt(
|
||||||
|
osg::Vec3(pos.x(), pos.y(), zmax), osg::Vec3(pos.x(), pos.y(), zmin), osg::Vec3(0, 1, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrecipitationOccluder::enable()
|
||||||
|
{
|
||||||
|
mSkyNode->setCullCallback(new PrecipitationOcclusionUpdater(mDepthTexture));
|
||||||
|
mCamera->setCullCallback(new DepthCameraUpdater);
|
||||||
|
|
||||||
|
mRootNode->removeChild(mCamera);
|
||||||
|
mRootNode->addChild(mCamera);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrecipitationOccluder::disable()
|
||||||
|
{
|
||||||
|
mSkyNode->setCullCallback(nullptr);
|
||||||
|
mCamera->setCullCallback(nullptr);
|
||||||
|
|
||||||
|
mRootNode->removeChild(mCamera);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrecipitationOccluder::updateRange(const osg::Vec3f range)
|
||||||
|
{
|
||||||
|
const osg::Vec3f margin = { -50, -50, 0 };
|
||||||
|
mRange = range - margin;
|
||||||
|
}
|
||||||
|
}
|
33
apps/openmw/mwrender/precipitationocclusion.hpp
Normal file
33
apps/openmw/mwrender/precipitationocclusion.hpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#ifndef OPENMW_MWRENDER_PRECIPITATIONOCCLUSION_H
|
||||||
|
#define OPENMW_MWRENDER_PRECIPITATIONOCCLUSION_H
|
||||||
|
|
||||||
|
#include <osg/Camera>
|
||||||
|
#include <osg/Texture2D>
|
||||||
|
|
||||||
|
namespace MWRender
|
||||||
|
{
|
||||||
|
class PrecipitationOccluder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PrecipitationOccluder(osg::Group* skyNode, osg::Group* sceneNode, osg::Group* rootNode, osg::Camera* camera);
|
||||||
|
|
||||||
|
void update();
|
||||||
|
|
||||||
|
void enable();
|
||||||
|
|
||||||
|
void disable();
|
||||||
|
|
||||||
|
void updateRange(const osg::Vec3f range);
|
||||||
|
|
||||||
|
private:
|
||||||
|
osg::Group* mSkyNode;
|
||||||
|
osg::Group* mSceneNode;
|
||||||
|
osg::Group* mRootNode;
|
||||||
|
osg::ref_ptr<osg::Camera> mCamera;
|
||||||
|
osg::ref_ptr<osg::Camera> mSceneCamera;
|
||||||
|
osg::ref_ptr<osg::Texture2D> mDepthTexture;
|
||||||
|
osg::Vec3f mRange;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -586,8 +586,8 @@ namespace MWRender
|
|||||||
|
|
||||||
mFog = std::make_unique<FogManager>();
|
mFog = std::make_unique<FogManager>();
|
||||||
|
|
||||||
mSky = std::make_unique<SkyManager>(sceneRoot, resourceSystem->getSceneManager(), mSkyBlending);
|
mSky = std::make_unique<SkyManager>(
|
||||||
mSky->setCamera(mViewer->getCamera());
|
sceneRoot, mRootNode, mViewer->getCamera(), resourceSystem->getSceneManager(), mSkyBlending);
|
||||||
if (mSkyBlending)
|
if (mSkyBlending)
|
||||||
{
|
{
|
||||||
int skyTextureUnit = mResourceSystem->getSceneManager()->getShaderManager().reserveGlobalTextureUnits(
|
int skyTextureUnit = mResourceSystem->getSceneManager()->getShaderManager().reserveGlobalTextureUnits(
|
||||||
|
@ -228,9 +228,10 @@ namespace
|
|||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
SkyManager::SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneManager, bool enableSkyRTT)
|
SkyManager::SkyManager(osg::Group* parentNode, osg::Group* rootNode, osg::Camera* camera,
|
||||||
|
Resource::SceneManager* sceneManager, bool enableSkyRTT)
|
||||||
: mSceneManager(sceneManager)
|
: mSceneManager(sceneManager)
|
||||||
, mCamera(nullptr)
|
, mCamera(camera)
|
||||||
, mAtmosphereNightRoll(0.f)
|
, mAtmosphereNightRoll(0.f)
|
||||||
, mCreated(false)
|
, mCreated(false)
|
||||||
, mIsStorm(false)
|
, mIsStorm(false)
|
||||||
@ -289,6 +290,8 @@ namespace MWRender
|
|||||||
mRootNode->setNodeMask(Mask_Sky);
|
mRootNode->setNodeMask(Mask_Sky);
|
||||||
mRootNode->addChild(mEarlyRenderBinRoot);
|
mRootNode->addChild(mEarlyRenderBinRoot);
|
||||||
mUnderwaterSwitch = new UnderwaterSwitchCallback(skyroot);
|
mUnderwaterSwitch = new UnderwaterSwitchCallback(skyroot);
|
||||||
|
|
||||||
|
mPrecipitationOccluder = std::make_unique<PrecipitationOccluder>(skyroot, parentNode, rootNode, camera);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkyManager::create()
|
void SkyManager::create()
|
||||||
@ -382,11 +385,6 @@ namespace MWRender
|
|||||||
mCreated = true;
|
mCreated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkyManager::setCamera(osg::Camera* camera)
|
|
||||||
{
|
|
||||||
mCamera = camera;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SkyManager::createRain()
|
void SkyManager::createRain()
|
||||||
{
|
{
|
||||||
if (mRainNode)
|
if (mRainNode)
|
||||||
@ -466,9 +464,11 @@ namespace MWRender
|
|||||||
mRainNode->setNodeMask(Mask_WeatherParticles);
|
mRainNode->setNodeMask(Mask_WeatherParticles);
|
||||||
|
|
||||||
mRainParticleSystem->setUserValue("simpleLighting", true);
|
mRainParticleSystem->setUserValue("simpleLighting", true);
|
||||||
|
mRainParticleSystem->setUserValue("particleOcclusion", true);
|
||||||
mSceneManager->recreateShaders(mRainNode);
|
mSceneManager->recreateShaders(mRainNode);
|
||||||
|
|
||||||
mRootNode->addChild(mRainNode);
|
mRootNode->addChild(mRainNode);
|
||||||
|
mPrecipitationOccluder->enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkyManager::destroyRain()
|
void SkyManager::destroyRain()
|
||||||
@ -482,6 +482,7 @@ namespace MWRender
|
|||||||
mCounter = nullptr;
|
mCounter = nullptr;
|
||||||
mRainParticleSystem = nullptr;
|
mRainParticleSystem = nullptr;
|
||||||
mRainShooter = nullptr;
|
mRainShooter = nullptr;
|
||||||
|
mPrecipitationOccluder->disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
SkyManager::~SkyManager()
|
SkyManager::~SkyManager()
|
||||||
@ -563,6 +564,7 @@ namespace MWRender
|
|||||||
* osg::DegreesToRadians(360.f) / (3600 * 96.f);
|
* osg::DegreesToRadians(360.f) / (3600 * 96.f);
|
||||||
if (mAtmosphereNightNode->getNodeMask() != 0)
|
if (mAtmosphereNightNode->getNodeMask() != 0)
|
||||||
mAtmosphereNightNode->setAttitude(osg::Quat(mAtmosphereNightRoll, osg::Vec3f(0, 0, 1)));
|
mAtmosphereNightNode->setAttitude(osg::Quat(mAtmosphereNightRoll, osg::Vec3f(0, 0, 1)));
|
||||||
|
mPrecipitationOccluder->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkyManager::setEnabled(bool enabled)
|
void SkyManager::setEnabled(bool enabled)
|
||||||
@ -606,6 +608,7 @@ namespace MWRender
|
|||||||
mPlacer->setZRange(-rainRange.z() / 2, rainRange.z() / 2);
|
mPlacer->setZRange(-rainRange.z() / 2, rainRange.z() / 2);
|
||||||
|
|
||||||
mCounter->setNumberOfParticlesPerSecondToCreate(mRainMaxRaindrops / mRainEntranceSpeed * 20);
|
mCounter->setNumberOfParticlesPerSecondToCreate(mRainMaxRaindrops / mRainEntranceSpeed * 20);
|
||||||
|
mPrecipitationOccluder->updateRange(rainRange);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -671,6 +674,10 @@ namespace MWRender
|
|||||||
mRootNode->removeChild(mParticleNode);
|
mRootNode->removeChild(mParticleNode);
|
||||||
mParticleNode = nullptr;
|
mParticleNode = nullptr;
|
||||||
}
|
}
|
||||||
|
if (mRainEffect.empty())
|
||||||
|
{
|
||||||
|
mPrecipitationOccluder->disable();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -693,6 +700,8 @@ namespace MWRender
|
|||||||
SceneUtil::FindByClassVisitor findPSVisitor("ParticleSystem");
|
SceneUtil::FindByClassVisitor findPSVisitor("ParticleSystem");
|
||||||
mParticleEffect->accept(findPSVisitor);
|
mParticleEffect->accept(findPSVisitor);
|
||||||
|
|
||||||
|
const osg::Vec3 defaultWrapRange = osg::Vec3(1024, 1024, 800);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < findPSVisitor.mFoundNodes.size(); ++i)
|
for (unsigned int i = 0; i < findPSVisitor.mFoundNodes.size(); ++i)
|
||||||
{
|
{
|
||||||
osgParticle::ParticleSystem* ps
|
osgParticle::ParticleSystem* ps
|
||||||
@ -700,7 +709,7 @@ namespace MWRender
|
|||||||
|
|
||||||
osg::ref_ptr<osgParticle::ModularProgram> program = new osgParticle::ModularProgram;
|
osg::ref_ptr<osgParticle::ModularProgram> program = new osgParticle::ModularProgram;
|
||||||
if (!mIsStorm)
|
if (!mIsStorm)
|
||||||
program->addOperator(new WrapAroundOperator(mCamera, osg::Vec3(1024, 1024, 800)));
|
program->addOperator(new WrapAroundOperator(mCamera, defaultWrapRange));
|
||||||
program->addOperator(new WeatherAlphaOperator(mPrecipitationAlpha, false));
|
program->addOperator(new WeatherAlphaOperator(mPrecipitationAlpha, false));
|
||||||
program->setParticleSystem(ps);
|
program->setParticleSystem(ps);
|
||||||
mParticleNode->addChild(program);
|
mParticleNode->addChild(program);
|
||||||
@ -713,9 +722,16 @@ namespace MWRender
|
|||||||
}
|
}
|
||||||
|
|
||||||
ps->setUserValue("simpleLighting", true);
|
ps->setUserValue("simpleLighting", true);
|
||||||
|
ps->setUserValue("particleOcclusion", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
mSceneManager->recreateShaders(mParticleNode);
|
mSceneManager->recreateShaders(mParticleNode);
|
||||||
|
|
||||||
|
if (mCurrentParticleEffect == "meshes\\snow.nif")
|
||||||
|
{
|
||||||
|
mPrecipitationOccluder->enable();
|
||||||
|
mPrecipitationOccluder->updateRange(defaultWrapRange);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <osg/Vec4f>
|
#include <osg/Vec4f>
|
||||||
#include <osg/ref_ptr>
|
#include <osg/ref_ptr>
|
||||||
|
|
||||||
|
#include "precipitationocclusion.hpp"
|
||||||
#include "skyutil.hpp"
|
#include "skyutil.hpp"
|
||||||
|
|
||||||
namespace osg
|
namespace osg
|
||||||
@ -43,7 +44,8 @@ namespace MWRender
|
|||||||
class SkyManager
|
class SkyManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneManager, bool enableSkyRTT);
|
SkyManager(osg::Group* parentNode, osg::Group* rootNode, osg::Camera* camera,
|
||||||
|
Resource::SceneManager* sceneManager, bool enableSkyRTT);
|
||||||
~SkyManager();
|
~SkyManager();
|
||||||
|
|
||||||
void update(float duration);
|
void update(float duration);
|
||||||
@ -98,8 +100,6 @@ namespace MWRender
|
|||||||
|
|
||||||
void listAssetsToPreload(std::vector<std::string>& models, std::vector<std::string>& textures);
|
void listAssetsToPreload(std::vector<std::string>& models, std::vector<std::string>& textures);
|
||||||
|
|
||||||
void setCamera(osg::Camera* camera);
|
|
||||||
|
|
||||||
float getBaseWindSpeed() const;
|
float getBaseWindSpeed() const;
|
||||||
|
|
||||||
void setSunglare(bool enabled);
|
void setSunglare(bool enabled);
|
||||||
@ -151,6 +151,8 @@ namespace MWRender
|
|||||||
osg::ref_ptr<RainCounter> mCounter;
|
osg::ref_ptr<RainCounter> mCounter;
|
||||||
osg::ref_ptr<RainShooter> mRainShooter;
|
osg::ref_ptr<RainShooter> mRainShooter;
|
||||||
|
|
||||||
|
std::unique_ptr<PrecipitationOccluder> mPrecipitationOccluder;
|
||||||
|
|
||||||
bool mCreated;
|
bool mCreated;
|
||||||
|
|
||||||
bool mIsStorm;
|
bool mIsStorm;
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include <components/sceneutil/morphgeometry.hpp>
|
#include <components/sceneutil/morphgeometry.hpp>
|
||||||
#include <components/sceneutil/riggeometry.hpp>
|
#include <components/sceneutil/riggeometry.hpp>
|
||||||
#include <components/sceneutil/riggeometryosgaextension.hpp>
|
#include <components/sceneutil/riggeometryosgaextension.hpp>
|
||||||
|
#include <components/settings/settings.hpp>
|
||||||
#include <components/stereo/stereomanager.hpp>
|
#include <components/stereo/stereomanager.hpp>
|
||||||
#include <components/vfs/manager.hpp>
|
#include <components/vfs/manager.hpp>
|
||||||
|
|
||||||
@ -675,6 +676,11 @@ namespace Shader
|
|||||||
if (simpleLighting || dynamic_cast<osgParticle::ParticleSystem*>(&node))
|
if (simpleLighting || dynamic_cast<osgParticle::ParticleSystem*>(&node))
|
||||||
defineMap["forcePPL"] = "0";
|
defineMap["forcePPL"] = "0";
|
||||||
|
|
||||||
|
bool particleOcclusion = false;
|
||||||
|
node.getUserValue("particleOcclusion", particleOcclusion);
|
||||||
|
defineMap["particleOcclusion"]
|
||||||
|
= particleOcclusion && Settings::Manager::getBool("weather particle occlusion", "Shaders") ? "1" : "0";
|
||||||
|
|
||||||
if (reqs.mAlphaBlend && mSupportsNormalsRT)
|
if (reqs.mAlphaBlend && mSupportsNormalsRT)
|
||||||
{
|
{
|
||||||
if (reqs.mSoftParticles)
|
if (reqs.mSoftParticles)
|
||||||
|
@ -287,3 +287,18 @@ the look of some particle systems.
|
|||||||
|
|
||||||
Note that the rendering will act as if you have 'force shaders' option enabled.
|
Note that the rendering will act as if you have 'force shaders' option enabled.
|
||||||
This means that shaders will be used to render all objects and the terrain.
|
This means that shaders will be used to render all objects and the terrain.
|
||||||
|
|
||||||
|
weather particle occlusion
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
:Type: boolean
|
||||||
|
:Range: True/False
|
||||||
|
:Default: False
|
||||||
|
|
||||||
|
Enables particle occlusion for rain and snow particle effects.
|
||||||
|
When enabled, rain and snow will not clip through ceilings and overhangs.
|
||||||
|
Currently this relies on an additional render pass, which may lead to a performance hit.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
This is an experimental feature that may cause visual oddities, especially when using default rain settings.
|
||||||
|
It is recommended to at least double the rain diameter through `openmw.cfg`.`
|
||||||
|
@ -499,6 +499,9 @@ adjust coverage for alpha test = true
|
|||||||
# Soften intersection of blended particle systems with opaque geometry
|
# Soften intersection of blended particle systems with opaque geometry
|
||||||
soft particles = false
|
soft particles = false
|
||||||
|
|
||||||
|
# Rain and snow particle occlusion
|
||||||
|
weather particle occlusion = false
|
||||||
|
|
||||||
[Input]
|
[Input]
|
||||||
|
|
||||||
# Capture control of the cursor prevent movement outside the window.
|
# Capture control of the cursor prevent movement outside the window.
|
||||||
|
@ -34,8 +34,8 @@ set(SHADER_FILES
|
|||||||
shadowcasting_vertex.glsl
|
shadowcasting_vertex.glsl
|
||||||
shadowcasting_fragment.glsl
|
shadowcasting_fragment.glsl
|
||||||
vertexcolors.glsl
|
vertexcolors.glsl
|
||||||
multiview_resolve_vertex.glsl
|
multiview_resolve_vertex.glsl
|
||||||
multiview_resolve_fragment.glsl
|
multiview_resolve_fragment.glsl
|
||||||
nv_default_vertex.glsl
|
nv_default_vertex.glsl
|
||||||
nv_default_fragment.glsl
|
nv_default_fragment.glsl
|
||||||
nv_nolighting_vertex.glsl
|
nv_nolighting_vertex.glsl
|
||||||
@ -55,6 +55,8 @@ set(SHADER_FILES
|
|||||||
fullscreen_tri_vertex.glsl
|
fullscreen_tri_vertex.glsl
|
||||||
fullscreen_tri_fragment.glsl
|
fullscreen_tri_fragment.glsl
|
||||||
fog.glsl
|
fog.glsl
|
||||||
|
precipitation_vertex.glsl
|
||||||
|
precipitation_fragment.glsl
|
||||||
)
|
)
|
||||||
|
|
||||||
copy_all_resource_files(${CMAKE_CURRENT_SOURCE_DIR} ${OPENMW_RESOURCES_ROOT} ${DDIRRELATIVE} "${SHADER_FILES}")
|
copy_all_resource_files(${CMAKE_CURRENT_SOURCE_DIR} ${OPENMW_RESOURCES_ROOT} ${DDIRRELATIVE} "${SHADER_FILES}")
|
||||||
|
@ -92,8 +92,30 @@ varying vec3 passNormal;
|
|||||||
#include "softparticles.glsl"
|
#include "softparticles.glsl"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if @particleOcclusion
|
||||||
|
uniform sampler2D orthoDepthMap;
|
||||||
|
|
||||||
|
varying vec3 orthoDepthMapCoord;
|
||||||
|
|
||||||
|
void precipitationOcclusion()
|
||||||
|
{
|
||||||
|
float sceneDepth = texture2D(orthoDepthMap, orthoDepthMapCoord.xy * 0.5 + 0.5).r;
|
||||||
|
#if @reverseZ
|
||||||
|
if (orthoDepthMapCoord.z < sceneDepth)
|
||||||
|
discard;
|
||||||
|
#else
|
||||||
|
if (orthoDepthMapCoord.z * 0.5 + 0.5 > sceneDepth)
|
||||||
|
discard;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
#if @particleOcclusion
|
||||||
|
precipitationOcclusion();
|
||||||
|
#endif
|
||||||
|
|
||||||
#if @diffuseMap
|
#if @diffuseMap
|
||||||
vec2 adjustedDiffuseUV = diffuseMapUV;
|
vec2 adjustedDiffuseUV = diffuseMapUV;
|
||||||
#endif
|
#endif
|
||||||
|
@ -66,8 +66,20 @@ varying vec3 passNormal;
|
|||||||
#include "lighting.glsl"
|
#include "lighting.glsl"
|
||||||
#include "depth.glsl"
|
#include "depth.glsl"
|
||||||
|
|
||||||
|
#if @particleOcclusion
|
||||||
|
varying vec3 orthoDepthMapCoord;
|
||||||
|
|
||||||
|
uniform mat4 depthSpaceMatrix;
|
||||||
|
uniform mat4 osg_ViewMatrixInverse;
|
||||||
|
#endif
|
||||||
|
|
||||||
void main(void)
|
void main(void)
|
||||||
{
|
{
|
||||||
|
#if @particleOcclusion
|
||||||
|
mat4 model = osg_ViewMatrixInverse * gl_ModelViewMatrix;
|
||||||
|
orthoDepthMapCoord = ((depthSpaceMatrix * model) * vec4(gl_Vertex.xyz, 1.0)).xyz;
|
||||||
|
#endif
|
||||||
|
|
||||||
gl_Position = mw_modelToClip(gl_Vertex);
|
gl_Position = mw_modelToClip(gl_Vertex);
|
||||||
|
|
||||||
vec4 viewPos = mw_modelToView(gl_Vertex);
|
vec4 viewPos = mw_modelToView(gl_Vertex);
|
||||||
|
15
files/shaders/precipitation_fragment.glsl
Normal file
15
files/shaders/precipitation_fragment.glsl
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#version 120
|
||||||
|
|
||||||
|
uniform sampler2D diffuseMap;
|
||||||
|
varying vec2 diffuseMapUV;
|
||||||
|
|
||||||
|
#include "vertexcolors.glsl"
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_FragData[0].rgb = vec3(1.0);
|
||||||
|
gl_FragData[0].a = texture2D(diffuseMap, diffuseMapUV).a * getDiffuseColor().a;
|
||||||
|
|
||||||
|
if (gl_FragData[0].a <= 0.5)
|
||||||
|
discard;
|
||||||
|
}
|
13
files/shaders/precipitation_vertex.glsl
Normal file
13
files/shaders/precipitation_vertex.glsl
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#version 120
|
||||||
|
|
||||||
|
uniform mat4 projectionMatrix;
|
||||||
|
varying vec2 diffuseMapUV;
|
||||||
|
|
||||||
|
#include "vertexcolors.glsl"
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = projectionMatrix * (gl_ModelViewMatrix * gl_Vertex);
|
||||||
|
diffuseMapUV = (gl_TextureMatrix[0] * gl_MultiTexCoord0).xy;
|
||||||
|
passColor = gl_Color;
|
||||||
|
}
|
@ -485,6 +485,16 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QCheckBox" name="weatherParticleOcclusionCheckBox">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>EXPERIMENTAL: Stop rain and snow from falling through overhangs and roofs.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Weather Particle Occlusion</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user