diff --git a/apps/openmw/mwrender/luminancecalculator.cpp b/apps/openmw/mwrender/luminancecalculator.cpp index a881b8818f..b267b94e59 100644 --- a/apps/openmw/mwrender/luminancecalculator.cpp +++ b/apps/openmw/mwrender/luminancecalculator.cpp @@ -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); diff --git a/apps/openmw/mwrender/pingpongcanvas.cpp b/apps/openmw/mwrender/pingpongcanvas.cpp index f05cefb8f3..ef3f3fb67f 100644 --- a/apps/openmw/mwrender/pingpongcanvas.cpp +++ b/apps/openmw/mwrender/pingpongcanvas.cpp @@ -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) diff --git a/apps/openmw/mwrender/precipitationocclusion.cpp b/apps/openmw/mwrender/precipitationocclusion.cpp index d9965e3ee3..444ed8a1ed 100644 --- a/apps/openmw/mwrender/precipitationocclusion.cpp +++ b/apps/openmw/mwrender/precipitationocclusion.cpp @@ -52,11 +52,7 @@ namespace Shader::ShaderManager& shaderMgr = MWBase::Environment::get().getResourceSystem()->getSceneManager()->getShaderManager(); - osg::ref_ptr vertex - = shaderMgr.getShader("precipitation_vertex.glsl", {}, osg::Shader::VERTEX); - osg::ref_ptr fragment - = shaderMgr.getShader("precipitation_fragment.glsl", {}, osg::Shader::FRAGMENT); - mProgram = shaderMgr.getProgram(vertex, fragment); + mProgram = shaderMgr.getProgram("depthclipped"); } private: diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index f226b089f4..f92c08fd64 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -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)); } diff --git a/apps/openmw/mwrender/screenshotmanager.cpp b/apps/openmw/mwrender/screenshotmanager.cpp index f43a94a033..fb04d11cc9 100644 --- a/apps/openmw/mwrender/screenshotmanager.cpp +++ b/apps/openmw/mwrender/screenshotmanager.cpp @@ -264,18 +264,10 @@ namespace MWRender osg::ref_ptr screenshotCamera(new osg::Camera); osg::ref_ptr quad(new osg::ShapeDrawable(new osg::Box(osg::Vec3(0, 0, 0), 2.0))); - std::map defineMap; - - Shader::ShaderManager& shaderMgr = mResourceSystem->getSceneManager()->getShaderManager(); - osg::ref_ptr fragmentShader( - shaderMgr.getShader("s360_fragment.glsl", defineMap, osg::Shader::FRAGMENT)); - osg::ref_ptr vertexShader(shaderMgr.getShader("s360_vertex.glsl", defineMap, osg::Shader::VERTEX)); osg::ref_ptr stateset = quad->getOrCreateStateSet(); - osg::ref_ptr 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)); diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 230a8dbd7c..1466117af4 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -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); diff --git a/apps/openmw/mwrender/transparentpass.cpp b/apps/openmw/mwrender/transparentpass.cpp index cd72f5b7d6..7973575f47 100644 --- a/apps/openmw/mwrender/transparentpass.cpp +++ b/apps/openmw/mwrender/transparentpass.cpp @@ -34,13 +34,9 @@ namespace MWRender Shader::ShaderManager::DefineMap defines; Stereo::Manager::instance().shaderStereoDefines(defines); - osg::ref_ptr vertex - = shaderManager.getShader("blended_depth_postpass_vertex.glsl", defines, osg::Shader::VERTEX); - osg::ref_ptr 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) diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 6d602f8687..b082ad5185 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -675,11 +675,7 @@ namespace MWRender Stereo::Manager::instance().shaderStereoDefines(defineMap); Shader::ShaderManager& shaderMgr = mResourceSystem->getSceneManager()->getShaderManager(); - osg::ref_ptr vertexShader( - shaderMgr.getShader("water_vertex.glsl", defineMap, osg::Shader::VERTEX)); - osg::ref_ptr fragmentShader( - shaderMgr.getShader("water_fragment.glsl", defineMap, osg::Shader::FRAGMENT)); - osg::ref_ptr program = shaderMgr.getProgram(vertexShader, fragmentShader); + osg::ref_ptr program = shaderMgr.getProgram("water", defineMap); osg::ref_ptr normalMap( new osg::Texture2D(mResourceSystem->getImageManager()->getImage("textures/omw/water_nm.png"))); diff --git a/apps/openmw_test_suite/nifosg/testnifloader.cpp b/apps/openmw_test_suite/nifosg/testnifloader.cpp index 5671227f80..3c13cb1f79 100644 --- a/apps/openmw_test_suite/nifosg/testnifloader.cpp +++ b/apps/openmw_test_suite/nifosg/testnifloader.cpp @@ -175,10 +175,10 @@ osg::Group { struct NifOsgLoaderBSShaderPrefixTest : TestWithParam, BaseNifOsgLoaderTest { static constexpr std::array sParams = { - ShaderPrefixParams{ static_cast(Nif::BSShaderType::ShaderType_Default), "nv_default" }, - ShaderPrefixParams{ static_cast(Nif::BSShaderType::ShaderType_NoLighting), "nv_nolighting" }, - ShaderPrefixParams{ static_cast(Nif::BSShaderType::ShaderType_Tile), "nv_default" }, - ShaderPrefixParams{ std::numeric_limits::max(), "nv_default" }, + ShaderPrefixParams{ static_cast(Nif::BSShaderType::ShaderType_Default), "bs/default" }, + ShaderPrefixParams{ static_cast(Nif::BSShaderType::ShaderType_NoLighting), "bs/nolighting" }, + ShaderPrefixParams{ static_cast(Nif::BSShaderType::ShaderType_Tile), "bs/default" }, + ShaderPrefixParams{ std::numeric_limits::max(), "bs/default" }, }; }; @@ -204,9 +204,9 @@ osg::Group { { static constexpr std::array sParams = { ShaderPrefixParams{ - static_cast(Nif::BSLightingShaderType::ShaderType_Default), "nv_default" }, - ShaderPrefixParams{ static_cast(Nif::BSLightingShaderType::ShaderType_Cloud), "nv_default" }, - ShaderPrefixParams{ std::numeric_limits::max(), "nv_default" }, + static_cast(Nif::BSLightingShaderType::ShaderType_Default), "bs/default" }, + ShaderPrefixParams{ static_cast(Nif::BSLightingShaderType::ShaderType_Cloud), "bs/default" }, + ShaderPrefixParams{ std::numeric_limits::max(), "bs/default" }, }; }; diff --git a/apps/openmw_test_suite/shader/shadermanager.cpp b/apps/openmw_test_suite/shader/shadermanager.cpp index 25f7e55444..3d7eaecf00 100644 --- a/apps/openmw_test_suite/shader/shadermanager.cpp +++ b/apps/openmw_test_suite/shader/shadermanager.cpp @@ -17,7 +17,7 @@ namespace ShaderManager mManager; ShaderManager::DefineMap mDefines; - ShaderManagerTest() { mManager.setShaderPath("."); } + ShaderManagerTest() { mManager.setShaderPath("tests_output"); } template void withShaderFile(const std::string& content, F&& f) @@ -28,16 +28,17 @@ namespace template 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)); }); } } diff --git a/apps/openmw_test_suite/testing_util.hpp b/apps/openmw_test_suite/testing_util.hpp index 39eacc3736..2f76a9df1d 100644 --- a/apps/openmw_test_suite/testing_util.hpp +++ b/apps/openmw_test_suite/testing_util.hpp @@ -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; diff --git a/cmake/OpenMWMacros.cmake b/cmake/OpenMWMacros.cmake index 0adc185b38..2cb7e6eec8 100644 --- a/cmake/OpenMWMacros.cmake +++ b/cmake/OpenMWMacros.cmake @@ -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) diff --git a/components/debug/debugdraw.cpp b/components/debug/debugdraw.cpp index 7aac5fd6ef..d7111a852b 100644 --- a/components/debug/debugdraw.cpp +++ b/components/debug/debugdraw.cpp @@ -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); diff --git a/components/myguiplatform/myguirendermanager.cpp b/components/myguiplatform/myguirendermanager.cpp index 8fff38d668..4ee1190a99 100644 --- a/components/myguiplatform/myguirendermanager.cpp +++ b/components/myguiplatform/myguirendermanager.cpp @@ -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)); diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 914d60c13c..7fadb0db8b 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -1991,9 +1991,9 @@ namespace NifOsg switch (static_cast(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(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, diff --git a/components/sceneutil/mwshadowtechnique.cpp b/components/sceneutil/mwshadowtechnique.cpp index d9a3c9270a..77ba74892f 100644 --- a/components/sceneutil/mwshadowtechnique.cpp +++ b/components/sceneutil/mwshadowtechnique.cpp @@ -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 castingVertexShader = shaderManager.getShader("shadowcasting_vertex.glsl", { }, osg::Shader::VERTEX); + osg::ref_ptr castingVertexShader = shaderManager.getShader("shadowcasting.vert"); osg::ref_ptr 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)); + })); } } diff --git a/components/shader/shadermanager.cpp b/components/shader/shadermanager.cpp index 9f31412713..5bca77b804 100644 --- a/components/shader/shadermanager.cpp +++ b/components/shader/shadermanager.cpp @@ -16,6 +16,29 @@ #include #include +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 ShaderManager::getShader( - const std::string& templateName, const ShaderManager::DefineMap& defines, osg::Shader::Type shaderType) + std::string templateName, const ShaderManager::DefineMap& defines, std::optional type) { std::unique_lock 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 insertedPaths; @@ -514,7 +547,7 @@ namespace Shader return nullptr; } - osg::ref_ptr shader(new osg::Shader(shaderType)); + osg::ref_ptr 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 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 ShaderManager::getProgram(osg::ref_ptr vertexShader, osg::ref_ptr fragmentShader, const osg::Program* programTemplate) { diff --git a/components/shader/shadermanager.hpp b/components/shader/shadermanager.hpp index e057867ee3..e3236f27e5 100644 --- a/components/shader/shadermanager.hpp +++ b/components/shader/shadermanager.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -36,13 +37,16 @@ namespace Shader typedef std::map 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 getShader( - const std::string& templateName, const DefineMap& defines, osg::Shader::Type shaderType); + osg::ref_ptr getShader(std::string templateName, const DefineMap& defines = {}, + std::optional type = std::nullopt); + + osg::ref_ptr getProgram(const std::string& templateName, const DefineMap& defines = {}, + const osg::Program* programTemplate = nullptr); osg::ref_ptr getProgram(osg::ref_ptr vertexShader, osg::ref_ptr fragmentShader, const osg::Program* programTemplate = nullptr); diff --git a/components/shader/shadervisitor.cpp b/components/shader/shadervisitor.cpp index 2a2429ff79..06f246e9bc 100644 --- a/components/shader/shadervisitor.cpp +++ b/components/shader/shadervisitor.cpp @@ -715,24 +715,14 @@ namespace Shader if (!node.getUserValue("shaderPrefix", shaderPrefix)) shaderPrefix = mDefaultShaderPrefix; - osg::ref_ptr vertexShader( - mShaderManager.getShader(shaderPrefix + "_vertex.glsl", defineMap, osg::Shader::VERTEX)); - osg::ref_ptr fragmentShader( - mShaderManager.getShader(shaderPrefix + "_fragment.glsl", defineMap, osg::Shader::FRAGMENT)); + auto program = mShaderManager.getProgram(shaderPrefix, defineMap, mProgramTemplate); + writableStateSet->setAttributeAndModes(program, osg::StateAttribute::ON); + addedState->setAttributeAndModes(program); - if (vertexShader && fragmentShader) + for (const auto& [unit, name] : reqs.mTextures) { - auto program = mShaderManager.getProgram(vertexShader, fragmentShader, mProgramTemplate); - writableStateSet->setAttributeAndModes(program, osg::StateAttribute::ON); - addedState->setAttributeAndModes(program); - - for (std::map::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); - } + writableStateSet->addUniform(new osg::Uniform(name.c_str(), unit), osg::StateAttribute::ON); + addedState->addUniform(name); } if (!addedState->empty()) diff --git a/components/terrain/material.cpp b/components/terrain/material.cpp index e7f08e7875..c06735d927 100644 --- a/components/terrain/material.cpp +++ b/components/terrain/material.cpp @@ -285,17 +285,7 @@ namespace Terrain defineMap["writeNormals"] = (it == layers.end() - 1) ? "1" : "0"; Stereo::Manager::instance().shaderStereoDefines(defineMap); - osg::ref_ptr vertexShader - = shaderManager.getShader("terrain_vertex.glsl", defineMap, osg::Shader::VERTEX); - osg::ref_ptr 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 diff --git a/files/shaders/CMakeLists.txt b/files/shaders/CMakeLists.txt index 7423a74aa6..9059360980 100644 --- a/files/shaders/CMakeLists.txt +++ b/files/shaders/CMakeLists.txt @@ -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}") diff --git a/files/shaders/nv_default_fragment.glsl b/files/shaders/compatibility/bs/default.frag similarity index 93% rename from files/shaders/nv_default_fragment.glsl rename to files/shaders/compatibility/bs/default.frag index 565e76357d..d1461eb821 100644 --- a/files/shaders/nv_default_fragment.glsl +++ b/files/shaders/compatibility/bs/default.frag @@ -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 diff --git a/files/shaders/nv_default_vertex.glsl b/files/shaders/compatibility/bs/default.vert similarity index 87% rename from files/shaders/nv_default_vertex.glsl rename to files/shaders/compatibility/bs/default.vert index 0d014b02fa..c2df86eb73 100644 --- a/files/shaders/nv_default_vertex.glsl +++ b/files/shaders/compatibility/bs/default.vert @@ -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); diff --git a/files/shaders/nv_nolighting_fragment.glsl b/files/shaders/compatibility/bs/nolighting.frag similarity index 87% rename from files/shaders/nv_nolighting_fragment.glsl rename to files/shaders/compatibility/bs/nolighting.frag index 09c00eaeae..dc038d491c 100644 --- a/files/shaders/nv_nolighting_fragment.glsl +++ b/files/shaders/compatibility/bs/nolighting.frag @@ -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); } diff --git a/files/shaders/nv_nolighting_vertex.glsl b/files/shaders/compatibility/bs/nolighting.vert similarity index 87% rename from files/shaders/nv_nolighting_vertex.glsl rename to files/shaders/compatibility/bs/nolighting.vert index f3c5d41c98..039017b53b 100644 --- a/files/shaders/nv_nolighting_vertex.glsl +++ b/files/shaders/compatibility/bs/nolighting.vert @@ -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); diff --git a/files/shaders/debug_fragment.glsl b/files/shaders/compatibility/debug.frag similarity index 100% rename from files/shaders/debug_fragment.glsl rename to files/shaders/compatibility/debug.frag diff --git a/files/shaders/debug_vertex.glsl b/files/shaders/compatibility/debug.vert similarity index 76% rename from files/shaders/debug_vertex.glsl rename to files/shaders/compatibility/debug.vert index df710fe6f7..1f97cfc025 100644 --- a/files/shaders/debug_vertex.glsl +++ b/files/shaders/compatibility/debug.vert @@ -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; diff --git a/files/shaders/blended_depth_postpass_fragment.glsl b/files/shaders/compatibility/depthclipped.frag similarity index 77% rename from files/shaders/blended_depth_postpass_fragment.glsl rename to files/shaders/compatibility/depthclipped.frag index fc86080030..bc2b12f729 100644 --- a/files/shaders/blended_depth_postpass_fragment.glsl +++ b/files/shaders/compatibility/depthclipped.frag @@ -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. } diff --git a/files/shaders/blended_depth_postpass_vertex.glsl b/files/shaders/compatibility/depthclipped.vert similarity index 68% rename from files/shaders/blended_depth_postpass_vertex.glsl rename to files/shaders/compatibility/depthclipped.vert index ee27507983..d348ea1a8a 100644 --- a/files/shaders/blended_depth_postpass_vertex.glsl +++ b/files/shaders/compatibility/depthclipped.vert @@ -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; diff --git a/files/shaders/fog.glsl b/files/shaders/compatibility/fog.glsl similarity index 75% rename from files/shaders/fog.glsl rename to files/shaders/compatibility/fog.glsl index d9d0548aa9..a7cccbf787 100644 --- a/files/shaders/fog.glsl +++ b/files/shaders/compatibility/fog.glsl @@ -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); } diff --git a/files/shaders/compatibility/fullscreen_tri.frag b/files/shaders/compatibility/fullscreen_tri.frag new file mode 100644 index 0000000000..751d3d7414 --- /dev/null +++ b/files/shaders/compatibility/fullscreen_tri.frag @@ -0,0 +1,10 @@ +#version 120 + +varying vec2 uv; + +#include "lib/core/fragment.h.glsl" + +void main() +{ + gl_FragColor = samplerLastShader(uv); +} \ No newline at end of file diff --git a/files/shaders/fullscreen_tri_vertex.glsl b/files/shaders/compatibility/fullscreen_tri.vert similarity index 84% rename from files/shaders/fullscreen_tri_vertex.glsl rename to files/shaders/compatibility/fullscreen_tri.vert index ab394190a8..3174384212 100644 --- a/files/shaders/fullscreen_tri_vertex.glsl +++ b/files/shaders/compatibility/fullscreen_tri.vert @@ -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() { diff --git a/files/shaders/groundcover_fragment.glsl b/files/shaders/compatibility/groundcover.frag similarity index 92% rename from files/shaders/groundcover_fragment.glsl rename to files/shaders/compatibility/groundcover.frag index f8599ecaa8..d975a71785 100644 --- a/files/shaders/groundcover_fragment.glsl +++ b/files/shaders/compatibility/groundcover.frag @@ -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; diff --git a/files/shaders/groundcover_vertex.glsl b/files/shaders/compatibility/groundcover.vert similarity index 97% rename from files/shaders/groundcover_vertex.glsl rename to files/shaders/compatibility/groundcover.vert index aa9dea3355..dd8d083a47 100644 --- a/files/shaders/groundcover_vertex.glsl +++ b/files/shaders/compatibility/groundcover.vert @@ -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); diff --git a/files/shaders/gui_fragment.glsl b/files/shaders/compatibility/gui.frag similarity index 100% rename from files/shaders/gui_fragment.glsl rename to files/shaders/compatibility/gui.frag diff --git a/files/shaders/gui_vertex.glsl b/files/shaders/compatibility/gui.vert similarity index 100% rename from files/shaders/gui_vertex.glsl rename to files/shaders/compatibility/gui.vert diff --git a/files/shaders/hdr_luminance_fragment.glsl b/files/shaders/compatibility/luminance/luminance.frag similarity index 51% rename from files/shaders/hdr_luminance_fragment.glsl rename to files/shaders/compatibility/luminance/luminance.frag index b6d527c85e..412defcc30 100644 --- a/files/shaders/hdr_luminance_fragment.glsl +++ b/files/shaders/compatibility/luminance/luminance.frag @@ -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); } diff --git a/files/shaders/hdr_resolve_fragment.glsl b/files/shaders/compatibility/luminance/resolve.frag similarity index 72% rename from files/shaders/hdr_resolve_fragment.glsl rename to files/shaders/compatibility/luminance/resolve.frag index e04ff7cb6a..d69135416e 100644 --- a/files/shaders/hdr_resolve_fragment.glsl +++ b/files/shaders/compatibility/luminance/resolve.frag @@ -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)); } diff --git a/files/shaders/multiview_resolve_fragment.glsl b/files/shaders/compatibility/multiview_resolve.frag similarity index 63% rename from files/shaders/multiview_resolve_fragment.glsl rename to files/shaders/compatibility/multiview_resolve.frag index c0a137464f..3655f1fa26 100644 --- a/files/shaders/multiview_resolve_fragment.glsl +++ b/files/shaders/compatibility/multiview_resolve.frag @@ -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); } \ No newline at end of file diff --git a/files/shaders/multiview_resolve_vertex.glsl b/files/shaders/compatibility/multiview_resolve.vert similarity index 100% rename from files/shaders/multiview_resolve_vertex.glsl rename to files/shaders/compatibility/multiview_resolve.vert diff --git a/files/shaders/objects_fragment.glsl b/files/shaders/compatibility/objects.frag similarity index 87% rename from files/shaders/objects_fragment.glsl rename to files/shaders/compatibility/objects.frag index c0a8fc9e26..5690309937 100644 --- a/files/shaders/objects_fragment.glsl +++ b/files/shaders/compatibility/objects.frag @@ -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 diff --git a/files/shaders/objects_vertex.glsl b/files/shaders/compatibility/objects.vert similarity index 94% rename from files/shaders/objects_vertex.glsl rename to files/shaders/compatibility/objects.vert index 12af0fa003..1ea4a1553f 100644 --- a/files/shaders/objects_vertex.glsl +++ b/files/shaders/compatibility/objects.vert @@ -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) diff --git a/files/shaders/compatibility/s360.frag b/files/shaders/compatibility/s360.frag new file mode 100644 index 0000000000..7e7241e174 --- /dev/null +++ b/files/shaders/compatibility/s360.frag @@ -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); +} diff --git a/files/shaders/s360_vertex.glsl b/files/shaders/compatibility/s360.vert similarity index 100% rename from files/shaders/s360_vertex.glsl rename to files/shaders/compatibility/s360.vert diff --git a/files/shaders/shadowcasting_fragment.glsl b/files/shaders/compatibility/shadowcasting.frag similarity index 86% rename from files/shaders/shadowcasting_fragment.glsl rename to files/shaders/compatibility/shadowcasting.frag index 07fad047e1..19cca14951 100644 --- a/files/shaders/shadowcasting_fragment.glsl +++ b/files/shaders/compatibility/shadowcasting.frag @@ -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 diff --git a/files/shaders/shadowcasting_vertex.glsl b/files/shaders/compatibility/shadowcasting.vert similarity index 100% rename from files/shaders/shadowcasting_vertex.glsl rename to files/shaders/compatibility/shadowcasting.vert diff --git a/files/shaders/shadows_fragment.glsl b/files/shaders/compatibility/shadows_fragment.glsl similarity index 100% rename from files/shaders/shadows_fragment.glsl rename to files/shaders/compatibility/shadows_fragment.glsl diff --git a/files/shaders/shadows_vertex.glsl b/files/shaders/compatibility/shadows_vertex.glsl similarity index 100% rename from files/shaders/shadows_vertex.glsl rename to files/shaders/compatibility/shadows_vertex.glsl diff --git a/files/shaders/sky_fragment.glsl b/files/shaders/compatibility/sky.frag similarity index 98% rename from files/shaders/sky_fragment.glsl rename to files/shaders/compatibility/sky.frag index e12614c082..7c4ea561d2 100644 --- a/files/shaders/sky_fragment.glsl +++ b/files/shaders/compatibility/sky.frag @@ -1,6 +1,6 @@ #version 120 -#include "skypasses.glsl" +#include "lib/sky/passes.glsl" uniform int pass; uniform sampler2D diffuseMap; diff --git a/files/shaders/sky_vertex.glsl b/files/shaders/compatibility/sky.vert similarity index 72% rename from files/shaders/sky_vertex.glsl rename to files/shaders/compatibility/sky.vert index 8ff9c0f156..0cd6c0660c 100644 --- a/files/shaders/sky_vertex.glsl +++ b/files/shaders/compatibility/sky.vert @@ -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) diff --git a/files/shaders/terrain_fragment.glsl b/files/shaders/compatibility/terrain.frag similarity index 96% rename from files/shaders/terrain_fragment.glsl rename to files/shaders/compatibility/terrain.frag index 831e653878..a2fbddf3f7 100644 --- a/files/shaders/terrain_fragment.glsl +++ b/files/shaders/compatibility/terrain.frag @@ -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; diff --git a/files/shaders/terrain_vertex.glsl b/files/shaders/compatibility/terrain.vert similarity index 88% rename from files/shaders/terrain_vertex.glsl rename to files/shaders/compatibility/terrain.vert index a426061941..5e154d912a 100644 --- a/files/shaders/terrain_vertex.glsl +++ b/files/shaders/compatibility/terrain.vert @@ -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); diff --git a/files/shaders/vertexcolors.glsl b/files/shaders/compatibility/vertexcolors.glsl similarity index 100% rename from files/shaders/vertexcolors.glsl rename to files/shaders/compatibility/vertexcolors.glsl diff --git a/files/shaders/water_fragment.glsl b/files/shaders/compatibility/water.frag similarity index 63% rename from files/shaders/water_fragment.glsl rename to files/shaders/compatibility/water.frag index 5849511316..8fe9c824fc 100644 --- a/files/shaders/water_fragment.glsl +++ b/files/shaders/compatibility/water.frag @@ -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); - } +{ + 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; diff --git a/files/shaders/water_vertex.glsl b/files/shaders/compatibility/water.vert similarity index 65% rename from files/shaders/water_vertex.glsl rename to files/shaders/compatibility/water.vert index b09d3b54ae..843118f46d 100644 --- a/files/shaders/water_vertex.glsl +++ b/files/shaders/compatibility/water.vert @@ -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)); diff --git a/files/shaders/core/gui.frag b/files/shaders/core/gui.frag new file mode 100644 index 0000000000..cff50c9d05 --- /dev/null +++ b/files/shaders/core/gui.frag @@ -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; +} diff --git a/files/shaders/core/gui.vert b/files/shaders/core/gui.vert new file mode 100644 index 0000000000..475d94c867 --- /dev/null +++ b/files/shaders/core/gui.vert @@ -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; +} diff --git a/files/shaders/depth.glsl b/files/shaders/depth.glsl deleted file mode 100644 index aa6f54b99d..0000000000 --- a/files/shaders/depth.glsl +++ /dev/null @@ -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 -} \ No newline at end of file diff --git a/files/shaders/fullscreen_tri_fragment.glsl b/files/shaders/fullscreen_tri_fragment.glsl deleted file mode 100644 index b71f98365d..0000000000 --- a/files/shaders/fullscreen_tri_fragment.glsl +++ /dev/null @@ -1,10 +0,0 @@ -#version 120 - -varying vec2 uv; - -#include "openmw_fragment.h.glsl" - -void main() -{ - gl_FragColor = mw_samplerLastShader(uv); -} \ No newline at end of file diff --git a/files/shaders/openmw_fragment.glsl b/files/shaders/lib/core/fragment.glsl similarity index 55% rename from files/shaders/openmw_fragment.glsl rename to files/shaders/lib/core/fragment.glsl index 8c8302f3ae..68fbe5e39d 100644 --- a/files/shaders/openmw_fragment.glsl +++ b/files/shaders/lib/core/fragment.glsl @@ -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; } diff --git a/files/shaders/lib/core/fragment.h.glsl b/files/shaders/lib/core/fragment.h.glsl new file mode 100644 index 0000000000..1bc2a1f79a --- /dev/null +++ b/files/shaders/lib/core/fragment.h.glsl @@ -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 diff --git a/files/shaders/lib/core/fragment_multiview.glsl b/files/shaders/lib/core/fragment_multiview.glsl new file mode 100644 index 0000000000..cc804d6c80 --- /dev/null +++ b/files/shaders/lib/core/fragment_multiview.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 diff --git a/files/shaders/lib/core/vertex.glsl b/files/shaders/lib/core/vertex.glsl new file mode 100644 index 0000000000..f0dee32bb3 --- /dev/null +++ b/files/shaders/lib/core/vertex.glsl @@ -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; +} diff --git a/files/shaders/lib/core/vertex.h.glsl b/files/shaders/lib/core/vertex.h.glsl new file mode 100644 index 0000000000..6e22f6deb1 --- /dev/null +++ b/files/shaders/lib/core/vertex.h.glsl @@ -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); diff --git a/files/shaders/openmw_vertex_multiview.glsl b/files/shaders/lib/core/vertex_multiview.glsl similarity index 58% rename from files/shaders/openmw_vertex_multiview.glsl rename to files/shaders/lib/core/vertex_multiview.glsl index 64230a6e4a..0447730e49 100644 --- a/files/shaders/openmw_vertex_multiview.glsl +++ b/files/shaders/lib/core/vertex_multiview.glsl @@ -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; -} \ No newline at end of file +} diff --git a/files/shaders/lighting.glsl b/files/shaders/lib/light/lighting.glsl similarity index 97% rename from files/shaders/lighting.glsl rename to files/shaders/lib/light/lighting.glsl index 177017f822..8c1262ba4d 100644 --- a/files/shaders/lighting.glsl +++ b/files/shaders/lib/light/lighting.glsl @@ -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 diff --git a/files/shaders/lighting_util.glsl b/files/shaders/lib/light/lighting_util.glsl similarity index 97% rename from files/shaders/lighting_util.glsl rename to files/shaders/lib/light/lighting_util.glsl index e27f1b04ae..afa38af86b 100644 --- a/files/shaders/lighting_util.glsl +++ b/files/shaders/lib/light/lighting_util.glsl @@ -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 diff --git a/files/shaders/lib/luminance/constants.glsl b/files/shaders/lib/luminance/constants.glsl new file mode 100644 index 0000000000..407b30847c --- /dev/null +++ b/files/shaders/lib/luminance/constants.glsl @@ -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 diff --git a/files/shaders/alpha.glsl b/files/shaders/lib/material/alpha.glsl similarity index 72% rename from files/shaders/alpha.glsl rename to files/shaders/lib/material/alpha.glsl index 46b748236c..5adfa18e88 100644 --- a/files/shaders/alpha.glsl +++ b/files/shaders/lib/material/alpha.glsl @@ -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 -} \ No newline at end of file + + return alpha; +} + +#endif diff --git a/files/shaders/parallax.glsl b/files/shaders/lib/material/parallax.glsl similarity index 81% rename from files/shaders/parallax.glsl rename to files/shaders/lib/material/parallax.glsl index 433dbcd3e4..7f4ce2d1dc 100644 --- a/files/shaders/parallax.glsl +++ b/files/shaders/lib/material/parallax.glsl @@ -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 \ No newline at end of file diff --git a/files/shaders/lib/particle/occlusion.glsl b/files/shaders/lib/particle/occlusion.glsl new file mode 100644 index 0000000000..7cf15f8b0c --- /dev/null +++ b/files/shaders/lib/particle/occlusion.glsl @@ -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 diff --git a/files/shaders/softparticles.glsl b/files/shaders/lib/particle/soft.glsl similarity index 55% rename from files/shaders/softparticles.glsl rename to files/shaders/lib/particle/soft.glsl index c4bb90ebe2..f12ec4d9cc 100644 --- a/files/shaders/softparticles.glsl +++ b/files/shaders/lib/particle/soft.glsl @@ -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 diff --git a/files/shaders/skypasses.glsl b/files/shaders/lib/sky/passes.glsl similarity index 75% rename from files/shaders/skypasses.glsl rename to files/shaders/lib/sky/passes.glsl index e80d4eb259..a32d097622 100644 --- a/files/shaders/skypasses.glsl +++ b/files/shaders/lib/sky/passes.glsl @@ -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 diff --git a/files/shaders/s360_fragment.glsl b/files/shaders/lib/util/coordinates.glsl similarity index 73% rename from files/shaders/s360_fragment.glsl rename to files/shaders/lib/util/coordinates.glsl index f52e1478ee..54b779b55e 100644 --- a/files/shaders/s360_fragment.glsl +++ b/files/shaders/lib/util/coordinates.glsl @@ -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 diff --git a/files/shaders/lib/util/quickstep.glsl b/files/shaders/lib/util/quickstep.glsl new file mode 100644 index 0000000000..2baa0a7430 --- /dev/null +++ b/files/shaders/lib/util/quickstep.glsl @@ -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 diff --git a/files/shaders/lib/view/depth.glsl b/files/shaders/lib/view/depth.glsl new file mode 100644 index 0000000000..7773c141de --- /dev/null +++ b/files/shaders/lib/view/depth.glsl @@ -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 diff --git a/files/shaders/lib/water/fresnel.glsl b/files/shaders/lib/water/fresnel.glsl new file mode 100644 index 0000000000..929b027400 --- /dev/null +++ b/files/shaders/lib/water/fresnel.glsl @@ -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 diff --git a/files/shaders/lib/water/ripples.glsl b/files/shaders/lib/water/ripples.glsl new file mode 100644 index 0000000000..4e5f85017b --- /dev/null +++ b/files/shaders/lib/water/ripples.glsl @@ -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 diff --git a/files/shaders/openmw_fragment.h.glsl b/files/shaders/openmw_fragment.h.glsl deleted file mode 100644 index f7c1e2f21e..0000000000 --- a/files/shaders/openmw_fragment.h.glsl +++ /dev/null @@ -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 diff --git a/files/shaders/openmw_fragment_multiview.glsl b/files/shaders/openmw_fragment_multiview.glsl deleted file mode 100644 index 61f69cc2d9..0000000000 --- a/files/shaders/openmw_fragment_multiview.glsl +++ /dev/null @@ -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 diff --git a/files/shaders/openmw_vertex.glsl b/files/shaders/openmw_vertex.glsl deleted file mode 100644 index b671570348..0000000000 --- a/files/shaders/openmw_vertex.glsl +++ /dev/null @@ -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; -} diff --git a/files/shaders/openmw_vertex.h.glsl b/files/shaders/openmw_vertex.h.glsl deleted file mode 100644 index 9d7f496a6a..0000000000 --- a/files/shaders/openmw_vertex.h.glsl +++ /dev/null @@ -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); \ No newline at end of file diff --git a/files/shaders/precipitation_fragment.glsl b/files/shaders/precipitation_fragment.glsl deleted file mode 100644 index b16eb0fd99..0000000000 --- a/files/shaders/precipitation_fragment.glsl +++ /dev/null @@ -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; -} \ No newline at end of file diff --git a/files/shaders/precipitation_vertex.glsl b/files/shaders/precipitation_vertex.glsl deleted file mode 100644 index a202d9cd96..0000000000 --- a/files/shaders/precipitation_vertex.glsl +++ /dev/null @@ -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; -} \ No newline at end of file