diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index db9df5a0..360f1097 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -131,11 +131,13 @@ add_library(XCEngine STATIC include/XCEngine/RHI/OpenGL/OpenGLBuffer.h include/XCEngine/RHI/OpenGL/OpenGLVertexArray.h include/XCEngine/RHI/OpenGL/OpenGLTexture.h + include/XCEngine/RHI/OpenGL/OpenGLPipelineState.h src/RHI/OpenGL/OpenGLDevice.cpp src/RHI/OpenGL/OpenGLShader.cpp src/RHI/OpenGL/OpenGLBuffer.cpp src/RHI/OpenGL/OpenGLVertexArray.cpp src/RHI/OpenGL/OpenGLTexture.cpp + src/RHI/OpenGL/OpenGLPipelineState.cpp ) target_include_directories(XCEngine PUBLIC diff --git a/engine/include/XCEngine/RHI/OpenGL/OpenGLPipelineState.h b/engine/include/XCEngine/RHI/OpenGL/OpenGLPipelineState.h new file mode 100644 index 00000000..1897cd95 --- /dev/null +++ b/engine/include/XCEngine/RHI/OpenGL/OpenGLPipelineState.h @@ -0,0 +1,100 @@ +#pragma once + +#include + +namespace XCEngine { +namespace RHI { + +enum class ComparisonFunc { + Never, + Less, + Equal, + LessEqual, + Greater, + NotEqual, + GreaterEqual, + Always +}; + +enum class BlendFactor { + Zero, + One, + SrcColor, + OneMinusSrcColor, + DstColor, + OneMinusDstColor, + SrcAlpha, + OneMinusSrcAlpha, + DstAlpha, + OneMinusDstAlpha, + ConstantColor, + OneMinusConstantColor, + ConstantAlpha, + OneMinusConstantAlpha +}; + +enum class CullFace { + Front, + Back, + FrontAndBack +}; + +enum class FrontFace { + Clockwise, + CounterClockwise +}; + +struct DepthStencilState { + bool depthTestEnable = true; + bool depthWriteEnable = true; + ComparisonFunc depthFunc = ComparisonFunc::Less; +}; + +struct BlendState { + bool blendEnable = false; + BlendFactor srcBlend = BlendFactor::SrcAlpha; + BlendFactor dstBlend = BlendFactor::OneMinusSrcAlpha; + BlendFactor srcBlendAlpha = BlendFactor::One; + BlendFactor dstBlendAlpha = BlendFactor::Zero; +}; + +struct RasterizerState { + bool cullFaceEnable = true; + CullFace cullFace = CullFace::Back; + FrontFace frontFace = FrontFace::CounterClockwise; + bool polygonModeFill = true; +}; + +struct ViewportState { + int x = 0; + int y = 0; + int width = 0; + int height = 0; + float minDepth = 0.0f; + float maxDepth = 1.0f; +}; + +class OpenGLPipelineState { +public: + OpenGLPipelineState(); + ~OpenGLPipelineState(); + + void SetDepthStencilState(const DepthStencilState& state); + void SetBlendState(const BlendState& state); + void SetRasterizerState(const RasterizerState& state); + void SetViewport(const ViewportState& state); + + void Apply(); + void SetClearColor(float r, float g, float b, float a); + void Clear(unsigned int buffers); + +private: + DepthStencilState m_depthStencilState; + BlendState m_blendState; + RasterizerState m_rasterizerState; + ViewportState m_viewportState; + float m_clearColor[4]; +}; + +} // namespace RHI +} // namespace XCEngine diff --git a/engine/src/RHI/OpenGL/OpenGLPipelineState.cpp b/engine/src/RHI/OpenGL/OpenGLPipelineState.cpp new file mode 100644 index 00000000..8726ae8c --- /dev/null +++ b/engine/src/RHI/OpenGL/OpenGLPipelineState.cpp @@ -0,0 +1,145 @@ +#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; + 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; + default: return GL_ONE; + } +} + +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; + } +} + +void OpenGLPipelineState::Apply() { + 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); + } + + 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) + ); + } else { + glDisable(GL_BLEND); + } + + if (m_rasterizerState.cullFaceEnable) { + glEnable(GL_CULL_FACE); + glCullFace(ToGLCullFace(m_rasterizerState.cullFace)); + glFrontFace(ToGLFrontFace(m_rasterizerState.frontFace)); + } else { + glDisable(GL_CULL_FACE); + } + + glViewport( + m_viewportState.x, + m_viewportState.y, + m_viewportState.width, + m_viewportState.height + ); + glDepthRange(m_viewportState.minDepth, m_viewportState.maxDepth); +} + +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 & 0x1) glBuffers |= GL_COLOR_BUFFER_BIT; + if (buffers & 0x2) glBuffers |= GL_DEPTH_BUFFER_BIT; + if (buffers & 0x4) glBuffers |= GL_STENCIL_BUFFER_BIT; + glClear(glBuffers); +} + +} // namespace RHI +} // namespace XCEngine diff --git a/tests/OpenGL/main.cpp b/tests/OpenGL/main.cpp index 856615f4..d3787128 100644 --- a/tests/OpenGL/main.cpp +++ b/tests/OpenGL/main.cpp @@ -19,6 +19,7 @@ #include "XCEngine/Debug/FileLogSink.h" #include "XCEngine/RHI/OpenGL/OpenGLShader.h" #include "XCEngine/RHI/OpenGL/OpenGLDevice.h" +#include "XCEngine/RHI/OpenGL/OpenGLPipelineState.h" using namespace XCEngine::Debug; using namespace XCEngine::RHI; @@ -262,6 +263,7 @@ private: Model* model = nullptr; OpenGLShader* shader = nullptr; OpenGLDevice* device = nullptr; +OpenGLPipelineState* pipeline = nullptr; int frameCount = 0; void framebuffer_size_callback(GLFWwindow* window, int width, int height) @@ -279,10 +281,17 @@ void Initialize() Log("OpenGL Test Application Started"); + pipeline = new OpenGLPipelineState(); + ViewportState viewport; + viewport.width = SCR_WIDTH; + viewport.height = SCR_HEIGHT; + pipeline->SetViewport(viewport); + pipeline->SetClearColor(0.1f, 0.1f, 0.1f, 1.0f); + pipeline->Apply(); + model = new Model("res/models/backpack/backpack.obj"); shader = new OpenGLShader(); shader->CompileFromFile("Shaders/vertexshader.glsl", "Shaders/fragmentshader.glsl"); - glEnable(GL_DEPTH_TEST); Log("Initialization complete"); } @@ -319,8 +328,7 @@ bool SaveScreenshot(const char* filename) void Render() { - glClearColor(0.1f, 0.1f, 0.1f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + pipeline->Clear(3); // COLOR_BUFFER_BIT | DEPTH_BUFFER_BIT shader->Use(); @@ -387,6 +395,7 @@ int main() Log("Application closed"); + delete pipeline; delete device; delete shader; delete model;