Merge branch 'shader_refactor_v2' into 'master'

Shader refactor

See merge request OpenMW/openmw!2667
update_gitlab_rules
psi29a 2 years ago
commit c02a159a26

@ -13,24 +13,13 @@ namespace MWRender
const float hdrExposureTime
= std::max(Settings::Manager::getFloat("auto exposure speed", "Post Processing"), 0.0001f);
constexpr float minLog = -9.0;
constexpr float maxLog = 4.0;
constexpr float logLumRange = (maxLog - minLog);
constexpr float invLogLumRange = 1.0 / logLumRange;
constexpr float epsilon = 0.004;
Shader::ShaderManager::DefineMap defines = {
{ "minLog", std::to_string(minLog) },
{ "maxLog", std::to_string(maxLog) },
{ "logLumRange", std::to_string(logLumRange) },
{ "invLogLumRange", std::to_string(invLogLumRange) },
{ "hdrExposureTime", std::to_string(hdrExposureTime) },
{ "epsilon", std::to_string(epsilon) },
};
auto vertex = shaderManager.getShader("fullscreen_tri_vertex.glsl", {}, osg::Shader::VERTEX);
auto luminanceFragment = shaderManager.getShader("hdr_luminance_fragment.glsl", defines, osg::Shader::FRAGMENT);
auto resolveFragment = shaderManager.getShader("hdr_resolve_fragment.glsl", defines, osg::Shader::FRAGMENT);
auto vertex = shaderManager.getShader("fullscreen_tri.vert", {});
auto luminanceFragment = shaderManager.getShader("luminance/luminance.frag", defines);
auto resolveFragment = shaderManager.getShader("luminance/resolve.frag", defines);
mResolveProgram = shaderManager.getProgram(vertex, resolveFragment);
mLuminanceProgram = shaderManager.getProgram(vertex, luminanceFragment);

@ -32,20 +32,15 @@ namespace MWRender
Shader::ShaderManager::DefineMap defines;
Stereo::Manager::instance().shaderStereoDefines(defines);
auto fallbackVertex = shaderManager.getShader("fullscreen_tri_vertex.glsl", defines, osg::Shader::VERTEX);
auto fallbackFragment = shaderManager.getShader("fullscreen_tri_fragment.glsl", defines, osg::Shader::FRAGMENT);
mFallbackProgram = shaderManager.getProgram(fallbackVertex, fallbackFragment);
mFallbackProgram = shaderManager.getProgram("fullscreen_tri");
mFallbackStateSet->setAttributeAndModes(mFallbackProgram);
mFallbackStateSet->addUniform(new osg::Uniform("omw_SamplerLastShader", 0));
mFallbackStateSet->addUniform(new osg::Uniform("lastShader", 0));
mFallbackStateSet->addUniform(new osg::Uniform("scaling", osg::Vec2f(1, 1)));
auto multiviewResolveVertex = shaderManager.getShader("multiview_resolve_vertex.glsl", {}, osg::Shader::VERTEX);
auto multiviewResolveFragment
= shaderManager.getShader("multiview_resolve_fragment.glsl", {}, osg::Shader::FRAGMENT);
mMultiviewResolveProgram = shaderManager.getProgram(multiviewResolveVertex, multiviewResolveFragment);
mMultiviewResolveProgram = shaderManager.getProgram("multiview_resolve");
mMultiviewResolveStateSet->setAttributeAndModes(mMultiviewResolveProgram);
mMultiviewResolveStateSet->addUniform(new osg::Uniform("omw_SamplerLastShader", 0));
mMultiviewResolveStateSet->addUniform(new osg::Uniform("lastShader", 0));
}
void PingPongCanvas::setCurrentFrameData(size_t frameId, fx::DispatchArray&& data)

@ -52,11 +52,7 @@ namespace
Shader::ShaderManager& shaderMgr
= MWBase::Environment::get().getResourceSystem()->getSceneManager()->getShaderManager();
osg::ref_ptr<osg::Shader> vertex
= shaderMgr.getShader("precipitation_vertex.glsl", {}, osg::Shader::VERTEX);
osg::ref_ptr<osg::Shader> fragment
= shaderMgr.getShader("precipitation_fragment.glsl", {}, osg::Shader::FRAGMENT);
mProgram = shaderMgr.getProgram(vertex, fragment);
mProgram = shaderMgr.getProgram("depthclipped");
}
private:

