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 const float hdrExposureTime
= std::max(Settings::Manager::getFloat("auto exposure speed", "Post Processing"), 0.0001f); = 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 = { 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) }, { "hdrExposureTime", std::to_string(hdrExposureTime) },
{ "epsilon", std::to_string(epsilon) },
}; };
auto vertex = shaderManager.getShader("fullscreen_tri_vertex.glsl", {}, osg::Shader::VERTEX); auto vertex = shaderManager.getShader("fullscreen_tri.vert", {});
auto luminanceFragment = shaderManager.getShader("hdr_luminance_fragment.glsl", defines, osg::Shader::FRAGMENT); auto luminanceFragment = shaderManager.getShader("luminance/luminance.frag", defines);
auto resolveFragment = shaderManager.getShader("hdr_resolve_fragment.glsl", defines, osg::Shader::FRAGMENT); auto resolveFragment = shaderManager.getShader("luminance/resolve.frag", defines);
mResolveProgram = shaderManager.getProgram(vertex, resolveFragment); mResolveProgram = shaderManager.getProgram(vertex, resolveFragment);
mLuminanceProgram = shaderManager.getProgram(vertex, luminanceFragment); mLuminanceProgram = shaderManager.getProgram(vertex, luminanceFragment);

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

@ -52,11 +52,7 @@ namespace
Shader::ShaderManager& shaderMgr Shader::ShaderManager& shaderMgr
= MWBase::Environment::get().getResourceSystem()->getSceneManager()->getShaderManager(); = MWBase::Environment::get().getResourceSystem()->getSceneManager()->getShaderManager();
osg::ref_ptr<osg::Shader> vertex mProgram = shaderMgr.getProgram("depthclipped");
= 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);
} }
private: private:

