mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-14 21:39:41 +00:00
mono-only version of the shader linking system introduced in the stereo MR
This commit is contained in:
parent
dd4f1e3044
commit
dc3045c970
19 changed files with 412 additions and 99 deletions
apps/openmw_test_suite
components/shader
files/shaders
|
@ -55,6 +55,7 @@ if (GTEST_FOUND AND GMOCK_FOUND)
|
|||
|
||||
shader/parsedefines.cpp
|
||||
shader/parsefors.cpp
|
||||
shader/parselinks.cpp
|
||||
shader/shadermanager.cpp
|
||||
|
||||
../openmw/options.cpp
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <gtest/gtest.h>
|
||||
#include <gmock/gmock.h>
|
||||
#include <vector>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -16,6 +17,12 @@ namespace
|
|||
const std::string mName = "shader";
|
||||
};
|
||||
|
||||
static bool parseFors(std::string& source, const std::string& templateName)
|
||||
{
|
||||
std::vector<std::string> dummy;
|
||||
return parseDirectives(source, dummy, {}, {}, templateName);
|
||||
}
|
||||
|
||||
TEST_F(ShaderParseForsTest, empty_should_succeed)
|
||||
{
|
||||
ASSERT_TRUE(parseFors(mSource, mName));
|
||||
|
|
100
apps/openmw_test_suite/shader/parselinks.cpp
Normal file
100
apps/openmw_test_suite/shader/parselinks.cpp
Normal file
|
@ -0,0 +1,100 @@
|
|||
#include <components/shader/shadermanager.hpp>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <gmock/gmock.h>
|
||||
#include <vector>
|
||||
|
||||
namespace
|
||||
{
|
||||
using namespace testing;
|
||||
using namespace Shader;
|
||||
|
||||
using DefineMap = ShaderManager::DefineMap;
|
||||
|
||||
struct ShaderParseLinksTest : Test
|
||||
{
|
||||
std::string mSource;
|
||||
std::vector<std::string> mLinkTargets;
|
||||
ShaderManager::DefineMap mDefines;
|
||||
const std::string mName = "my_shader.glsl";
|
||||
|
||||
bool parseLinks()
|
||||
{
|
||||
return parseDirectives(mSource, mLinkTargets, mDefines, {}, mName);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(ShaderParseLinksTest, empty_should_succeed)
|
||||
{
|
||||
ASSERT_TRUE(parseLinks());
|
||||
EXPECT_EQ(mSource, "");
|
||||
EXPECT_TRUE(mLinkTargets.empty());
|
||||
}
|
||||
|
||||
TEST_F(ShaderParseLinksTest, should_fail_for_single_escape_symbol)
|
||||
{
|
||||
mSource = "$";
|
||||
ASSERT_FALSE(parseLinks());
|
||||
EXPECT_EQ(mSource, "$");
|
||||
EXPECT_TRUE(mLinkTargets.empty());
|
||||
}
|
||||
|
||||
TEST_F(ShaderParseLinksTest, should_fail_on_first_found_escaped_not_valid_directive)
|
||||
{
|
||||
mSource = "$foo ";
|
||||
ASSERT_FALSE(parseLinks());
|
||||
EXPECT_EQ(mSource, "$foo ");
|
||||
EXPECT_TRUE(mLinkTargets.empty());
|
||||
}
|
||||
|
||||
TEST_F(ShaderParseLinksTest, should_fail_on_absent_link_target)
|
||||
{
|
||||
mSource = "$link ";
|
||||
ASSERT_FALSE(parseLinks());
|
||||
EXPECT_EQ(mSource, "$link ");
|
||||
EXPECT_TRUE(mLinkTargets.empty());
|
||||
}
|
||||
|
||||
TEST_F(ShaderParseLinksTest, should_not_require_newline)
|
||||
{
|
||||
mSource = "$link \"foo.glsl\"";
|
||||
ASSERT_TRUE(parseLinks());
|
||||
EXPECT_EQ(mSource, "");
|
||||
ASSERT_EQ(mLinkTargets.size(), 1);
|
||||
EXPECT_EQ(mLinkTargets[0], "foo.glsl");
|
||||
}
|
||||
|
||||
TEST_F(ShaderParseLinksTest, should_require_quotes)
|
||||
{
|
||||
mSource = "$link foo.glsl";
|
||||
ASSERT_FALSE(parseLinks());
|
||||
EXPECT_EQ(mSource, "$link foo.glsl");
|
||||
EXPECT_EQ(mLinkTargets.size(), 0);
|
||||
}
|
||||
|
||||
TEST_F(ShaderParseLinksTest, should_be_replaced_with_empty_line)
|
||||
{
|
||||
mSource = "$link \"foo.glsl\"\nbar";
|
||||
ASSERT_TRUE(parseLinks());
|
||||
EXPECT_EQ(mSource, "\nbar");
|
||||
ASSERT_EQ(mLinkTargets.size(), 1);
|
||||
EXPECT_EQ(mLinkTargets[0], "foo.glsl");
|
||||
}
|
||||
|
||||
TEST_F(ShaderParseLinksTest, should_only_accept_on_true_condition)
|
||||
{
|
||||
mSource =
|
||||
R"glsl(
|
||||
$link "foo.glsl" if 1
|
||||
$link "bar.glsl" if 0
|
||||
)glsl";
|
||||
ASSERT_TRUE(parseLinks());
|
||||
EXPECT_EQ(mSource,
|
||||
R"glsl(
|
||||
|
||||
|
||||
)glsl");
|
||||
ASSERT_EQ(mLinkTargets.size(), 1);
|
||||
EXPECT_EQ(mLinkTargets[0], "foo.glsl");
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
#include <fstream>
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <regex>
|
||||
|
||||
#include <osg/Program>
|
||||
|
||||
|
@ -142,11 +143,123 @@ namespace Shader
|
|||
return true;
|
||||
}
|
||||
|
||||
bool parseFors(std::string& source, const std::string& templateName)
|
||||
bool parseForeachDirective(std::string& source, const std::string& templateName, size_t foundPos)
|
||||
{
|
||||
size_t iterNameStart = foundPos + strlen("$foreach") + 1;
|
||||
size_t iterNameEnd = source.find_first_of(" \n\r()[].;,", iterNameStart);
|
||||
if (iterNameEnd == std::string::npos)
|
||||
{
|
||||
Log(Debug::Error) << "Shader " << templateName << " error: Unexpected EOF";
|
||||
return false;
|
||||
}
|
||||
std::string iteratorName = "$" + source.substr(iterNameStart, iterNameEnd - iterNameStart);
|
||||
|
||||
size_t listStart = iterNameEnd + 1;
|
||||
size_t listEnd = source.find_first_of("\n\r", listStart);
|
||||
if (listEnd == std::string::npos)
|
||||
{
|
||||
Log(Debug::Error) << "Shader " << templateName << " error: Unexpected EOF";
|
||||
return false;
|
||||
}
|
||||
std::string list = source.substr(listStart, listEnd - listStart);
|
||||
std::vector<std::string> listElements;
|
||||
if (list != "")
|
||||
Misc::StringUtils::split(list, listElements, ",");
|
||||
|
||||
size_t contentStart = source.find_first_not_of("\n\r", listEnd);
|
||||
size_t contentEnd = source.find("$endforeach", contentStart);
|
||||
if (contentEnd == std::string::npos)
|
||||
{
|
||||
Log(Debug::Error) << "Shader " << templateName << " error: Unexpected EOF";
|
||||
return false;
|
||||
}
|
||||
std::string content = source.substr(contentStart, contentEnd - contentStart);
|
||||
|
||||
size_t overallEnd = contentEnd + std::string("$endforeach").length();
|
||||
|
||||
size_t lineDirectivePosition = source.rfind("#line", overallEnd);
|
||||
int lineNumber;
|
||||
if (lineDirectivePosition != std::string::npos)
|
||||
{
|
||||
size_t lineNumberStart = lineDirectivePosition + std::string("#line ").length();
|
||||
size_t lineNumberEnd = source.find_first_not_of("0123456789", lineNumberStart);
|
||||
std::string lineNumberString = source.substr(lineNumberStart, lineNumberEnd - lineNumberStart);
|
||||
lineNumber = std::stoi(lineNumberString);
|
||||
}
|
||||
else
|
||||
{
|
||||
lineDirectivePosition = 0;
|
||||
lineNumber = 2;
|
||||
}
|
||||
lineNumber += std::count(source.begin() + lineDirectivePosition, source.begin() + overallEnd, '\n');
|
||||
|
||||
std::string replacement = "";
|
||||
for (std::vector<std::string>::const_iterator element = listElements.cbegin(); element != listElements.cend(); element++)
|
||||
{
|
||||
std::string contentInstance = content;
|
||||
size_t foundIterator;
|
||||
while ((foundIterator = contentInstance.find(iteratorName)) != std::string::npos)
|
||||
contentInstance.replace(foundIterator, iteratorName.length(), *element);
|
||||
replacement += contentInstance;
|
||||
}
|
||||
replacement += "\n#line " + std::to_string(lineNumber);
|
||||
source.replace(foundPos, overallEnd - foundPos, replacement);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parseLinkDirective(std::string& source, std::string& linkTarget, const std::string& templateName, size_t foundPos)
|
||||
{
|
||||
size_t endPos = foundPos + 5;
|
||||
size_t lineEnd = source.find_first_of('\n', endPos);
|
||||
// If lineEnd = npos, this is the last line, so no need to check
|
||||
std::string linkStatement = source.substr(endPos, lineEnd - endPos);
|
||||
std::regex linkRegex(
|
||||
R"r(\s*"([^"]+)"\s*)r" // Find any quoted string as the link name -> match[1]
|
||||
R"r((if\s+)r" // Begin optional condition -> match[2]
|
||||
R"r((!)?\s*)r" // Optional ! -> match[3]
|
||||
R"r(([_a-zA-Z0-9]+)?)r" // The condition -> match[4]
|
||||
R"r()?\s*)r" // End optional condition -> match[2]
|
||||
);
|
||||
std::smatch linkMatch;
|
||||
bool hasCondition = false;
|
||||
std::string linkConditionExpression;
|
||||
if (std::regex_match(linkStatement, linkMatch, linkRegex))
|
||||
{
|
||||
linkTarget = linkMatch[1].str();
|
||||
hasCondition = !linkMatch[2].str().empty();
|
||||
linkConditionExpression = linkMatch[4].str();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(Debug::Error) << "Shader " << templateName << " error: Expected a shader filename to link";
|
||||
return false;
|
||||
}
|
||||
if (linkTarget.empty())
|
||||
{
|
||||
Log(Debug::Error) << "Shader " << templateName << " error: Empty link name";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hasCondition)
|
||||
{
|
||||
bool condition = !(linkConditionExpression.empty() || linkConditionExpression == "0");
|
||||
if (linkMatch[3].str() == "!")
|
||||
condition = !condition;
|
||||
|
||||
if (!condition)
|
||||
linkTarget = "";
|
||||
}
|
||||
|
||||
source.replace(foundPos, lineEnd - foundPos, "");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parseDirectives(std::string& source, std::vector<std::string>& linkedShaderTemplateNames, const ShaderManager::DefineMap& defines, const ShaderManager::DefineMap& globalDefines, const std::string& templateName)
|
||||
{
|
||||
const char escapeCharacter = '$';
|
||||
size_t foundPos = 0;
|
||||
while ((foundPos = source.find(escapeCharacter)) != std::string::npos)
|
||||
|
||||
while ((foundPos = source.find(escapeCharacter, foundPos)) != std::string::npos)
|
||||
{
|
||||
size_t endPos = source.find_first_of(" \n\r()[].;,", foundPos);
|
||||
if (endPos == std::string::npos)
|
||||
|
@ -154,72 +267,25 @@ namespace Shader
|
|||
Log(Debug::Error) << "Shader " << templateName << " error: Unexpected EOF";
|
||||
return false;
|
||||
}
|
||||
std::string command = source.substr(foundPos + 1, endPos - (foundPos + 1));
|
||||
if (command != "foreach")
|
||||
std::string directive = source.substr(foundPos + 1, endPos - (foundPos + 1));
|
||||
if (directive == "foreach")
|
||||
{
|
||||
Log(Debug::Error) << "Shader " << templateName << " error: Unknown shader directive: $" << command;
|
||||
return false;
|
||||
if (!parseForeachDirective(source, templateName, foundPos))
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t iterNameStart = endPos + 1;
|
||||
size_t iterNameEnd = source.find_first_of(" \n\r()[].;,", iterNameStart);
|
||||
if (iterNameEnd == std::string::npos)
|
||||
else if (directive == "link")
|
||||
{
|
||||
Log(Debug::Error) << "Shader " << templateName << " error: Unexpected EOF";
|
||||
return false;
|
||||
}
|
||||
std::string iteratorName = "$" + source.substr(iterNameStart, iterNameEnd - iterNameStart);
|
||||
|
||||
size_t listStart = iterNameEnd + 1;
|
||||
size_t listEnd = source.find_first_of("\n\r", listStart);
|
||||
if (listEnd == std::string::npos)
|
||||
{
|
||||
Log(Debug::Error) << "Shader " << templateName << " error: Unexpected EOF";
|
||||
return false;
|
||||
}
|
||||
std::string list = source.substr(listStart, listEnd - listStart);
|
||||
std::vector<std::string> listElements;
|
||||
if (list != "")
|
||||
Misc::StringUtils::split (list, listElements, ",");
|
||||
|
||||
size_t contentStart = source.find_first_not_of("\n\r", listEnd);
|
||||
size_t contentEnd = source.find("$endforeach", contentStart);
|
||||
if (contentEnd == std::string::npos)
|
||||
{
|
||||
Log(Debug::Error) << "Shader " << templateName << " error: Unexpected EOF";
|
||||
return false;
|
||||
}
|
||||
std::string content = source.substr(contentStart, contentEnd - contentStart);
|
||||
|
||||
size_t overallEnd = contentEnd + std::string("$endforeach").length();
|
||||
|
||||
size_t lineDirectivePosition = source.rfind("#line", overallEnd);
|
||||
int lineNumber;
|
||||
if (lineDirectivePosition != std::string::npos)
|
||||
{
|
||||
size_t lineNumberStart = lineDirectivePosition + std::string("#line ").length();
|
||||
size_t lineNumberEnd = source.find_first_not_of("0123456789", lineNumberStart);
|
||||
std::string lineNumberString = source.substr(lineNumberStart, lineNumberEnd - lineNumberStart);
|
||||
lineNumber = std::stoi(lineNumberString);
|
||||
std::string linkTarget;
|
||||
if (!parseLinkDirective(source, linkTarget, templateName, foundPos))
|
||||
return false;
|
||||
if (!linkTarget.empty() && linkTarget != templateName)
|
||||
linkedShaderTemplateNames.push_back(linkTarget);
|
||||
}
|
||||
else
|
||||
{
|
||||
lineDirectivePosition = 0;
|
||||
lineNumber = 2;
|
||||
Log(Debug::Error) << "Shader " << templateName << " error: Unknown shader directive: $" << directive;
|
||||
return false;
|
||||
}
|
||||
lineNumber += std::count(source.begin() + lineDirectivePosition, source.begin() + overallEnd, '\n');
|
||||
|
||||
std::string replacement = "";
|
||||
for (std::vector<std::string>::const_iterator element = listElements.cbegin(); element != listElements.cend(); element++)
|
||||
{
|
||||
std::string contentInstance = content;
|
||||
size_t foundIterator;
|
||||
while ((foundIterator = contentInstance.find(iteratorName)) != std::string::npos)
|
||||
contentInstance.replace(foundIterator, iteratorName.length(), *element);
|
||||
replacement += contentInstance;
|
||||
}
|
||||
replacement += "\n#line " + std::to_string(lineNumber);
|
||||
source.replace(foundPos, overallEnd - foundPos, replacement);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -265,6 +331,10 @@ namespace Shader
|
|||
else
|
||||
forIterators.pop_back();
|
||||
}
|
||||
else if (define == "link")
|
||||
{
|
||||
source.replace(foundPos, 1, "$");
|
||||
}
|
||||
else if (std::find(forIterators.begin(), forIterators.end(), define) != forIterators.end())
|
||||
{
|
||||
source.replace(foundPos, 1, "$");
|
||||
|
@ -288,7 +358,7 @@ namespace Shader
|
|||
|
||||
osg::ref_ptr<osg::Shader> ShaderManager::getShader(const std::string &templateName, const ShaderManager::DefineMap &defines, osg::Shader::Type shaderType)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
std::unique_lock<std::mutex> lock(mMutex);
|
||||
|
||||
// read the template if we haven't already
|
||||
TemplateMap::iterator templateIt = mShaderTemplates.find(templateName);
|
||||
|
@ -319,7 +389,8 @@ namespace Shader
|
|||
if (shaderIt == mShaders.end())
|
||||
{
|
||||
std::string shaderSource = templateIt->second;
|
||||
if (!parseDefines(shaderSource, defines, mGlobalDefines, templateName) || !parseFors(shaderSource, templateName))
|
||||
std::vector<std::string> linkedShaderNames;
|
||||
if (!createSourceFromTemplate(shaderSource, linkedShaderNames, templateName, defines))
|
||||
{
|
||||
// Add to the cache anyway to avoid logging the same error over and over.
|
||||
mShaders.insert(std::make_pair(std::make_pair(templateName, defines), nullptr));
|
||||
|
@ -333,6 +404,10 @@ namespace Shader
|
|||
static unsigned int counter = 0;
|
||||
shader->setName(Misc::StringUtils::format("%u %s", counter++, templateName));
|
||||
|
||||
lock.unlock();
|
||||
getLinkedShaders(shader, linkedShaderNames, defines);
|
||||
lock.lock();
|
||||
|
||||
shaderIt = mShaders.insert(std::make_pair(std::make_pair(templateName, defines), shader)).first;
|
||||
}
|
||||
return shaderIt->second;
|
||||
|
@ -348,6 +423,9 @@ namespace Shader
|
|||
osg::ref_ptr<osg::Program> program = programTemplate ? cloneProgram(programTemplate) : osg::ref_ptr<osg::Program>(new osg::Program);
|
||||
program->addShader(vertexShader);
|
||||
program->addShader(fragmentShader);
|
||||
addLinkedShaders(vertexShader, program);
|
||||
addLinkedShaders(fragmentShader, program);
|
||||
|
||||
found = mPrograms.insert(std::make_pair(std::make_pair(vertexShader, fragmentShader), program)).first;
|
||||
}
|
||||
return found->second;
|
||||
|
@ -377,11 +455,14 @@ namespace Shader
|
|||
// I'm not sure how to handle a shader that was already broken as there's no way to get a potential replacement to the nodes that need it.
|
||||
continue;
|
||||
std::string shaderSource = mShaderTemplates[templateId];
|
||||
if (!parseDefines(shaderSource, defines, mGlobalDefines, templateId) || !parseFors(shaderSource, templateId))
|
||||
std::vector<std::string> linkedShaderNames;
|
||||
if (!createSourceFromTemplate(shaderSource, linkedShaderNames, templateId, defines))
|
||||
// We just broke the shader and there's no way to force existing objects back to fixed-function mode as we would when creating the shader.
|
||||
// If we put a nullptr in the shader map, we just lose the ability to put a working one in later.
|
||||
continue;
|
||||
shader->setShaderSource(shaderSource);
|
||||
|
||||
getLinkedShaders(shader, linkedShaderNames, defines);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -397,4 +478,35 @@ namespace Shader
|
|||
program->releaseGLObjects(state);
|
||||
}
|
||||
|
||||
bool ShaderManager::createSourceFromTemplate(std::string& source, std::vector<std::string>& linkedShaderTemplateNames, const std::string& templateName, const ShaderManager::DefineMap& defines)
|
||||
{
|
||||
if (!parseDefines(source, defines, mGlobalDefines, templateName))
|
||||
return false;
|
||||
if (!parseDirectives(source, linkedShaderTemplateNames, defines, mGlobalDefines, templateName))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ShaderManager::getLinkedShaders(osg::ref_ptr<osg::Shader> shader, const std::vector<std::string>& linkedShaderNames, const DefineMap& defines)
|
||||
{
|
||||
mLinkedShaders.erase(shader);
|
||||
if (linkedShaderNames.empty())
|
||||
return;
|
||||
|
||||
for (auto& linkedShaderName : linkedShaderNames)
|
||||
{
|
||||
auto linkedShader = getShader(linkedShaderName, defines, shader->getType());
|
||||
if (linkedShader)
|
||||
mLinkedShaders[shader].emplace_back(linkedShader);
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderManager::addLinkedShaders(osg::ref_ptr<osg::Shader> shader, osg::ref_ptr<osg::Program> program)
|
||||
{
|
||||
auto linkedIt = mLinkedShaders.find(shader);
|
||||
if (linkedIt != mLinkedShaders.end())
|
||||
for (const auto& linkedShader : linkedIt->second)
|
||||
program->addShader(linkedShader);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <string>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
|
||||
|
@ -51,7 +52,12 @@ namespace Shader
|
|||
|
||||
void releaseGLObjects(osg::State* state);
|
||||
|
||||
bool createSourceFromTemplate(std::string& source, std::vector<std::string>& linkedShaderTemplateNames, const std::string& templateName, const ShaderManager::DefineMap& defines);
|
||||
|
||||
private:
|
||||
void getLinkedShaders(osg::ref_ptr<osg::Shader> shader, const std::vector<std::string>& linkedShaderNames, const DefineMap& defines);
|
||||
void addLinkedShaders(osg::ref_ptr<osg::Shader> shader, osg::ref_ptr<osg::Program> program);
|
||||
|
||||
std::string mPath;
|
||||
|
||||
DefineMap mGlobalDefines;
|
||||
|
@ -67,15 +73,23 @@ namespace Shader
|
|||
typedef std::map<std::pair<osg::ref_ptr<osg::Shader>, osg::ref_ptr<osg::Shader> >, osg::ref_ptr<osg::Program> > ProgramMap;
|
||||
ProgramMap mPrograms;
|
||||
|
||||
typedef std::vector<osg::ref_ptr<osg::Shader> > ShaderList;
|
||||
typedef std::map<osg::ref_ptr<osg::Shader>, ShaderList> LinkedShadersMap;
|
||||
LinkedShadersMap mLinkedShaders;
|
||||
|
||||
std::mutex mMutex;
|
||||
|
||||
osg::ref_ptr<const osg::Program> mProgramTemplate;
|
||||
};
|
||||
|
||||
bool parseFors(std::string& source, const std::string& templateName);
|
||||
bool parseForeachDirective(std::string& source, const std::string& templateName, size_t foundPos);
|
||||
bool parseLinkDirective(std::string& source, std::string& linkTarget, const std::string& templateName, size_t foundPos);
|
||||
|
||||
bool parseDefines(std::string& source, const ShaderManager::DefineMap& defines,
|
||||
const ShaderManager::DefineMap& globalDefines, const std::string& templateName);
|
||||
|
||||
bool parseDirectives(std::string& source, std::vector<std::string>& linkedShaderTemplateNames, const ShaderManager::DefineMap& defines,
|
||||
const ShaderManager::DefineMap& globalDefines, const std::string& templateName);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -16,6 +16,10 @@ set(SHADER_FILES
|
|||
depth.glsl
|
||||
objects_vertex.glsl
|
||||
objects_fragment.glsl
|
||||
openmw_fragment.glsl
|
||||
openmw_fragment.h.glsl
|
||||
openmw_vertex.glsl
|
||||
openmw_vertex.h.glsl
|
||||
terrain_vertex.glsl
|
||||
terrain_fragment.glsl
|
||||
lighting.glsl
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
#version 120
|
||||
|
||||
uniform mat4 projectionMatrix;
|
||||
#include "openmw_vertex.glsl"
|
||||
|
||||
centroid varying vec4 passColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projectionMatrix * (gl_ModelViewMatrix * gl_Vertex);
|
||||
gl_Position = mw_modelToClip(gl_Vertex);
|
||||
|
||||
passColor = gl_Color;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#version 120
|
||||
|
||||
#include "openmw_vertex.h.glsl"
|
||||
|
||||
#if @useUBO
|
||||
#extension GL_ARB_uniform_buffer_object : require
|
||||
#endif
|
||||
|
@ -46,7 +48,6 @@ uniform mat4 osg_ViewMatrixInverse;
|
|||
uniform mat4 osg_ViewMatrix;
|
||||
uniform float windSpeed;
|
||||
uniform vec3 playerPos;
|
||||
uniform mat4 projectionMatrix;
|
||||
|
||||
#if @groundcoverStompMode == 0
|
||||
#else
|
||||
|
@ -143,7 +144,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 = projectionMatrix * viewPos;
|
||||
gl_Position = mw_viewToClip(mw_viewStereoAdjust(viewPos));
|
||||
|
||||
linearDepth = getLinearDepth(gl_Position.z, viewPos.z);
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#version 120
|
||||
|
||||
#include "openmw_vertex.h.glsl"
|
||||
|
||||
#if @useUBO
|
||||
#extension GL_ARB_uniform_buffer_object : require
|
||||
#endif
|
||||
|
@ -8,8 +10,6 @@
|
|||
#extension GL_EXT_gpu_shader4: require
|
||||
#endif
|
||||
|
||||
uniform mat4 projectionMatrix;
|
||||
|
||||
#if @diffuseMap
|
||||
varying vec2 diffuseMapUV;
|
||||
#endif
|
||||
|
@ -38,9 +38,9 @@ varying vec3 passNormal;
|
|||
|
||||
void main(void)
|
||||
{
|
||||
gl_Position = projectionMatrix * (gl_ModelViewMatrix * gl_Vertex);
|
||||
gl_Position = mw_modelToClip(gl_Vertex);
|
||||
|
||||
vec4 viewPos = (gl_ModelViewMatrix * gl_Vertex);
|
||||
vec4 viewPos = mw_modelToView(gl_Vertex);
|
||||
gl_ClipVertex = viewPos;
|
||||
euclideanDepth = length(viewPos.xyz);
|
||||
linearDepth = getLinearDepth(gl_Position.z, viewPos.z);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#version 120
|
||||
|
||||
uniform mat4 projectionMatrix;
|
||||
#include "openmw_vertex.h.glsl"
|
||||
|
||||
#if @diffuseMap
|
||||
varying vec2 diffuseMapUV;
|
||||
|
@ -23,9 +23,9 @@ varying float passFalloff;
|
|||
|
||||
void main(void)
|
||||
{
|
||||
gl_Position = projectionMatrix * (gl_ModelViewMatrix * gl_Vertex);
|
||||
gl_Position = mw_modelToClip(gl_Vertex);
|
||||
|
||||
vec4 viewPos = (gl_ModelViewMatrix * gl_Vertex);
|
||||
vec4 viewPos = mw_modelToView(gl_Vertex);
|
||||
gl_ClipVertex = viewPos;
|
||||
#if @radialFog
|
||||
euclideanDepth = length(viewPos.xyz);
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#version 120
|
||||
|
||||
#include "openmw_vertex.h.glsl"
|
||||
|
||||
#if @useUBO
|
||||
#extension GL_ARB_uniform_buffer_object : require
|
||||
#endif
|
||||
|
@ -8,8 +10,6 @@
|
|||
#extension GL_EXT_gpu_shader4: require
|
||||
#endif
|
||||
|
||||
uniform mat4 projectionMatrix;
|
||||
|
||||
#if @diffuseMap
|
||||
varying vec2 diffuseMapUV;
|
||||
#endif
|
||||
|
@ -72,9 +72,9 @@ varying vec3 passNormal;
|
|||
|
||||
void main(void)
|
||||
{
|
||||
gl_Position = projectionMatrix * (gl_ModelViewMatrix * gl_Vertex);
|
||||
gl_Position = mw_modelToClip(gl_Vertex);
|
||||
|
||||
vec4 viewPos = (gl_ModelViewMatrix * gl_Vertex);
|
||||
vec4 viewPos = mw_modelToView(gl_Vertex);
|
||||
|
||||
gl_ClipVertex = viewPos;
|
||||
euclideanDepth = length(viewPos.xyz);
|
||||
|
|
26
files/shaders/openmw_fragment.glsl
Normal file
26
files/shaders/openmw_fragment.glsl
Normal file
|
@ -0,0 +1,26 @@
|
|||
#version 120
|
||||
|
||||
#include "openmw_fragment.h.glsl"
|
||||
|
||||
uniform sampler2D reflectionMap;
|
||||
|
||||
vec4 mw_sampleReflectionMap(vec2 uv)
|
||||
{
|
||||
return texture2D(reflectionMap, uv);
|
||||
}
|
||||
|
||||
#if @refraction_enabled
|
||||
uniform sampler2D refractionMap;
|
||||
uniform sampler2D refractionDepthMap;
|
||||
|
||||
vec4 mw_sampleRefractionMap(vec2 uv)
|
||||
{
|
||||
return texture2D(refractionMap, uv);
|
||||
}
|
||||
|
||||
float mw_sampleRefractionDepthMap(vec2 uv)
|
||||
{
|
||||
return texture2D(refractionDepthMap, uv).x;
|
||||
}
|
||||
|
||||
#endif
|
8
files/shaders/openmw_fragment.h.glsl
Normal file
8
files/shaders/openmw_fragment.h.glsl
Normal file
|
@ -0,0 +1,8 @@
|
|||
@link "openmw_fragment.glsl"
|
||||
|
||||
vec4 mw_sampleReflectionMap(vec2 uv);
|
||||
|
||||
#if @refraction_enabled
|
||||
vec4 mw_sampleRefractionMap(vec2 uv);
|
||||
float mw_sampleRefractionDepthMap(vec2 uv);
|
||||
#endif
|
35
files/shaders/openmw_vertex.glsl
Normal file
35
files/shaders/openmw_vertex.glsl
Normal file
|
@ -0,0 +1,35 @@
|
|||
#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;
|
||||
}
|
||||
|
||||
vec4 mw_viewStereoAdjust(vec4 pos)
|
||||
{
|
||||
return pos;
|
||||
}
|
||||
|
||||
mat4 mw_viewMatrix()
|
||||
{
|
||||
return gl_ModelViewMatrix;
|
||||
}
|
||||
|
||||
mat4 mw_projectionMatrix()
|
||||
{
|
||||
return projectionMatrix;
|
||||
}
|
8
files/shaders/openmw_vertex.h.glsl
Normal file
8
files/shaders/openmw_vertex.h.glsl
Normal file
|
@ -0,0 +1,8 @@
|
|||
@link "openmw_vertex.glsl"
|
||||
|
||||
vec4 mw_modelToClip(vec4 pos);
|
||||
vec4 mw_modelToView(vec4 pos);
|
||||
vec4 mw_viewToClip(vec4 pos);
|
||||
vec4 mw_viewStereoAdjust(vec4 pos);
|
||||
mat4 mw_viewMatrix();
|
||||
mat4 mw_projectionMatrix();
|
|
@ -1,8 +1,9 @@
|
|||
#version 120
|
||||
|
||||
#include "openmw_vertex.h.glsl"
|
||||
|
||||
#include "skypasses.glsl"
|
||||
|
||||
uniform mat4 projectionMatrix;
|
||||
uniform int pass;
|
||||
|
||||
varying vec4 passColor;
|
||||
|
@ -10,7 +11,7 @@ varying vec2 diffuseMapUV;
|
|||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projectionMatrix * (gl_ModelViewMatrix * gl_Vertex);
|
||||
gl_Position = mw_modelToClip(gl_Vertex);
|
||||
passColor = gl_Color;
|
||||
|
||||
if (pass == PASS_CLOUDS)
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#version 120
|
||||
|
||||
#include "openmw_vertex.h.glsl"
|
||||
|
||||
#if @useUBO
|
||||
#extension GL_ARB_uniform_buffer_object : require
|
||||
#endif
|
||||
|
@ -8,8 +10,6 @@
|
|||
#extension GL_EXT_gpu_shader4: require
|
||||
#endif
|
||||
|
||||
uniform mat4 projectionMatrix;
|
||||
|
||||
varying vec2 uv;
|
||||
varying float euclideanDepth;
|
||||
varying float linearDepth;
|
||||
|
@ -31,9 +31,9 @@ varying vec3 passNormal;
|
|||
|
||||
void main(void)
|
||||
{
|
||||
gl_Position = projectionMatrix * (gl_ModelViewMatrix * gl_Vertex);
|
||||
gl_Position = mw_modelToClip(gl_Vertex);
|
||||
|
||||
vec4 viewPos = (gl_ModelViewMatrix * gl_Vertex);
|
||||
vec4 viewPos = mw_modelToView(gl_Vertex);
|
||||
gl_ClipVertex = viewPos;
|
||||
euclideanDepth = length(viewPos.xyz);
|
||||
linearDepth = getLinearDepth(gl_Position.z, viewPos.z);
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#version 120
|
||||
|
||||
#include "openmw_fragment.h.glsl"
|
||||
|
||||
#if @useUBO
|
||||
#extension GL_ARB_uniform_buffer_object : require
|
||||
#endif
|
||||
|
@ -207,12 +209,6 @@ varying float linearDepth;
|
|||
|
||||
uniform sampler2D normalMap;
|
||||
|
||||
uniform sampler2D reflectionMap;
|
||||
#if REFRACTION
|
||||
uniform sampler2D refractionMap;
|
||||
uniform sampler2D refractionDepthMap;
|
||||
#endif
|
||||
|
||||
uniform float osg_SimulationTime;
|
||||
|
||||
uniform float near;
|
||||
|
@ -299,14 +295,14 @@ void main(void)
|
|||
|
||||
vec2 screenCoordsOffset = normal.xy * REFL_BUMP;
|
||||
#if REFRACTION
|
||||
float depthSample = linearizeDepth(texture2D(refractionDepthMap,screenCoords).x) * radialise;
|
||||
float depthSampleDistorted = linearizeDepth(texture2D(refractionDepthMap,screenCoords-screenCoordsOffset).x) * radialise;
|
||||
float depthSample = linearizeDepth(mw_sampleRefractionDepthMap(screenCoords)) * radialise;
|
||||
float depthSampleDistorted = linearizeDepth(mw_sampleRefractionDepthMap(screenCoords-screenCoordsOffset)) * radialise;
|
||||
float surfaceDepth = linearizeDepth(gl_FragCoord.z) * 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 = texture2D(reflectionMap, screenCoords + screenCoordsOffset).rgb;
|
||||
vec3 reflection = mw_sampleReflectionMap(screenCoords + screenCoordsOffset).rgb;
|
||||
|
||||
// specular
|
||||
float specular = pow(max(dot(reflect(vVec, normal), lVec), 0.0),SPEC_HARDNESS) * shadow;
|
||||
|
@ -324,7 +320,7 @@ void main(void)
|
|||
rainSpecular *= clamp(fresnel*6.0 + specular * sunSpec.w, 0.0, 1.0);
|
||||
|
||||
// refraction
|
||||
vec3 refraction = texture2D(refractionMap, screenCoords - screenCoordsOffset).rgb;
|
||||
vec3 refraction = mw_sampleRefractionMap(screenCoords - screenCoordsOffset).rgb;
|
||||
vec3 rawRefraction = refraction;
|
||||
|
||||
// brighten up the refraction underwater
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#version 120
|
||||
|
||||
uniform mat4 projectionMatrix;
|
||||
#include "openmw_vertex.h.glsl"
|
||||
|
||||
varying vec4 position;
|
||||
varying float linearDepth;
|
||||
|
@ -10,11 +10,11 @@ varying float linearDepth;
|
|||
|
||||
void main(void)
|
||||
{
|
||||
gl_Position = projectionMatrix * (gl_ModelViewMatrix * gl_Vertex);
|
||||
gl_Position = mw_modelToClip(gl_Vertex);
|
||||
|
||||
position = gl_Vertex;
|
||||
|
||||
vec4 viewPos = gl_ModelViewMatrix * gl_Vertex;
|
||||
vec4 viewPos = mw_modelToView(gl_Vertex);
|
||||
linearDepth = getLinearDepth(gl_Position.z, viewPos.z);
|
||||
|
||||
setupShadowCoords(viewPos, normalize((gl_NormalMatrix * gl_Normal).xyz));
|
||||
|
|
Loading…
Reference in a new issue