/* * Copyright 2016 - 2024 Gary Talent (gary@drinkingtea.net). All rights reserved. */ #pragma once #include #include #include #include #include #include #include #include #include namespace glutils { struct Empty { virtual ~Empty() noexcept = default; }; struct TextureBase { GLsizei width = 0; GLsizei height = 0; constexpr TextureBase() noexcept = default; constexpr TextureBase(TextureBase &&tb) noexcept { width = tb.width; height = tb.height; tb.width = 0; tb.height = 0; } constexpr TextureBase &operator=(TextureBase &&tb) noexcept { width = tb.width; height = tb.height; tb.width = 0; tb.height = 0; return *this; } virtual ~TextureBase() noexcept = default; }; template struct GLObject: public Base { GLuint id = 0; constexpr GLObject() noexcept = default; explicit constexpr GLObject(GLuint id) noexcept { this->id = id; } constexpr GLObject(GLObject &&o) noexcept: Base(std::move(o)) { id = o.id; o.id = 0; } ~GLObject() noexcept override { del(id); } GLObject &operator=(GLObject &&o) noexcept { if (this != &o) { del(id); Base::operator=(std::move(o)); id = o.id; o.id = 0; } return *this; } constexpr GLuint release() noexcept { auto out = id; id = 0; return out; } constexpr operator GLuint&() noexcept { return id; } constexpr operator const GLuint&() const noexcept { return id; } }; void deleteBuffer(GLuint b) noexcept; void deleteFrameBuffer(GLuint b) noexcept; void deleteRenderBuffer(GLuint b) noexcept; void deleteTexture(GLuint t) noexcept; void deleteVertexArray(GLuint v) noexcept; void deleteProgram(GLuint p) noexcept; void deleteShader(GLuint s) noexcept; extern template struct GLObject; extern template struct GLObject; extern template struct GLObject; extern template struct GLObject; extern template struct GLObject; extern template struct GLObject; extern template struct GLObject; using GLBuffer = GLObject; using GLFrameBuffer = GLObject; using GLRenderBuffer = GLObject; using GLShader = GLObject; using GLProgram = GLObject; using GLTexture = GLObject; using GLVertexArray = GLObject; /** * FrameBuffer holds everything needed for a usable frame buffer to exist. * It differs from GLFrameBuffer in that GLFrameBuffer only manages the FBO * and not its dependencies. */ struct FrameBuffer { int width = 0; int height = 0; GLFrameBuffer fbo; GLTexture color; GLRenderBuffer depth; constexpr operator GLuint&() noexcept { return fbo.id; } constexpr operator const GLuint&() const noexcept { return fbo.id; } [[nodiscard]] constexpr ox::Vec2 sizef() const noexcept { return { static_cast(width), static_cast(height), }; } [[nodiscard]] constexpr ox::Size size() const noexcept { return { width, height, }; } }; class FrameBufferBind { private: static const FrameBuffer *s_activeFb; const FrameBuffer *m_restoreFb = nullptr; public: explicit FrameBufferBind(const FrameBuffer &fb) noexcept; ~FrameBufferBind() noexcept; }; void bind(const FrameBuffer &fb) noexcept; struct ShaderVarSet { GLsizei len{}; ox::String name; }; struct ProgramSource { ox::Vector const shaderParams; GLsizei const rowLen = [this] { GLsizei len{}; for (auto const&v : shaderParams) { len += v.len; } return len; }(); GLsizei const vboLen = rowLen * 4; ox::String const vertShader{}; ox::String const fragShader{}; ox::String const geomShader{}; }; ox::Result buildShaderProgram(ProgramSource const&src) noexcept; ox::Result buildShaderProgram( ox::CStringView const&vert, ox::CStringView const&frag, ox::CStringView const&geo = "") noexcept; void setupShaderParams( GLProgram const&shader, ox::Vector const&vars, GLsizei vertexRowLen) noexcept; void setupShaderParams(GLProgram const&shader, ox::Vector const&vars) noexcept; glutils::GLVertexArray generateVertexArrayObject() noexcept; glutils::GLBuffer generateBuffer() noexcept; [[nodiscard]] FrameBuffer generateFrameBuffer(int width, int height) noexcept; void resizeFrameBuffer(FrameBuffer &fb, int width, int height) noexcept; /** * Resizes a FrameBuffer, and creates if it does not already exist. */ void resizeInitFrameBuffer(FrameBuffer &fb, int width, int height) noexcept; void resizeInitFrameBuffer(FrameBuffer &fb, ox::Size const&sz) noexcept; struct BufferSet { glutils::GLVertexArray vao; glutils::GLBuffer vbo; glutils::GLBuffer ebo; glutils::GLTexture tex; ox::Vector vertices; ox::Vector elements; }; void sendVbo(BufferSet const&bs) noexcept; void sendEbo(BufferSet const&bs) noexcept; void clearScreen() noexcept; }