rain occlusion

7220-lua-add-a-general-purpose-lexical-parser
glassmancody.info 2 years ago
parent c9d57788fb
commit 9a4977d334

@ -219,6 +219,7 @@
Feature #5198: Implement "Magic effect expired" event
Feature #5454: Clear active spells from actor when he disappears from scene
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 #5737: OpenMW-CS: Handle instance move from one cell to another
Feature #5928: Allow Glow in the Dahrk to be disabled

@ -126,6 +126,7 @@ bool Launcher::AdvancedPage::loadSettings()
antialiasAlphaTestCheckBox->setCheckState(Qt::Unchecked);
}
loadSettingBool(adjustCoverageForAlphaTestCheckBox, "adjust coverage for alpha test", "Shaders");
loadSettingBool(weatherParticleOcclusionCheckBox, "weather particle occlusion", "Shaders");
loadSettingBool(magicItemAnimationsCheckBox, "use magic item animations", "Game");
connect(animSourcesCheckBox, &QCheckBox::toggled, this, &AdvancedPage::slotAnimSourcesToggled);
loadSettingBool(animSourcesCheckBox, "use additional anim sources", "Game");
@ -285,6 +286,7 @@ void Launcher::AdvancedPage::saveSettings()
saveSettingBool(softParticlesCheckBox, "soft particles", "Shaders");
saveSettingBool(antialiasAlphaTestCheckBox, "antialias 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(animSourcesCheckBox, "use additional anim sources", "Game");
saveSettingBool(weaponSheathingCheckBox, "weapon sheathing", "Game");

@ -23,7 +23,7 @@ add_openmw_dir (mwrender
creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation screenshotmanager
bulletdebugdraw globalmap characterpreview camera localmap water terrainstorage ripplesimulation
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

@ -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;
}
}

@ -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>();
mSky = std::make_unique<SkyManager>(sceneRoot, resourceSystem->getSceneManager(), mSkyBlending);
mSky->setCamera(mViewer->getCamera());
mSky = std::make_unique<SkyManager>(
sceneRoot, mRootNode, mViewer->getCamera(), resourceSystem->getSceneManager(), mSkyBlending);
if (mSkyBlending)
{
int skyTextureUnit = mResourceSystem->getSceneManager()->getShaderManager().reserveGlobalTextureUnits(

@ -228,9 +228,10 @@ namespace
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)
, mCamera(nullptr)
, mCamera(camera)
, mAtmosphereNightRoll(0.f)
, mCreated(false)
, mIsStorm(false)
@ -289,6 +290,8 @@ namespace MWRender
mRootNode->setNodeMask(Mask_Sky);
mRootNode->addChild(mEarlyRenderBinRoot);
mUnderwaterSwitch = new UnderwaterSwitchCallback(skyroot);
mPrecipitationOccluder = std::make_unique<PrecipitationOccluder>(skyroot, parentNode, rootNode, camera);
}
void SkyManager::create()
@ -382,11 +385,6 @@ namespace MWRender
mCreated = true;
}
void SkyManager::setCamera(osg::Camera* camera)
{
mCamera = camera;
}
void SkyManager::createRain()
{
if (mRainNode)
@ -466,9 +464,11 @@ namespace MWRender
mRainNode->setNodeMask(Mask_WeatherParticles);
mRainParticleSystem->setUserValue("simpleLighting", true);
mRainParticleSystem->setUserValue("particleOcclusion", true);
mSceneManager->recreateShaders(mRainNode);
mRootNode->addChild(mRainNode);
mPrecipitationOccluder->enable();
}
void SkyManager::destroyRain()
@ -482,6 +482,7 @@ namespace MWRender
mCounter = nullptr;
mRainParticleSystem = nullptr;
mRainShooter = nullptr;
mPrecipitationOccluder->disable();
}
SkyManager::~SkyManager()
@ -563,6 +564,7 @@ namespace MWRender
* osg::DegreesToRadians(360.f) / (3600 * 96.f);
if (mAtmosphereNightNode->getNodeMask() != 0)
mAtmosphereNightNode->setAttitude(osg::Quat(mAtmosphereNightRoll, osg::Vec3f(0, 0, 1)));
mPrecipitationOccluder->update();
}
void SkyManager::setEnabled(bool enabled)
@ -606,6 +608,7 @@ namespace MWRender
mPlacer->setZRange(-rainRange.z() / 2, rainRange.z() / 2);
mCounter->setNumberOfParticlesPerSecondToCreate(mRainMaxRaindrops / mRainEntranceSpeed * 20);
mPrecipitationOccluder->updateRange(rainRange);
}
}
@ -671,6 +674,10 @@ namespace MWRender
mRootNode->removeChild(mParticleNode);
mParticleNode = nullptr;
}
if (mRainEffect.empty())
{
mPrecipitationOccluder->disable();
}
}
else
{
@ -693,6 +700,8 @@ namespace MWRender
SceneUtil::FindByClassVisitor findPSVisitor("ParticleSystem");
mParticleEffect->accept(findPSVisitor);
const osg::Vec3 defaultWrapRange = osg::Vec3(1024, 1024, 800);
for (unsigned int i = 0; i < findPSVisitor.mFoundNodes.size(); ++i)
{
osgParticle::ParticleSystem* ps
@ -700,7 +709,7 @@ namespace MWRender
osg::ref_ptr<osgParticle::ModularProgram> program = new osgParticle::ModularProgram;
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->setParticleSystem(ps);
mParticleNode->addChild(program);
@ -713,9 +722,16 @@ namespace MWRender
}
ps->setUserValue("simpleLighting", true);
ps->setUserValue("particleOcclusion", true);
}
mSceneManager->recreateShaders(mParticleNode);
if (mCurrentParticleEffect == "meshes\\snow.nif")
{
mPrecipitationOccluder->enable();
mPrecipitationOccluder->updateRange(defaultWrapRange);
}
}
}

