1
0
mirror of synced 2024-12-15 17:21:16 +01:00
ImHex/lib/libimhex/include/hex/helpers/opengl.hpp

225 lines
5.8 KiB
C++
Raw Normal View History

#pragma once
#include <hex.hpp>
#include <hex/helpers/concepts.hpp>
#include <cmath>
#include <map>
#include <span>
#include <string>
#if defined(OS_WEB)
#define GLFW_INCLUDE_ES3
#include <GLES3/gl3.h>
#else
#include <imgui_impl_opengl3_loader.h>
#endif
#include <GLFW/glfw3.h>
namespace hex::gl {
2023-11-10 20:47:08 +01:00
namespace impl {
template<typename T>
GLuint getType() {
if constexpr (std::is_same_v<T, float>)
return GL_FLOAT;
else if constexpr (std::is_same_v<T, u32>)
return GL_UNSIGNED_INT;
2023-11-10 20:47:08 +01:00
else {
static_assert(hex::always_false<T>::value, "Unsupported type");
2023-11-10 20:47:08 +01:00
return 0;
}
}
}
template<typename T, size_t Size>
class Vector {
public:
Vector() = default;
Vector(std::array<T, Size> data) : m_data(data) { }
T &operator[](size_t index) { return this->m_data[index]; }
const T &operator[](size_t index) const { return this->m_data[index]; }
T *data() { return this->m_data.data(); }
const T *data() const { return this->m_data.data(); }
[[nodiscard]] size_t size() const { return this->m_data.size(); }
2023-11-10 20:47:08 +01:00
auto operator+(const Vector& other) {
auto copy = *this;
for (size_t i = 0; i < Size; i++)
copy[i] += other[i];
return copy;
}
2023-11-10 20:47:08 +01:00
auto operator-(const Vector& other) {
auto copy = *this;
for (size_t i = 0; i < Size; i++)
copy[i] -= other[i];
return copy;
}
2023-11-10 20:47:08 +01:00
auto dot(const Vector& other) {
T result = 0;
for (size_t i = 0; i < Size; i++)
result += this->m_data[i] * other[i];
return result;
}
2023-11-10 20:47:08 +01:00
auto cross(const Vector& other) {
static_assert(Size == 3, "Cross product is only defined for 3D vectors");
2023-11-10 20:47:08 +01:00
return Vector({ this->m_data[1] * other[2] - this->m_data[2] * other[1], this->m_data[2] * other[0] - this->m_data[0] * other[2], this->m_data[0] * other[1] - this->m_data[1] * other[0] });
}
auto normalize() {
auto copy = *this;
auto length = std::sqrt(copy.dot(copy));
for (size_t i = 0; i < Size; i++)
copy[i] /= length;
return copy;
}
2023-11-10 20:47:08 +01:00
auto operator==(const Vector& other) {
for (size_t i = 0; i < Size; i++)
if (this->m_data[i] != other[i])
return false;
return true;
}
private:
std::array<T, Size> m_data;
};
class Shader {
public:
Shader() = default;
Shader(std::string_view vertexSource, std::string_view fragmentSource);
~Shader();
Shader(const Shader&) = delete;
Shader(Shader&& other) noexcept;
Shader& operator=(const Shader&) = delete;
Shader& operator=(Shader&& other) noexcept;
void bind() const;
void unbind() const;
void setUniform(std::string_view name, const float &value);
void setUniform(std::string_view name, const Vector<float, 3> &value);
private:
void compile(GLuint shader, std::string_view source);
GLint getUniformLocation(std::string_view name);
private:
GLuint m_program = 0;
std::map<std::string, GLint> m_uniforms;
};
enum class BufferType {
Vertex = GL_ARRAY_BUFFER,
Index = GL_ELEMENT_ARRAY_BUFFER
};
template<typename T>
class Buffer {
public:
Buffer() = default;
Buffer(BufferType type, std::span<T> data);
~Buffer();
Buffer(const Buffer&) = delete;
Buffer(Buffer&& other) noexcept;
Buffer& operator=(const Buffer&) = delete;
Buffer& operator=(Buffer&& other) noexcept;
void bind() const;
void unbind() const;
void draw() const;
size_t getSize() const;
private:
GLuint m_buffer = 0;
size_t m_size = 0;
GLuint m_type = 0;
};
extern template class Buffer<float>;
extern template class Buffer<u32>;
class VertexArray {
public:
VertexArray();
~VertexArray();
VertexArray(const VertexArray&) = delete;
VertexArray(VertexArray&& other) noexcept;
VertexArray& operator=(const VertexArray&) = delete;
VertexArray& operator=(VertexArray&& other) noexcept;
template<typename T>
void addBuffer(u32 index, const Buffer<T> &buffer) const {
glEnableVertexAttribArray(index);
buffer.bind();
2023-11-10 20:47:08 +01:00
glVertexAttribPointer(index, 3, impl::getType<T>(), GL_FALSE, 3 * sizeof(T), nullptr);
buffer.unbind();
}
void bind() const;
void unbind() const;
private:
2023-11-10 20:47:08 +01:00
GLuint m_array = 0;
};
class Texture {
public:
Texture(u32 width, u32 height);
~Texture();
Texture(const Texture&) = delete;
Texture(Texture&& other) noexcept;
Texture& operator=(const Texture&) = delete;
Texture& operator=(Texture&& other) noexcept;
void bind() const;
void unbind() const;
GLuint getTexture() const;
u32 getWidth() const;
u32 getHeight() const;
GLuint release();
private:
GLuint m_texture;
u32 m_width, m_height;
};
class FrameBuffer {
public:
FrameBuffer();
~FrameBuffer();
FrameBuffer(const FrameBuffer&) = delete;
FrameBuffer(FrameBuffer&& other) noexcept;
FrameBuffer& operator=(const FrameBuffer&) = delete;
FrameBuffer& operator=(FrameBuffer&& other) noexcept;
void bind() const;
void unbind() const;
void attachTexture(const Texture &texture) const;
private:
GLuint m_frameBuffer, m_renderBuffer;
};
}