OpenGLRenderer: Fix Y flipping for FBOs
This commit is contained in:
parent
fb3468854f
commit
311cfeaf3c
|
|
@ -106,6 +106,7 @@ namespace Nz
|
||||||
std::optional<Nz::Recti> scissorRegion;
|
std::optional<Nz::Recti> scissorRegion;
|
||||||
std::optional<Nz::Recti> viewportRegion;
|
std::optional<Nz::Recti> viewportRegion;
|
||||||
std::vector<VertexBuffer> vertexBuffers;
|
std::vector<VertexBuffer> vertexBuffers;
|
||||||
|
bool shouldFlipY = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DrawData
|
struct DrawData
|
||||||
|
|
|
||||||
|
|
@ -142,6 +142,8 @@ namespace Nz
|
||||||
std::copy(clearValues.begin(), clearValues.end(), setFramebuffer.clearValues.begin());
|
std::copy(clearValues.begin(), clearValues.end(), setFramebuffer.clearValues.begin());
|
||||||
|
|
||||||
m_commands.emplace_back(std::move(setFramebuffer));
|
m_commands.emplace_back(std::move(setFramebuffer));
|
||||||
|
|
||||||
|
m_currentStates.shouldFlipY = (framebuffer.GetType() == OpenGLFramebuffer::Type::Window);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void OpenGLCommandBuffer::SetScissor(Nz::Recti scissorRegion)
|
inline void OpenGLCommandBuffer::SetScissor(Nz::Recti scissorRegion)
|
||||||
|
|
|
||||||
|
|
@ -24,11 +24,15 @@ namespace Nz
|
||||||
|
|
||||||
void Apply(const GL::Context& context) const;
|
void Apply(const GL::Context& context) const;
|
||||||
|
|
||||||
|
void FlipY(bool shouldFlipY) const;
|
||||||
|
|
||||||
inline const RenderPipelineInfo& GetPipelineInfo() const override;
|
inline const RenderPipelineInfo& GetPipelineInfo() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RenderPipelineInfo m_pipelineInfo;
|
RenderPipelineInfo m_pipelineInfo;
|
||||||
GL::Program m_program;
|
GL::Program m_program;
|
||||||
|
GLint m_flipYUniformLocation;
|
||||||
|
mutable bool m_isYFlipped;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,10 +26,14 @@ namespace Nz::GL
|
||||||
|
|
||||||
inline void AttachShader(GLuint shader);
|
inline void AttachShader(GLuint shader);
|
||||||
|
|
||||||
inline bool GetLinkStatus(std::string* error = nullptr);
|
inline bool GetLinkStatus(std::string* error = nullptr) const;
|
||||||
|
inline GLint GetUniformLocation(const char* uniformName) const;
|
||||||
|
inline GLint GetUniformLocation(const std::string& uniformName) const;
|
||||||
|
|
||||||
inline void Link();
|
inline void Link();
|
||||||
|
|
||||||
|
inline void Uniform(GLint uniformLocation, float value) const;
|
||||||
|
|
||||||
Program& operator=(const Program&) = delete;
|
Program& operator=(const Program&) = delete;
|
||||||
Program& operator=(Program&&) noexcept = default;
|
Program& operator=(Program&&) noexcept = default;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ namespace Nz::GL
|
||||||
context.glAttachShader(m_objectId, shader);
|
context.glAttachShader(m_objectId, shader);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool Program::GetLinkStatus(std::string* error)
|
inline bool Program::GetLinkStatus(std::string* error) const
|
||||||
{
|
{
|
||||||
assert(m_objectId);
|
assert(m_objectId);
|
||||||
const Context& context = EnsureDeviceContext();
|
const Context& context = EnsureDeviceContext();
|
||||||
|
|
@ -45,6 +45,19 @@ namespace Nz::GL
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline GLint Program::GetUniformLocation(const char* uniformName) const
|
||||||
|
{
|
||||||
|
assert(m_objectId);
|
||||||
|
const Context& context = EnsureDeviceContext();
|
||||||
|
|
||||||
|
return context.glGetUniformLocation(m_objectId, uniformName);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline GLint Program::GetUniformLocation(const std::string& uniformName) const
|
||||||
|
{
|
||||||
|
return GetUniformLocation(uniformName.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
inline void Program::Link()
|
inline void Program::Link()
|
||||||
{
|
{
|
||||||
assert(m_objectId);
|
assert(m_objectId);
|
||||||
|
|
@ -53,6 +66,15 @@ namespace Nz::GL
|
||||||
context.glLinkProgram(m_objectId);
|
context.glLinkProgram(m_objectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void Program::Uniform(GLint uniformLocation, float value) const
|
||||||
|
{
|
||||||
|
assert(m_objectId);
|
||||||
|
|
||||||
|
const Context& context = EnsureDeviceContext();
|
||||||
|
context.BindProgram(m_objectId);
|
||||||
|
context.glUniform1f(uniformLocation, value);
|
||||||
|
}
|
||||||
|
|
||||||
inline GLuint Program::CreateHelper(OpenGLDevice& /*device*/, const Context& context)
|
inline GLuint Program::CreateHelper(OpenGLDevice& /*device*/, const Context& context)
|
||||||
{
|
{
|
||||||
return context.glCreateProgram();
|
return context.glCreateProgram();
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,8 @@ namespace Nz
|
||||||
bool flipYPosition = false;
|
bool flipYPosition = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char* GetFlipYUniformName();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Append(ShaderExpressionType type);
|
void Append(ShaderExpressionType type);
|
||||||
void Append(ShaderNodes::BuiltinEntry builtin);
|
void Append(ShaderNodes::BuiltinEntry builtin);
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#include <Nazara/OpenGLRenderer/Utils.hpp>
|
#include <Nazara/OpenGLRenderer/Utils.hpp>
|
||||||
#include <Nazara/OpenGLRenderer/OpenGLRenderPipelineLayout.hpp>
|
#include <Nazara/OpenGLRenderer/OpenGLRenderPipelineLayout.hpp>
|
||||||
#include <Nazara/OpenGLRenderer/OpenGLShaderStage.hpp>
|
#include <Nazara/OpenGLRenderer/OpenGLShaderStage.hpp>
|
||||||
|
#include <Nazara/Shader/GlslWriter.hpp>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <Nazara/OpenGLRenderer/Debug.hpp>
|
#include <Nazara/OpenGLRenderer/Debug.hpp>
|
||||||
|
|
@ -14,7 +15,8 @@
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
OpenGLRenderPipeline::OpenGLRenderPipeline(OpenGLDevice& device, RenderPipelineInfo pipelineInfo) :
|
OpenGLRenderPipeline::OpenGLRenderPipeline(OpenGLDevice& device, RenderPipelineInfo pipelineInfo) :
|
||||||
m_pipelineInfo(std::move(pipelineInfo))
|
m_pipelineInfo(std::move(pipelineInfo)),
|
||||||
|
m_isYFlipped(false)
|
||||||
{
|
{
|
||||||
if (!m_program.Create(device))
|
if (!m_program.Create(device))
|
||||||
throw std::runtime_error("failed to create program");
|
throw std::runtime_error("failed to create program");
|
||||||
|
|
@ -30,6 +32,10 @@ namespace Nz
|
||||||
std::string errLog;
|
std::string errLog;
|
||||||
if (!m_program.GetLinkStatus(&errLog))
|
if (!m_program.GetLinkStatus(&errLog))
|
||||||
throw std::runtime_error("failed to link program: " + errLog);
|
throw std::runtime_error("failed to link program: " + errLog);
|
||||||
|
|
||||||
|
m_flipYUniformLocation = m_program.GetUniformLocation(GlslWriter::GetFlipYUniformName());
|
||||||
|
if (m_flipYUniformLocation != -1)
|
||||||
|
m_program.Uniform(m_flipYUniformLocation, 1.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLRenderPipeline::Apply(const GL::Context& context) const
|
void OpenGLRenderPipeline::Apply(const GL::Context& context) const
|
||||||
|
|
@ -37,4 +43,13 @@ namespace Nz
|
||||||
context.UpdateStates(m_pipelineInfo);
|
context.UpdateStates(m_pipelineInfo);
|
||||||
context.BindProgram(m_program.GetObjectId()); //< Bind program after states
|
context.BindProgram(m_program.GetObjectId()); //< Bind program after states
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OpenGLRenderPipeline::FlipY(bool shouldFlipY) const
|
||||||
|
{
|
||||||
|
if (m_isYFlipped != shouldFlipY)
|
||||||
|
{
|
||||||
|
m_program.Uniform(m_flipYUniformLocation, (shouldFlipY) ? -1.f : 1.f);
|
||||||
|
m_isYFlipped = shouldFlipY;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include <Nazara/Shader/ShaderAstCloner.hpp>
|
#include <Nazara/Shader/ShaderAstCloner.hpp>
|
||||||
#include <Nazara/Shader/ShaderAstUtils.hpp>
|
#include <Nazara/Shader/ShaderAstUtils.hpp>
|
||||||
#include <Nazara/Shader/ShaderAstValidator.hpp>
|
#include <Nazara/Shader/ShaderAstValidator.hpp>
|
||||||
|
#include <optional>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <Nazara/Shader/Debug.hpp>
|
#include <Nazara/Shader/Debug.hpp>
|
||||||
|
|
||||||
|
|
@ -17,6 +18,8 @@ namespace Nz
|
||||||
{
|
{
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
static const char* flipYUniformName = "_NzFlipValue";
|
||||||
|
|
||||||
struct AstAdapter : ShaderAstCloner
|
struct AstAdapter : ShaderAstCloner
|
||||||
{
|
{
|
||||||
void Visit(ShaderNodes::AssignOp& node) override
|
void Visit(ShaderNodes::AssignOp& node) override
|
||||||
|
|
@ -35,8 +38,11 @@ namespace Nz
|
||||||
if (builtinVar.entry != ShaderNodes::BuiltinEntry::VertexPosition)
|
if (builtinVar.entry != ShaderNodes::BuiltinEntry::VertexPosition)
|
||||||
return ShaderAstCloner::Visit(node);
|
return ShaderAstCloner::Visit(node);
|
||||||
|
|
||||||
auto fixYConstant = ShaderBuilder::Constant(Nz::Vector4f(1.f, -1.f, 1.f, 1.f));
|
auto flipVar = ShaderBuilder::Uniform(flipYUniformName, ShaderNodes::BasicType::Float1);
|
||||||
auto mulFix = ShaderBuilder::Multiply(CloneExpression(node.right), fixYConstant);
|
|
||||||
|
auto oneConstant = ShaderBuilder::Constant(1.f);
|
||||||
|
auto fixYValue = ShaderBuilder::Cast<ShaderNodes::BasicType::Float4>(oneConstant, ShaderBuilder::Identifier(flipVar), oneConstant, oneConstant);
|
||||||
|
auto mulFix = ShaderBuilder::Multiply(CloneExpression(node.right), fixYValue);
|
||||||
|
|
||||||
PushExpression(ShaderNodes::AssignOp::Build(node.op, CloneExpression(node.left), mulFix));
|
PushExpression(ShaderNodes::AssignOp::Build(node.op, CloneExpression(node.left), mulFix));
|
||||||
}
|
}
|
||||||
|
|
@ -50,8 +56,21 @@ namespace Nz
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GlslWriter::Generate(const ShaderAst& shader, const States& conditions)
|
std::string GlslWriter::Generate(const ShaderAst& inputShader, const States& conditions)
|
||||||
{
|
{
|
||||||
|
const ShaderAst* selectedShader = &inputShader;
|
||||||
|
std::optional<ShaderAst> modifiedShader;
|
||||||
|
if (inputShader.GetStage() == ShaderStageType::Vertex && m_environment.flipYPosition)
|
||||||
|
{
|
||||||
|
modifiedShader.emplace(inputShader);
|
||||||
|
|
||||||
|
modifiedShader->AddUniform(flipYUniformName, ShaderNodes::BasicType::Float1);
|
||||||
|
|
||||||
|
selectedShader = &modifiedShader.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
const ShaderAst& shader = *selectedShader;
|
||||||
|
|
||||||
std::string error;
|
std::string error;
|
||||||
if (!ValidateShader(shader, &error))
|
if (!ValidateShader(shader, &error))
|
||||||
throw std::runtime_error("Invalid shader AST: " + error);
|
throw std::runtime_error("Invalid shader AST: " + error);
|
||||||
|
|
@ -201,6 +220,11 @@ namespace Nz
|
||||||
m_environment = std::move(environment);
|
m_environment = std::move(environment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* GlslWriter::GetFlipYUniformName()
|
||||||
|
{
|
||||||
|
return flipYUniformName;
|
||||||
|
}
|
||||||
|
|
||||||
void GlslWriter::Append(ShaderExpressionType type)
|
void GlslWriter::Append(ShaderExpressionType type)
|
||||||
{
|
{
|
||||||
std::visit([&](auto&& arg)
|
std::visit([&](auto&& arg)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue