/* * 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 GLuint const&() 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 GLuint const&() 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 FrameBuffer const *s_activeFb; FrameBuffer const *m_restoreFb = nullptr; public: explicit FrameBufferBind(FrameBuffer const &fb) noexcept; ~FrameBufferBind() noexcept; }; void bind(FrameBuffer const &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; GLVertexArray generateVertexArrayObject() noexcept; 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 { GLVertexArray vao; GLBuffer vbo; GLBuffer ebo; GLTexture tex; ox::Vector vertices; ox::Vector elements; }; void sendVbo(BufferSet const &bs) noexcept; void sendEbo(BufferSet const &bs) noexcept; void clearScreen() noexcept; }