From 1de66b835de9fa2eda0d33b2c268b7493a3af9cb Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Tue, 17 Mar 2026 02:15:48 +0800 Subject: [PATCH] Enhance OpenGLPipelineState with comprehensive state management - Add BlendOp enum for blend operations - Add PolygonMode enum for polygon rendering mode - Add StencilOp enum for stencil operations - Add ScissorState and LogicalOperation structs - Add DepthStencilState: stencil enable, read/write mask, stencil ref, stencil func, stencil ops - Add BlendState: blend equation, color write mask, blend factor - Add RasterizerState: polygon mode, polygon offset, depth clip, scissor test, multisample - Add ViewportState: float coordinates with min/max depth - Add Apply methods for individual state groups - Add AttachShader/DetachShader for program management - Add getter methods for state structs --- .../XCEngine/RHI/OpenGL/OpenGLPipelineState.h | 90 +++++++- engine/src/RHI/OpenGL/OpenGLPipelineState.cpp | 211 ++++++++++++++---- 2 files changed, 255 insertions(+), 46 deletions(-) diff --git a/engine/include/XCEngine/RHI/OpenGL/OpenGLPipelineState.h b/engine/include/XCEngine/RHI/OpenGL/OpenGLPipelineState.h index 1897cd95..56bdbe2e 100644 --- a/engine/include/XCEngine/RHI/OpenGL/OpenGLPipelineState.h +++ b/engine/include/XCEngine/RHI/OpenGL/OpenGLPipelineState.h @@ -1,6 +1,8 @@ #pragma once #include +#include +#include namespace XCEngine { namespace RHI { @@ -30,7 +32,19 @@ enum class BlendFactor { ConstantColor, OneMinusConstantColor, ConstantAlpha, - OneMinusConstantAlpha + OneMinusConstantAlpha, + Src1Color, + InvSrc1Color, + Src1Alpha, + InvSrc1Alpha +}; + +enum class BlendOp { + Add, + Subtract, + ReverseSubtract, + Min, + Max }; enum class CullFace { @@ -44,10 +58,35 @@ enum class FrontFace { CounterClockwise }; +enum class PolygonMode { + Point, + Line, + Fill +}; + +enum class StencilOp { + Keep, + Zero, + Replace, + Incr, + IncrWrap, + Decr, + DecrWrap, + Invert +}; + struct DepthStencilState { bool depthTestEnable = true; bool depthWriteEnable = true; ComparisonFunc depthFunc = ComparisonFunc::Less; + bool stencilEnable = false; + uint8_t stencilReadMask = 0xFF; + uint8_t stencilWriteMask = 0xFF; + int stencilRef = 0; + ComparisonFunc stencilFunc = ComparisonFunc::Always; + StencilOp stencilFailOp = StencilOp::Keep; + StencilOp stencilDepthFailOp = StencilOp::Keep; + StencilOp stencilDepthPassOp = StencilOp::Keep; }; struct BlendState { @@ -56,22 +95,45 @@ struct BlendState { BlendFactor dstBlend = BlendFactor::OneMinusSrcAlpha; BlendFactor srcBlendAlpha = BlendFactor::One; BlendFactor dstBlendAlpha = BlendFactor::Zero; + BlendOp blendOp = BlendOp::Add; + BlendOp blendOpAlpha = BlendOp::Add; + uint8_t colorWriteMask = 0xF; + float blendFactor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; }; struct RasterizerState { bool cullFaceEnable = true; CullFace cullFace = CullFace::Back; FrontFace frontFace = FrontFace::CounterClockwise; - bool polygonModeFill = true; + PolygonMode polygonMode = PolygonMode::Fill; + float polygonOffsetFactor = 0.0f; + float polygonOffsetUnits = 0.0f; + bool depthClipEnable = true; + bool scissorTestEnable = false; + bool multisampleEnable = false; + bool sampleAlphaToCoverageEnable = false; }; struct ViewportState { + float x = 0.0f; + float y = 0.0f; + float width = 0.0f; + float height = 0.0f; + float minDepth = 0.0f; + float maxDepth = 1.0f; +}; + +struct ScissorState { + bool enable = false; int x = 0; int y = 0; int width = 0; int height = 0; - float minDepth = 0.0f; - float maxDepth = 1.0f; +}; + +struct LogicalOperation { + bool enable = false; + uint32_t operation = 0; }; class OpenGLPipelineState { @@ -83,17 +145,37 @@ public: void SetBlendState(const BlendState& state); void SetRasterizerState(const RasterizerState& state); void SetViewport(const ViewportState& state); + void SetScissor(const ScissorState& state); + void SetLogicalOperation(const LogicalOperation& state); void Apply(); + void ApplyDepthStencil(); + void ApplyBlend(); + void ApplyRasterizer(); + void ApplyViewport(); + void ApplyScissor(); + void SetClearColor(float r, float g, float b, float a); void Clear(unsigned int buffers); + void AttachShader(unsigned int program); + void DetachShader(); + + const DepthStencilState& GetDepthStencilState() const { return m_depthStencilState; } + const BlendState& GetBlendState() const { return m_blendState; } + const RasterizerState& GetRasterizerState() const { return m_rasterizerState; } + const ViewportState& GetViewportState() const { return m_viewportState; } + private: DepthStencilState m_depthStencilState; BlendState m_blendState; RasterizerState m_rasterizerState; ViewportState m_viewportState; + ScissorState m_scissorState; + LogicalOperation m_logicalOperation; float m_clearColor[4]; + unsigned int m_program; + bool m_programAttached; }; } // namespace RHI diff --git a/engine/src/RHI/OpenGL/OpenGLPipelineState.cpp b/engine/src/RHI/OpenGL/OpenGLPipelineState.cpp index 8726ae8c..2d3d5431 100644 --- a/engine/src/RHI/OpenGL/OpenGLPipelineState.cpp +++ b/engine/src/RHI/OpenGL/OpenGLPipelineState.cpp @@ -1,37 +1,10 @@ #define GLFW_INCLUDE_NONE #include "XCEngine/RHI/OpenGL/OpenGLPipelineState.h" #include -#include namespace XCEngine { namespace RHI { -OpenGLPipelineState::OpenGLPipelineState() { - m_clearColor[0] = 0.1f; - m_clearColor[1] = 0.1f; - m_clearColor[2] = 0.1f; - m_clearColor[3] = 1.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; -} - static unsigned int ToGLComparisonFunc(ComparisonFunc func) { switch (func) { case ComparisonFunc::Never: return GL_NEVER; @@ -62,10 +35,25 @@ static unsigned int ToGLBlendFactor(BlendFactor factor) { 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; @@ -83,31 +71,124 @@ static unsigned int ToGLFrontFace(FrontFace face) { } } +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); - glDepthFunc(ToGLComparisonFunc(m_depthStencilState.depthFunc)); - glDepthMask(m_depthStencilState.depthWriteEnable ? GL_TRUE : GL_FALSE); } 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); - glBlendFunc( - ToGLBlendFactor(m_blendState.srcBlend), - ToGLBlendFactor(m_blendState.dstBlend) - ); 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)); @@ -116,15 +197,49 @@ void OpenGLPipelineState::Apply() { glDisable(GL_CULL_FACE); } - glViewport( - m_viewportState.x, - m_viewportState.y, - m_viewportState.width, - m_viewportState.height - ); + 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; @@ -135,11 +250,23 @@ void OpenGLPipelineState::SetClearColor(float r, float g, float b, float a) { void OpenGLPipelineState::Clear(unsigned int buffers) { unsigned int glBuffers = 0; - if (buffers & 0x1) glBuffers |= GL_COLOR_BUFFER_BIT; - if (buffers & 0x2) glBuffers |= GL_DEPTH_BUFFER_BIT; - if (buffers & 0x4) glBuffers |= GL_STENCIL_BUFFER_BIT; + 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