OpenGL: Implement RenderPipeline

This commit is contained in:
Lynix
2020-05-11 14:01:17 +02:00
parent 49c68e581a
commit 3cf53c4d9a
5 changed files with 177 additions and 298 deletions

View File

@@ -197,6 +197,157 @@ namespace Nz::GL
return true;
}
void Context::UpdateStates(const RenderStates& renderStates) const
{
if (!SetCurrentContext(this))
throw std::runtime_error("failed to activate context");
if (renderStates.blending)
{
if (m_state.renderStates.dstBlend != renderStates.dstBlend ||
m_state.renderStates.srcBlend != renderStates.srcBlend)
{
glBlendFunc(ToOpenGL(renderStates.srcBlend), ToOpenGL(renderStates.dstBlend));
m_state.renderStates.dstBlend = renderStates.dstBlend;
m_state.renderStates.srcBlend = renderStates.srcBlend;
}
}
if (renderStates.depthBuffer)
{
if (m_state.renderStates.depthCompare != renderStates.depthCompare)
{
glDepthFunc(ToOpenGL(m_state.renderStates.depthCompare));
m_state.renderStates.depthCompare = renderStates.depthCompare;
}
if (m_state.renderStates.depthWrite != renderStates.depthWrite)
{
glDepthMask((renderStates.depthWrite) ? GL_TRUE : GL_FALSE);
m_state.renderStates.depthWrite = renderStates.depthWrite;
}
}
if (renderStates.faceCulling)
{
if (m_state.renderStates.cullingSide != renderStates.cullingSide)
{
glCullFace(ToOpenGL(m_state.renderStates.cullingSide));
m_state.renderStates.cullingSide = renderStates.cullingSide;
}
}
/*
TODO: Use glPolyonMode if available (OpenGL)
if (m_state.renderStates.faceFilling != renderStates.faceFilling)
{
glPolygonMode(GL_FRONT_AND_BACK, FaceFilling[states.faceFilling]);
m_state.renderStates.faceFilling = renderStates.faceFilling;
}*/
if (renderStates.stencilTest)
{
auto ApplyStencilStates = [&](bool front)
{
auto& currentStencilData = (front) ? m_state.renderStates.stencilFront : m_state.renderStates.stencilBack;
auto& newStencilData = (front) ? renderStates.stencilFront : renderStates.stencilBack;
if (currentStencilData.compare != newStencilData.compare ||
currentStencilData.reference != newStencilData.reference ||
currentStencilData.writeMask != newStencilData.writeMask)
{
glStencilFuncSeparate((front) ? GL_FRONT : GL_BACK, ToOpenGL(newStencilData.compare), newStencilData.reference, newStencilData.writeMask);
currentStencilData.compare = newStencilData.compare;
currentStencilData.reference = newStencilData.reference;
currentStencilData.writeMask = newStencilData.writeMask;
}
if (currentStencilData.depthFail != newStencilData.depthFail ||
currentStencilData.fail != newStencilData.fail ||
currentStencilData.pass != newStencilData.pass)
{
glStencilOpSeparate((front) ? GL_FRONT : GL_BACK, ToOpenGL(newStencilData.fail), ToOpenGL(newStencilData.depthFail), ToOpenGL(newStencilData.pass));
currentStencilData.depthFail = newStencilData.depthFail;
currentStencilData.fail = newStencilData.fail;
currentStencilData.pass = newStencilData.pass;
}
};
ApplyStencilStates(true);
ApplyStencilStates(false);
}
if (!NumberEquals(m_state.renderStates.lineWidth, renderStates.lineWidth, 0.001f))
{
glLineWidth(renderStates.lineWidth);
m_state.renderStates.lineWidth = renderStates.lineWidth;
}
/*if (!NumberEquals(m_state.renderStates.pointSize, renderStates.pointSize, 0.001f))
{
glPointSize(renderStates.pointSize);
m_state.renderStates.pointSize = renderStates.pointSize;
}*/
if (m_state.renderStates.blending != renderStates.blending)
{
if (renderStates.blending)
glEnable(GL_BLEND);
else
glDisable(GL_BLEND);
m_state.renderStates.blending = renderStates.blending;
}
if (m_state.renderStates.colorWrite != renderStates.colorWrite)
{
GLboolean param = (renderStates.colorWrite) ? GL_TRUE : GL_FALSE;
glColorMask(param, param, param, param);
m_state.renderStates.colorWrite = renderStates.colorWrite;
}
if (m_state.renderStates.depthBuffer != renderStates.depthBuffer)
{
if (renderStates.depthBuffer)
glEnable(GL_DEPTH_TEST);
else
glDisable(GL_DEPTH_TEST);
m_state.renderStates.depthBuffer = renderStates.depthBuffer;
}
if (m_state.renderStates.faceCulling != renderStates.faceCulling)
{
if (renderStates.faceCulling)
glEnable(GL_CULL_FACE);
else
glDisable(GL_CULL_FACE);
m_state.renderStates.faceCulling = renderStates.faceCulling;
}
if (m_state.renderStates.scissorTest != renderStates.scissorTest)
{
if (renderStates.scissorTest)
glEnable(GL_SCISSOR_TEST);
else
glDisable(GL_SCISSOR_TEST);
m_state.renderStates.scissorTest = renderStates.scissorTest;
}
if (m_state.renderStates.stencilTest != renderStates.stencilTest)
{
if (renderStates.stencilTest)
glEnable(GL_STENCIL_TEST);
else
glDisable(GL_STENCIL_TEST);
m_state.renderStates.stencilTest = renderStates.stencilTest;
}
}
const Context* Context::GetCurrentContext()
{
return s_currentContext;