Merge branch 'baby_it_is_occluded_outside' into 'master'

Weather Particle Occlusion (#5492)

Closes #5492

See merge request OpenMW/openmw!1328
7220-lua-add-a-general-purpose-lexical-parser
psi29a 2 years ago
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

@ -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>(); 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);

@ -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> </property>
</widget> </widget>
</item> </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> </layout>
</widget> </widget>
</item> </item>

Loading…
Cancel
Save