@ -8,6 +8,7 @@
#include <osg/Vec4f>
#include <osg/ref_ptr>
#include "precipitationocclusion.hpp"
#include "skyutil.hpp"
namespace osg
@ -43,7 +44,8 @@ namespace MWRender
class SkyManager
{
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();
void update(float duration);
@ -98,8 +100,6 @@ namespace MWRender
void listAssetsToPreload(std::vector<std::string>& models, std::vector<std::string>& textures);
void setCamera(osg::Camera* camera);
float getBaseWindSpeed() const;
void setSunglare(bool enabled);
@ -151,6 +151,8 @@ namespace MWRender
osg::ref_ptr<RainCounter> mCounter;
osg::ref_ptr<RainShooter> mRainShooter;
std::unique_ptr<PrecipitationOccluder> mPrecipitationOccluder;
bool mCreated;
bool mIsStorm;

@ -25,6 +25,7 @@
#include <components/sceneutil/morphgeometry.hpp>
#include <components/sceneutil/riggeometry.hpp>
#include <components/sceneutil/riggeometryosgaextension.hpp>
#include <components/settings/settings.hpp>
#include <components/stereo/stereomanager.hpp>
#include <components/vfs/manager.hpp>
@ -675,6 +676,11 @@ namespace Shader
if (simpleLighting || dynamic_cast<osgParticle::ParticleSystem*>(&node))
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.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.
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
soft particles = false
# Rain and snow particle occlusion
weather particle occlusion = false
[Input]
# Capture control of the cursor prevent movement outside the window.

@ -34,8 +34,8 @@ set(SHADER_FILES
shadowcasting_vertex.glsl
shadowcasting_fragment.glsl
vertexcolors.glsl
multiview_resolve_vertex.glsl
multiview_resolve_fragment.glsl
multiview_resolve_vertex.glsl
multiview_resolve_fragment.glsl
nv_default_vertex.glsl
nv_default_fragment.glsl
nv_nolighting_vertex.glsl
@ -55,6 +55,8 @@ set(SHADER_FILES
fullscreen_tri_vertex.glsl
fullscreen_tri_fragment.glsl
fog.glsl
precipitation_vertex.glsl
precipitation_fragment.glsl
)
copy_all_resource_files(${CMAKE_CURRENT_SOURCE_DIR} ${OPENMW_RESOURCES_ROOT} ${DDIRRELATIVE} "${SHADER_FILES}")

@ -92,8 +92,30 @@ varying vec3 passNormal;
#include "softparticles.glsl"
#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()
{
#if @particleOcclusion
precipitationOcclusion();
#endif
#if @diffuseMap
vec2 adjustedDiffuseUV = diffuseMapUV;
#endif

@ -66,8 +66,20 @@ varying vec3 passNormal;
#include "lighting.glsl"
#include "depth.glsl"
#if @particleOcclusion
varying vec3 orthoDepthMapCoord;
uniform mat4 depthSpaceMatrix;
uniform mat4 osg_ViewMatrixInverse;
#endif
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);
vec4 viewPos = mw_modelToView(gl_Vertex);

@ -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;
}

@ -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>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="weatherParticleOcclusionCheckBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;EXPERIMENTAL: Stop rain and snow from falling through overhangs and roofs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Weather Particle Occlusion</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>

Loading…
Cancel
Save