#define GLFW_INCLUDE_NONE #include "XCEngine/RHI/OpenGL/OpenGLPipelineState.h" #include namespace XCEngine { namespace RHI { static unsigned int ToGLComparisonFunc(ComparisonFunc func) { switch (func) { case ComparisonFunc::Never: return GL_NEVER; case ComparisonFunc::Less: return GL_LESS; case ComparisonFunc::Equal: return GL_EQUAL; case ComparisonFunc::LessEqual: return GL_LEQUAL; case ComparisonFunc::Greater: return GL_GREATER; case ComparisonFunc::NotEqual: return GL_NOTEQUAL; case ComparisonFunc::GreaterEqual: return GL_GEQUAL; case ComparisonFunc::Always: return GL_ALWAYS; default: return GL_LESS; } } static unsigned int ToGLBlendFactor(BlendFactor factor) { switch (factor) { case BlendFactor::Zero: return GL_ZERO; case BlendFactor::One: return GL_ONE; case BlendFactor::SrcColor: return GL_SRC_COLOR; case BlendFactor::OneMinusSrcColor: return GL_ONE_MINUS_SRC_COLOR; case BlendFactor::DstColor: return GL_DST_COLOR; case BlendFactor::OneMinusDstColor: return GL_ONE_MINUS_DST_COLOR; case BlendFactor::SrcAlpha: return GL_SRC_ALPHA; case BlendFactor::OneMinusSrcAlpha: return GL_ONE_MINUS_SRC_ALPHA; case BlendFactor::DstAlpha: return GL_DST_ALPHA; case BlendFactor::OneMinusDstAlpha: return GL_ONE_MINUS_DST_ALPHA; case BlendFactor::ConstantColor: return GL_CONSTANT_COLOR; case BlendFactor::OneMinusConstantColor: return GL_ONE_MINUS_CONSTANT_COLOR; case BlendFactor::ConstantAlpha: return GL_CONSTANT_ALPHA; case BlendFactor::OneMinusConstantAlpha: return GL_ONE_MINUS_CONSTANT_ALPHA; case BlendFactor::Src1Color: return GL_SRC1_COLOR; case BlendFactor::InvSrc1Color: return GL_ONE_MINUS_SRC1_COLOR; case BlendFactor::Src1Alpha: return GL_SRC1_ALPHA; case BlendFactor::InvSrc1Alpha: return GL_ONE_MINUS_SRC1_ALPHA; default: return GL_ONE; } } static unsigned int ToGLBlendOp(BlendOp op) { switch (op) { case BlendOp::Add: return GL_FUNC_ADD; case BlendOp::Subtract: return GL_FUNC_SUBTRACT; case BlendOp::ReverseSubtract: return GL_FUNC_REVERSE_SUBTRACT; case BlendOp::Min: return GL_MIN; case BlendOp::Max: return GL_MAX; default: return GL_FUNC_ADD; } } static unsigned int ToGLCullFace(CullFace face) { switch (face) { case CullFace::Front: return GL_FRONT; case CullFace::Back: return GL_BACK; case CullFace::FrontAndBack: return GL_FRONT_AND_BACK; default: return GL_BACK; } } static unsigned int ToGLFrontFace(FrontFace face) { switch (face) { case FrontFace::Clockwise: return GL_CW; case FrontFace::CounterClockwise: return GL_CCW; default: return GL_CCW; } } static unsigned int ToGLPolygonMode(PolygonMode mode) { switch (mode) { case PolygonMode::Point: return GL_POINT; case PolygonMode::Line: return GL_LINE; case PolygonMode::Fill: return GL_FILL; default: return GL_FILL; } } static unsigned int ToGLStencilOp(StencilOp op) { switch (op) { case StencilOp::Keep: return GL_KEEP; case StencilOp::Zero: return GL_ZERO; case StencilOp::Replace: return GL_REPLACE; case StencilOp::Incr: return GL_INCR; case StencilOp::IncrWrap: return GL_INCR_WRAP; case StencilOp::Decr: return GL_DECR; case StencilOp::DecrWrap: return GL_DECR_WRAP; case StencilOp::Invert: return GL_INVERT; default: return GL_KEEP; } } OpenGLPipelineState::OpenGLPipelineState() : m_program(0) , m_programAttached(false) { m_clearColor[0] = m_clearColor[1] = m_clearColor[2] = m_clearColor[3] = 0.0f; } OpenGLPipelineState::~OpenGLPipelineState() { } void OpenGLPipelineState::SetDepthStencilState(const DepthStencilState& state) { m_depthStencilState = state; } void OpenGLPipelineState::SetBlendState(const BlendState& state) { m_blendState = state; } void OpenGLPipelineState::SetRasterizerState(const RasterizerState& state) { m_rasterizerState = state; } void OpenGLPipelineState::SetViewport(const ViewportState& state) { m_viewportState = state; } void OpenGLPipelineState::SetScissor(const ScissorState& state) { m_scissorState = state; } void OpenGLPipelineState::SetLogicalOperation(const LogicalOperation& state) { m_logicalOperation = state; } void OpenGLPipelineState::Apply() { ApplyDepthStencil(); ApplyBlend(); ApplyRasterizer(); ApplyViewport(); ApplyScissor(); } void OpenGLPipelineState::ApplyDepthStencil() { if (m_depthStencilState.depthTestEnable) { glEnable(GL_DEPTH_TEST); } else { glDisable(GL_DEPTH_TEST); } glDepthMask(m_depthStencilState.depthWriteEnable ? GL_TRUE : GL_FALSE); glDepthFunc(ToGLComparisonFunc(m_depthStencilState.depthFunc)); if (m_depthStencilState.stencilEnable) { glEnable(GL_STENCIL_TEST); glStencilMask(m_depthStencilState.stencilWriteMask); glStencilFunc(ToGLComparisonFunc(m_depthStencilState.stencilFunc), m_depthStencilState.stencilRef, m_depthStencilState.stencilReadMask); glStencilOp( ToGLStencilOp(m_depthStencilState.stencilFailOp), ToGLStencilOp(m_depthStencilState.stencilDepthFailOp), ToGLStencilOp(m_depthStencilState.stencilDepthPassOp) ); } else { glDisable(GL_STENCIL_TEST); } } void OpenGLPipelineState::ApplyBlend() { if (m_blendState.blendEnable) { glEnable(GL_BLEND); glBlendFuncSeparate( ToGLBlendFactor(m_blendState.srcBlend), ToGLBlendFactor(m_blendState.dstBlend), ToGLBlendFactor(m_blendState.srcBlendAlpha), ToGLBlendFactor(m_blendState.dstBlendAlpha) ); glBlendEquationSeparate( ToGLBlendOp(m_blendState.blendOp), ToGLBlendOp(m_blendState.blendOpAlpha) ); glBlendColor( m_blendState.blendFactor[0], m_blendState.blendFactor[1], m_blendState.blendFactor[2], m_blendState.blendFactor[3] ); glColorMask( (m_blendState.colorWriteMask & 1) != 0, (m_blendState.colorWriteMask & 2) != 0, (m_blendState.colorWriteMask & 4) != 0, (m_blendState.colorWriteMask & 8) != 0 ); } else { glDisable(GL_BLEND); } } void OpenGLPipelineState::ApplyRasterizer() { if (m_rasterizerState.cullFaceEnable) { glEnable(GL_CULL_FACE); glCullFace(ToGLCullFace(m_rasterizerState.cullFace)); glFrontFace(ToGLFrontFace(m_rasterizerState.frontFace)); } else { glDisable(GL_CULL_FACE); } glPolygonMode(GL_FRONT_AND_BACK, ToGLPolygonMode(m_rasterizerState.polygonMode)); if (m_rasterizerState.polygonOffsetFactor != 0.0f || m_rasterizerState.polygonOffsetUnits != 0.0f) { glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(m_rasterizerState.polygonOffsetFactor, m_rasterizerState.polygonOffsetUnits); } else { glDisable(GL_POLYGON_OFFSET_FILL); } if (m_rasterizerState.scissorTestEnable) { glEnable(GL_SCISSOR_TEST); } else { glDisable(GL_SCISSOR_TEST); } if (m_rasterizerState.multisampleEnable) { glEnable(GL_MULTISAMPLE); } else { glDisable(GL_MULTISAMPLE); } if (m_rasterizerState.sampleAlphaToCoverageEnable) { glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE); } else { glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); } } void OpenGLPipelineState::ApplyViewport() { glViewport((GLint)m_viewportState.x, (GLint)m_viewportState.y, (GLsizei)m_viewportState.width, (GLsizei)m_viewportState.height); glDepthRange(m_viewportState.minDepth, m_viewportState.maxDepth); } void OpenGLPipelineState::ApplyScissor() { if (m_scissorState.enable) { glEnable(GL_SCISSOR_TEST); glScissor(m_scissorState.x, m_scissorState.y, m_scissorState.width, m_scissorState.height); } else { glDisable(GL_SCISSOR_TEST); } } void OpenGLPipelineState::SetClearColor(float r, float g, float b, float a) { m_clearColor[0] = r; m_clearColor[1] = g; m_clearColor[2] = b; m_clearColor[3] = a; glClearColor(r, g, b, a); } void OpenGLPipelineState::Clear(unsigned int buffers) { unsigned int glBuffers = 0; if (buffers & 1) glBuffers |= GL_COLOR_BUFFER_BIT; if (buffers & 2) glBuffers |= GL_DEPTH_BUFFER_BIT; if (buffers & 4) glBuffers |= GL_STENCIL_BUFFER_BIT; glClear(glBuffers); } void OpenGLPipelineState::AttachShader(unsigned int program) { m_program = program; m_programAttached = true; glUseProgram(program); } void OpenGLPipelineState::DetachShader() { m_program = 0; m_programAttached = false; glUseProgram(0); } } // namespace RHI } // namespace XCEngine