@ -156,8 +156,7 @@ namespace MWRender
{
public:
SharedUniformStateUpdater(bool usePlayerUniforms)
: mLinearFac(0.f)
, mNear(0.f)
: mNear(0.f)
, mFar(0.f)
, mWindSpeed(0.f)
, mSkyBlendingStartCoef(Settings::Manager::getFloat("sky blending start", "Fog"))
@ -167,7 +166,6 @@ namespace MWRender
void setDefaults(osg::StateSet* stateset) override
{
stateset->addUniform(new osg::Uniform("linearFac", 0.f));
stateset->addUniform(new osg::Uniform("near", 0.f));
stateset->addUniform(new osg::Uniform("far", 0.f));
stateset->addUniform(new osg::Uniform("skyBlendingStart", 0.f));
@ -183,7 +181,6 @@ namespace MWRender
void apply(osg::StateSet* stateset, osg::NodeVisitor* nv) override
{
stateset->getUniform("linearFac")->set(mLinearFac);
stateset->getUniform("near")->set(mNear);
stateset->getUniform("far")->set(mFar);
stateset->getUniform("skyBlendingStart")->set(mFar * mSkyBlendingStartCoef);
@ -196,8 +193,6 @@ namespace MWRender
}
}
void setLinearFac(float linearFac) { mLinearFac = linearFac; }
void setNear(float near) { mNear = near; }
void setFar(float far) { mFar = far; }
@ -209,7 +204,6 @@ namespace MWRender
void setPlayerPos(osg::Vec3f playerPos) { mPlayerPos = playerPos; }
private:
float mLinearFac;
float mNear;
float mFar;
float mWindSpeed;
@ -1293,7 +1287,6 @@ namespace MWRender
if (SceneUtil::AutoDepth::isReversed())
{
mSharedUniformStateUpdater->setLinearFac(-mNearClip / (mViewDistance - mNearClip) - 1.f);
mPerViewUniformStateUpdater->setProjectionMatrix(
SceneUtil::getReversedZProjectionMatrixAsPerspective(fov, aspect, mNearClip, mViewDistance));
}

@ -264,18 +264,10 @@ namespace MWRender
osg::ref_ptr<osg::Camera> screenshotCamera(new osg::Camera);
osg::ref_ptr<osg::ShapeDrawable> quad(new osg::ShapeDrawable(new osg::Box(osg::Vec3(0, 0, 0), 2.0)));
std::map<std::string, std::string> defineMap;
Shader::ShaderManager& shaderMgr = mResourceSystem->getSceneManager()->getShaderManager();
osg::ref_ptr<osg::Shader> fragmentShader(
shaderMgr.getShader("s360_fragment.glsl", defineMap, osg::Shader::FRAGMENT));
osg::ref_ptr<osg::Shader> vertexShader(shaderMgr.getShader("s360_vertex.glsl", defineMap, osg::Shader::VERTEX));
osg::ref_ptr<osg::StateSet> stateset = quad->getOrCreateStateSet();
osg::ref_ptr<osg::Program> program(new osg::Program);
program->addShader(fragmentShader);
program->addShader(vertexShader);
stateset->setAttributeAndModes(program, osg::StateAttribute::ON);
Shader::ShaderManager& shaderMgr = mResourceSystem->getSceneManager()->getShaderManager();
stateset->setAttributeAndModes(shaderMgr.getProgram("360"), osg::StateAttribute::ON);
stateset->addUniform(new osg::Uniform("cubeMap", 0));
stateset->addUniform(new osg::Uniform("mapping", screenshotMapping));

@ -366,10 +366,7 @@ namespace MWRender
{
Shader::ShaderManager::DefineMap defines = {};
Stereo::Manager::instance().shaderStereoDefines(defines);
auto vertex = mSceneManager->getShaderManager().getShader("sky_vertex.glsl", defines, osg::Shader::VERTEX);
auto fragment
= mSceneManager->getShaderManager().getShader("sky_fragment.glsl", defines, osg::Shader::FRAGMENT);
auto program = mSceneManager->getShaderManager().getProgram(vertex, fragment);
auto program = mSceneManager->getShaderManager().getProgram("sky", defines);
mEarlyRenderBinRoot->getOrCreateStateSet()->addUniform(new osg::Uniform("pass", -1));
mEarlyRenderBinRoot->getOrCreateStateSet()->setAttributeAndModes(
program, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);

@ -34,13 +34,9 @@ namespace MWRender
Shader::ShaderManager::DefineMap defines;
Stereo::Manager::instance().shaderStereoDefines(defines);
osg::ref_ptr<osg::Shader> vertex
= shaderManager.getShader("blended_depth_postpass_vertex.glsl", defines, osg::Shader::VERTEX);
osg::ref_ptr<osg::Shader> fragment
= shaderManager.getShader("blended_depth_postpass_fragment.glsl", defines, osg::Shader::FRAGMENT);
mStateSet->setAttributeAndModes(new osg::BlendFunc, modeOff);
mStateSet->setAttributeAndModes(shaderManager.getProgram(vertex, fragment), modeOn);
mStateSet->setAttributeAndModes(shaderManager.getProgram("depthclipped", defines), modeOn);
mStateSet->setAttributeAndModes(new SceneUtil::AutoDepth, modeOn);
for (unsigned int unit = 1; unit < 8; ++unit)

@ -675,11 +675,7 @@ namespace MWRender
Stereo::Manager::instance().shaderStereoDefines(defineMap);
Shader::ShaderManager& shaderMgr = mResourceSystem->getSceneManager()->getShaderManager();
osg::ref_ptr<osg::Shader> vertexShader(
shaderMgr.getShader("water_vertex.glsl", defineMap, osg::Shader::VERTEX));
osg::ref_ptr<osg::Shader> fragmentShader(
shaderMgr.getShader("water_fragment.glsl", defineMap, osg::Shader::FRAGMENT));
osg::ref_ptr<osg::Program> program = shaderMgr.getProgram(vertexShader, fragmentShader);
osg::ref_ptr<osg::Program> program = shaderMgr.getProgram("water", defineMap);
osg::ref_ptr<osg::Texture2D> normalMap(
new osg::Texture2D(mResourceSystem->getImageManager()->getImage("textures/omw/water_nm.png")));

@ -175,10 +175,10 @@ osg::Group {
struct NifOsgLoaderBSShaderPrefixTest : TestWithParam<ShaderPrefixParams>, BaseNifOsgLoaderTest
{
static constexpr std::array sParams = {
ShaderPrefixParams{ static_cast<unsigned int>(Nif::BSShaderType::ShaderType_Default), "nv_default" },
ShaderPrefixParams{ static_cast<unsigned int>(Nif::BSShaderType::ShaderType_NoLighting), "nv_nolighting" },
ShaderPrefixParams{ static_cast<unsigned int>(Nif::BSShaderType::ShaderType_Tile), "nv_default" },
ShaderPrefixParams{ std::numeric_limits<unsigned int>::max(), "nv_default" },
ShaderPrefixParams{ static_cast<unsigned int>(Nif::BSShaderType::ShaderType_Default), "bs/default" },
ShaderPrefixParams{ static_cast<unsigned int>(Nif::BSShaderType::ShaderType_NoLighting), "bs/nolighting" },
ShaderPrefixParams{ static_cast<unsigned int>(Nif::BSShaderType::ShaderType_Tile), "bs/default" },
ShaderPrefixParams{ std::numeric_limits<unsigned int>::max(), "bs/default" },
};
};
@ -204,9 +204,9 @@ osg::Group {
{
static constexpr std::array sParams = {
ShaderPrefixParams{
static_cast<unsigned int>(Nif::BSLightingShaderType::ShaderType_Default), "nv_default" },
ShaderPrefixParams{ static_cast<unsigned int>(Nif::BSLightingShaderType::ShaderType_Cloud), "nv_default" },
ShaderPrefixParams{ std::numeric_limits<unsigned int>::max(), "nv_default" },
static_cast<unsigned int>(Nif::BSLightingShaderType::ShaderType_Default), "bs/default" },
ShaderPrefixParams{ static_cast<unsigned int>(Nif::BSLightingShaderType::ShaderType_Cloud), "bs/default" },
ShaderPrefixParams{ std::numeric_limits<unsigned int>::max(), "bs/default" },
};
};

@ -17,7 +17,7 @@ namespace
ShaderManager mManager;
ShaderManager::DefineMap mDefines;
ShaderManagerTest() { mManager.setShaderPath("."); }
ShaderManagerTest() { mManager.setShaderPath("tests_output"); }
template <class F>
void withShaderFile(const std::string& content, F&& f)
@ -28,16 +28,17 @@ namespace
template <class F>
void withShaderFile(const std::string& suffix, const std::string& content, F&& f)
{
auto path = TestingOpenMW::outputFilePath(
std::string(UnitTest::GetInstance()->current_test_info()->name()) + suffix + ".glsl");
auto subdir = std::filesystem::path("lib")
/ std::filesystem::path(
std::string(UnitTest::GetInstance()->current_test_info()->name()) + suffix + ".vert");
auto path = TestingOpenMW::outputFilePathWithSubDir(subdir);
{
std::ofstream stream(path);
stream << content;
stream.close();
}
f(path);
f(subdir);
}
};
@ -46,7 +47,7 @@ namespace
const std::string content;
withShaderFile(content, [this](const std::filesystem::path& templateName) {
EXPECT_TRUE(mManager.getShader(Files::pathToUnicodeString(templateName), {}, osg::Shader::VERTEX));
EXPECT_TRUE(mManager.getShader(Files::pathToUnicodeString(templateName)));
});
}
@ -57,8 +58,7 @@ namespace
"void main() {}\n";
withShaderFile(content, [&](const std::filesystem::path& templateName) {
const auto shader
= mManager.getShader(Files::pathToUnicodeString(templateName), mDefines, osg::Shader::VERTEX);
const auto shader = mManager.getShader(Files::pathToUnicodeString(templateName), mDefines);
ASSERT_TRUE(shader);
EXPECT_EQ(shader->getShaderSource(), content);
});
@ -80,8 +80,7 @@ namespace
"void main() { bar() }\n";
withShaderFile(content2, [&](const std::filesystem::path& templateName2) {
const auto shader
= mManager.getShader(Files::pathToUnicodeString(templateName2), mDefines, osg::Shader::VERTEX);
const auto shader = mManager.getShader(Files::pathToUnicodeString(templateName2), mDefines);
ASSERT_TRUE(shader);
const std::string expected
= "#version 120\n"
@ -111,8 +110,7 @@ namespace
withShaderFile(content, [&](const std::filesystem::path& templateName) {
mDefines["flag"] = "1";
const auto shader
= mManager.getShader(Files::pathToUnicodeString(templateName), mDefines, osg::Shader::VERTEX);
const auto shader = mManager.getShader(Files::pathToUnicodeString(templateName), mDefines);
ASSERT_TRUE(shader);
const std::string expected
= "#version 120\n"
@ -133,8 +131,7 @@ namespace
withShaderFile(content, [&](const std::filesystem::path& templateName) {
mDefines["list"] = "1,2,3";
const auto shader
= mManager.getShader(Files::pathToUnicodeString(templateName), mDefines, osg::Shader::VERTEX);
const auto shader = mManager.getShader(Files::pathToUnicodeString(templateName), mDefines);
ASSERT_TRUE(shader);
const std::string expected
= "#version 120\n"
@ -174,8 +171,7 @@ namespace
withShaderFile(content, [&](const std::filesystem::path& templateName) {
mDefines["list"] = "1,2,3";
const auto shader
= mManager.getShader(Files::pathToUnicodeString(templateName), mDefines, osg::Shader::VERTEX);
const auto shader = mManager.getShader(Files::pathToUnicodeString(templateName), mDefines);
ASSERT_TRUE(shader);
const std::string expected
= "#version 120\n"
@ -221,7 +217,7 @@ namespace
"void main() {}\n";
withShaderFile(content, [&](const std::filesystem::path& templateName) {
EXPECT_FALSE(mManager.getShader(Files::pathToUnicodeString(templateName), mDefines, osg::Shader::VERTEX));
EXPECT_FALSE(mManager.getShader(Files::pathToUnicodeString(templateName), mDefines));
});
}
@ -233,7 +229,7 @@ namespace
"void main() {}\n";
withShaderFile(content, [&](const std::filesystem::path& templateName) {
EXPECT_FALSE(mManager.getShader(Files::pathToUnicodeString(templateName), mDefines, osg::Shader::VERTEX));
EXPECT_FALSE(mManager.getShader(Files::pathToUnicodeString(templateName), mDefines));
});
}
}

@ -18,6 +18,14 @@ namespace TestingOpenMW
return dir / Misc::StringUtils::stringToU8String(name);
}
inline std::filesystem::path outputFilePathWithSubDir(const std::filesystem::path& subpath)
{
std::filesystem::path path("tests_output");
path /= subpath;
std::filesystem::create_directories(path.parent_path());
return path;
}
inline std::filesystem::path temporaryFilePath(const std::string name)
{
return std::filesystem::temp_directory_path() / name;

@ -187,6 +187,6 @@ endmacro (pack_resource_file)
macro (copy_all_resource_files source_dir destination_dir_base destination_dir_relative files)
foreach (f ${files})
get_filename_component(filename ${f} NAME)
copy_resource_file("${source_dir}/${f}" "${destination_dir_base}" "${destination_dir_relative}/${filename}")
copy_resource_file("${source_dir}/${f}" "${destination_dir_base}" "${destination_dir_relative}/${f}")
endforeach (f)
endmacro (copy_all_resource_files)

@ -339,12 +339,8 @@ Debug::DebugDrawer::DebugDrawer(Shader::ShaderManager& shaderManager, osg::ref_p
: mParentNode(parentNode)
{
mCurrentFrame = 0;
auto vertexShader
= shaderManager.getShader("debug_vertex.glsl", Shader::ShaderManager::DefineMap(), osg::Shader::Type::VERTEX);
auto fragmentShader = shaderManager.getShader(
"debug_fragment.glsl", Shader::ShaderManager::DefineMap(), osg::Shader::Type::FRAGMENT);
auto program = shaderManager.getProgram(vertexShader, fragmentShader);
auto program = shaderManager.getProgram("debug");
mDebugDrawSceneObjects = new osg::Group;
mDebugDrawSceneObjects->setCullingActive(false);

@ -416,9 +416,7 @@ namespace osgMyGUI
void RenderManager::enableShaders(Shader::ShaderManager& shaderManager)
{
auto vertexShader = shaderManager.getShader("gui_vertex.glsl", {}, osg::Shader::VERTEX);
auto fragmentShader = shaderManager.getShader("gui_fragment.glsl", {}, osg::Shader::FRAGMENT);
auto program = shaderManager.getProgram(vertexShader, fragmentShader);
auto program = shaderManager.getProgram("gui");
mDrawable->getDrawableStateSet()->setAttributeAndModes(program, osg::StateAttribute::ON);
mDrawable->getDrawableStateSet()->addUniform(new osg::Uniform("diffuseMap", 0));

@ -1991,9 +1991,9 @@ namespace NifOsg
switch (static_cast<Nif::BSShaderType>(type))
{
case Nif::BSShaderType::ShaderType_Default:
return "nv_default";
return "bs/default";
case Nif::BSShaderType::ShaderType_NoLighting:
return "nv_nolighting";
return "bs/nolighting";
case Nif::BSShaderType::ShaderType_TallGrass:
case Nif::BSShaderType::ShaderType_Sky:
case Nif::BSShaderType::ShaderType_Skin:
@ -2001,10 +2001,10 @@ namespace NifOsg
case Nif::BSShaderType::ShaderType_Lighting30:
case Nif::BSShaderType::ShaderType_Tile:
Log(Debug::Warning) << "Unhandled BSShaderType " << type << " in " << mFilename;
return "nv_default";
return "bs/default";
}
Log(Debug::Warning) << "Unknown BSShaderType " << type << " in " << mFilename;
return "nv_default";
return "bs/default";
}
std::string_view getBSLightingShaderPrefix(unsigned int type) const
@ -2012,7 +2012,7 @@ namespace NifOsg
switch (static_cast<Nif::BSLightingShaderType>(type))
{
case Nif::BSLightingShaderType::ShaderType_Default:
return "nv_default";
return "bs/default";
case Nif::BSLightingShaderType::ShaderType_EnvMap:
case Nif::BSLightingShaderType::ShaderType_Glow:
case Nif::BSLightingShaderType::ShaderType_Parallax:
@ -2034,10 +2034,10 @@ namespace NifOsg
case Nif::BSLightingShaderType::ShaderType_MultitexLandLODBlend:
case Nif::BSLightingShaderType::ShaderType_Dismemberment:
Log(Debug::Warning) << "Unhandled BSLightingShaderType " << type << " in " << mFilename;
return "nv_default";
return "bs/default";
}
Log(Debug::Warning) << "Unknown BSLightingShaderType " << type << " in " << mFilename;
return "nv_default";
return "bs/default";
}
void handleProperty(const Nif::Property* property, osg::Node* node,

@ -922,7 +922,7 @@ void SceneUtil::MWShadowTechnique::setupCastingShader(Shader::ShaderManager & sh
{
// This can't be part of the constructor as OSG mandates that there be a trivial constructor available
osg::ref_ptr<osg::Shader> castingVertexShader = shaderManager.getShader("shadowcasting_vertex.glsl", { }, osg::Shader::VERTEX);
osg::ref_ptr<osg::Shader> castingVertexShader = shaderManager.getShader("shadowcasting.vert");
osg::ref_ptr<osg::GLExtensions> exts = osg::GLExtensions::Get(0, false);
std::string useGPUShader4 = exts && exts->isGpuShader4Supported ? "1" : "0";
for (int alphaFunc = GL_NEVER; alphaFunc <= GL_ALWAYS; ++alphaFunc)
@ -930,11 +930,11 @@ void SceneUtil::MWShadowTechnique::setupCastingShader(Shader::ShaderManager & sh
auto& program = _castingPrograms[alphaFunc - GL_NEVER];
program = new osg::Program();
program->addShader(castingVertexShader);
program->addShader(shaderManager.getShader("shadowcasting_fragment.glsl", { {"alphaFunc", std::to_string(alphaFunc)},
program->addShader(shaderManager.getShader("shadowcasting.frag", { {"alphaFunc", std::to_string(alphaFunc)},
{"alphaToCoverage", "0"},
{"adjustCoverage", "1"},
{"useGPUShader4", useGPUShader4}
}, osg::Shader::FRAGMENT));
}));
}
}

@ -16,6 +16,29 @@
#include <sstream>
#include <unordered_map>
namespace
{
osg::Shader::Type getShaderType(const std::string& templateName)
{
auto ext = std::filesystem::path(templateName).extension();
if (ext == ".vert")
return osg::Shader::VERTEX;
if (ext == ".frag")
return osg::Shader::FRAGMENT;
if (ext == ".geom")
return osg::Shader::GEOMETRY;
if (ext == ".comp")
return osg::Shader::COMPUTE;
if (ext == ".tese")
return osg::Shader::TESSEVALUATION;
if (ext == ".tesc")
return osg::Shader::TESSCONTROL;
throw std::runtime_error("unrecognized shader template name: " + templateName);
}
}
namespace Shader
{
@ -106,7 +129,11 @@ namespace Shader
return false;
}
std::string includeFilename = source.substr(start + 1, end - (start + 1));
std::filesystem::path includePath = shaderPath / includeFilename;
std::filesystem::path includePath
= shaderPath / std::filesystem::path(fileName).parent_path() / includeFilename;
if (!std::filesystem::exists(includePath))
includePath = shaderPath / includeFilename;
// Determine the line number that will be used for the #line directive following the included source
size_t lineDirectivePosition = source.rfind("#line", foundPos);
@ -471,10 +498,16 @@ namespace Shader
};
osg::ref_ptr<osg::Shader> ShaderManager::getShader(
const std::string& templateName, const ShaderManager::DefineMap& defines, osg::Shader::Type shaderType)
std::string templateName, const ShaderManager::DefineMap& defines, std::optional<osg::Shader::Type> type)
{
std::unique_lock<std::mutex> lock(mMutex);
// TODO: Implement mechanism to switch to core or compatibility profile shaders.
// This logic is temporary until core support is supported.
if (!templateName.starts_with("lib") && !templateName.starts_with("compatibility")
&& !templateName.starts_with("core"))
templateName = "compatibility/" + templateName;
// read the template if we haven't already
TemplateMap::iterator templateIt = mShaderTemplates.find(templateName);
std::set<std::filesystem::path> insertedPaths;
@ -514,7 +547,7 @@ namespace Shader
return nullptr;
}
osg::ref_ptr<osg::Shader> shader(new osg::Shader(shaderType));
osg::ref_ptr<osg::Shader> shader(new osg::Shader(type ? *type : getShaderType(templateName)));
shader->setShaderSource(shaderSource);
// Assign a unique prefix to allow the SharedStateManager to compare shaders efficiently.
// Append shader source filename for debugging.
@ -532,6 +565,18 @@ namespace Shader
return shaderIt->second;
}
osg::ref_ptr<osg::Program> ShaderManager::getProgram(
const std::string& templateName, const DefineMap& defines, const osg::Program* programTemplate)
{
auto vert = getShader(templateName + ".vert", defines);
auto frag = getShader(templateName + ".frag", defines);
if (!vert || !frag)
throw std::runtime_error("failed initializing shader: " + templateName);
return getProgram(vert, frag, programTemplate);
}
osg::ref_ptr<osg::Program> ShaderManager::getProgram(osg::ref_ptr<osg::Shader> vertexShader,
osg::ref_ptr<osg::Shader> fragmentShader, const osg::Program* programTemplate)
{

@ -5,6 +5,7 @@
#include <map>
#include <memory>
#include <mutex>
#include <optional>
#include <string>
#include <vector>
@ -36,13 +37,16 @@ namespace Shader
typedef std::map<std::string, std::string> DefineMap;
/// Create or retrieve a shader instance.
/// @param shaderTemplate The filename of the shader template.
/// @param templateName The path of the shader template.
/// @param defines Define values that can be retrieved by the shader template.
/// @param shaderType The type of shader (usually vertex or fragment shader).
/// @note May return nullptr on failure.
/// @note Thread safe.
osg::ref_ptr<osg::Shader> getShader(
const std::string& templateName, const DefineMap& defines, osg::Shader::Type shaderType);
osg::ref_ptr<osg::Shader> getShader(std::string templateName, const DefineMap& defines = {},
std::optional<osg::Shader::Type> type = std::nullopt);
osg::ref_ptr<osg::Program> getProgram(const std::string& templateName, const DefineMap& defines = {},
const osg::Program* programTemplate = nullptr);
osg::ref_ptr<osg::Program> getProgram(osg::ref_ptr<osg::Shader> vertexShader,
osg::ref_ptr<osg::Shader> fragmentShader, const osg::Program* programTemplate = nullptr);

@ -715,24 +715,14 @@ namespace Shader
if (!node.getUserValue("shaderPrefix", shaderPrefix))
shaderPrefix = mDefaultShaderPrefix;
osg::ref_ptr<osg::Shader> vertexShader(
mShaderManager.getShader(shaderPrefix + "_vertex.glsl", defineMap, osg::Shader::VERTEX));
osg::ref_ptr<osg::Shader> fragmentShader(
mShaderManager.getShader(shaderPrefix + "_fragment.glsl", defineMap, osg::Shader::FRAGMENT));
if (vertexShader && fragmentShader)
{
auto program = mShaderManager.getProgram(vertexShader, fragmentShader, mProgramTemplate);
auto program = mShaderManager.getProgram(shaderPrefix, defineMap, mProgramTemplate);
writableStateSet->setAttributeAndModes(program, osg::StateAttribute::ON);
addedState->setAttributeAndModes(program);
for (std::map<int, std::string>::const_iterator texIt = reqs.mTextures.begin();
texIt != reqs.mTextures.end(); ++texIt)
for (const auto& [unit, name] : reqs.mTextures)
{
writableStateSet->addUniform(
new osg::Uniform(texIt->second.c_str(), texIt->first), osg::StateAttribute::ON);
addedState->addUniform(texIt->second);
}
writableStateSet->addUniform(new osg::Uniform(name.c_str(), unit), osg::StateAttribute::ON);
addedState->addUniform(name);
}
if (!addedState->empty())

@ -285,17 +285,7 @@ namespace Terrain
defineMap["writeNormals"] = (it == layers.end() - 1) ? "1" : "0";
Stereo::Manager::instance().shaderStereoDefines(defineMap);
osg::ref_ptr<osg::Shader> vertexShader
= shaderManager.getShader("terrain_vertex.glsl", defineMap, osg::Shader::VERTEX);
osg::ref_ptr<osg::Shader> fragmentShader
= shaderManager.getShader("terrain_fragment.glsl", defineMap, osg::Shader::FRAGMENT);
if (!vertexShader || !fragmentShader)
{
// Try again without shader. Error already logged by above
return createPasses(false, sceneManager, layers, blendmaps, blendmapScale, layerTileSize);
}
stateset->setAttributeAndModes(shaderManager.getProgram(vertexShader, fragmentShader));
stateset->setAttributeAndModes(shaderManager.getProgram("terrain", defineMap));
stateset->addUniform(UniformCollection::value().mColorMode);
}
else

@ -7,55 +7,61 @@ set(SDIR ${CMAKE_CURRENT_SOURCE_DIR})
set(DDIRRELATIVE resources/shaders)
set(SHADER_FILES
groundcover_vertex.glsl
groundcover_fragment.glsl
water_vertex.glsl
water_fragment.glsl
alpha.glsl
depth.glsl
objects_vertex.glsl
objects_fragment.glsl
openmw_fragment.glsl
openmw_fragment.h.glsl
openmw_fragment_multiview.glsl
openmw_vertex.glsl
openmw_vertex.h.glsl
openmw_vertex_multiview.glsl
terrain_vertex.glsl
terrain_fragment.glsl
lighting.glsl
lighting_util.glsl
parallax.glsl
s360_fragment.glsl
s360_vertex.glsl
shadows_vertex.glsl
shadows_fragment.glsl
shadowcasting_vertex.glsl
shadowcasting_fragment.glsl
vertexcolors.glsl
multiview_resolve_vertex.glsl
multiview_resolve_fragment.glsl
nv_default_vertex.glsl
nv_default_fragment.glsl
nv_nolighting_vertex.glsl
nv_nolighting_fragment.glsl
blended_depth_postpass_vertex.glsl
blended_depth_postpass_fragment.glsl
gui_vertex.glsl
gui_fragment.glsl
debug_vertex.glsl
debug_fragment.glsl
sky_vertex.glsl
sky_fragment.glsl
skypasses.glsl
softparticles.glsl
hdr_resolve_fragment.glsl
hdr_luminance_fragment.glsl
fullscreen_tri_vertex.glsl
fullscreen_tri_fragment.glsl
fog.glsl
precipitation_vertex.glsl
precipitation_fragment.glsl
lib/water/fresnel.glsl
lib/water/ripples.glsl
lib/view/depth.glsl
lib/luminance/constants.glsl
lib/particle/soft.glsl
lib/particle/occlusion.glsl
lib/util/quickstep.glsl
lib/util/coordinates.glsl
lib/core/fragment.glsl
lib/core/fragment.h.glsl
lib/core/fragment_multiview.glsl
lib/core/vertex.glsl
lib/core/vertex.h.glsl
lib/core/vertex_multiview.glsl
lib/light/lighting.glsl
lib/light/lighting_util.glsl
lib/sky/passes.glsl
lib/material/parallax.glsl
lib/material/alpha.glsl
compatibility/fog.glsl
compatibility/groundcover.vert
compatibility/groundcover.frag
compatibility/water.vert
compatibility/water.frag
compatibility/objects.vert
compatibility/objects.frag
compatibility/terrain.vert
compatibility/terrain.frag
compatibility/s360.frag
compatibility/s360.vert
compatibility/shadows_vertex.glsl
compatibility/shadows_fragment.glsl
compatibility/shadowcasting.vert
compatibility/shadowcasting.frag
compatibility/vertexcolors.glsl
compatibility/multiview_resolve.vert
compatibility/multiview_resolve.frag
compatibility/depthclipped.vert
compatibility/depthclipped.frag
compatibility/gui.vert
compatibility/gui.frag
compatibility/debug.vert
compatibility/debug.frag
compatibility/sky.vert
compatibility/sky.frag
compatibility/fullscreen_tri.vert
compatibility/fullscreen_tri.frag
compatibility/bs/default.vert
compatibility/bs/default.frag
compatibility/bs/nolighting.vert
compatibility/bs/nolighting.frag
compatibility/luminance/resolve.frag
compatibility/luminance/luminance.frag
core/gui.frag
core/gui.vert
)
copy_all_resource_files(${CMAKE_CURRENT_SOURCE_DIR} ${OPENMW_RESOURCES_ROOT} ${DDIRRELATIVE} "${SHADER_FILES}")

@ -34,11 +34,13 @@ varying vec3 passViewPos;
varying vec3 passNormal;
uniform vec2 screenRes;
uniform float far;
uniform float alphaRef;
#include "vertexcolors.glsl"
#include "shadows_fragment.glsl"
#include "lighting.glsl"
#include "alpha.glsl"
#include "lib/light/lighting.glsl"
#include "lib/material/alpha.glsl"
#include "fog.glsl"
uniform float emissiveMult;
@ -57,7 +59,7 @@ void main()
vec4 diffuseColor = getDiffuseColor();
gl_FragData[0].a *= diffuseColor.a;
alphaTest();
gl_FragData[0].a = alphaTest(gl_FragData[0].a);
#if @normalMap
vec4 normalTex = texture2D(normalMap, normalMapUV);
@ -93,7 +95,7 @@ void main()
if (matSpec != vec3(0.0))
gl_FragData[0].xyz += getSpecular(viewNormal, normalize(passViewPos.xyz), shininess, matSpec) * shadowing;
gl_FragData[0] = applyFogAtDist(gl_FragData[0], euclideanDepth, linearDepth);
gl_FragData[0] = applyFogAtDist(gl_FragData[0], euclideanDepth, linearDepth, far);
#if defined(FORCE_OPAQUE) && FORCE_OPAQUE
// having testing & blending isn't enough - we need to write an opaque pixel to be opaque

@ -8,7 +8,7 @@
#extension GL_EXT_gpu_shader4: require
#endif
#include "openmw_vertex.h.glsl"
#include "lib/core/vertex.h.glsl"
#if @diffuseMap
varying vec2 diffuseMapUV;
#endif
@ -32,14 +32,14 @@ varying vec3 passNormal;
#include "vertexcolors.glsl"
#include "shadows_vertex.glsl"
#include "lighting.glsl"
#include "depth.glsl"
#include "lib/light/lighting.glsl"
#include "lib/view/depth.glsl"
void main(void)
{
gl_Position = mw_modelToClip(gl_Vertex);
gl_Position = modelToClip(gl_Vertex);
vec4 viewPos = mw_modelToView(gl_Vertex);
vec4 viewPos = modelToView(gl_Vertex);
gl_ClipVertex = viewPos;
euclideanDepth = length(viewPos.xyz);
linearDepth = getLinearDepth(gl_Position.z, viewPos.z);

@ -16,11 +16,13 @@ varying float linearDepth;
uniform bool useFalloff;
uniform vec2 screenRes;
uniform float emissiveMult;
uniform float far;
uniform float alphaRef;
varying float passFalloff;
#include "lib/material/alpha.glsl"
#include "vertexcolors.glsl"
#include "alpha.glsl"
#include "fog.glsl"
void main()
@ -41,11 +43,11 @@ void main()
gl_FragData[0].rgb *= emissionColor.rgb * emissiveMult;
gl_FragData[0].a *= emissionColor.a * emissionColor.a; // sic
alphaTest();
gl_FragData[0].a = alphaTest(gl_FragData[0].a);
#if defined(FORCE_OPAQUE) && FORCE_OPAQUE
gl_FragData[0].a = 1.0;
#endif
gl_FragData[0] = applyFogAtDist(gl_FragData[0], euclideanDepth, linearDepth);
gl_FragData[0] = applyFogAtDist(gl_FragData[0], euclideanDepth, linearDepth, far);
}

@ -1,6 +1,6 @@
#version 120
#include "openmw_vertex.h.glsl"
#include "lib/core/vertex.h.glsl"
#if @diffuseMap
varying vec2 diffuseMapUV;
@ -18,13 +18,13 @@ uniform vec4 falloffParams;
varying float passFalloff;
#include "vertexcolors.glsl"
#include "depth.glsl"
#include "lib/view/depth.glsl"
void main(void)
{
gl_Position = mw_modelToClip(gl_Vertex);
gl_Position = modelToClip(gl_Vertex);
vec4 viewPos = mw_modelToView(gl_Vertex);
vec4 viewPos = modelToView(gl_Vertex);
gl_ClipVertex = viewPos;
#if @radialFog
euclideanDepth = length(viewPos.xyz);

@ -1,6 +1,6 @@
#version 120
#include "openmw_vertex.h.glsl"
#include "lib/core/vertex.h.glsl"
uniform vec3 color;
uniform vec3 trans;
@ -15,13 +15,13 @@ void main()
{
if(!useAdvancedShader)
{
gl_Position = mw_modelToClip( vec4(gl_Vertex));
gl_Position = modelToClip( vec4(gl_Vertex));
vertexNormal = vec3(1., 1., 1.);
passColor = gl_Color;
}
else
{
gl_Position = mw_modelToClip( vec4(gl_Vertex.xyz * scale + trans,1));
gl_Position = modelToClip( vec4(gl_Vertex.xyz * scale + trans,1));
vertexNormal = useNormalAsColor ? vec3(1., 1., 1.) : gl_Normal.xyz;
vec3 colorOut = useNormalAsColor? gl_Normal.xyz : color;

@ -15,5 +15,5 @@ void main()
discard;
// DO NOT write to color!
// This is a post-pass of transparent objects in charge of only updating depth buffer.
// This is in charge of only updating depth buffer.
}

@ -1,16 +1,17 @@
#version 120
uniform mat4 projectionMatrix;
varying vec2 diffuseMapUV;
varying float alphaPassthrough;
#include "openmw_vertex.h.glsl"
#include "lib/core/vertex.h.glsl"
#include "vertexcolors.glsl"
void main()
{
gl_Position = mw_modelToClip(gl_Vertex);
gl_Position = modelToClip(gl_Vertex);
vec4 viewPos = modelToView(gl_Vertex);
gl_ClipVertex = viewPos;
if (colorMode == 2)
alphaPassthrough = gl_Color.a;

@ -1,12 +1,10 @@
uniform float far;
#if @skyBlending
#include "openmw_fragment.h.glsl"
#include "lib/core/fragment.h.glsl"
uniform float skyBlendingStart;
#endif
vec4 applyFogAtDist(vec4 color, float euclideanDist, float linearDist)
vec4 applyFogAtDist(vec4 color, float euclideanDist, float linearDist, float far)
{
#if @radialFog
float dist = euclideanDist;
@ -30,14 +28,14 @@ vec4 applyFogAtDist(vec4 color, float euclideanDist, float linearDist)
#ifdef ADDITIVE_BLENDING
color.xyz *= fadeValue;
#else
color.xyz = mix(mw_sampleSkyColor(gl_FragCoord.xy / screenRes), color.xyz, fadeValue);
color.xyz = mix(sampleSkyColor(gl_FragCoord.xy / screenRes), color.xyz, fadeValue);
#endif
#endif
return color;
}
vec4 applyFogAtPos(vec4 color, vec3 pos)
vec4 applyFogAtPos(vec4 color, vec3 pos, float far)
{
return applyFogAtDist(color, length(pos), pos.z);
return applyFogAtDist(color, length(pos), pos.z, far);
}

@ -0,0 +1,10 @@
#version 120
varying vec2 uv;
#include "lib/core/fragment.h.glsl"
void main()
{
gl_FragColor = samplerLastShader(uv);
}

@ -4,7 +4,7 @@ uniform vec2 scaling = vec2(1.0, 1.0);
varying vec2 uv;
#include "openmw_vertex.h.glsl"
#include "lib/core/vertex.h.glsl"
void main()
{

@ -28,6 +28,8 @@ varying vec4 passTangent;
varying float euclideanDepth;
varying float linearDepth;
uniform vec2 screenRes;
uniform float far;
uniform float alphaRef;
#if PER_PIXEL_LIGHTING
varying vec3 passViewPos;
@ -39,8 +41,8 @@ centroid varying vec3 shadowDiffuseLighting;
varying vec3 passNormal;
#include "shadows_fragment.glsl"
#include "lighting.glsl"
#include "alpha.glsl"
#include "lib/light/lighting.glsl"
#include "lib/material/alpha.glsl"
#include "fog.glsl"
void main()
@ -68,7 +70,7 @@ void main()
if (euclideanDepth > @groundcoverFadeStart)
gl_FragData[0].a *= 1.0-smoothstep(@groundcoverFadeStart, @groundcoverFadeEnd, euclideanDepth);
alphaTest();
gl_FragData[0].a = alphaTest(gl_FragData[0].a);
float shadowing = unshadowedLightRatio(linearDepth);
@ -84,7 +86,7 @@ void main()
clampLightingResult(lighting);
gl_FragData[0].xyz *= lighting;
gl_FragData[0] = applyFogAtDist(gl_FragData[0], euclideanDepth, linearDepth);
gl_FragData[0] = applyFogAtDist(gl_FragData[0], euclideanDepth, linearDepth, far);
#if !@disableNormals
gl_FragData[1].xyz = viewNormal * 0.5 + 0.5;

@ -8,7 +8,7 @@
#extension GL_EXT_gpu_shader4: require
#endif
#include "openmw_vertex.h.glsl"
#include "lib/core/vertex.h.glsl"
#define GROUNDCOVER
@ -41,8 +41,8 @@ centroid varying vec3 shadowDiffuseLighting;
varying vec3 passNormal;
#include "shadows_vertex.glsl"
#include "lighting.glsl"
#include "depth.glsl"
#include "lib/light/lighting.glsl"
#include "lib/view/depth.glsl"
uniform float osg_SimulationTime;
uniform mat4 osg_ViewMatrixInverse;
@ -145,7 +145,7 @@ void main(void)
if (length(gl_ModelViewMatrix * vec4(position, 1.0)) > @groundcoverFadeEnd)
gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
else
gl_Position = mw_viewToClip(viewPos);
gl_Position = viewToClip(viewPos);
linearDepth = getLinearDepth(gl_Position.z, viewPos.z);

@ -1,12 +1,14 @@
#version 120
#include "lib/luminance/constants.glsl"
varying vec2 uv;
uniform sampler2D sceneTex;
void main()
{
float lum = dot(texture2D(sceneTex, uv).rgb, vec3(0.2126, 0.7152, 0.0722));
lum = max(lum, @epsilon);
lum = max(lum, epsilon);
gl_FragColor.r = clamp((log2(lum) - @minLog) * @invLogLumRange, 0.0, 1.0);
gl_FragColor.r = clamp((log2(lum) - minLog) * invLogLumRange, 0.0, 1.0);
}

@ -1,5 +1,7 @@
#version 120
#include "lib/luminance/constants.glsl"
varying vec2 uv;
uniform sampler2D luminanceSceneTex;
uniform sampler2D prevLuminanceSceneTex;
@ -11,6 +13,6 @@ void main()
float prevLum = texture2D(prevLuminanceSceneTex, vec2(0.5, 0.5)).r;
float currLum = texture2D(luminanceSceneTex, vec2(0.5, 0.5)).r;
float avgLum = exp2((currLum * @logLumRange) + @minLog);
gl_FragColor.r = prevLum + (avgLum - prevLum) * (1.0 - exp(-osg_DeltaFrameTime * @hdrExposureTime));
float avgLum = exp2((currLum * logLumRange) + minLog);
gl_FragColor.r = prevLum + (avgLum - prevLum) * (1.0 - exp(-osg_DeltaFrameTime * hdrExposureTime));
}

@ -2,7 +2,7 @@
#extension GL_EXT_texture_array : require
varying vec2 uv;
uniform sampler2DArray omw_SamplerLastShader;
uniform sampler2DArray lastShader;
void main()
{
@ -14,5 +14,5 @@ void main()
uvz.z = 1;
}
gl_FragColor = texture2DArray(omw_SamplerLastShader, uvz);
gl_FragColor = texture2DArray(lastShader, uvz);
}

@ -64,6 +64,9 @@ varying vec2 glossMapUV;
#endif
uniform vec2 screenRes;
uniform float near;
uniform float far;
uniform float alphaRef;
#define PER_PIXEL_LIGHTING (@normalMap || @forcePPL)
@ -83,37 +86,29 @@ varying vec3 passNormal;
#include "vertexcolors.glsl"
#include "shadows_fragment.glsl"
#include "lighting.glsl"
#include "parallax.glsl"
#include "alpha.glsl"
#include "lib/light/lighting.glsl"
#include "lib/material/parallax.glsl"
#include "lib/material/alpha.glsl"
#include "fog.glsl"
#if @softParticles
#include "softparticles.glsl"
#include "lib/particle/soft.glsl"
uniform sampler2D opaqueDepthTex;
uniform float particleSize;
uniform bool particleFade;
#endif
#if @particleOcclusion
#include "lib/particle/occlusion.glsl"
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();
applyOcclusionDiscard(orthoDepthMapCoord, texture2D(orthoDepthMap, orthoDepthMapCoord.xy * 0.5 + 0.5).r);
#endif
#if @diffuseMap
@ -169,7 +164,7 @@ vec3 viewNormal = normalize(gl_NormalMatrix * normal);
gl_FragData[0].a *= coveragePreservingAlphaScale(darkMap, darkMapUV);
#endif
alphaTest();
gl_FragData[0].a = alphaTest(gl_FragData[0].a);
#if @detailMap
gl_FragData[0].xyz *= texture2D(detailMap, detailMapUV).xyz * 2.0;
@ -248,10 +243,20 @@ vec3 viewNormal = normalize(gl_NormalMatrix * normal);
gl_FragData[0].xyz += getSpecular(viewNormal, viewVec, shininess, matSpec) * shadowing;
}
gl_FragData[0] = applyFogAtPos(gl_FragData[0], passViewPos);
gl_FragData[0] = applyFogAtPos(gl_FragData[0], passViewPos, far);
vec2 screenCoords = gl_FragCoord.xy / screenRes;
#if !defined(FORCE_OPAQUE) && @softParticles
gl_FragData[0].a *= calcSoftParticleFade(viewVec, viewNormal, passViewPos);
gl_FragData[0].a *= calcSoftParticleFade(
viewVec,
passViewPos,
viewNormal,
near,
far,
texture2D(opaqueDepthTex, screenCoords).x,
particleSize,
particleFade
);
#endif
#if defined(FORCE_OPAQUE) && FORCE_OPAQUE

@ -8,7 +8,7 @@
#extension GL_EXT_gpu_shader4: require
#endif
#include "openmw_vertex.h.glsl"
#include "lib/core/vertex.h.glsl"
#if @diffuseMap
varying vec2 diffuseMapUV;
#endif
@ -63,8 +63,8 @@ varying vec3 passNormal;
#include "vertexcolors.glsl"
#include "shadows_vertex.glsl"
#include "lighting.glsl"
#include "depth.glsl"
#include "lib/light/lighting.glsl"
#include "lib/view/depth.glsl"
#if @particleOcclusion
varying vec3 orthoDepthMapCoord;
@ -80,9 +80,9 @@ void main(void)
orthoDepthMapCoord = ((depthSpaceMatrix * model) * vec4(gl_Vertex.xyz, 1.0)).xyz;
#endif
gl_Position = mw_modelToClip(gl_Vertex);
gl_Position = modelToClip(gl_Vertex);
vec4 viewPos = mw_modelToView(gl_Vertex);
vec4 viewPos = modelToView(gl_Vertex);
gl_ClipVertex = viewPos;
#if (@envMap || !PER_PIXEL_LIGHTING || @shadows_enabled)

@ -0,0 +1,21 @@
#version 120
varying vec2 uv;
uniform samplerCube cubeMap;
uniform int mapping;
#include "lib/util/coordinates.glsl"
void main(void)
{
vec3 c;
if (mapping == 0)
c = sphericalCoords(uv);
else if (mapping == 1)
c = cylindricalCoords(uv);
else
c = planetCoords(uv);
gl_FragData[0] = textureCube(cubeMap,c);
}

@ -11,8 +11,9 @@ varying float alphaPassthrough;
uniform bool useDiffuseMapForShadowAlpha;
uniform bool alphaTestShadows;
uniform float alphaRef;
#include "alpha.glsl"
#include "lib/material/alpha.glsl"
void main()
{
@ -22,7 +23,7 @@ void main()
else
gl_FragData[0].a = alphaPassthrough;
alphaTest();
gl_FragData[0].a = alphaTest(gl_FragData[0].a);
// Prevent translucent things casting shadow (including the player using an invisibility effect).
// This replaces alpha blending, which obviously doesn't work with depth buffers

@ -1,6 +1,6 @@
#version 120
#include "skypasses.glsl"
#include "lib/sky/passes.glsl"
uniform int pass;
uniform sampler2D diffuseMap;

@ -1,8 +1,8 @@
#version 120
#include "openmw_vertex.h.glsl"
#include "lib/core/vertex.h.glsl"
#include "skypasses.glsl"
#include "lib/sky/passes.glsl"
uniform int pass;
@ -11,7 +11,7 @@ varying vec2 diffuseMapUV;
void main()
{
gl_Position = mw_modelToClip(gl_Vertex);
gl_Position = modelToClip(gl_Vertex);
passColor = gl_Color;
if (pass == PASS_CLOUDS)

@ -33,11 +33,12 @@ varying vec3 passViewPos;
varying vec3 passNormal;
uniform vec2 screenRes;
uniform float far;
#include "vertexcolors.glsl"
#include "shadows_fragment.glsl"
#include "lighting.glsl"
#include "parallax.glsl"
#include "lib/light/lighting.glsl"
#include "lib/material/parallax.glsl"
#include "fog.glsl"
void main()
@ -110,7 +111,7 @@ void main()
gl_FragData[0].xyz += getSpecular(viewNormal, normalize(passViewPos), shininess, matSpec) * shadowing;
}
gl_FragData[0] = applyFogAtDist(gl_FragData[0], euclideanDepth, linearDepth);
gl_FragData[0] = applyFogAtDist(gl_FragData[0], euclideanDepth, linearDepth, far);
#if !@disableNormals && @writeNormals
gl_FragData[1].xyz = viewNormal * 0.5 + 0.5;

@ -8,7 +8,7 @@
#extension GL_EXT_gpu_shader4: require
#endif
#include "openmw_vertex.h.glsl"
#include "lib/core/vertex.h.glsl"
varying vec2 uv;
varying float euclideanDepth;
varying float linearDepth;
@ -25,14 +25,14 @@ varying vec3 passNormal;
#include "vertexcolors.glsl"
#include "shadows_vertex.glsl"
#include "lighting.glsl"
#include "depth.glsl"
#include "lib/light/lighting.glsl"
#include "lib/view/depth.glsl"
void main(void)
{
gl_Position = mw_modelToClip(gl_Vertex);
gl_Position = modelToClip(gl_Vertex);
vec4 viewPos = mw_modelToView(gl_Vertex);
vec4 viewPos = modelToView(gl_Vertex);
gl_ClipVertex = viewPos;
euclideanDepth = length(viewPos.xyz);
linearDepth = getLinearDepth(gl_Position.z, viewPos.z);

@ -8,10 +8,9 @@
#extension GL_EXT_gpu_shader4: require
#endif
#include "openmw_fragment.h.glsl"
#include "lib/core/fragment.h.glsl"
#define REFRACTION @refraction_enabled
#define RAIN_RIPPLE_DETAIL @rain_ripple_detail
// Inspired by Blender GLSL Water by martinsh ( https://devlog-martinsh.blogspot.de/2012/07/waterundewater-shader-wip.html )
@ -56,153 +55,12 @@ const vec3 WATER_COLOR = vec3(0.090195, 0.115685, 0.12745);
const float WOBBLY_SHORE_FADE_DISTANCE = 6200.0; // fade out wobbly shores to mask precision errors, the effect is almost impossible to see at a distance
// ---------------- rain ripples related stuff ---------------------
const float RAIN_RIPPLE_GAPS = 10.0;
const float RAIN_RIPPLE_RADIUS = 0.2;
float scramble(float x, float z)
{
return fract(pow(fract(x)*3.0+1.0, z));
}
vec2 randOffset(vec2 c, float time)
{
time = fract(time/1000.0);
c = vec2(c.x * c.y / 8.0 + c.y * 0.3 + c.x * 0.2,
c.x * c.y / 14.0 + c.y * 0.5 + c.x * 0.7);
c.x *= scramble(scramble(time + c.x/1000.0, 4.0), 3.0) + 1.0;
c.y *= scramble(scramble(time + c.y/1000.0, 3.5), 3.0) + 1.0;
return fract(c);
}
float randPhase(vec2 c)
{
return fract((c.x * c.y) / (c.x + c.y + 0.1));
}
float blip(float x)
{
x = max(0.0, 1.0-x*x);
return x*x*x;
}
float blipDerivative(float x)
{
x = clamp(x, -1.0, 1.0);
float n = x*x-1.0;
return -6.0*x*n*n;
}
const float RAIN_RING_TIME_OFFSET = 1.0/6.0;
vec4 circle(vec2 coords, vec2 corner, float adjusted_time)
{
vec2 center = vec2(0.5,0.5) + (0.5 - RAIN_RIPPLE_RADIUS) * (2.0 * randOffset(corner, floor(adjusted_time)) - 1.0);
float phase = fract(adjusted_time);
vec2 toCenter = coords - center;
float r = RAIN_RIPPLE_RADIUS;
float d = length(toCenter);
float ringfollower = (phase-d/r)/RAIN_RING_TIME_OFFSET-1.0; // -1.0 ~ +1.0 cover the breadth of the ripple's ring
#if RAIN_RIPPLE_DETAIL > 0
// normal mapped ripples
if(ringfollower < -1.0 || ringfollower > 1.0)
return vec4(0.0);
if(d > 1.0) // normalize center direction vector, but not for near-center ripples
toCenter /= d;
float height = blip(ringfollower*2.0+0.5); // brighten up outer edge of ring; for fake specularity
float range_limit = blip(min(0.0, ringfollower));
float energy = 1.0-phase;
vec2 normal2d = -toCenter*blipDerivative(ringfollower)*5.0;
vec3 normal = vec3(normal2d, 0.5);
vec4 ret = vec4(normal, height);
ret.xyw *= energy*energy;
// do energy adjustment here rather than later, so that we can use the w component for fake specularity
ret.xyz = normalize(ret.xyz) * energy*range_limit;
ret.z *= range_limit;
return ret;
#else
// ring-only ripples
if(ringfollower < -1.0 || ringfollower > 0.5)
return vec4(0.0);
float energy = 1.0-phase;
float height = blip(ringfollower*2.0+0.5)*energy*energy; // fake specularity
return vec4(0.0, 0.0, 0.0, height);
#endif
}
vec4 rain(vec2 uv, float time)
{
uv *= RAIN_RIPPLE_GAPS;
vec2 f_part = fract(uv);
vec2 i_part = floor(uv);
float adjusted_time = time * 1.2 + randPhase(i_part);
#if RAIN_RIPPLE_DETAIL > 0
vec4 a = circle(f_part, i_part, adjusted_time);
vec4 b = circle(f_part, i_part, adjusted_time - RAIN_RING_TIME_OFFSET);
vec4 c = circle(f_part, i_part, adjusted_time - RAIN_RING_TIME_OFFSET*2.0);
vec4 d = circle(f_part, i_part, adjusted_time - RAIN_RING_TIME_OFFSET*3.0);
vec4 ret;
ret.xy = a.xy - b.xy/2.0 + c.xy/4.0 - d.xy/8.0;
// z should always point up
ret.z = a.z + b.z /2.0 + c.z /4.0 + d.z /8.0;
//ret.xyz *= 1.5;
// fake specularity looks weird if we use every single ring, also if the inner rings are too bright
ret.w = (a.w + c.w /8.0)*1.5;
return ret;
#else
return circle(f_part, i_part, adjusted_time) * 1.5;
#endif
}
vec2 complex_mult(vec2 a, vec2 b)
{
return vec2(a.x*b.x - a.y*b.y, a.x*b.y + a.y*b.x);
}
vec4 rainCombined(vec2 uv, float time) // returns ripple normal in xyz and fake specularity in w
{
return
rain(uv, time)
+ rain(complex_mult(uv, vec2(0.4, 0.7)) + vec2(1.2, 3.0),time)
#if RAIN_RIPPLE_DETAIL == 2
+ rain(uv * 0.75 + vec2( 3.7,18.9),time)
+ rain(uv * 0.9 + vec2( 5.7,30.1),time)
+ rain(uv * 1.0 + vec2(10.5 ,5.7),time)
#endif
;
}
// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
float fresnel_dielectric(vec3 Incoming, vec3 Normal, float eta)
{
float c = abs(dot(Incoming, Normal));
float g = eta * eta - 1.0 + c * c;
float result;
if(g > 0.0) {
g = sqrt(g);
float A =(g - c)/(g + c);
float B =(c *(g + c)- 1.0)/(c *(g - c)+ 1.0);
result = 0.5 * A * A *(1.0 + B * B);
}
else
result = 1.0; /* TIR (no refracted component) */
return result;
}
vec2 normalCoords(vec2 uv, float scale, float speed, float time, float timer1, float timer2, vec3 previousNormal)
{
{
return uv * (WAVE_SCALE * scale) + WIND_DIR * time * (WIND_SPEED * speed) -(previousNormal.xy/previousNormal.zz) * WAVE_CHOPPYNESS + vec2(time * timer1,time * timer2);
}
}
varying vec4 position;
varying float linearDepth;
@ -212,6 +70,7 @@ uniform sampler2D normalMap;
uniform float osg_SimulationTime;
uniform float near;
uniform float far;
uniform vec3 nodePosition;
uniform float rainIntensity;
@ -221,24 +80,14 @@ uniform vec2 screenRes;
#define PER_PIXEL_LIGHTING 0
#include "shadows_fragment.glsl"
#include "lighting.glsl"
#include "lib/light/lighting.glsl"
#include "fog.glsl"
float frustumDepth;
float linearizeDepth(float depth)
{
#if @reverseZ
depth = 1.0 - depth;
#endif
float z_n = 2.0 * depth - 1.0;
depth = 2.0 * near * far / (far + near - z_n * frustumDepth);
return depth;
}
#include "lib/water/fresnel.glsl"
#include "lib/water/ripples.glsl"
#include "lib/view/depth.glsl"
void main(void)
{
frustumDepth = abs(far - near);
vec3 worldPos = position.xyz + nodePosition.xyz;
vec2 UV = worldPos.xy / (8192.0*5.0) * 3.0;
UV.y *= -1.0;
@ -297,14 +146,14 @@ void main(void)
vec2 screenCoordsOffset = normal.xy * REFL_BUMP;
#if REFRACTION
float depthSample = linearizeDepth(mw_sampleRefractionDepthMap(screenCoords)) * radialise;
float depthSampleDistorted = linearizeDepth(mw_sampleRefractionDepthMap(screenCoords-screenCoordsOffset)) * radialise;
float surfaceDepth = linearizeDepth(gl_FragCoord.z) * radialise;
float depthSample = linearizeDepth(sampleRefractionDepthMap(screenCoords), near, far) * radialise;
float depthSampleDistorted = linearizeDepth(sampleRefractionDepthMap(screenCoords-screenCoordsOffset), near, far) * radialise;
float surfaceDepth = linearizeDepth(gl_FragCoord.z, near, far) * radialise;
float realWaterDepth = depthSample - surfaceDepth; // undistorted water depth in view direction, independent of frustum
screenCoordsOffset *= clamp(realWaterDepth / BUMP_SUPPRESS_DEPTH,0,1);
#endif
// reflection
vec3 reflection = mw_sampleReflectionMap(screenCoords + screenCoordsOffset).rgb;
vec3 reflection = sampleReflectionMap(screenCoords + screenCoordsOffset).rgb;
// specular
float specular = pow(max(dot(reflect(vVec, normal), lVec), 0.0),SPEC_HARDNESS) * shadow;
@ -322,7 +171,7 @@ void main(void)
rainSpecular *= clamp(fresnel*6.0 + specular * sunSpec.w, 0.0, 1.0);
// refraction
vec3 refraction = mw_sampleRefractionMap(screenCoords - screenCoordsOffset).rgb;
vec3 refraction = sampleRefractionMap(screenCoords - screenCoordsOffset).rgb;
vec3 rawRefraction = refraction;
// brighten up the refraction underwater
@ -357,7 +206,7 @@ void main(void)
gl_FragData[0].w = clamp(fresnel*6.0 + specular * sunSpec.w, 0.0, 1.0); //clamp(fresnel*2.0 + specular * gl_LightSource[0].specular.w, 0.0, 1.0);
#endif
gl_FragData[0] = applyFogAtDist(gl_FragData[0], radialDepth, linearDepth);
gl_FragData[0] = applyFogAtDist(gl_FragData[0], radialDepth, linearDepth, far);
#if !@disableNormals
gl_FragData[1].rgb = normalize(gl_NormalMatrix * normal) * 0.5 + 0.5;

@ -1,20 +1,20 @@
#version 120
#include "openmw_vertex.h.glsl"
#include "lib/core/vertex.h.glsl"
varying vec4 position;
varying float linearDepth;
#include "shadows_vertex.glsl"
#include "depth.glsl"
#include "lib/view/depth.glsl"
void main(void)
{
gl_Position = mw_modelToClip(gl_Vertex);
gl_Position = modelToClip(gl_Vertex);
position = gl_Vertex;
vec4 viewPos = mw_modelToView(gl_Vertex);
vec4 viewPos = modelToView(gl_Vertex);
linearDepth = getLinearDepth(gl_Position.z, viewPos.z);
setupShadowCoords(viewPos, normalize((gl_NormalMatrix * gl_Normal).xyz));

@ -0,0 +1,15 @@
#version 430 core
layout (location = 0) in vec4 Position;
layout (location = 3) in vec4 Color;
layout (location = 8) in vec3 TexCoord0;
out vec4 passColor;
out vec2 uv;
void main()
{
gl_Position = vec4(Position.xyz, 1.0);
uv = TexCoord0.xy;
passColor = Color;
}

@ -0,0 +1,13 @@
#version 430 core
layout(location = 0) out vec4 Color;
layout(location = 0) uniform sampler2D diffuseMap;
in vec4 passColor;
in vec2 uv;
void main()
{
Color = texture(diffuseMap, uv) * passColor;
}

@ -1,12 +0,0 @@
#if @reverseZ
uniform float linearFac;
#endif
float getLinearDepth(in float z, in float viewZ)
{
#if @reverseZ
return linearFac*viewZ;
#else
return z;
#endif
}

@ -1,10 +0,0 @@
#version 120
varying vec2 uv;
#include "openmw_fragment.h.glsl"
void main()
{
gl_FragColor = mw_samplerLastShader(uv);
}

@ -1,10 +1,10 @@
#version 120
#include "openmw_fragment.h.glsl"
#include "lib/core/fragment.h.glsl"
uniform sampler2D reflectionMap;
vec4 mw_sampleReflectionMap(vec2 uv)
vec4 sampleReflectionMap(vec2 uv)
{
return texture2D(reflectionMap, uv);
}
@ -13,29 +13,29 @@ vec4 mw_sampleReflectionMap(vec2 uv)
uniform sampler2D refractionMap;
uniform sampler2D refractionDepthMap;
vec4 mw_sampleRefractionMap(vec2 uv)
vec4 sampleRefractionMap(vec2 uv)
{
return texture2D(refractionMap, uv);
}
float mw_sampleRefractionDepthMap(vec2 uv)
float sampleRefractionDepthMap(vec2 uv)
{
return texture2D(refractionDepthMap, uv).x;
}
#endif
uniform sampler2D omw_SamplerLastShader;
uniform sampler2D lastShader;
vec4 mw_samplerLastShader(vec2 uv)
vec4 samplerLastShader(vec2 uv)
{
return texture2D(omw_SamplerLastShader, uv);
return texture2D(lastShader, uv);
}
#if @skyBlending
uniform sampler2D sky;
vec3 mw_sampleSkyColor(vec2 uv)
vec3 sampleSkyColor(vec2 uv)
{
return texture2D(sky, uv).xyz;
}

@ -0,0 +1,20 @@
#ifndef OPENMW_FRAGMENT_H_GLSL
#define OPENMW_FRAGMENT_H_GLSL
@link "lib/core/fragment.glsl" if !@useOVR_multiview
@link "lib/core/fragment_multiview.glsl" if @useOVR_multiview
vec4 sampleReflectionMap(vec2 uv);
#if @refraction_enabled
vec4 sampleRefractionMap(vec2 uv);
float sampleRefractionDepthMap(vec2 uv);
#endif
vec4 samplerLastShader(vec2 uv);
#if @skyBlending
vec3 sampleSkyColor(vec2 uv);
#endif
#endif // OPENMW_FRAGMENT_H_GLSL

@ -0,0 +1,46 @@
#version 330
#extension GL_OVR_multiview : require
#extension GL_OVR_multiview2 : require
#include "lib/core/fragment.h.glsl"
uniform sampler2DArray reflectionMap;
vec4 sampleReflectionMap(vec2 uv)
{
return texture(reflectionMap, vec3((uv), gl_ViewID_OVR));
}
#if @refraction_enabled
uniform sampler2DArray refractionMap;
uniform sampler2DArray refractionDepthMap;
vec4 sampleRefractionMap(vec2 uv)
{
return texture(refractionMap, vec3((uv), gl_ViewID_OVR));
}
float sampleRefractionDepthMap(vec2 uv)
{
return texture(refractionDepthMap, vec3((uv), gl_ViewID_OVR)).x;
}
#endif
uniform sampler2DArray lastShader;
vec4 samplerLastShader(vec2 uv)
{
return texture(lastShader, vec3((uv), gl_ViewID_OVR));
}
#if @skyBlending
uniform sampler2DArray sky;
vec3 sampleSkyColor(vec2 uv)
{
return texture(sky, vec3((uv), gl_ViewID_OVR)).xyz;
}
#endif

@ -0,0 +1,20 @@
#version 120
#include "lib/core/vertex.h.glsl"
uniform mat4 projectionMatrix;
vec4 modelToClip(vec4 pos)
{
return projectionMatrix * modelToView(pos);
}
vec4 modelToView(vec4 pos)
{
return gl_ModelViewMatrix * pos;
}
vec4 viewToClip(vec4 pos)
{
return projectionMatrix * pos;
}

@ -0,0 +1,6 @@
@link "lib/core/vertex.glsl" if !@useOVR_multiview
@link "lib/core/vertex_multiview.glsl" if @useOVR_multiview
vec4 modelToClip(vec4 pos);
vec4 modelToView(vec4 pos);
vec4 viewToClip(vec4 pos);

@ -1,25 +1,25 @@
#version 330 compatibility
#version 330
#extension GL_OVR_multiview : require
#extension GL_OVR_multiview2 : require
layout(num_views = @numViews) in;
#include "openmw_vertex.h.glsl"
#include "lib/core/vertex.h.glsl"
uniform mat4 projectionMatrixMultiView[@numViews];
vec4 mw_modelToClip(vec4 pos)
vec4 modelToClip(vec4 pos)
{
return mw_viewToClip(mw_modelToView(pos));
return viewToClip(modelToView(pos));
}
vec4 mw_modelToView(vec4 pos)
vec4 modelToView(vec4 pos)
{
return gl_ModelViewMatrix * pos;
}
vec4 mw_viewToClip(vec4 pos)
vec4 viewToClip(vec4 pos)
{
return projectionMatrixMultiView[gl_ViewID_OVR] * pos;
}

@ -1,3 +1,6 @@
#ifndef LIB_LIGHT_LIGHTING
#define LIB_LIGHT_LIGHTING
#include "lighting_util.glsl"
void perLightSun(out vec3 diffuseOut, vec3 viewPos, vec3 viewNormal)
@ -97,3 +100,5 @@ vec3 getSpecular(vec3 viewNormal, vec3 viewDirection, float shininess, vec3 matS
float NdotH = dot(viewNormal, halfVec);
return pow(max(NdotH, 0.0), max(1e-4, shininess)) * lcalcSpecular(0).xyz * matSpec;
}
#endif

@ -1,10 +1,7 @@
float quickstep(float x)
{
x = clamp(x, 0.0, 1.0);
x = 1.0 - x*x;
x = 1.0 - x*x;
return x;
}
#ifndef LIB_LIGHTING_UTIL
#define LIB_LIGHTING_UTIL
#include "lib/util/quickstep.glsl"
#if @lightingMethodUBO
@ -136,3 +133,5 @@ void clampLightingResult(inout vec3 lighting)
lighting = max(lighting, 0.0);
#endif
}
#endif

@ -0,0 +1,11 @@
#ifndef LUMINANCE_CONSTANTS
#define LUMINANCE_CONSTANTS
const float minLog = -9.0;
const float maxLog = 4.0;
const float logLumRange = (maxLog - minLog);
const float invLogLumRange = 1.0 / logLumRange;
const float epsilon = 0.004;
const float hdrExposureTime = @hdrExposureTime;
#endif

@ -1,3 +1,5 @@
#ifndef LIB_MATERIAL_ALPHA
#define LIB_MATERIAL_ALPHA
#define FUNC_NEVER 512 // 0x0200
#define FUNC_LESS 513 // 0x0201
@ -8,10 +10,6 @@
#define FUNC_GEQUAL 518 // 0x0206
#define FUNC_ALWAYS 519 // 0x0207
#if @alphaFunc != FUNC_ALWAYS && @alphaFunc != FUNC_NEVER
uniform float alphaRef;
#endif
float mipmapLevel(vec2 scaleduv)
{
vec2 dUVdx = dFdx(scaleduv);
@ -35,51 +33,55 @@ float coveragePreservingAlphaScale(sampler2D diffuseMap, vec2 uv)
#endif
}
void alphaTest()
float alphaTest(float alpha)
{
#if @alphaToCoverage
float coverageAlpha = (gl_FragData[0].a - clamp(alphaRef, 0.0001, 0.9999)) / max(fwidth(gl_FragData[0].a), 0.0001) + 0.5;
float coverageAlpha = (alpha - clamp(alphaRef, 0.0001, 0.9999)) / max(fwidth(alpha), 0.0001) + 0.5;
// Some functions don't make sense with A2C or are a pain to think about and no meshes use them anyway
// Use regular alpha testing in such cases until someone complains.
#if @alphaFunc == FUNC_NEVER
discard;
#elif @alphaFunc == FUNC_LESS
gl_FragData[0].a = 1.0 - coverageAlpha;
return 1.0 - coverageAlpha;
#elif @alphaFunc == FUNC_EQUAL
if (gl_FragData[0].a != alphaRef)
if (alpha != alphaRef)
discard;
#elif @alphaFunc == FUNC_LEQUAL
gl_FragData[0].a = 1.0 - coverageAlpha;
return 1.0 - coverageAlpha;
#elif @alphaFunc == FUNC_GREATER
gl_FragData[0].a = coverageAlpha;
return coverageAlpha;
#elif @alphaFunc == FUNC_NOTEQUAL
if (gl_FragData[0].a == alphaRef)
if (alpha == alphaRef)
discard;
#elif @alphaFunc == FUNC_GEQUAL
gl_FragData[0].a = coverageAlpha;
return coverageAlpha;
#endif
#else
#if @alphaFunc == FUNC_NEVER
discard;
#elif @alphaFunc == FUNC_LESS
if (gl_FragData[0].a >= alphaRef)
if (alpha >= alphaRef)
discard;
#elif @alphaFunc == FUNC_EQUAL
if (gl_FragData[0].a != alphaRef)
if (alpha != alphaRef)
discard;
#elif @alphaFunc == FUNC_LEQUAL
if (gl_FragData[0].a > alphaRef)
if (alpha > alphaRef)
discard;
#elif @alphaFunc == FUNC_GREATER
if (gl_FragData[0].a <= alphaRef)
if (alpha <= alphaRef)
discard;
#elif @alphaFunc == FUNC_NOTEQUAL
if (gl_FragData[0].a == alphaRef)
if (alpha == alphaRef)
discard;
#elif @alphaFunc == FUNC_GEQUAL
if (gl_FragData[0].a < alphaRef)
if (alpha < alphaRef)
discard;
#endif
#endif
return alpha;
}
#endif

@ -1,3 +1,6 @@
#ifndef LIB_MATERIAL_PARALLAX
#define LIB_MATERIAL_PARALLAX
#define PARALLAX_SCALE 0.04
#define PARALLAX_BIAS -0.02
@ -6,3 +9,5 @@ vec2 getParallaxOffset(vec3 eyeDir, mat3 tbnTranspose, float height, float flipY
vec3 TSeyeDir = normalize(eyeDir * tbnTranspose);
return vec2(TSeyeDir.x, TSeyeDir.y * flipY) * ( height * PARALLAX_SCALE + PARALLAX_BIAS );
}
#endif

@ -0,0 +1,15 @@
#ifndef LIB_PARTICLE_OCCLUSION
#define LIB_PARTICLE_OCCLUSION
void applyOcclusionDiscard(in vec3 coord, float sceneDepth)
{
#if @reverseZ
if (coord.z < sceneDepth)
discard;
#else
if (coord.z * 0.5 + 0.5 > sceneDepth)
discard;
#endif
}
#endif

@ -1,9 +1,9 @@
uniform float near;
uniform sampler2D opaqueDepthTex;
uniform float particleSize;
uniform bool particleFade;
#ifndef LIB_PARTICLE_SOFT
#define LIB_PARTICLE_SOFT
float viewDepth(float depth)
#include "lib/util/quickstep.glsl"
float viewDepth(float depth, float near, float far)
{
#if @reverseZ
depth = 1.0 - depth;
@ -11,26 +11,31 @@ float viewDepth(float depth)
return (near * far) / ((far - near) * depth - far);
}
float calcSoftParticleFade(in vec3 viewDir, in vec3 viewNormal, in vec3 viewPos)
float calcSoftParticleFade(
in vec3 viewDir,
in vec3 viewPos,
in vec3 viewNormal,
float near,
float far,
float depth,
float size,
bool fade
)
{
float euclidianDepth = length(viewPos);
const float falloffMultiplier = 0.33;
const float contrast = 1.30;
vec2 screenCoords = gl_FragCoord.xy / screenRes;
float depth = texture2D(opaqueDepthTex, screenCoords).x;
float sceneDepth = viewDepth(depth);
float particleDepth = passViewPos.z;
float falloff = particleSize * falloffMultiplier;
float sceneDepth = viewDepth(depth, near, far);
float particleDepth = viewPos.z;
float falloff = size * falloffMultiplier;
float delta = particleDepth - sceneDepth;
const float nearMult = 300.0;
float viewBias = 1.0;
if (particleFade) {
if (fade) {
float VdotN = dot(viewDir, viewNormal);
viewBias = abs(VdotN) * quickstep(euclidianDepth / nearMult) * (1.0 - pow(1.0 + VdotN, 1.3));
}
@ -38,3 +43,5 @@ float calcSoftParticleFade(in vec3 viewDir, in vec3 viewNormal, in vec3 viewPos)
const float shift = 0.845;
return shift * pow(clamp(delta/falloff, 0.0, 1.0), contrast) * viewBias;
}
#endif

@ -1,3 +1,6 @@
#ifndef LIB_SKY_PASSES
#define LIB_SKY_PASSES
#define PASS_ATMOSPHERE 0
#define PASS_ATMOSPHERE_NIGHT 1
#define PASS_CLOUDS 2
@ -5,3 +8,5 @@
#define PASS_SUN 4
#define PASS_SUNFLASH_QUERY 5
#define PASS_SUNGLARE 6
#endif

@ -1,8 +1,5 @@
#version 120
varying vec2 uv;
uniform samplerCube cubeMap;
uniform int mapping;
#ifndef LIB_UTIL_COORDINATES
#define LIB_UTIL_COORDINATES
#define PI 3.1415926535
@ -37,16 +34,4 @@ vec3 planetCoords(vec2 coords)
return sphericalCoords(coords);
}
void main(void)
{
vec3 c;
if (mapping == 0)
c = sphericalCoords(uv);
else if (mapping == 1)
c = cylindricalCoords(uv);
else
c = planetCoords(uv);
gl_FragData[0] = textureCube(cubeMap,c);
}
#endif

@ -0,0 +1,12 @@
#ifndef LIB_UTIL_QUICKSTEP
#define LIB_UTIL_QUICKSTEP
float quickstep(float x)
{
x = clamp(x, 0.0, 1.0);
x = 1.0 - x*x;
x = 1.0 - x*x;
return x;
}
#endif

@ -0,0 +1,24 @@
#ifndef LIB_VIEW_DEPTH
#define LIB_VIEW_DEPTH
float linearizeDepth(float depth, float near, float far)
{
#if @reverseZ
depth = 1.0 - depth;
#endif
float z_n = 2.0 * depth - 1.0;
depth = 2.0 * near * far / (far + near - z_n * (far - near));
return depth;
}
float getLinearDepth(in float z, in float viewZ)
{
#if @reverseZ
// FIXME: Fixme, figure out how to calculate correct linear depth for reverse z
return -viewZ;
#else
return z;
#endif
}
#endif

@ -0,0 +1,23 @@
#ifndef LIB_WATER_FRESNEL
#define LIB_WATER_FRESNEL
float fresnel_dielectric(vec3 Incoming, vec3 Normal, float eta)
{
float c = abs(dot(Incoming, Normal));
float g = eta * eta - 1.0 + c * c;
float result;
if (g > 0.0) {
g = sqrt(g);
float A =(g - c)/(g + c);
float B =(c *(g + c)- 1.0)/(c *(g - c)+ 1.0);
result = 0.5 * A * A *(1.0 + B * B);
}
else {
result = 1.0; /* TIR (no refracted component) */
}
return result;
}
#endif

@ -0,0 +1,126 @@
#ifndef LIB_WATER_RIPPLES
#define LIB_WATER_RIPPLES
#define RAIN_RIPPLE_DETAIL @rain_ripple_detail
const float RAIN_RIPPLE_GAPS = 10.0;
const float RAIN_RIPPLE_RADIUS = 0.2;
float scramble(float x, float z)
{
return fract(pow(fract(x)*3.0+1.0, z));
}
vec2 randOffset(vec2 c, float time)
{
time = fract(time/1000.0);
c = vec2(c.x * c.y / 8.0 + c.y * 0.3 + c.x * 0.2,
c.x * c.y / 14.0 + c.y * 0.5 + c.x * 0.7);
c.x *= scramble(scramble(time + c.x/1000.0, 4.0), 3.0) + 1.0;
c.y *= scramble(scramble(time + c.y/1000.0, 3.5), 3.0) + 1.0;
return fract(c);
}
float randPhase(vec2 c)
{
return fract((c.x * c.y) / (c.x + c.y + 0.1));
}
float blip(float x)
{
x = max(0.0, 1.0-x*x);
return x*x*x;
}
float blipDerivative(float x)
{
x = clamp(x, -1.0, 1.0);
float n = x*x-1.0;
return -6.0*x*n*n;
}
const float RAIN_RING_TIME_OFFSET = 1.0/6.0;
vec4 circle(vec2 coords, vec2 corner, float adjusted_time)
{
vec2 center = vec2(0.5,0.5) + (0.5 - RAIN_RIPPLE_RADIUS) * (2.0 * randOffset(corner, floor(adjusted_time)) - 1.0);
float phase = fract(adjusted_time);
vec2 toCenter = coords - center;
float r = RAIN_RIPPLE_RADIUS;
float d = length(toCenter);
float ringfollower = (phase-d/r)/RAIN_RING_TIME_OFFSET-1.0; // -1.0 ~ +1.0 cover the breadth of the ripple's ring
#if RAIN_RIPPLE_DETAIL > 0
// normal mapped ripples
if(ringfollower < -1.0 || ringfollower > 1.0)
return vec4(0.0);
if(d > 1.0) // normalize center direction vector, but not for near-center ripples
toCenter /= d;
float height = blip(ringfollower*2.0+0.5); // brighten up outer edge of ring; for fake specularity
float range_limit = blip(min(0.0, ringfollower));
float energy = 1.0-phase;
vec2 normal2d = -toCenter*blipDerivative(ringfollower)*5.0;
vec3 normal = vec3(normal2d, 0.5);
vec4 ret = vec4(normal, height);
ret.xyw *= energy*energy;
// do energy adjustment here rather than later, so that we can use the w component for fake specularity
ret.xyz = normalize(ret.xyz) * energy*range_limit;
ret.z *= range_limit;
return ret;
#else
// ring-only ripples
if(ringfollower < -1.0 || ringfollower > 0.5)
return vec4(0.0);
float energy = 1.0-phase;
float height = blip(ringfollower*2.0+0.5)*energy*energy; // fake specularity
return vec4(0.0, 0.0, 0.0, height);
#endif
}
vec4 rain(vec2 uv, float time)
{
uv *= RAIN_RIPPLE_GAPS;
vec2 f_part = fract(uv);
vec2 i_part = floor(uv);
float adjusted_time = time * 1.2 + randPhase(i_part);
#if RAIN_RIPPLE_DETAIL > 0
vec4 a = circle(f_part, i_part, adjusted_time);
vec4 b = circle(f_part, i_part, adjusted_time - RAIN_RING_TIME_OFFSET);
vec4 c = circle(f_part, i_part, adjusted_time - RAIN_RING_TIME_OFFSET*2.0);
vec4 d = circle(f_part, i_part, adjusted_time - RAIN_RING_TIME_OFFSET*3.0);
vec4 ret;
ret.xy = a.xy - b.xy/2.0 + c.xy/4.0 - d.xy/8.0;
// z should always point up
ret.z = a.z + b.z /2.0 + c.z /4.0 + d.z /8.0;
//ret.xyz *= 1.5;
// fake specularity looks weird if we use every single ring, also if the inner rings are too bright
ret.w = (a.w + c.w /8.0)*1.5;
return ret;
#else
return circle(f_part, i_part, adjusted_time) * 1.5;
#endif
}
vec2 complex_mult(vec2 a, vec2 b)
{
return vec2(a.x*b.x - a.y*b.y, a.x*b.y + a.y*b.x);
}
vec4 rainCombined(vec2 uv, float time) // returns ripple normal in xyz and fake specularity in w
{
return
rain(uv, time)
+ rain(complex_mult(uv, vec2(0.4, 0.7)) + vec2(1.2, 3.0),time)
#if RAIN_RIPPLE_DETAIL == 2
+ rain(uv * 0.75 + vec2( 3.7,18.9),time)
+ rain(uv * 0.9 + vec2( 5.7,30.1),time)
+ rain(uv * 1.0 + vec2(10.5 ,5.7),time)
#endif
;
}
#endif

@ -1,20 +0,0 @@
#ifndef OPENMW_FRAGMENT_H_GLSL
#define OPENMW_FRAGMENT_H_GLSL
@link "openmw_fragment.glsl" if !@useOVR_multiview
@link "openmw_fragment_multiview.glsl" if @useOVR_multiview
vec4 mw_sampleReflectionMap(vec2 uv);
#if @refraction_enabled
vec4 mw_sampleRefractionMap(vec2 uv);
float mw_sampleRefractionDepthMap(vec2 uv);
#endif
vec4 mw_samplerLastShader(vec2 uv);
#if @skyBlending
vec3 mw_sampleSkyColor(vec2 uv);
#endif
#endif // OPENMW_FRAGMENT_H_GLSL

@ -1,47 +0,0 @@
#version 330 compatibility
#extension GL_OVR_multiview : require
#extension GL_OVR_multiview2 : require
#extension GL_EXT_texture_array : require
#include "openmw_fragment.h.glsl"
uniform sampler2DArray reflectionMap;
vec4 mw_sampleReflectionMap(vec2 uv)
{
return texture2DArray(reflectionMap, vec3((uv), gl_ViewID_OVR));
}
#if @refraction_enabled
uniform sampler2DArray refractionMap;
uniform sampler2DArray refractionDepthMap;
vec4 mw_sampleRefractionMap(vec2 uv)
{
return texture2DArray(refractionMap, vec3((uv), gl_ViewID_OVR));
}
float mw_sampleRefractionDepthMap(vec2 uv)
{
return texture2DArray(refractionDepthMap, vec3((uv), gl_ViewID_OVR)).x;
}
#endif
uniform sampler2DArray omw_SamplerLastShader;
vec4 mw_samplerLastShader(vec2 uv)
{
return texture2DArray(omw_SamplerLastShader, vec3((uv), gl_ViewID_OVR));
}
#if @skyBlending
uniform sampler2DArray sky;
vec3 mw_sampleSkyColor(vec2 uv)
{
return texture2DArray(sky, vec3((uv), gl_ViewID_OVR)).xyz;
}
#endif

@ -1,20 +0,0 @@
#version 120
#include "openmw_vertex.h.glsl"
uniform mat4 projectionMatrix;
vec4 mw_modelToClip(vec4 pos)
{
return projectionMatrix * mw_modelToView(pos);
}
vec4 mw_modelToView(vec4 pos)
{
return gl_ModelViewMatrix * pos;
}
vec4 mw_viewToClip(vec4 pos)
{
return projectionMatrix * pos;
}

@ -1,6 +0,0 @@
@link "openmw_vertex.glsl" if !@useOVR_multiview
@link "openmw_vertex_multiview.glsl" if @useOVR_multiview
vec4 mw_modelToClip(vec4 pos);
vec4 mw_modelToView(vec4 pos);
vec4 mw_viewToClip(vec4 pos);

@ -1,15 +0,0 @@
#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;
}

@ -1,13 +0,0 @@
#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;
}
Loading…
Cancel
Save