@ -156,8 +156,7 @@ namespace MWRender
{ {
public: public:
SharedUniformStateUpdater(bool usePlayerUniforms) SharedUniformStateUpdater(bool usePlayerUniforms)
: mLinearFac(0.f) : mNear(0.f)
, mNear(0.f)
, mFar(0.f) , mFar(0.f)
, mWindSpeed(0.f) , mWindSpeed(0.f)
, mSkyBlendingStartCoef(Settings::Manager::getFloat("sky blending start", "Fog")) , mSkyBlendingStartCoef(Settings::Manager::getFloat("sky blending start", "Fog"))
@ -167,7 +166,6 @@ namespace MWRender
void setDefaults(osg::StateSet* stateset) override 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("near", 0.f));
stateset->addUniform(new osg::Uniform("far", 0.f)); stateset->addUniform(new osg::Uniform("far", 0.f));
stateset->addUniform(new osg::Uniform("skyBlendingStart", 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 void apply(osg::StateSet* stateset, osg::NodeVisitor* nv) override
{ {
stateset->getUniform("linearFac")->set(mLinearFac);
stateset->getUniform("near")->set(mNear); stateset->getUniform("near")->set(mNear);
stateset->getUniform("far")->set(mFar); stateset->getUniform("far")->set(mFar);
stateset->getUniform("skyBlendingStart")->set(mFar * mSkyBlendingStartCoef); 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 setNear(float near) { mNear = near; }
void setFar(float far) { mFar = far; } void setFar(float far) { mFar = far; }
@ -209,7 +204,6 @@ namespace MWRender
void setPlayerPos(osg::Vec3f playerPos) { mPlayerPos = playerPos; } void setPlayerPos(osg::Vec3f playerPos) { mPlayerPos = playerPos; }
private: private:
float mLinearFac;
float mNear; float mNear;
float mFar; float mFar;
float mWindSpeed; float mWindSpeed;
@ -1293,7 +1287,6 @@ namespace MWRender
if (SceneUtil::AutoDepth::isReversed()) if (SceneUtil::AutoDepth::isReversed())
{ {
mSharedUniformStateUpdater->setLinearFac(-mNearClip / (mViewDistance - mNearClip) - 1.f);
mPerViewUniformStateUpdater->setProjectionMatrix( mPerViewUniformStateUpdater->setProjectionMatrix(
SceneUtil::getReversedZProjectionMatrixAsPerspective(fov, aspect, mNearClip, mViewDistance)); 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::Camera> screenshotCamera(new osg::Camera);
osg::ref_ptr<osg::ShapeDrawable> quad(new osg::ShapeDrawable(new osg::Box(osg::Vec3(0, 0, 0), 2.0))); 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::StateSet> stateset = quad->getOrCreateStateSet();
osg::ref_ptr<osg::Program> program(new osg::Program); Shader::ShaderManager& shaderMgr = mResourceSystem->getSceneManager()->getShaderManager();
program->addShader(fragmentShader); stateset->setAttributeAndModes(shaderMgr.getProgram("360"), osg::StateAttribute::ON);
program->addShader(vertexShader);
stateset->setAttributeAndModes(program, osg::StateAttribute::ON);
stateset->addUniform(new osg::Uniform("cubeMap", 0)); stateset->addUniform(new osg::Uniform("cubeMap", 0));
stateset->addUniform(new osg::Uniform("mapping", screenshotMapping)); stateset->addUniform(new osg::Uniform("mapping", screenshotMapping));

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

@ -34,13 +34,9 @@ namespace MWRender
Shader::ShaderManager::DefineMap defines; Shader::ShaderManager::DefineMap defines;
Stereo::Manager::instance().shaderStereoDefines(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(new osg::BlendFunc, modeOff);
mStateSet->setAttributeAndModes(shaderManager.getProgram(vertex, fragment), modeOn); mStateSet->setAttributeAndModes(shaderManager.getProgram("depthclipped", defines), modeOn);
mStateSet->setAttributeAndModes(new SceneUtil::AutoDepth, modeOn); mStateSet->setAttributeAndModes(new SceneUtil::AutoDepth, modeOn);
for (unsigned int unit = 1; unit < 8; ++unit) for (unsigned int unit = 1; unit < 8; ++unit)

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

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

@ -17,7 +17,7 @@ namespace
ShaderManager mManager; ShaderManager mManager;
ShaderManager::DefineMap mDefines; ShaderManager::DefineMap mDefines;
ShaderManagerTest() { mManager.setShaderPath("."); } ShaderManagerTest() { mManager.setShaderPath("tests_output"); }
template <class F> template <class F>
void withShaderFile(const std::string& content, F&& f) void withShaderFile(const std::string& content, F&& f)
@ -28,16 +28,17 @@ namespace
template <class F> template <class F>
void withShaderFile(const std::string& suffix, const std::string& content, F&& f) void withShaderFile(const std::string& suffix, const std::string& content, F&& f)
{ {
auto path = TestingOpenMW::outputFilePath( auto subdir = std::filesystem::path("lib")
std::string(UnitTest::GetInstance()->current_test_info()->name()) + suffix + ".glsl"); / std::filesystem::path(
std::string(UnitTest::GetInstance()->current_test_info()->name()) + suffix + ".vert");
auto path = TestingOpenMW::outputFilePathWithSubDir(subdir);
{ {
std::ofstream stream(path); std::ofstream stream(path);
stream << content; stream << content;
stream.close(); stream.close();
} }
f(path); f(subdir);
} }
}; };
@ -46,7 +47,7 @@ namespace
const std::string content; const std::string content;
withShaderFile(content, [this](const std::filesystem::path& templateName) { 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"; "void main() {}\n";
withShaderFile(content, [&](const std::filesystem::path& templateName) { withShaderFile(content, [&](const std::filesystem::path& templateName) {
const auto shader const auto shader = mManager.getShader(Files::pathToUnicodeString(templateName), mDefines);
= mManager.getShader(Files::pathToUnicodeString(templateName), mDefines, osg::Shader::VERTEX);
ASSERT_TRUE(shader); ASSERT_TRUE(shader);
EXPECT_EQ(shader->getShaderSource(), content); EXPECT_EQ(shader->getShaderSource(), content);
}); });
@ -80,8 +80,7 @@ namespace
"void main() { bar() }\n"; "void main() { bar() }\n";
withShaderFile(content2, [&](const std::filesystem::path& templateName2) { withShaderFile(content2, [&](const std::filesystem::path& templateName2) {
const auto shader const auto shader = mManager.getShader(Files::pathToUnicodeString(templateName2), mDefines);
= mManager.getShader(Files::pathToUnicodeString(templateName2), mDefines, osg::Shader::VERTEX);
ASSERT_TRUE(shader); ASSERT_TRUE(shader);
const std::string expected const std::string expected
= "#version 120\n" = "#version 120\n"
@ -111,8 +110,7 @@ namespace
withShaderFile(content, [&](const std::filesystem::path& templateName) { withShaderFile(content, [&](const std::filesystem::path& templateName) {
mDefines["flag"] = "1"; mDefines["flag"] = "1";
const auto shader const auto shader = mManager.getShader(Files::pathToUnicodeString(templateName), mDefines);
= mManager.getShader(Files::pathToUnicodeString(templateName), mDefines, osg::Shader::VERTEX);
ASSERT_TRUE(shader); ASSERT_TRUE(shader);
const std::string expected const std::string expected
= "#version 120\n" = "#version 120\n"
@ -133,8 +131,7 @@ namespace
withShaderFile(content, [&](const std::filesystem::path& templateName) { withShaderFile(content, [&](const std::filesystem::path& templateName) {
mDefines["list"] = "1,2,3"; mDefines["list"] = "1,2,3";
const auto shader const auto shader = mManager.getShader(Files::pathToUnicodeString(templateName), mDefines);
= mManager.getShader(Files::pathToUnicodeString(templateName), mDefines, osg::Shader::VERTEX);
ASSERT_TRUE(shader); ASSERT_TRUE(shader);
const std::string expected const std::string expected
= "#version 120\n" = "#version 120\n"
@ -174,8 +171,7 @@ namespace
withShaderFile(content, [&](const std::filesystem::path& templateName) { withShaderFile(content, [&](const std::filesystem::path& templateName) {
mDefines["list"] = "1,2,3"; mDefines["list"] = "1,2,3";
const auto shader const auto shader = mManager.getShader(Files::pathToUnicodeString(templateName), mDefines);
= mManager.getShader(Files::pathToUnicodeString(templateName), mDefines, osg::Shader::VERTEX);
ASSERT_TRUE(shader); ASSERT_TRUE(shader);
const std::string expected const std::string expected
= "#version 120\n" = "#version 120\n"
@ -221,7 +217,7 @@ namespace
"void main() {}\n"; "void main() {}\n";
withShaderFile(content, [&](const std::filesystem::path& templateName) { 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"; "void main() {}\n";
withShaderFile(content, [&](const std::filesystem::path& templateName) { 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); 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) inline std::filesystem::path temporaryFilePath(const std::string name)
{ {
return std::filesystem::temp_directory_path() / 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) macro (copy_all_resource_files source_dir destination_dir_base destination_dir_relative files)
foreach (f ${files}) foreach (f ${files})
get_filename_component(filename ${f} NAME) 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) endforeach (f)
endmacro (copy_all_resource_files) endmacro (copy_all_resource_files)

@ -339,12 +339,8 @@ Debug::DebugDrawer::DebugDrawer(Shader::ShaderManager& shaderManager, osg::ref_p
: mParentNode(parentNode) : mParentNode(parentNode)
{ {
mCurrentFrame = 0; 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 = new osg::Group;
mDebugDrawSceneObjects->setCullingActive(false); mDebugDrawSceneObjects->setCullingActive(false);

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

@ -1991,9 +1991,9 @@ namespace NifOsg
switch (static_cast<Nif::BSShaderType>(type)) switch (static_cast<Nif::BSShaderType>(type))
{ {
case Nif::BSShaderType::ShaderType_Default: case Nif::BSShaderType::ShaderType_Default:
return "nv_default"; return "bs/default";
case Nif::BSShaderType::ShaderType_NoLighting: case Nif::BSShaderType::ShaderType_NoLighting:
return "nv_nolighting"; return "bs/nolighting";
case Nif::BSShaderType::ShaderType_TallGrass: case Nif::BSShaderType::ShaderType_TallGrass:
case Nif::BSShaderType::ShaderType_Sky: case Nif::BSShaderType::ShaderType_Sky:
case Nif::BSShaderType::ShaderType_Skin: case Nif::BSShaderType::ShaderType_Skin:
@ -2001,10 +2001,10 @@ namespace NifOsg
case Nif::BSShaderType::ShaderType_Lighting30: case Nif::BSShaderType::ShaderType_Lighting30:
case Nif::BSShaderType::ShaderType_Tile: case Nif::BSShaderType::ShaderType_Tile:
Log(Debug::Warning) << "Unhandled BSShaderType " << type << " in " << mFilename; Log(Debug::Warning) << "Unhandled BSShaderType " << type << " in " << mFilename;
return "nv_default"; return "bs/default";
} }
Log(Debug::Warning) << "Unknown BSShaderType " << type << " in " << mFilename; Log(Debug::Warning) << "Unknown BSShaderType " << type << " in " << mFilename;
return "nv_default"; return "bs/default";
} }
std::string_view getBSLightingShaderPrefix(unsigned int type) const std::string_view getBSLightingShaderPrefix(unsigned int type) const
@ -2012,7 +2012,7 @@ namespace NifOsg
switch (static_cast<Nif::BSLightingShaderType>(type)) switch (static_cast<Nif::BSLightingShaderType>(type))
{ {
case Nif::BSLightingShaderType::ShaderType_Default: case Nif::BSLightingShaderType::ShaderType_Default:
return "nv_default"; return "bs/default";
case Nif::BSLightingShaderType::ShaderType_EnvMap: case Nif::BSLightingShaderType::ShaderType_EnvMap:
case Nif::BSLightingShaderType::ShaderType_Glow: case Nif::BSLightingShaderType::ShaderType_Glow:
case Nif::BSLightingShaderType::ShaderType_Parallax: case Nif::BSLightingShaderType::ShaderType_Parallax:
@ -2034,10 +2034,10 @@ namespace NifOsg
case Nif::BSLightingShaderType::ShaderType_MultitexLandLODBlend: case Nif::BSLightingShaderType::ShaderType_MultitexLandLODBlend:
case Nif::BSLightingShaderType::ShaderType_Dismemberment: case Nif::BSLightingShaderType::ShaderType_Dismemberment:
Log(Debug::Warning) << "Unhandled BSLightingShaderType " << type << " in " << mFilename; Log(Debug::Warning) << "Unhandled BSLightingShaderType " << type << " in " << mFilename;
return "nv_default"; return "bs/default";
} }
Log(Debug::Warning) << "Unknown BSLightingShaderType " << type << " in " << mFilename; Log(Debug::Warning) << "Unknown BSLightingShaderType " << type << " in " << mFilename;
return "nv_default"; return "bs/default";
} }
void handleProperty(const Nif::Property* property, osg::Node* node, 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 // 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); osg::ref_ptr<osg::GLExtensions> exts = osg::GLExtensions::Get(0, false);
std::string useGPUShader4 = exts && exts->isGpuShader4Supported ? "1" : "0"; std::string useGPUShader4 = exts && exts->isGpuShader4Supported ? "1" : "0";
for (int alphaFunc = GL_NEVER; alphaFunc <= GL_ALWAYS; ++alphaFunc) 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]; auto& program = _castingPrograms[alphaFunc - GL_NEVER];
program = new osg::Program(); program = new osg::Program();
program->addShader(castingVertexShader); 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"}, {"alphaToCoverage", "0"},
{"adjustCoverage", "1"}, {"adjustCoverage", "1"},
{"useGPUShader4", useGPUShader4} {"useGPUShader4", useGPUShader4}
}, osg::Shader::FRAGMENT)); }));
} }
} }

@ -16,6 +16,29 @@
#include <sstream> #include <sstream>
#include <unordered_map> #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 namespace Shader
{ {
@ -106,7 +129,11 @@ namespace Shader
return false; return false;
} }
std::string includeFilename = source.substr(start + 1, end - (start + 1)); 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 // Determine the line number that will be used for the #line directive following the included source
size_t lineDirectivePosition = source.rfind("#line", foundPos); size_t lineDirectivePosition = source.rfind("#line", foundPos);
@ -471,10 +498,16 @@ namespace Shader
}; };
osg::ref_ptr<osg::Shader> ShaderManager::getShader( 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); 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 // read the template if we haven't already
TemplateMap::iterator templateIt = mShaderTemplates.find(templateName); TemplateMap::iterator templateIt = mShaderTemplates.find(templateName);
std::set<std::filesystem::path> insertedPaths; std::set<std::filesystem::path> insertedPaths;
@ -514,7 +547,7 @@ namespace Shader
return nullptr; 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); shader->setShaderSource(shaderSource);
// Assign a unique prefix to allow the SharedStateManager to compare shaders efficiently. // Assign a unique prefix to allow the SharedStateManager to compare shaders efficiently.
// Append shader source filename for debugging. // Append shader source filename for debugging.
@ -532,6 +565,18 @@ namespace Shader
return shaderIt->second; 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::Program> ShaderManager::getProgram(osg::ref_ptr<osg::Shader> vertexShader,
osg::ref_ptr<osg::Shader> fragmentShader, const osg::Program* programTemplate) osg::ref_ptr<osg::Shader> fragmentShader, const osg::Program* programTemplate)
{ {

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

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

@ -285,17 +285,7 @@ namespace Terrain
defineMap["writeNormals"] = (it == layers.end() - 1) ? "1" : "0"; defineMap["writeNormals"] = (it == layers.end() - 1) ? "1" : "0";
Stereo::Manager::instance().shaderStereoDefines(defineMap); Stereo::Manager::instance().shaderStereoDefines(defineMap);
osg::ref_ptr<osg::Shader> vertexShader stateset->setAttributeAndModes(shaderManager.getProgram("terrain", defineMap));
= 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->addUniform(UniformCollection::value().mColorMode); stateset->addUniform(UniformCollection::value().mColorMode);
} }
else else

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

@ -34,11 +34,13 @@ varying vec3 passViewPos;
varying vec3 passNormal; varying vec3 passNormal;
uniform vec2 screenRes; uniform vec2 screenRes;
uniform float far;
uniform float alphaRef;
#include "vertexcolors.glsl" #include "vertexcolors.glsl"
#include "shadows_fragment.glsl" #include "shadows_fragment.glsl"
#include "lighting.glsl" #include "lib/light/lighting.glsl"
#include "alpha.glsl" #include "lib/material/alpha.glsl"
#include "fog.glsl" #include "fog.glsl"
uniform float emissiveMult; uniform float emissiveMult;
@ -57,7 +59,7 @@ void main()
vec4 diffuseColor = getDiffuseColor(); vec4 diffuseColor = getDiffuseColor();
gl_FragData[0].a *= diffuseColor.a; gl_FragData[0].a *= diffuseColor.a;
alphaTest(); gl_FragData[0].a = alphaTest(gl_FragData[0].a);
#if @normalMap #if @normalMap
vec4 normalTex = texture2D(normalMap, normalMapUV); vec4 normalTex = texture2D(normalMap, normalMapUV);
@ -93,7 +95,7 @@ void main()
if (matSpec != vec3(0.0)) if (matSpec != vec3(0.0))
gl_FragData[0].xyz += getSpecular(viewNormal, normalize(passViewPos.xyz), shininess, matSpec) * shadowing; 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 #if defined(FORCE_OPAQUE) && FORCE_OPAQUE
// having testing & blending isn't enough - we need to write an opaque pixel to be 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 #extension GL_EXT_gpu_shader4: require
#endif #endif
#include "openmw_vertex.h.glsl" #include "lib/core/vertex.h.glsl"
#if @diffuseMap #if @diffuseMap
varying vec2 diffuseMapUV; varying vec2 diffuseMapUV;
#endif #endif
@ -32,14 +32,14 @@ varying vec3 passNormal;
#include "vertexcolors.glsl" #include "vertexcolors.glsl"
#include "shadows_vertex.glsl" #include "shadows_vertex.glsl"
#include "lighting.glsl" #include "lib/light/lighting.glsl"
#include "depth.glsl" #include "lib/view/depth.glsl"
void main(void) 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; gl_ClipVertex = viewPos;
euclideanDepth = length(viewPos.xyz); euclideanDepth = length(viewPos.xyz);
linearDepth = getLinearDepth(gl_Position.z, viewPos.z); linearDepth = getLinearDepth(gl_Position.z, viewPos.z);

@ -16,11 +16,13 @@ varying float linearDepth;
uniform bool useFalloff; uniform bool useFalloff;
uniform vec2 screenRes; uniform vec2 screenRes;
uniform float emissiveMult; uniform float emissiveMult;
uniform float far;
uniform float alphaRef;
varying float passFalloff; varying float passFalloff;
#include "lib/material/alpha.glsl"
#include "vertexcolors.glsl" #include "vertexcolors.glsl"
#include "alpha.glsl"
#include "fog.glsl" #include "fog.glsl"
void main() void main()
@ -41,11 +43,11 @@ void main()
gl_FragData[0].rgb *= emissionColor.rgb * emissiveMult; gl_FragData[0].rgb *= emissionColor.rgb * emissiveMult;
gl_FragData[0].a *= emissionColor.a * emissionColor.a; // sic 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 #if defined(FORCE_OPAQUE) && FORCE_OPAQUE
gl_FragData[0].a = 1.0; gl_FragData[0].a = 1.0;
#endif #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 #version 120
#include "openmw_vertex.h.glsl" #include "lib/core/vertex.h.glsl"
#if @diffuseMap #if @diffuseMap
varying vec2 diffuseMapUV; varying vec2 diffuseMapUV;
@ -18,13 +18,13 @@ uniform vec4 falloffParams;
varying float passFalloff; varying float passFalloff;
#include "vertexcolors.glsl" #include "vertexcolors.glsl"
#include "depth.glsl" #include "lib/view/depth.glsl"
void main(void) 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; gl_ClipVertex = viewPos;
#if @radialFog #if @radialFog
euclideanDepth = length(viewPos.xyz); euclideanDepth = length(viewPos.xyz);

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

@ -15,5 +15,5 @@ void main()
discard; discard;
// DO NOT write to color! // 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 #version 120
uniform mat4 projectionMatrix;
varying vec2 diffuseMapUV; varying vec2 diffuseMapUV;
varying float alphaPassthrough; varying float alphaPassthrough;
#include "openmw_vertex.h.glsl" #include "lib/core/vertex.h.glsl"
#include "vertexcolors.glsl" #include "vertexcolors.glsl"
void main() void main()
{ {
gl_Position = mw_modelToClip(gl_Vertex); gl_Position = modelToClip(gl_Vertex);
vec4 viewPos = modelToView(gl_Vertex);
gl_ClipVertex = viewPos;
if (colorMode == 2) if (colorMode == 2)
alphaPassthrough = gl_Color.a; alphaPassthrough = gl_Color.a;

@ -1,12 +1,10 @@
uniform float far;
#if @skyBlending #if @skyBlending
#include "openmw_fragment.h.glsl" #include "lib/core/fragment.h.glsl"
uniform float skyBlendingStart; uniform float skyBlendingStart;
#endif #endif
vec4 applyFogAtDist(vec4 color, float euclideanDist, float linearDist) vec4 applyFogAtDist(vec4 color, float euclideanDist, float linearDist, float far)
{ {
#if @radialFog #if @radialFog
float dist = euclideanDist; float dist = euclideanDist;
@ -30,14 +28,14 @@ vec4 applyFogAtDist(vec4 color, float euclideanDist, float linearDist)
#ifdef ADDITIVE_BLENDING #ifdef ADDITIVE_BLENDING
color.xyz *= fadeValue; color.xyz *= fadeValue;
#else #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
#endif #endif
return color; 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; varying vec2 uv;
#include "openmw_vertex.h.glsl" #include "lib/core/vertex.h.glsl"
void main() void main()
{ {

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

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

@ -1,12 +1,14 @@
#version 120 #version 120
#include "lib/luminance/constants.glsl"
varying vec2 uv; varying vec2 uv;
uniform sampler2D sceneTex; uniform sampler2D sceneTex;
void main() void main()
{ {
float lum = dot(texture2D(sceneTex, uv).rgb, vec3(0.2126, 0.7152, 0.0722)); 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 #version 120
#include "lib/luminance/constants.glsl"
varying vec2 uv; varying vec2 uv;
uniform sampler2D luminanceSceneTex; uniform sampler2D luminanceSceneTex;
uniform sampler2D prevLuminanceSceneTex; uniform sampler2D prevLuminanceSceneTex;
@ -11,6 +13,6 @@ void main()
float prevLum = texture2D(prevLuminanceSceneTex, vec2(0.5, 0.5)).r; float prevLum = texture2D(prevLuminanceSceneTex, vec2(0.5, 0.5)).r;
float currLum = texture2D(luminanceSceneTex, vec2(0.5, 0.5)).r; float currLum = texture2D(luminanceSceneTex, vec2(0.5, 0.5)).r;
float avgLum = exp2((currLum * @logLumRange) + @minLog); float avgLum = exp2((currLum * logLumRange) + minLog);
gl_FragColor.r = prevLum + (avgLum - prevLum) * (1.0 - exp(-osg_DeltaFrameTime * @hdrExposureTime)); gl_FragColor.r = prevLum + (avgLum - prevLum) * (1.0 - exp(-osg_DeltaFrameTime * hdrExposureTime));
} }

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

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

@ -8,7 +8,7 @@
#extension GL_EXT_gpu_shader4: require #extension GL_EXT_gpu_shader4: require
#endif #endif
#include "openmw_vertex.h.glsl" #include "lib/core/vertex.h.glsl"
#if @diffuseMap #if @diffuseMap
varying vec2 diffuseMapUV; varying vec2 diffuseMapUV;
#endif #endif
@ -63,8 +63,8 @@ varying vec3 passNormal;
#include "vertexcolors.glsl" #include "vertexcolors.glsl"
#include "shadows_vertex.glsl" #include "shadows_vertex.glsl"
#include "lighting.glsl" #include "lib/light/lighting.glsl"
#include "depth.glsl" #include "lib/view/depth.glsl"
#if @particleOcclusion #if @particleOcclusion
varying vec3 orthoDepthMapCoord; varying vec3 orthoDepthMapCoord;
@ -80,9 +80,9 @@ void main(void)
orthoDepthMapCoord = ((depthSpaceMatrix * model) * vec4(gl_Vertex.xyz, 1.0)).xyz; orthoDepthMapCoord = ((depthSpaceMatrix * model) * vec4(gl_Vertex.xyz, 1.0)).xyz;
#endif #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; gl_ClipVertex = viewPos;
#if (@envMap || !PER_PIXEL_LIGHTING || @shadows_enabled) #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 useDiffuseMapForShadowAlpha;
uniform bool alphaTestShadows; uniform bool alphaTestShadows;
uniform float alphaRef;
#include "alpha.glsl" #include "lib/material/alpha.glsl"
void main() void main()
{ {
@ -22,7 +23,7 @@ void main()
else else
gl_FragData[0].a = alphaPassthrough; 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). // Prevent translucent things casting shadow (including the player using an invisibility effect).
// This replaces alpha blending, which obviously doesn't work with depth buffers // This replaces alpha blending, which obviously doesn't work with depth buffers

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

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

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

@ -8,7 +8,7 @@
#extension GL_EXT_gpu_shader4: require #extension GL_EXT_gpu_shader4: require
#endif #endif
#include "openmw_vertex.h.glsl" #include "lib/core/vertex.h.glsl"
varying vec2 uv; varying vec2 uv;
varying float euclideanDepth; varying float euclideanDepth;
varying float linearDepth; varying float linearDepth;
@ -25,14 +25,14 @@ varying vec3 passNormal;
#include "vertexcolors.glsl" #include "vertexcolors.glsl"
#include "shadows_vertex.glsl" #include "shadows_vertex.glsl"
#include "lighting.glsl" #include "lib/light/lighting.glsl"
#include "depth.glsl" #include "lib/view/depth.glsl"
void main(void) 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; gl_ClipVertex = viewPos;
euclideanDepth = length(viewPos.xyz); euclideanDepth = length(viewPos.xyz);
linearDepth = getLinearDepth(gl_Position.z, viewPos.z); linearDepth = getLinearDepth(gl_Position.z, viewPos.z);

@ -8,10 +8,9 @@
#extension GL_EXT_gpu_shader4: require #extension GL_EXT_gpu_shader4: require
#endif #endif
#include "openmw_fragment.h.glsl" #include "lib/core/fragment.h.glsl"
#define REFRACTION @refraction_enabled #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 ) // 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 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) 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); 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 vec4 position;
varying float linearDepth; varying float linearDepth;
@ -212,6 +70,7 @@ uniform sampler2D normalMap;
uniform float osg_SimulationTime; uniform float osg_SimulationTime;
uniform float near; uniform float near;
uniform float far;
uniform vec3 nodePosition; uniform vec3 nodePosition;
uniform float rainIntensity; uniform float rainIntensity;
@ -221,24 +80,14 @@ uniform vec2 screenRes;
#define PER_PIXEL_LIGHTING 0 #define PER_PIXEL_LIGHTING 0
#include "shadows_fragment.glsl" #include "shadows_fragment.glsl"
#include "lighting.glsl" #include "lib/light/lighting.glsl"
#include "fog.glsl" #include "fog.glsl"
#include "lib/water/fresnel.glsl"
float frustumDepth; #include "lib/water/ripples.glsl"
#include "lib/view/depth.glsl"
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;
}
void main(void) void main(void)
{ {
frustumDepth = abs(far - near);
vec3 worldPos = position.xyz + nodePosition.xyz; vec3 worldPos = position.xyz + nodePosition.xyz;
vec2 UV = worldPos.xy / (8192.0*5.0) * 3.0; vec2 UV = worldPos.xy / (8192.0*5.0) * 3.0;
UV.y *= -1.0; UV.y *= -1.0;
@ -297,14 +146,14 @@ void main(void)
vec2 screenCoordsOffset = normal.xy * REFL_BUMP; vec2 screenCoordsOffset = normal.xy * REFL_BUMP;
#if REFRACTION #if REFRACTION
float depthSample = linearizeDepth(mw_sampleRefractionDepthMap(screenCoords)) * radialise; float depthSample = linearizeDepth(sampleRefractionDepthMap(screenCoords), near, far) * radialise;
float depthSampleDistorted = linearizeDepth(mw_sampleRefractionDepthMap(screenCoords-screenCoordsOffset)) * radialise; float depthSampleDistorted = linearizeDepth(sampleRefractionDepthMap(screenCoords-screenCoordsOffset), near, far) * radialise;
float surfaceDepth = linearizeDepth(gl_FragCoord.z) * radialise; float surfaceDepth = linearizeDepth(gl_FragCoord.z, near, far) * radialise;
float realWaterDepth = depthSample - surfaceDepth; // undistorted water depth in view direction, independent of frustum float realWaterDepth = depthSample - surfaceDepth; // undistorted water depth in view direction, independent of frustum
screenCoordsOffset *= clamp(realWaterDepth / BUMP_SUPPRESS_DEPTH,0,1); screenCoordsOffset *= clamp(realWaterDepth / BUMP_SUPPRESS_DEPTH,0,1);
#endif #endif
// reflection // reflection
vec3 reflection = mw_sampleReflectionMap(screenCoords + screenCoordsOffset).rgb; vec3 reflection = sampleReflectionMap(screenCoords + screenCoordsOffset).rgb;
// specular // specular
float specular = pow(max(dot(reflect(vVec, normal), lVec), 0.0),SPEC_HARDNESS) * shadow; 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); rainSpecular *= clamp(fresnel*6.0 + specular * sunSpec.w, 0.0, 1.0);
// refraction // refraction
vec3 refraction = mw_sampleRefractionMap(screenCoords - screenCoordsOffset).rgb; vec3 refraction = sampleRefractionMap(screenCoords - screenCoordsOffset).rgb;
vec3 rawRefraction = refraction; vec3 rawRefraction = refraction;
// brighten up the refraction underwater // 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); 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 #endif
gl_FragData[0] = applyFogAtDist(gl_FragData[0], radialDepth, linearDepth); gl_FragData[0] = applyFogAtDist(gl_FragData[0], radialDepth, linearDepth, far);
#if !@disableNormals #if !@disableNormals
gl_FragData[1].rgb = normalize(gl_NormalMatrix * normal) * 0.5 + 0.5; gl_FragData[1].rgb = normalize(gl_NormalMatrix * normal) * 0.5 + 0.5;

@ -1,20 +1,20 @@
#version 120 #version 120
#include "openmw_vertex.h.glsl" #include "lib/core/vertex.h.glsl"
varying vec4 position; varying vec4 position;
varying float linearDepth; varying float linearDepth;
#include "shadows_vertex.glsl" #include "shadows_vertex.glsl"
#include "depth.glsl" #include "lib/view/depth.glsl"
void main(void) void main(void)
{ {
gl_Position = mw_modelToClip(gl_Vertex); gl_Position = modelToClip(gl_Vertex);
position = gl_Vertex; position = gl_Vertex;
vec4 viewPos = mw_modelToView(gl_Vertex); vec4 viewPos = modelToView(gl_Vertex);
linearDepth = getLinearDepth(gl_Position.z, viewPos.z); linearDepth = getLinearDepth(gl_Position.z, viewPos.z);
setupShadowCoords(viewPos, normalize((gl_NormalMatrix * gl_Normal).xyz)); 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 #version 120
#include "openmw_fragment.h.glsl" #include "lib/core/fragment.h.glsl"
uniform sampler2D reflectionMap; uniform sampler2D reflectionMap;
vec4 mw_sampleReflectionMap(vec2 uv) vec4 sampleReflectionMap(vec2 uv)
{ {
return texture2D(reflectionMap, uv); return texture2D(reflectionMap, uv);
} }
@ -13,29 +13,29 @@ vec4 mw_sampleReflectionMap(vec2 uv)
uniform sampler2D refractionMap; uniform sampler2D refractionMap;
uniform sampler2D refractionDepthMap; uniform sampler2D refractionDepthMap;
vec4 mw_sampleRefractionMap(vec2 uv) vec4 sampleRefractionMap(vec2 uv)
{ {
return texture2D(refractionMap, uv); return texture2D(refractionMap, uv);
} }
float mw_sampleRefractionDepthMap(vec2 uv) float sampleRefractionDepthMap(vec2 uv)
{ {
return texture2D(refractionDepthMap, uv).x; return texture2D(refractionDepthMap, uv).x;
} }
#endif #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 #if @skyBlending
uniform sampler2D sky; uniform sampler2D sky;
vec3 mw_sampleSkyColor(vec2 uv) vec3 sampleSkyColor(vec2 uv)
{ {
return texture2D(sky, uv).xyz; 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_multiview : require
#extension GL_OVR_multiview2 : require #extension GL_OVR_multiview2 : require
layout(num_views = @numViews) in; layout(num_views = @numViews) in;
#include "openmw_vertex.h.glsl" #include "lib/core/vertex.h.glsl"
uniform mat4 projectionMatrixMultiView[@numViews]; 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; return gl_ModelViewMatrix * pos;
} }
vec4 mw_viewToClip(vec4 pos) vec4 viewToClip(vec4 pos)
{ {
return projectionMatrixMultiView[gl_ViewID_OVR] * pos; return projectionMatrixMultiView[gl_ViewID_OVR] * pos;
} }

@ -1,3 +1,6 @@
#ifndef LIB_LIGHT_LIGHTING
#define LIB_LIGHT_LIGHTING
#include "lighting_util.glsl" #include "lighting_util.glsl"
void perLightSun(out vec3 diffuseOut, vec3 viewPos, vec3 viewNormal) 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); float NdotH = dot(viewNormal, halfVec);
return pow(max(NdotH, 0.0), max(1e-4, shininess)) * lcalcSpecular(0).xyz * matSpec; return pow(max(NdotH, 0.0), max(1e-4, shininess)) * lcalcSpecular(0).xyz * matSpec;
} }
#endif

@ -1,10 +1,7 @@
float quickstep(float x) #ifndef LIB_LIGHTING_UTIL
{ #define LIB_LIGHTING_UTIL
x = clamp(x, 0.0, 1.0);
x = 1.0 - x*x; #include "lib/util/quickstep.glsl"
x = 1.0 - x*x;
return x;
}
#if @lightingMethodUBO #if @lightingMethodUBO
@ -136,3 +133,5 @@ void clampLightingResult(inout vec3 lighting)
lighting = max(lighting, 0.0); lighting = max(lighting, 0.0);
#endif #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_NEVER 512 // 0x0200
#define FUNC_LESS 513 // 0x0201 #define FUNC_LESS 513 // 0x0201
@ -8,10 +10,6 @@
#define FUNC_GEQUAL 518 // 0x0206 #define FUNC_GEQUAL 518 // 0x0206
#define FUNC_ALWAYS 519 // 0x0207 #define FUNC_ALWAYS 519 // 0x0207
#if @alphaFunc != FUNC_ALWAYS && @alphaFunc != FUNC_NEVER
uniform float alphaRef;
#endif
float mipmapLevel(vec2 scaleduv) float mipmapLevel(vec2 scaleduv)
{ {
vec2 dUVdx = dFdx(scaleduv); vec2 dUVdx = dFdx(scaleduv);
@ -35,51 +33,55 @@ float coveragePreservingAlphaScale(sampler2D diffuseMap, vec2 uv)
#endif #endif
} }
void alphaTest() float alphaTest(float alpha)
{ {
#if @alphaToCoverage #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 // 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. // Use regular alpha testing in such cases until someone complains.
#if @alphaFunc == FUNC_NEVER #if @alphaFunc == FUNC_NEVER
discard; discard;
#elif @alphaFunc == FUNC_LESS #elif @alphaFunc == FUNC_LESS
gl_FragData[0].a = 1.0 - coverageAlpha; return 1.0 - coverageAlpha;
#elif @alphaFunc == FUNC_EQUAL #elif @alphaFunc == FUNC_EQUAL
if (gl_FragData[0].a != alphaRef) if (alpha != alphaRef)
discard; discard;
#elif @alphaFunc == FUNC_LEQUAL #elif @alphaFunc == FUNC_LEQUAL
gl_FragData[0].a = 1.0 - coverageAlpha; return 1.0 - coverageAlpha;
#elif @alphaFunc == FUNC_GREATER #elif @alphaFunc == FUNC_GREATER
gl_FragData[0].a = coverageAlpha; return coverageAlpha;
#elif @alphaFunc == FUNC_NOTEQUAL #elif @alphaFunc == FUNC_NOTEQUAL
if (gl_FragData[0].a == alphaRef) if (alpha == alphaRef)
discard; discard;
#elif @alphaFunc == FUNC_GEQUAL #elif @alphaFunc == FUNC_GEQUAL
gl_FragData[0].a = coverageAlpha; return coverageAlpha;
#endif #endif
#else #else
#if @alphaFunc == FUNC_NEVER #if @alphaFunc == FUNC_NEVER
discard; discard;
#elif @alphaFunc == FUNC_LESS #elif @alphaFunc == FUNC_LESS
if (gl_FragData[0].a >= alphaRef) if (alpha >= alphaRef)
discard; discard;
#elif @alphaFunc == FUNC_EQUAL #elif @alphaFunc == FUNC_EQUAL
if (gl_FragData[0].a != alphaRef) if (alpha != alphaRef)
discard; discard;
#elif @alphaFunc == FUNC_LEQUAL #elif @alphaFunc == FUNC_LEQUAL
if (gl_FragData[0].a > alphaRef) if (alpha > alphaRef)
discard; discard;
#elif @alphaFunc == FUNC_GREATER #elif @alphaFunc == FUNC_GREATER
if (gl_FragData[0].a <= alphaRef) if (alpha <= alphaRef)
discard; discard;
#elif @alphaFunc == FUNC_NOTEQUAL #elif @alphaFunc == FUNC_NOTEQUAL
if (gl_FragData[0].a == alphaRef) if (alpha == alphaRef)
discard; discard;
#elif @alphaFunc == FUNC_GEQUAL #elif @alphaFunc == FUNC_GEQUAL
if (gl_FragData[0].a < alphaRef) if (alpha < alphaRef)
discard; discard;
#endif #endif
#endif #endif
}
return alpha;
}
#endif

@ -1,3 +1,6 @@
#ifndef LIB_MATERIAL_PARALLAX
#define LIB_MATERIAL_PARALLAX
#define PARALLAX_SCALE 0.04 #define PARALLAX_SCALE 0.04
#define PARALLAX_BIAS -0.02 #define PARALLAX_BIAS -0.02
@ -6,3 +9,5 @@ vec2 getParallaxOffset(vec3 eyeDir, mat3 tbnTranspose, float height, float flipY
vec3 TSeyeDir = normalize(eyeDir * tbnTranspose); vec3 TSeyeDir = normalize(eyeDir * tbnTranspose);
return vec2(TSeyeDir.x, TSeyeDir.y * flipY) * ( height * PARALLAX_SCALE + PARALLAX_BIAS ); 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; #ifndef LIB_PARTICLE_SOFT
uniform sampler2D opaqueDepthTex; #define LIB_PARTICLE_SOFT
uniform float particleSize;
uniform bool particleFade;
float viewDepth(float depth) #include "lib/util/quickstep.glsl"
float viewDepth(float depth, float near, float far)
{ {
#if @reverseZ #if @reverseZ
depth = 1.0 - depth; depth = 1.0 - depth;
@ -11,26 +11,31 @@ float viewDepth(float depth)
return (near * far) / ((far - near) * depth - far); 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); float euclidianDepth = length(viewPos);
const float falloffMultiplier = 0.33; const float falloffMultiplier = 0.33;
const float contrast = 1.30; const float contrast = 1.30;
vec2 screenCoords = gl_FragCoord.xy / screenRes; float sceneDepth = viewDepth(depth, near, far);
float particleDepth = viewPos.z;
float depth = texture2D(opaqueDepthTex, screenCoords).x; float falloff = size * falloffMultiplier;
float sceneDepth = viewDepth(depth);
float particleDepth = passViewPos.z;
float falloff = particleSize * falloffMultiplier;
float delta = particleDepth - sceneDepth; float delta = particleDepth - sceneDepth;
const float nearMult = 300.0; const float nearMult = 300.0;
float viewBias = 1.0; float viewBias = 1.0;
if (particleFade) { if (fade) {
float VdotN = dot(viewDir, viewNormal); float VdotN = dot(viewDir, viewNormal);
viewBias = abs(VdotN) * quickstep(euclidianDepth / nearMult) * (1.0 - pow(1.0 + VdotN, 1.3)); 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; const float shift = 0.845;
return shift * pow(clamp(delta/falloff, 0.0, 1.0), contrast) * viewBias; 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 0
#define PASS_ATMOSPHERE_NIGHT 1 #define PASS_ATMOSPHERE_NIGHT 1
#define PASS_CLOUDS 2 #define PASS_CLOUDS 2
@ -5,3 +8,5 @@
#define PASS_SUN 4 #define PASS_SUN 4
#define PASS_SUNFLASH_QUERY 5 #define PASS_SUNFLASH_QUERY 5
#define PASS_SUNGLARE 6 #define PASS_SUNGLARE 6
#endif

@ -1,8 +1,5 @@
#version 120 #ifndef LIB_UTIL_COORDINATES
#define LIB_UTIL_COORDINATES
varying vec2 uv;
uniform samplerCube cubeMap;
uniform int mapping;
#define PI 3.1415926535 #define PI 3.1415926535
@ -37,16 +34,4 @@ vec3 planetCoords(vec2 coords)
return sphericalCoords(coords); return sphericalCoords(coords);
} }
void main(void) #endif
{
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);
}

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