mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-04-28 21:07:59 +03:00
shade refactor
This commit is contained in:
parent
cc5f20d66a
commit
ac4787aeec
84 changed files with 737 additions and 658 deletions
|
@ -16,6 +16,29 @@
|
|||
#include <sstream>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace
|
||||
{
|
||||
osg::Shader::Type getShaderType(const std::string& templateName)
|
||||
{
|
||||
auto ext = std::filesystem::path(templateName).extension();
|
||||
|
||||
if (ext == ".vert")
|
||||
return osg::Shader::VERTEX;
|
||||
if (ext == ".frag")
|
||||
return osg::Shader::FRAGMENT;
|
||||
if (ext == ".geom")
|
||||
return osg::Shader::GEOMETRY;
|
||||
if (ext == ".comp")
|
||||
return osg::Shader::COMPUTE;
|
||||
if (ext == ".tese")
|
||||
return osg::Shader::TESSEVALUATION;
|
||||
if (ext == ".tesc")
|
||||
return osg::Shader::TESSCONTROL;
|
||||
|
||||
throw std::runtime_error("unrecognized shader template name: " + templateName);
|
||||
}
|
||||
}
|
||||
|
||||
namespace Shader
|
||||
{
|
||||
|
||||
|
@ -106,7 +129,11 @@ namespace Shader
|
|||
return false;
|
||||
}
|
||||
std::string includeFilename = source.substr(start + 1, end - (start + 1));
|
||||
std::filesystem::path includePath = shaderPath / includeFilename;
|
||||
std::filesystem::path includePath
|
||||
= shaderPath / std::filesystem::path(fileName).parent_path() / includeFilename;
|
||||
|
||||
if (!std::filesystem::exists(includePath))
|
||||
includePath = shaderPath / includeFilename;
|
||||
|
||||
// Determine the line number that will be used for the #line directive following the included source
|
||||
size_t lineDirectivePosition = source.rfind("#line", foundPos);
|
||||
|
@ -471,10 +498,16 @@ namespace Shader
|
|||
};
|
||||
|
||||
osg::ref_ptr<osg::Shader> ShaderManager::getShader(
|
||||
const std::string& templateName, const ShaderManager::DefineMap& defines, osg::Shader::Type shaderType)
|
||||
std::string templateName, const ShaderManager::DefineMap& defines, std::optional<osg::Shader::Type> type)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mMutex);
|
||||
|
||||
// TODO: Implement mechanism to switch to core or compatibility profile shaders.
|
||||
// This logic is temporary until core support is supported.
|
||||
if (!templateName.starts_with("lib") && !templateName.starts_with("compatibility")
|
||||
&& !templateName.starts_with("core"))
|
||||
templateName = "compatibility/" + templateName;
|
||||
|
||||
// read the template if we haven't already
|
||||
TemplateMap::iterator templateIt = mShaderTemplates.find(templateName);
|
||||
std::set<std::filesystem::path> insertedPaths;
|
||||
|
@ -514,7 +547,7 @@ namespace Shader
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Shader> shader(new osg::Shader(shaderType));
|
||||
osg::ref_ptr<osg::Shader> shader(new osg::Shader(type ? *type : getShaderType(templateName)));
|
||||
shader->setShaderSource(shaderSource);
|
||||
// Assign a unique prefix to allow the SharedStateManager to compare shaders efficiently.
|
||||
// Append shader source filename for debugging.
|
||||
|
@ -532,6 +565,18 @@ namespace Shader
|
|||
return shaderIt->second;
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Program> ShaderManager::getProgram(
|
||||
const std::string& templateName, const DefineMap& defines, const osg::Program* programTemplate)
|
||||
{
|
||||
auto vert = getShader(templateName + ".vert", defines);
|
||||
auto frag = getShader(templateName + ".frag", defines);
|
||||
|
||||
if (!vert || !frag)
|
||||
throw std::runtime_error("failed initializing shader: " + templateName);
|
||||
|
||||
return getProgram(vert, frag, programTemplate);
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Program> ShaderManager::getProgram(osg::ref_ptr<osg::Shader> vertexShader,
|
||||
osg::ref_ptr<osg::Shader> fragmentShader, const osg::Program* programTemplate)
|
||||
{
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
@ -36,13 +37,16 @@ namespace Shader
|
|||
typedef std::map<std::string, std::string> DefineMap;
|
||||
|
||||
/// Create or retrieve a shader instance.
|
||||
/// @param shaderTemplate The filename of the shader template.
|
||||
/// @param templateName The path of the shader template.
|
||||
/// @param defines Define values that can be retrieved by the shader template.
|
||||
/// @param shaderType The type of shader (usually vertex or fragment shader).
|
||||
/// @note May return nullptr on failure.
|
||||
/// @note Thread safe.
|
||||
osg::ref_ptr<osg::Shader> getShader(
|
||||
const std::string& templateName, const DefineMap& defines, osg::Shader::Type shaderType);
|
||||
osg::ref_ptr<osg::Shader> getShader(std::string templateName, const DefineMap& defines = {},
|
||||
std::optional<osg::Shader::Type> type = std::nullopt);
|
||||
|
||||
osg::ref_ptr<osg::Program> getProgram(const std::string& templateName, const DefineMap& defines = {},
|
||||
const osg::Program* programTemplate = nullptr);
|
||||
|
||||
osg::ref_ptr<osg::Program> getProgram(osg::ref_ptr<osg::Shader> vertexShader,
|
||||
osg::ref_ptr<osg::Shader> fragmentShader, const osg::Program* programTemplate = nullptr);
|
||||
|
|
|
@ -715,24 +715,14 @@ namespace Shader
|
|||
if (!node.getUserValue("shaderPrefix", shaderPrefix))
|
||||
shaderPrefix = mDefaultShaderPrefix;
|
||||
|
||||
osg::ref_ptr<osg::Shader> vertexShader(
|
||||
mShaderManager.getShader(shaderPrefix + "_vertex.glsl", defineMap, osg::Shader::VERTEX));
|
||||
osg::ref_ptr<osg::Shader> fragmentShader(
|
||||
mShaderManager.getShader(shaderPrefix + "_fragment.glsl", defineMap, osg::Shader::FRAGMENT));
|
||||
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<int, std::string>::const_iterator texIt = reqs.mTextures.begin();
|
||||
texIt != reqs.mTextures.end(); ++texIt)
|
||||
{
|
||||
writableStateSet->addUniform(
|
||||
new osg::Uniform(texIt->second.c_str(), texIt->first), osg::StateAttribute::ON);
|
||||
addedState->addUniform(texIt->second);
|
||||
}
|
||||
writableStateSet->addUniform(new osg::Uniform(name.c_str(), unit), osg::StateAttribute::ON);
|
||||
addedState->addUniform(name);
|
||||
}
|
||||
|
||||
if (!addedState->empty())
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue