From 712e9756104188ee01503c7aefcd32a0077137c7 Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Wed, 25 Mar 2026 19:01:36 +0800 Subject: [PATCH] refactor: Refactor OpenGL backend to use OpenGLEnums Use centralized OpenGLEnums.h for enum conversion: - Remove local ToGL* functions from OpenGLCommandList - Replace with ToOpenGL() and ToOpenGLClearBuffer() from OpenGLEnums - Simplify OpenGLTexture, OpenGLBuffer, OpenGLSampler, etc. --- .../XCEngine/RHI/OpenGL/OpenGLDevice.h | 2 +- .../XCEngine/RHI/OpenGL/OpenGLScreenshot.h | 9 +- engine/src/RHI/OpenGL/OpenGLBuffer.cpp | 28 +--- engine/src/RHI/OpenGL/OpenGLCommandList.cpp | 142 +++--------------- .../src/RHI/OpenGL/OpenGLDepthStencilView.cpp | 14 +- engine/src/RHI/OpenGL/OpenGLDevice.cpp | 2 +- engine/src/RHI/OpenGL/OpenGLFramebuffer.cpp | 20 +-- engine/src/RHI/OpenGL/OpenGLPipelineState.cpp | 37 +++-- .../src/RHI/OpenGL/OpenGLRenderTargetView.cpp | 16 +- engine/src/RHI/OpenGL/OpenGLSampler.cpp | 37 +---- engine/src/RHI/OpenGL/OpenGLScreenshot.cpp | 6 + engine/src/RHI/OpenGL/OpenGLTexture.cpp | 66 ++------ engine/src/RHI/OpenGL/OpenGLVertexArray.cpp | 26 +--- 13 files changed, 108 insertions(+), 297 deletions(-) diff --git a/engine/include/XCEngine/RHI/OpenGL/OpenGLDevice.h b/engine/include/XCEngine/RHI/OpenGL/OpenGLDevice.h index fdca9591..1d0ba5e5 100644 --- a/engine/include/XCEngine/RHI/OpenGL/OpenGLDevice.h +++ b/engine/include/XCEngine/RHI/OpenGL/OpenGLDevice.h @@ -39,7 +39,7 @@ public: RHISwapChain* CreateSwapChain(const SwapChainDesc& desc) override; RHICommandList* CreateCommandList(const CommandListDesc& desc) override; RHICommandQueue* CreateCommandQueue(const CommandQueueDesc& desc) override; - RHIShader* CompileShader(const ShaderCompileDesc& desc) override; + RHIShader* CreateShader(const ShaderCompileDesc& desc) override; RHIPipelineState* CreatePipelineState(const GraphicsPipelineDesc& desc) override; RHIPipelineLayout* CreatePipelineLayout(const RHIPipelineLayoutDesc& desc) override; RHIFence* CreateFence(const FenceDesc& desc) override; diff --git a/engine/include/XCEngine/RHI/OpenGL/OpenGLScreenshot.h b/engine/include/XCEngine/RHI/OpenGL/OpenGLScreenshot.h index f120ced3..26e74756 100644 --- a/engine/include/XCEngine/RHI/OpenGL/OpenGLScreenshot.h +++ b/engine/include/XCEngine/RHI/OpenGL/OpenGLScreenshot.h @@ -2,6 +2,7 @@ #include #include +#include "../RHIScreenshot.h" namespace XCEngine { namespace RHI { @@ -9,8 +10,11 @@ namespace RHI { class OpenGLSwapChain; class OpenGLDevice; -class OpenGLScreenshot { +class OpenGLScreenshot : public RHIScreenshot { public: + bool Capture(RHIDevice* device, RHISwapChain* swapChain, const char* filename) override; + void Shutdown() override {} + static bool Capture(OpenGLDevice& device, OpenGLSwapChain& swapChain, const char* filename); @@ -23,7 +27,8 @@ public: private: static bool SavePPM(const char* filename, - int width, int height); + int width, + int height); }; } // namespace RHI diff --git a/engine/src/RHI/OpenGL/OpenGLBuffer.cpp b/engine/src/RHI/OpenGL/OpenGLBuffer.cpp index dc84c7ab..30a35663 100644 --- a/engine/src/RHI/OpenGL/OpenGLBuffer.cpp +++ b/engine/src/RHI/OpenGL/OpenGLBuffer.cpp @@ -1,24 +1,10 @@ #include "XCEngine/RHI/OpenGL/OpenGLBuffer.h" +#include "XCEngine/RHI/OpenGL/OpenGLEnums.h" #include namespace XCEngine { namespace RHI { -static unsigned int ToGLBufferTarget(OpenGLBufferType type) { - switch (type) { - case OpenGLBufferType::Vertex: return GL_ARRAY_BUFFER; - case OpenGLBufferType::Index: return GL_ELEMENT_ARRAY_BUFFER; - case OpenGLBufferType::Uniform: return GL_UNIFORM_BUFFER; - case OpenGLBufferType::CopyRead: return GL_COPY_READ_BUFFER; - case OpenGLBufferType::CopyWrite: return GL_COPY_WRITE_BUFFER; - case OpenGLBufferType::AtomicCounter: return GL_ATOMIC_COUNTER_BUFFER; - case OpenGLBufferType::DispatchIndirect: return GL_DISPATCH_INDIRECT_BUFFER; - case OpenGLBufferType::DrawIndirect: return GL_DRAW_INDIRECT_BUFFER; - case OpenGLBufferType::ShaderBindingTable: return GL_SHADER_STORAGE_BUFFER; - default: return GL_ARRAY_BUFFER; - } -} - OpenGLBuffer::OpenGLBuffer() : m_buffer(0) , m_size(0) @@ -37,7 +23,7 @@ bool OpenGLBuffer::Initialize(OpenGLBufferType type, size_t size, const void* da m_dynamic = dynamic; m_isIndexBuffer = (type == OpenGLBufferType::Index); - unsigned int target = ToGLBufferTarget(type); + unsigned int target = ToOpenGL(type); GLenum usage = dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW; glGenBuffers(1, &m_buffer); @@ -64,12 +50,12 @@ void OpenGLBuffer::Shutdown() { } void OpenGLBuffer::Bind() const { - unsigned int target = ToGLBufferTarget(m_type); + unsigned int target = ToOpenGL(m_type); glBindBuffer(target, m_buffer); } void OpenGLBuffer::Unbind() const { - unsigned int target = ToGLBufferTarget(m_type); + unsigned int target = ToOpenGL(m_type); glBindBuffer(target, 0); } @@ -78,7 +64,7 @@ void OpenGLBuffer::BindBase(unsigned int target, unsigned int index) const { } void* OpenGLBuffer::Map() { - unsigned int target = ToGLBufferTarget(m_type); + unsigned int target = ToOpenGL(m_type); glBindBuffer(target, m_buffer); void* ptr = glMapBuffer(target, GL_WRITE_ONLY); glBindBuffer(target, 0); @@ -86,14 +72,14 @@ void* OpenGLBuffer::Map() { } void OpenGLBuffer::Unmap() { - unsigned int target = ToGLBufferTarget(m_type); + unsigned int target = ToOpenGL(m_type); glBindBuffer(target, m_buffer); glUnmapBuffer(target); glBindBuffer(target, 0); } void OpenGLBuffer::SetData(const void* data, size_t size, size_t offset) { - unsigned int target = ToGLBufferTarget(m_type); + unsigned int target = ToOpenGL(m_type); glBindBuffer(target, m_buffer); if (offset == 0 && size == m_size) { glBufferData(target, size, data, m_dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW); diff --git a/engine/src/RHI/OpenGL/OpenGLCommandList.cpp b/engine/src/RHI/OpenGL/OpenGLCommandList.cpp index ce1fa308..e566fdda 100644 --- a/engine/src/RHI/OpenGL/OpenGLCommandList.cpp +++ b/engine/src/RHI/OpenGL/OpenGLCommandList.cpp @@ -5,27 +5,13 @@ #include "XCEngine/RHI/OpenGL/OpenGLFramebuffer.h" #include "XCEngine/RHI/OpenGL/OpenGLRenderPass.h" #include "XCEngine/RHI/OpenGL/OpenGLDescriptorSet.h" +#include "XCEngine/RHI/OpenGL/OpenGLEnums.h" #include namespace XCEngine { namespace RHI { -static unsigned int ToGLPrimitiveType(PrimitiveType type) { - switch (type) { - case PrimitiveType::Points: return GL_POINTS; - case PrimitiveType::Lines: return GL_LINES; - case PrimitiveType::LineStrip: return GL_LINE_STRIP; - case PrimitiveType::Triangles: return GL_TRIANGLES; - case PrimitiveType::TriangleStrip: return GL_TRIANGLE_STRIP; - case PrimitiveType::TriangleFan: return GL_TRIANGLE_FAN; - case PrimitiveType::LineListAdj: return GL_LINES_ADJACENCY; - case PrimitiveType::TriangleListAdj: return GL_TRIANGLES_ADJACENCY; - case PrimitiveType::Patch: return GL_PATCHES; - default: return GL_TRIANGLES; - } -} - -OpenGLCommandList::OpenGLCommandList() +OpenGLCommandList::OpenGLCommandList() : m_primitiveType(GL_TRIANGLES) , m_currentVAO(0) , m_currentProgram(0) @@ -37,11 +23,7 @@ OpenGLCommandList::~OpenGLCommandList() { void OpenGLCommandList::Clear(float r, float g, float b, float a, unsigned int buffers) { glClearColor(r, g, b, a); - 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); + glClear(ToOpenGLClearBuffer(buffers)); } void OpenGLCommandList::ClearColor(float r, float g, float b, float a) { @@ -206,35 +188,35 @@ void OpenGLCommandList::SetPolygonOffset(float factor, float units) { } void OpenGLCommandList::SetPrimitiveType(PrimitiveType type) { - m_primitiveType = ToGLPrimitiveType(type); + m_primitiveType = ToOpenGL(type); } void OpenGLCommandList::Draw(PrimitiveType type, unsigned int vertexCount, unsigned int startVertex) { - m_primitiveType = ToGLPrimitiveType(type); + m_primitiveType = ToOpenGL(type); glDrawArrays(m_primitiveType, startVertex, vertexCount); } void OpenGLCommandList::DrawInstanced(PrimitiveType type, unsigned int vertexCount, unsigned int instanceCount, unsigned int startVertex, unsigned int startInstance) { - m_primitiveType = ToGLPrimitiveType(type); + m_primitiveType = ToOpenGL(type); glDrawArraysInstanced(m_primitiveType, startVertex, vertexCount, instanceCount); (void)startInstance; } void OpenGLCommandList::DrawIndexed(PrimitiveType type, unsigned int indexCount, unsigned int startIndex, int baseVertex) { - m_primitiveType = ToGLPrimitiveType(type); + m_primitiveType = ToOpenGL(type); glDrawElements(m_primitiveType, indexCount, GL_UNSIGNED_INT, (void*)(startIndex * sizeof(unsigned int))); (void)baseVertex; } void OpenGLCommandList::DrawIndexedInstanced(PrimitiveType type, unsigned int indexCount, unsigned int instanceCount, unsigned int startIndex, int baseVertex, unsigned int startInstance) { - m_primitiveType = ToGLPrimitiveType(type); + m_primitiveType = ToOpenGL(type); glDrawElementsInstanced(m_primitiveType, indexCount, GL_UNSIGNED_INT, (void*)(startIndex * sizeof(unsigned int)), instanceCount); (void)baseVertex; (void)startInstance; } void OpenGLCommandList::DrawIndirect(PrimitiveType type, unsigned int buffer, size_t offset, unsigned int drawCount, unsigned int stride) { - m_primitiveType = ToGLPrimitiveType(type); + m_primitiveType = ToOpenGL(type); glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer); glDrawArraysIndirect(m_primitiveType, (void*)offset); glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0); @@ -243,7 +225,7 @@ void OpenGLCommandList::DrawIndirect(PrimitiveType type, unsigned int buffer, si } void OpenGLCommandList::DrawIndexedIndirect(PrimitiveType type, unsigned int buffer, size_t offset, unsigned int drawCount, unsigned int stride) { - m_primitiveType = ToGLPrimitiveType(type); + m_primitiveType = ToOpenGL(type); glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer); glDrawElementsIndirect(m_primitiveType, GL_UNSIGNED_INT, (void*)offset); glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0); @@ -252,12 +234,12 @@ void OpenGLCommandList::DrawIndexedIndirect(PrimitiveType type, unsigned int buf } void OpenGLCommandList::MultiDrawArrays(PrimitiveType type, const int* first, const int* count, unsigned int drawCount) { - m_primitiveType = ToGLPrimitiveType(type); + m_primitiveType = ToOpenGL(type); glMultiDrawArrays(m_primitiveType, first, count, drawCount); } void OpenGLCommandList::MultiDrawElements(PrimitiveType type, const int* count, unsigned int type_, const void* const* indices, unsigned int drawCount) { - m_primitiveType = ToGLPrimitiveType(type); + m_primitiveType = ToOpenGL(type); glMultiDrawElements(m_primitiveType, count, type_, indices, drawCount); } @@ -483,25 +465,25 @@ void OpenGLCommandList::BeginRenderPass(RHIRenderPass* renderPass, RHIFramebuffe (void)renderArea; (void)clearValueCount; (void)clearValues; - + if (!framebuffer) return; - + OpenGLFramebuffer* glFramebuffer = static_cast(framebuffer); glFramebuffer->Bind(); - + if (!renderPass) return; - + OpenGLRenderPass* glRenderPass = static_cast(renderPass); if (glRenderPass) { const AttachmentDesc* colorAttachments = glRenderPass->GetColorAttachments(); uint32_t colorCount = glRenderPass->GetColorAttachmentCount(); - + for (uint32_t i = 0; i < colorCount && i < clearValueCount; ++i) { if (colorAttachments[i].loadOp == LoadAction::Clear) { glClearBufferfv(GL_COLOR, i, &clearValues[i].color.r); } } - + const AttachmentDesc* dsAttachment = glRenderPass->GetDepthStencilAttachment(); if (dsAttachment && clearValueCount > colorCount) { if (dsAttachment->loadOp == LoadAction::Clear) { @@ -566,7 +548,7 @@ void OpenGLCommandList::SetRenderTargets(uint32_t count, RHIResourceView** rende std::vector drawBuffers(count); for (uint32_t i = 0; i < count; ++i) { - drawBuffers[i] = GL_COLOR_ATTACHMENT0 + i; + drawBuffers[i] = ToOpenGLColorAttachment(i); } glDrawBuffers(count, drawBuffers.data()); @@ -627,7 +609,7 @@ void OpenGLCommandList::SetGraphicsDescriptorSets( RHIPipelineLayout* pipelineLayout) { (void)firstSet; (void)pipelineLayout; - + for (uint32_t i = 0; i < count; ++i) { if (descriptorSets[i] != nullptr) { OpenGLDescriptorSet* glSet = static_cast(descriptorSets[i]); @@ -643,7 +625,7 @@ void OpenGLCommandList::SetComputeDescriptorSets( RHIPipelineLayout* pipelineLayout) { (void)firstSet; (void)pipelineLayout; - + for (uint32_t i = 0; i < count; ++i) { if (descriptorSets[i] != nullptr) { OpenGLDescriptorSet* glSet = static_cast(descriptorSets[i]); @@ -657,7 +639,7 @@ void OpenGLCommandList::SetVertexBuffers(uint32_t startSlot, uint32_t count, RHI if (!buffers[i]) continue; OpenGLResourceView* view = static_cast(buffers[i]); if (!view->IsValid()) continue; - + GLuint glBuffer = view->GetBuffer(); glBindBuffer(GL_ARRAY_BUFFER, glBuffer); glEnableVertexAttribArray(startSlot + i); @@ -700,86 +682,8 @@ void OpenGLCommandList::DrawIndexed(uint32_t indexCount, uint32_t instanceCount, reinterpret_cast(startIndex * sizeof(GLuint)), static_cast(instanceCount)); } -static unsigned int ToGLPrimitiveTopology(PrimitiveTopology topology) { - switch (topology) { - case PrimitiveTopology::PointList: return GL_POINTS; - case PrimitiveTopology::LineList: return GL_LINES; - case PrimitiveTopology::LineStrip: return GL_LINE_STRIP; - case PrimitiveTopology::TriangleList: return GL_TRIANGLES; - case PrimitiveTopology::TriangleStrip: return GL_TRIANGLE_STRIP; - case PrimitiveTopology::LineListAdj: return GL_LINES_ADJACENCY; - case PrimitiveTopology::LineStripAdj: return GL_LINE_STRIP_ADJACENCY; - case PrimitiveTopology::TriangleListAdj: return GL_TRIANGLES_ADJACENCY; - case PrimitiveTopology::TriangleStripAdj: return GL_TRIANGLE_STRIP_ADJACENCY; - case PrimitiveTopology::PatchList: return GL_PATCHES; - default: return GL_TRIANGLES; - } -} - -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 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::IncrSat: return GL_INCR; - case StencilOp::DecrSat: return GL_DECR; - case StencilOp::Invert: return GL_INVERT; - case StencilOp::Incr: return GL_INCR_WRAP; - case StencilOp::Decr: return GL_DECR_WRAP; - default: return GL_KEEP; - } -} - -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::InvSrcColor: return GL_ONE_MINUS_SRC_COLOR; - case BlendFactor::SrcAlpha: return GL_SRC_ALPHA; - case BlendFactor::InvSrcAlpha: return GL_ONE_MINUS_SRC_ALPHA; - case BlendFactor::DstAlpha: return GL_DST_ALPHA; - case BlendFactor::InvDstAlpha: return GL_ONE_MINUS_DST_ALPHA; - case BlendFactor::DstColor: return GL_DST_COLOR; - case BlendFactor::InvDstColor: return GL_ONE_MINUS_DST_COLOR; - case BlendFactor::SrcAlphaSat: return GL_SRC_ALPHA_SATURATE; - case BlendFactor::BlendFactor: return GL_CONSTANT_COLOR; - case BlendFactor::InvBlendFactor: return GL_ONE_MINUS_CONSTANT_COLOR; - 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; - } -} - void OpenGLCommandList::SetPrimitiveTopology(PrimitiveTopology topology) { - m_primitiveType = ToGLPrimitiveTopology(topology); + m_primitiveType = ToOpenGL(topology); } void OpenGLCommandList::SetStencilRef(uint8_t ref) { diff --git a/engine/src/RHI/OpenGL/OpenGLDepthStencilView.cpp b/engine/src/RHI/OpenGL/OpenGLDepthStencilView.cpp index a127d7da..e2535aee 100644 --- a/engine/src/RHI/OpenGL/OpenGLDepthStencilView.cpp +++ b/engine/src/RHI/OpenGL/OpenGLDepthStencilView.cpp @@ -1,10 +1,11 @@ #include "XCEngine/RHI/OpenGL/OpenGLDepthStencilView.h" +#include "XCEngine/RHI/OpenGL/OpenGLEnums.h" #include namespace XCEngine { namespace RHI { -OpenGLDepthStencilView::OpenGLDepthStencilView() +OpenGLDepthStencilView::OpenGLDepthStencilView() : m_texture(0) , m_framebuffer(0) , m_mipLevel(0) @@ -26,18 +27,15 @@ bool OpenGLDepthStencilView::Initialize(unsigned int texture, const OpenGLDepthS glGenFramebuffers(1, &m_framebuffer); glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer); - GLenum depthAttachment = GL_DEPTH_ATTACHMENT; - GLenum stencilAttachment = GL_STENCIL_ATTACHMENT; - switch (desc.type) { case DepthStencilType::Texture2D: - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, texture, desc.mipLevel); + glFramebufferTexture2D(GL_FRAMEBUFFER, ToOpenGLDepthAttachment(), GL_TEXTURE_2D, texture, desc.mipLevel); break; case DepthStencilType::Texture2DArray: - glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, texture, desc.mipLevel, desc.baseArraySlice); + glFramebufferTextureLayer(GL_FRAMEBUFFER, ToOpenGLDepthAttachment(), texture, desc.mipLevel, desc.baseArraySlice); break; case DepthStencilType::TextureCube: - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + desc.baseArraySlice, texture, desc.mipLevel); + glFramebufferTexture2D(GL_FRAMEBUFFER, ToOpenGLDepthAttachment(), GL_TEXTURE_CUBE_MAP_POSITIVE_X + desc.baseArraySlice, texture, desc.mipLevel); break; } @@ -63,7 +61,7 @@ bool OpenGLDepthStencilView::InitializeCubemap(unsigned int cubemap, int face, i glGenFramebuffers(1, &m_framebuffer); glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, cubemap, mipLevel); + glFramebufferTexture2D(GL_FRAMEBUFFER, ToOpenGLDepthAttachment(), GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, cubemap, mipLevel); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { glBindFramebuffer(GL_FRAMEBUFFER, 0); diff --git a/engine/src/RHI/OpenGL/OpenGLDevice.cpp b/engine/src/RHI/OpenGL/OpenGLDevice.cpp index 2216cc07..561310f9 100644 --- a/engine/src/RHI/OpenGL/OpenGLDevice.cpp +++ b/engine/src/RHI/OpenGL/OpenGLDevice.cpp @@ -353,7 +353,7 @@ RHICommandQueue* OpenGLDevice::CreateCommandQueue(const CommandQueueDesc& desc) return queue; } -RHIShader* OpenGLDevice::CompileShader(const ShaderCompileDesc& desc) { +RHIShader* OpenGLDevice::CreateShader(const ShaderCompileDesc& desc) { auto* shader = new OpenGLShader(); if (desc.sourceLanguage == ShaderLanguage::GLSL && !desc.source.empty()) { diff --git a/engine/src/RHI/OpenGL/OpenGLFramebuffer.cpp b/engine/src/RHI/OpenGL/OpenGLFramebuffer.cpp index d1a00cf6..318d9443 100644 --- a/engine/src/RHI/OpenGL/OpenGLFramebuffer.cpp +++ b/engine/src/RHI/OpenGL/OpenGLFramebuffer.cpp @@ -1,5 +1,6 @@ #include "XCEngine/RHI/OpenGL/OpenGLFramebuffer.h" #include "XCEngine/RHI/OpenGL/OpenGLResourceView.h" +#include "XCEngine/RHI/OpenGL/OpenGLEnums.h" #include namespace XCEngine { @@ -30,7 +31,7 @@ bool OpenGLFramebuffer::Initialize(const FramebufferDesc& desc) { for (size_t i = 0; i < desc.colorAttachments.size() && i < 16; ++i) { const auto& attachment = desc.colorAttachments[i]; - GLenum glAttachment = GL_COLOR_ATTACHMENT0 + static_cast(i); + GLenum glAttachment = ToOpenGLColorAttachment(static_cast(i)); switch (attachment.type) { case FramebufferAttachmentType::Color: @@ -47,9 +48,9 @@ bool OpenGLFramebuffer::Initialize(const FramebufferDesc& desc) { } if (desc.depthAttachment.texture != 0) { - GLenum depthAttachment = GL_DEPTH_ATTACHMENT; + GLenum depthAttachment = ToOpenGLDepthAttachment(); if (desc.stencilAttachment.texture != 0) { - depthAttachment = GL_DEPTH_STENCIL_ATTACHMENT; + depthAttachment = ToOpenGLDepthStencilAttachment(); } if (desc.depthAttachment.layer == 0 && desc.depthAttachment.mipLevel == 0) { @@ -62,12 +63,13 @@ bool OpenGLFramebuffer::Initialize(const FramebufferDesc& desc) { } if (desc.stencilAttachment.texture != 0 && desc.stencilAttachment.texture != desc.depthAttachment.texture) { + GLenum stencilAttachment = ToOpenGLStencilAttachment(); if (desc.stencilAttachment.layer == 0 && desc.stencilAttachment.mipLevel == 0) { - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, desc.stencilAttachment.texture, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, stencilAttachment, GL_TEXTURE_2D, desc.stencilAttachment.texture, 0); } else if (desc.stencilAttachment.layer > 0) { - glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, desc.stencilAttachment.texture, desc.stencilAttachment.mipLevel, desc.stencilAttachment.layer); + glFramebufferTextureLayer(GL_FRAMEBUFFER, stencilAttachment, desc.stencilAttachment.texture, desc.stencilAttachment.mipLevel, desc.stencilAttachment.layer); } else { - glFramebufferTexture(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, desc.stencilAttachment.texture, desc.stencilAttachment.mipLevel); + glFramebufferTexture(GL_FRAMEBUFFER, stencilAttachment, desc.stencilAttachment.texture, desc.stencilAttachment.mipLevel); } } @@ -115,7 +117,7 @@ bool OpenGLFramebuffer::Initialize(class RHIRenderPass* renderPass, uint32_t wid for (uint32_t i = 0; i < colorAttachmentCount && i < 16; ++i) { if (colorAttachments[i]) { OpenGLResourceView* view = static_cast(colorAttachments[i]); - GLenum glAttachment = GL_COLOR_ATTACHMENT0 + static_cast(i); + GLenum glAttachment = ToOpenGLColorAttachment(i); unsigned int texture = view->GetTexture(); if (texture) { glFramebufferTexture2D(GL_FRAMEBUFFER, glAttachment, GL_TEXTURE_2D, texture, 0); @@ -128,7 +130,7 @@ bool OpenGLFramebuffer::Initialize(class RHIRenderPass* renderPass, uint32_t wid OpenGLResourceView* view = static_cast(depthStencilAttachment); unsigned int texture = view->GetTexture(); if (texture) { - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, texture, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, ToOpenGLDepthStencilAttachment(), GL_TEXTURE_2D, texture, 0); } } @@ -190,4 +192,4 @@ void OpenGLFramebuffer::UnbindFramebuffer() { } } // namespace RHI -} // namespace XCEngine \ No newline at end of file +} // namespace XCEngine diff --git a/engine/src/RHI/OpenGL/OpenGLPipelineState.cpp b/engine/src/RHI/OpenGL/OpenGLPipelineState.cpp index 3a487b71..4204304e 100644 --- a/engine/src/RHI/OpenGL/OpenGLPipelineState.cpp +++ b/engine/src/RHI/OpenGL/OpenGLPipelineState.cpp @@ -1,5 +1,6 @@ #include "XCEngine/RHI/OpenGL/OpenGLPipelineState.h" #include "XCEngine/RHI/OpenGL/OpenGLShader.h" +#include "XCEngine/RHI/OpenGL/OpenGLEnums.h" #include namespace XCEngine { @@ -86,20 +87,20 @@ void OpenGLPipelineState::ApplyDepthStencil() { glDisable(GL_DEPTH_TEST); } glDepthMask(m_glDepthStencilState.depthWriteEnable ? GL_TRUE : GL_FALSE); - glDepthFunc(static_cast(m_glDepthStencilState.depthFunc)); + glDepthFunc(ToOpenGL(m_glDepthStencilState.depthFunc)); if (m_glDepthStencilState.stencilEnable) { glEnable(GL_STENCIL_TEST); glStencilMask(m_glDepthStencilState.stencilWriteMask); glStencilFunc( - static_cast(m_glDepthStencilState.stencilFunc), + ToOpenGL(m_glDepthStencilState.stencilFunc), m_glDepthStencilState.stencilRef, m_glDepthStencilState.stencilReadMask ); glStencilOp( - static_cast(m_glDepthStencilState.stencilFailOp), - static_cast(m_glDepthStencilState.stencilDepthFailOp), - static_cast(m_glDepthStencilState.stencilDepthPassOp) + ToOpenGL(m_glDepthStencilState.stencilFailOp), + ToOpenGL(m_glDepthStencilState.stencilDepthFailOp), + ToOpenGL(m_glDepthStencilState.stencilDepthPassOp) ); } else { glDisable(GL_STENCIL_TEST); @@ -110,14 +111,14 @@ void OpenGLPipelineState::ApplyBlend() { if (m_glBlendState.blendEnable) { glEnable(GL_BLEND); glBlendFuncSeparate( - static_cast(m_glBlendState.srcBlend), - static_cast(m_glBlendState.dstBlend), - static_cast(m_glBlendState.srcBlendAlpha), - static_cast(m_glBlendState.dstBlendAlpha) + ToOpenGL(m_glBlendState.srcBlend), + ToOpenGL(m_glBlendState.dstBlend), + ToOpenGL(m_glBlendState.srcBlendAlpha), + ToOpenGL(m_glBlendState.dstBlendAlpha) ); glBlendEquationSeparate( - static_cast(m_glBlendState.blendOp), - static_cast(m_glBlendState.blendOpAlpha) + ToOpenGL(m_glBlendState.blendOp), + ToOpenGL(m_glBlendState.blendOpAlpha) ); glColorMask( (m_glBlendState.colorWriteMask & 1) != 0, @@ -133,13 +134,13 @@ void OpenGLPipelineState::ApplyBlend() { void OpenGLPipelineState::ApplyRasterizer() { if (m_glRasterizerState.cullFaceEnable) { glEnable(GL_CULL_FACE); - glCullFace(static_cast(m_glRasterizerState.cullFace)); - glFrontFace(static_cast(m_glRasterizerState.frontFace)); + glCullFace(ToOpenGL(m_glRasterizerState.cullFace)); + glFrontFace(ToOpenGL(m_glRasterizerState.frontFace)); } else { glDisable(GL_CULL_FACE); } - glPolygonMode(GL_FRONT_AND_BACK, static_cast(m_glRasterizerState.polygonMode)); + glPolygonMode(GL_FRONT_AND_BACK, ToOpenGL(m_glRasterizerState.polygonMode)); if (m_glRasterizerState.multisampleEnable) { glEnable(GL_MULTISAMPLE); @@ -197,11 +198,7 @@ void OpenGLPipelineState::SetClearColor(float r, float g, float b, float 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); + glClear(ToOpenGLClearBuffer(buffers)); } void OpenGLPipelineState::AttachShader(unsigned int program) { @@ -229,4 +226,4 @@ const OpenGLRasterizerState& OpenGLPipelineState::GetOpenGLRasterizerState() con } } // namespace RHI -} // namespace XCEngine \ No newline at end of file +} // namespace XCEngine diff --git a/engine/src/RHI/OpenGL/OpenGLRenderTargetView.cpp b/engine/src/RHI/OpenGL/OpenGLRenderTargetView.cpp index 0b8047bd..355f6c31 100644 --- a/engine/src/RHI/OpenGL/OpenGLRenderTargetView.cpp +++ b/engine/src/RHI/OpenGL/OpenGLRenderTargetView.cpp @@ -1,21 +1,11 @@ #include "XCEngine/RHI/OpenGL/OpenGLRenderTargetView.h" +#include "XCEngine/RHI/OpenGL/OpenGLEnums.h" #include namespace XCEngine { namespace RHI { -static unsigned int ToGLRenderTargetType(RenderTargetType type) { - switch (type) { - case RenderTargetType::Texture2D: return GL_TEXTURE_2D; - case RenderTargetType::Texture2DArray: return GL_TEXTURE_2D_ARRAY; - case RenderTargetType::Texture3D: return GL_TEXTURE_3D; - case RenderTargetType::TextureCube: return GL_TEXTURE_CUBE_MAP; - case RenderTargetType::TextureCubeArray: return GL_TEXTURE_CUBE_MAP_ARRAY; - default: return GL_TEXTURE_2D; - } -} - -OpenGLRenderTargetView::OpenGLRenderTargetView() +OpenGLRenderTargetView::OpenGLRenderTargetView() : m_texture(0) , m_framebuffer(0) , m_mipLevel(0) @@ -36,7 +26,7 @@ bool OpenGLRenderTargetView::Initialize(unsigned int texture, const OpenGLRender glGenFramebuffers(1, &m_framebuffer); glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer); - unsigned int target = ToGLRenderTargetType(desc.type); + unsigned int target = ToOpenGL(desc.type); GLenum attachment = GL_COLOR_ATTACHMENT0; switch (desc.type) { diff --git a/engine/src/RHI/OpenGL/OpenGLSampler.cpp b/engine/src/RHI/OpenGL/OpenGLSampler.cpp index e41e4006..7867fe87 100644 --- a/engine/src/RHI/OpenGL/OpenGLSampler.cpp +++ b/engine/src/RHI/OpenGL/OpenGLSampler.cpp @@ -1,31 +1,10 @@ #include "XCEngine/RHI/OpenGL/OpenGLSampler.h" +#include "XCEngine/RHI/OpenGL/OpenGLEnums.h" #include namespace XCEngine { namespace RHI { -static unsigned int ToGLWrapMode(SamplerWrapMode mode) { - switch (mode) { - case SamplerWrapMode::Repeat: return GL_REPEAT; - case SamplerWrapMode::MirroredRepeat: return GL_MIRRORED_REPEAT; - case SamplerWrapMode::ClampToEdge: return GL_CLAMP_TO_EDGE; - case SamplerWrapMode::ClampToBorder: return GL_CLAMP_TO_BORDER; - default: return GL_REPEAT; - } -} - -static unsigned int ToGLFilter(SamplerFilter filter) { - switch (filter) { - case SamplerFilter::Nearest: return GL_NEAREST; - case SamplerFilter::Linear: return GL_LINEAR; - case SamplerFilter::NearestMipmapNearest: return GL_NEAREST_MIPMAP_NEAREST; - case SamplerFilter::LinearMipmapNearest: return GL_LINEAR_MIPMAP_NEAREST; - case SamplerFilter::NearestMipmapLinear: return GL_NEAREST_MIPMAP_LINEAR; - case SamplerFilter::LinearMipmapLinear: return GL_LINEAR_MIPMAP_LINEAR; - default: return GL_LINEAR; - } -} - OpenGLSampler::OpenGLSampler() : m_sampler(0) { } @@ -35,16 +14,16 @@ OpenGLSampler::~OpenGLSampler() { bool OpenGLSampler::Initialize(const OpenGLSamplerDesc& desc) { m_desc = desc; glGenSamplers(1, &m_sampler); - - glSamplerParameteri(m_sampler, GL_TEXTURE_MIN_FILTER, ToGLFilter(desc.minFilter)); - glSamplerParameteri(m_sampler, GL_TEXTURE_MAG_FILTER, ToGLFilter(desc.magFilter)); - glSamplerParameteri(m_sampler, GL_TEXTURE_WRAP_S, ToGLWrapMode(desc.wrapS)); - glSamplerParameteri(m_sampler, GL_TEXTURE_WRAP_T, ToGLWrapMode(desc.wrapT)); - glSamplerParameteri(m_sampler, GL_TEXTURE_WRAP_R, ToGLWrapMode(desc.wrapR)); + + glSamplerParameteri(m_sampler, GL_TEXTURE_MIN_FILTER, ToOpenGL(desc.minFilter)); + glSamplerParameteri(m_sampler, GL_TEXTURE_MAG_FILTER, ToOpenGL(desc.magFilter)); + glSamplerParameteri(m_sampler, GL_TEXTURE_WRAP_S, ToOpenGL(desc.wrapS)); + glSamplerParameteri(m_sampler, GL_TEXTURE_WRAP_T, ToOpenGL(desc.wrapT)); + glSamplerParameteri(m_sampler, GL_TEXTURE_WRAP_R, ToOpenGL(desc.wrapR)); glSamplerParameterf(m_sampler, GL_TEXTURE_MIN_LOD, desc.minLod); glSamplerParameterf(m_sampler, GL_TEXTURE_MAX_LOD, desc.maxLod); glSamplerParameterf(m_sampler, GL_TEXTURE_MAX_ANISOTROPY, desc.maxAnisotropy); - + return true; } diff --git a/engine/src/RHI/OpenGL/OpenGLScreenshot.cpp b/engine/src/RHI/OpenGL/OpenGLScreenshot.cpp index f77e412c..38bb77fc 100644 --- a/engine/src/RHI/OpenGL/OpenGLScreenshot.cpp +++ b/engine/src/RHI/OpenGL/OpenGLScreenshot.cpp @@ -61,5 +61,11 @@ bool OpenGLScreenshot::Capture(OpenGLDevice& device, OpenGLSwapChain& swapChain, return true; } +bool OpenGLScreenshot::Capture(RHIDevice* device, RHISwapChain* swapChain, const char* filename) { + auto* oglDevice = static_cast(device); + auto* oglSwapChain = static_cast(swapChain); + return Capture(*oglDevice, *oglSwapChain, filename); +} + } // namespace RHI } // namespace XCEngine \ No newline at end of file diff --git a/engine/src/RHI/OpenGL/OpenGLTexture.cpp b/engine/src/RHI/OpenGL/OpenGLTexture.cpp index 64183c48..875605aa 100644 --- a/engine/src/RHI/OpenGL/OpenGLTexture.cpp +++ b/engine/src/RHI/OpenGL/OpenGLTexture.cpp @@ -1,4 +1,5 @@ #include "XCEngine/RHI/OpenGL/OpenGLTexture.h" +#include "XCEngine/RHI/OpenGL/OpenGLEnums.h" #include #include #include @@ -6,47 +7,6 @@ namespace XCEngine { namespace RHI { -static unsigned int ToGLTextureTarget(OpenGLTextureType type) { - switch (type) { - case OpenGLTextureType::Texture1D: return GL_TEXTURE_1D; - case OpenGLTextureType::Texture2D: return GL_TEXTURE_2D; - case OpenGLTextureType::Texture2DArray: return GL_TEXTURE_2D_ARRAY; - case OpenGLTextureType::Texture3D: return GL_TEXTURE_3D; - case OpenGLTextureType::TextureCube: return GL_TEXTURE_CUBE_MAP; - case OpenGLTextureType::TextureCubeArray: return GL_TEXTURE_CUBE_MAP_ARRAY; - default: return GL_TEXTURE_2D; - } -} - -static void ToGLFormat(OpenGLFormat fmt, unsigned int& internalFormat, unsigned int& glFormat, unsigned int& glType) { - switch (fmt) { - case OpenGLFormat::R8: - internalFormat = GL_R8; glFormat = GL_RED; glType = GL_UNSIGNED_BYTE; - break; - case OpenGLFormat::RG8: - internalFormat = GL_RG8; glFormat = GL_RG; glType = GL_UNSIGNED_BYTE; - break; - case OpenGLFormat::RGBA8: - internalFormat = GL_RGBA8; glFormat = GL_RGBA; glType = GL_UNSIGNED_BYTE; - break; - case OpenGLFormat::RGBA16F: - internalFormat = GL_RGBA16F; glFormat = GL_RGBA; glType = GL_HALF_FLOAT; - break; - case OpenGLFormat::RGBA32F: - internalFormat = GL_RGBA32F; glFormat = GL_RGBA; glType = GL_FLOAT; - break; - case OpenGLFormat::Depth24Stencil8: - internalFormat = GL_DEPTH24_STENCIL8; glFormat = GL_DEPTH_STENCIL; glType = GL_UNSIGNED_INT_24_8; - break; - case OpenGLFormat::Depth32F: - internalFormat = GL_DEPTH_COMPONENT32F; glFormat = GL_DEPTH_COMPONENT; glType = GL_FLOAT; - break; - default: - internalFormat = GL_RGBA8; glFormat = GL_RGBA; glType = GL_UNSIGNED_BYTE; - break; - } -} - OpenGLTexture::OpenGLTexture() : m_texture(0) , m_type(OpenGLTextureType::Texture2D) @@ -68,9 +28,10 @@ bool OpenGLTexture::Initialize(OpenGLTextureType type, int width, int height, in m_depth = depth; m_mipLevels = mipLevels; - unsigned int target = ToGLTextureTarget(type); - unsigned int internalFormat, glFormat, glType; - ToGLFormat(format, internalFormat, glFormat, glType); + unsigned int target = ToOpenGL(type); + GLint internalFormat; + GLenum glFormat, glType; + ToOpenGLFormat(format, internalFormat, glFormat, glType); glGenTextures(1, &m_texture); glBindTexture(target, m_texture); @@ -136,8 +97,9 @@ bool OpenGLTexture::InitializeCubeMap(int size, int mipLevels, OpenGLFormat form m_depth = 1; m_mipLevels = mipLevels; - unsigned int internalFormat, glFormat, glType; - ToGLFormat(format, internalFormat, glFormat, glType); + GLint internalFormat; + GLenum glFormat, glType; + ToOpenGLFormat(format, internalFormat, glFormat, glType); glGenTextures(1, &m_texture); glBindTexture(GL_TEXTURE_CUBE_MAP, m_texture); @@ -178,31 +140,31 @@ void OpenGLTexture::Shutdown() { } void OpenGLTexture::Bind(int slot) const { - unsigned int target = ToGLTextureTarget(m_type); + unsigned int target = ToOpenGL(m_type); glActiveTexture(GL_TEXTURE0 + slot); glBindTexture(target, m_texture); } void OpenGLTexture::Unbind() const { - unsigned int target = ToGLTextureTarget(m_type); + unsigned int target = ToOpenGL(m_type); glBindTexture(target, 0); } void OpenGLTexture::BindImage(int slot, bool read, bool write) const { - unsigned int target = ToGLTextureTarget(m_type); + unsigned int target = ToOpenGL(m_type); GLenum access = (read && write) ? GL_READ_WRITE : (read ? GL_READ_ONLY : GL_WRITE_ONLY); glBindImageTexture(slot, m_texture, 0, GL_FALSE, 0, access, GL_RGBA8); } void OpenGLTexture::GenerateMipmap() { - unsigned int target = ToGLTextureTarget(m_type); + unsigned int target = ToOpenGL(m_type); glBindTexture(target, m_texture); glGenerateMipmap(target); glBindTexture(target, 0); } void OpenGLTexture::SetFiltering(int minFilter, int magFilter) { - unsigned int target = ToGLTextureTarget(m_type); + unsigned int target = ToOpenGL(m_type); glBindTexture(target, m_texture); glTexParameteri(target, GL_TEXTURE_MIN_FILTER, minFilter); glTexParameteri(target, GL_TEXTURE_MAG_FILTER, magFilter); @@ -210,7 +172,7 @@ void OpenGLTexture::SetFiltering(int minFilter, int magFilter) { } void OpenGLTexture::SetWrapping(int wrapS, int wrapT, int wrapR) { - unsigned int target = ToGLTextureTarget(m_type); + unsigned int target = ToOpenGL(m_type); glBindTexture(target, m_texture); glTexParameteri(target, GL_TEXTURE_WRAP_S, wrapS); glTexParameteri(target, GL_TEXTURE_WRAP_T, wrapT); diff --git a/engine/src/RHI/OpenGL/OpenGLVertexArray.cpp b/engine/src/RHI/OpenGL/OpenGLVertexArray.cpp index 00bdeb2a..c0d4e09c 100644 --- a/engine/src/RHI/OpenGL/OpenGLVertexArray.cpp +++ b/engine/src/RHI/OpenGL/OpenGLVertexArray.cpp @@ -1,28 +1,10 @@ #include "XCEngine/RHI/OpenGL/OpenGLVertexArray.h" +#include "XCEngine/RHI/OpenGL/OpenGLEnums.h" #include namespace XCEngine { namespace RHI { -static unsigned int ToGLAttributeType(VertexAttributeType type) { - switch (type) { - case VertexAttributeType::Float: return GL_FLOAT; - case VertexAttributeType::Int: return GL_INT; - case VertexAttributeType::UnsignedInt: return GL_UNSIGNED_INT; - case VertexAttributeType::Short: return GL_SHORT; - case VertexAttributeType::UnsignedShort: return GL_UNSIGNED_SHORT; - case VertexAttributeType::Byte: return GL_BYTE; - case VertexAttributeType::UnsignedByte: return GL_UNSIGNED_BYTE; - case VertexAttributeType::Double: return GL_DOUBLE; - case VertexAttributeType::HalfFloat: return GL_HALF_FLOAT; - case VertexAttributeType::Fixed: return GL_FIXED; - case VertexAttributeType::Int2101010Rev: return GL_INT_2_10_10_10_REV; - case VertexAttributeType::UnsignedInt2101010Rev: return GL_UNSIGNED_INT_2_10_10_10_REV; - case VertexAttributeType::UnsignedInt10F11F11FRev: return GL_UNSIGNED_INT_10F_11F_11F_REV; - default: return GL_FLOAT; - } -} - OpenGLVertexArray::OpenGLVertexArray() : m_vao(0) , m_indexBuffer(0) @@ -43,9 +25,9 @@ void OpenGLVertexArray::AddVertexBuffer(unsigned int buffer, const VertexAttribu glBindVertexArray(m_vao); glBindBuffer(GL_ARRAY_BUFFER, buffer); glEnableVertexAttribArray(attribute.index); - glVertexAttribPointer(attribute.index, attribute.count, - ToGLAttributeType(attribute.type), - attribute.normalized == VertexAttributeNormalized::True ? GL_TRUE : GL_FALSE, + glVertexAttribPointer(attribute.index, attribute.count, + ToOpenGL(attribute.type), + attribute.normalized == VertexAttributeNormalized::True ? GL_TRUE : GL_FALSE, attribute.stride, (void*)attribute.offset); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0);