mirror of
https://github.com/OpenMW/openmw.git
synced 2025-03-01 03:09:42 +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
17 changed files with 338 additions and 16 deletions
|
@ -220,6 +220,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
|
||||
|
|
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>();
|
||||
|
||||
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);
|
||||
|
|
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>
|
||||
</widget>
|
||||
</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>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
Loading…
Reference in a new issue