Renderer: Implement and fix front face (winding order) between Vulkan / OpenGL
This commit is contained in:
parent
299585a7de
commit
ff505e9019
|
|
@ -63,6 +63,7 @@ int main()
|
|||
|
||||
std::shared_ptr<Nz::Material> material = std::make_shared<Nz::Material>(Nz::BasicMaterial::GetSettings());
|
||||
material->EnableDepthBuffer(true);
|
||||
material->EnableFaceCulling(true);
|
||||
|
||||
Nz::BasicMaterial basicMat(*material);
|
||||
basicMat.EnableAlphaTest(true);
|
||||
|
|
|
|||
|
|
@ -190,6 +190,7 @@ int main()
|
|||
|
||||
Nz::RenderPipelineInfo pipelineInfo;
|
||||
pipelineInfo.pipelineLayout = renderPipelineLayout;
|
||||
pipelineInfo.faceCulling = true;
|
||||
|
||||
pipelineInfo.depthBuffer = true;
|
||||
pipelineInfo.shaderModules.emplace_back(fragVertShader);
|
||||
|
|
|
|||
|
|
@ -22,9 +22,7 @@ namespace Nz
|
|||
OpenGLRenderPipeline(OpenGLDevice& device, RenderPipelineInfo pipelineInfo);
|
||||
~OpenGLRenderPipeline() = default;
|
||||
|
||||
void Apply(const GL::Context& context) const;
|
||||
|
||||
void FlipY(bool shouldFlipY) const;
|
||||
void Apply(const GL::Context& context, bool flipViewport) const;
|
||||
|
||||
inline const RenderPipelineInfo& GetPipelineInfo() const override;
|
||||
|
||||
|
|
@ -32,7 +30,7 @@ namespace Nz
|
|||
RenderPipelineInfo m_pipelineInfo;
|
||||
GL::Program m_program;
|
||||
GLint m_flipYUniformLocation;
|
||||
mutable bool m_isYFlipped;
|
||||
mutable bool m_isViewportFlipped;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,8 @@ namespace Nz
|
|||
|
||||
inline GLenum ToOpenGL(BlendEquation blendEquation);
|
||||
inline GLenum ToOpenGL(BlendFunc blendFunc);
|
||||
inline GLenum ToOpenGL(FaceSide filter);
|
||||
inline GLenum ToOpenGL(FaceSide side);
|
||||
inline GLenum ToOpenGL(FrontFace face);
|
||||
inline GLenum ToOpenGL(PrimitiveMode primitiveMode);
|
||||
inline GLenum ToOpenGL(SamplerFilter filter);
|
||||
inline GLenum ToOpenGL(SamplerFilter minFilter, SamplerMipmapMode mipmapFilter);
|
||||
|
|
|
|||
|
|
@ -72,9 +72,9 @@ namespace Nz
|
|||
return {};
|
||||
}
|
||||
|
||||
inline GLenum ToOpenGL(FaceSide filter)
|
||||
inline GLenum ToOpenGL(FaceSide side)
|
||||
{
|
||||
switch (filter)
|
||||
switch (side)
|
||||
{
|
||||
case FaceSide::None:
|
||||
break;
|
||||
|
|
@ -84,11 +84,23 @@ namespace Nz
|
|||
case FaceSide::FrontAndBack: return GL_FRONT_AND_BACK;
|
||||
}
|
||||
|
||||
NazaraError("Unhandled FaceSide 0x" + NumberToString(UnderlyingCast(filter), 16));
|
||||
NazaraError("Unhandled FaceSide 0x" + NumberToString(UnderlyingCast(side), 16));
|
||||
return {};
|
||||
}
|
||||
|
||||
GLenum ToOpenGL(PrimitiveMode primitiveMode)
|
||||
inline GLenum ToOpenGL(FrontFace face)
|
||||
{
|
||||
switch (face)
|
||||
{
|
||||
case FrontFace::Clockwise: return GL_CW;
|
||||
case FrontFace::CounterClockwise: return GL_CCW;
|
||||
}
|
||||
|
||||
NazaraError("Unhandled FrontFace 0x" + NumberToString(UnderlyingCast(face), 16));
|
||||
return {};
|
||||
}
|
||||
|
||||
inline GLenum ToOpenGL(PrimitiveMode primitiveMode)
|
||||
{
|
||||
switch (primitiveMode)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ namespace Nz::GL
|
|||
|
||||
virtual void SwapBuffers() = 0;
|
||||
|
||||
void UpdateStates(const RenderStates& renderStates) const;
|
||||
void UpdateStates(const RenderStates& renderStates, bool isViewportFlipped) const;
|
||||
|
||||
#define NAZARA_OPENGLRENDERER_FUNC(name, sig) sig name = nullptr;
|
||||
NAZARA_OPENGLRENDERER_FOREACH_GLES_FUNC(NAZARA_OPENGLRENDERER_FUNC, NAZARA_OPENGLRENDERER_FUNC)
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ typedef void (GL_APIENTRYP PFNGLSPECIALIZESHADERARBPROC) (GLuint shader, const G
|
|||
cb(glFramebufferRenderbuffer, PFNGLFRAMEBUFFERRENDERBUFFERPROC) \
|
||||
cb(glFramebufferTexture2D, PFNGLFRAMEBUFFERTEXTURE2DPROC) \
|
||||
cb(glFramebufferTextureLayer, PFNGLFRAMEBUFFERTEXTURELAYERPROC) \
|
||||
cb(glFrontFace, PFNGLFRONTFACEPROC) \
|
||||
cb(glGenBuffers, PFNGLGENBUFFERSPROC) \
|
||||
cb(glGenFramebuffers, PFNGLGENFRAMEBUFFERSPROC) \
|
||||
cb(glGenQueries, PFNGLGENQUERIESPROC) \
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ namespace Nz
|
|||
{
|
||||
FaceFilling faceFilling = FaceFilling::Fill;
|
||||
FaceSide cullingSide = FaceSide::Back;
|
||||
FrontFace frontFace = FrontFace::Clockwise;
|
||||
RendererComparison depthCompare = RendererComparison::Less;
|
||||
PrimitiveMode primitiveMode = PrimitiveMode::TriangleList;
|
||||
|
||||
|
|
|
|||
|
|
@ -149,6 +149,14 @@ namespace Nz
|
|||
Max = FrontAndBack
|
||||
};
|
||||
|
||||
enum class FrontFace
|
||||
{
|
||||
Clockwise,
|
||||
CounterClockwise,
|
||||
|
||||
Max = CounterClockwise
|
||||
};
|
||||
|
||||
enum class ImageType
|
||||
{
|
||||
E1D,
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ namespace Nz
|
|||
inline VkFormat ToVulkan(ComponentType componentType);
|
||||
inline VkCullModeFlagBits ToVulkan(FaceSide faceSide);
|
||||
inline VkPolygonMode ToVulkan(FaceFilling faceFilling);
|
||||
inline VkFrontFace ToVulkan(FrontFace frontFace);
|
||||
inline VkAccessFlagBits ToVulkan(MemoryAccess memoryAccess);
|
||||
inline VkAccessFlags ToVulkan(MemoryAccessFlags memoryAccessFlags);
|
||||
inline VkPipelineStageFlagBits ToVulkan(PipelineStage pipelineStage);
|
||||
|
|
|
|||
|
|
@ -154,6 +154,18 @@ namespace Nz
|
|||
return VK_POLYGON_MODE_FILL;
|
||||
}
|
||||
|
||||
inline VkFrontFace ToVulkan(FrontFace frontFace)
|
||||
{
|
||||
switch (frontFace)
|
||||
{
|
||||
case FrontFace::Clockwise: return VK_FRONT_FACE_CLOCKWISE;
|
||||
case FrontFace::CounterClockwise: return VK_FRONT_FACE_COUNTER_CLOCKWISE;
|
||||
}
|
||||
|
||||
NazaraError("Unhandled FrontFace 0x" + NumberToString(UnderlyingCast(frontFace), 16));
|
||||
return {};
|
||||
}
|
||||
|
||||
inline VkAccessFlagBits ToVulkan(MemoryAccess memoryAccess)
|
||||
{
|
||||
switch (memoryAccess)
|
||||
|
|
|
|||
|
|
@ -241,10 +241,7 @@ namespace Nz
|
|||
|
||||
void OpenGLCommandBuffer::ApplyStates(const GL::Context& context, const DrawStates& states)
|
||||
{
|
||||
states.pipeline->Apply(context);
|
||||
|
||||
states.pipeline->FlipY(states.shouldFlipY);
|
||||
|
||||
states.pipeline->Apply(context, states.shouldFlipY);
|
||||
states.shaderBindings->Apply(context);
|
||||
|
||||
if (states.scissorRegion)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ namespace Nz
|
|||
{
|
||||
OpenGLRenderPipeline::OpenGLRenderPipeline(OpenGLDevice& device, RenderPipelineInfo pipelineInfo) :
|
||||
m_pipelineInfo(std::move(pipelineInfo)),
|
||||
m_isYFlipped(false)
|
||||
m_isViewportFlipped(false)
|
||||
{
|
||||
if (!m_program.Create(device))
|
||||
throw std::runtime_error("failed to create program");
|
||||
|
|
@ -39,18 +39,14 @@ namespace Nz
|
|||
m_program.Uniform(m_flipYUniformLocation, 1.f);
|
||||
}
|
||||
|
||||
void OpenGLRenderPipeline::Apply(const GL::Context& context) const
|
||||
void OpenGLRenderPipeline::Apply(const GL::Context& context, bool flipViewport) const
|
||||
{
|
||||
context.UpdateStates(m_pipelineInfo);
|
||||
context.BindProgram(m_program.GetObjectId()); //< Bind program after states
|
||||
}
|
||||
|
||||
void OpenGLRenderPipeline::FlipY(bool shouldFlipY) const
|
||||
{
|
||||
if (m_isYFlipped != shouldFlipY)
|
||||
context.UpdateStates(m_pipelineInfo, flipViewport);
|
||||
context.BindProgram(m_program.GetObjectId()); //< Bind program after states (for shader caching)
|
||||
if (m_isViewportFlipped != flipViewport)
|
||||
{
|
||||
m_program.Uniform(m_flipYUniformLocation, (shouldFlipY) ? -1.f : 1.f);
|
||||
m_isYFlipped = shouldFlipY;
|
||||
m_program.Uniform(m_flipYUniformLocation, (flipViewport) ? -1.f : 1.f);
|
||||
m_isViewportFlipped = flipViewport;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -363,6 +363,8 @@ namespace Nz::GL
|
|||
glGetIntegerv(GL_VIEWPORT, res.data());
|
||||
m_state.viewport = { res[0], res[1], res[2], res[3] };
|
||||
|
||||
m_state.renderStates.frontFace = FrontFace::CounterClockwise; //< OpenGL default front face is counter-clockwise
|
||||
|
||||
EnableVerticalSync(false);
|
||||
|
||||
return true;
|
||||
|
|
@ -435,7 +437,7 @@ namespace Nz::GL
|
|||
}
|
||||
}
|
||||
|
||||
void Context::UpdateStates(const RenderStates& renderStates) const
|
||||
void Context::UpdateStates(const RenderStates& renderStates, bool isViewportFlipped) const
|
||||
{
|
||||
if (!SetCurrentContext(this))
|
||||
throw std::runtime_error("failed to activate context");
|
||||
|
|
@ -482,11 +484,21 @@ namespace Nz::GL
|
|||
{
|
||||
if (m_state.renderStates.cullingSide != renderStates.cullingSide)
|
||||
{
|
||||
glCullFace(ToOpenGL(m_state.renderStates.cullingSide));
|
||||
glCullFace(ToOpenGL(renderStates.cullingSide));
|
||||
m_state.renderStates.cullingSide = renderStates.cullingSide;
|
||||
}
|
||||
}
|
||||
|
||||
FrontFace targetFrontFace = renderStates.frontFace;
|
||||
if (!isViewportFlipped)
|
||||
targetFrontFace = (targetFrontFace == FrontFace::Clockwise) ? FrontFace::CounterClockwise : FrontFace::Clockwise;
|
||||
|
||||
if (m_state.renderStates.frontFace != targetFrontFace)
|
||||
{
|
||||
glFrontFace(ToOpenGL(targetFrontFace));
|
||||
m_state.renderStates.frontFace = targetFrontFace;
|
||||
}
|
||||
|
||||
/*
|
||||
TODO: Use glPolyonMode if available (OpenGL)
|
||||
if (m_state.renderStates.faceFilling != renderStates.faceFilling)
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@ namespace Nz
|
|||
VkPipelineRasterizationStateCreateInfo createInfo = {};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
||||
createInfo.polygonMode = ToVulkan(pipelineInfo.faceFilling);
|
||||
createInfo.cullMode = ToVulkan(pipelineInfo.cullingSide);
|
||||
createInfo.frontFace = VK_FRONT_FACE_CLOCKWISE; //< TODO
|
||||
createInfo.cullMode = (pipelineInfo.faceCulling) ? ToVulkan(pipelineInfo.cullingSide) : VK_CULL_MODE_NONE;
|
||||
createInfo.frontFace = ToVulkan(pipelineInfo.frontFace);
|
||||
createInfo.lineWidth = pipelineInfo.lineWidth;
|
||||
|
||||
return createInfo;
|
||||
|
|
|
|||
Loading…
Reference in New Issue