236 lines
5.1 KiB
C++
236 lines
5.1 KiB
C++
/*
|
|
* Copyright 2016 - 2024 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <ox/std/defines.hpp>
|
|
|
|
#include <glad/glad.h>
|
|
|
|
#include <ox/std/bounds.hpp>
|
|
#include <ox/std/cstringview.hpp>
|
|
#include <ox/std/error.hpp>
|
|
#include <ox/std/size.hpp>
|
|
#include <ox/std/string.hpp>
|
|
#include <ox/std/vec.hpp>
|
|
#include <ox/std/vector.hpp>
|
|
|
|
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<auto del, typename Base = Empty>
|
|
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<deleteBuffer>;
|
|
extern template struct GLObject<deleteFrameBuffer>;
|
|
extern template struct GLObject<deleteRenderBuffer>;
|
|
extern template struct GLObject<deleteTexture, TextureBase>;
|
|
extern template struct GLObject<deleteVertexArray>;
|
|
extern template struct GLObject<deleteProgram>;
|
|
extern template struct GLObject<deleteShader>;
|
|
|
|
using GLBuffer = GLObject<deleteBuffer>;
|
|
using GLFrameBuffer = GLObject<deleteFrameBuffer>;
|
|
using GLRenderBuffer = GLObject<deleteRenderBuffer>;
|
|
using GLShader = GLObject<deleteShader>;
|
|
using GLProgram = GLObject<deleteProgram>;
|
|
using GLTexture = GLObject<deleteTexture, TextureBase>;
|
|
using GLVertexArray = GLObject<deleteVertexArray>;
|
|
|
|
/**
|
|
* 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<float>(width),
|
|
static_cast<float>(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<glutils::ShaderVarSet> 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<GLProgram> buildShaderProgram(ProgramSource const&src) noexcept;
|
|
|
|
ox::Result<GLProgram> buildShaderProgram(
|
|
ox::CStringView const&vert,
|
|
ox::CStringView const&frag,
|
|
ox::CStringView const&geo = "") noexcept;
|
|
|
|
void setupShaderParams(
|
|
GLProgram const&shader,
|
|
ox::Vector<ShaderVarSet> const&vars,
|
|
GLsizei vertexRowLen) noexcept;
|
|
|
|
void setupShaderParams(GLProgram const&shader, ox::Vector<ShaderVarSet> 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<float> vertices;
|
|
ox::Vector<GLuint> elements;
|
|
};
|
|
|
|
void sendVbo(BufferSet const&bs) noexcept;
|
|
|
|
void sendEbo(BufferSet const&bs) noexcept;
|
|
|
|
void clearScreen() noexcept;
|
|
|
|
}
|