diff --git a/lib/external/imgui/include/imgui_impl_opengl3_loader.h b/lib/external/imgui/include/imgui_impl_opengl3_loader.h index 4a6bbdcef..7e7a58541 100644 --- a/lib/external/imgui/include/imgui_impl_opengl3_loader.h +++ b/lib/external/imgui/include/imgui_impl_opengl3_loader.h @@ -32,31 +32,7 @@ #ifndef __gl3w_h_ #define __gl3w_h_ -// Adapted from KHR/khrplatform.h to avoid including entire file. -typedef float khronos_float_t; -typedef signed char khronos_int8_t; -typedef unsigned char khronos_uint8_t; -typedef signed short int khronos_int16_t; -typedef unsigned short int khronos_uint16_t; -#ifdef _WIN64 -typedef signed long long int khronos_intptr_t; -typedef signed long long int khronos_ssize_t; -#else -typedef signed long int khronos_intptr_t; -typedef signed long int khronos_ssize_t; -#endif - -#if defined(_MSC_VER) && !defined(__clang__) -typedef signed __int64 khronos_int64_t; -typedef unsigned __int64 khronos_uint64_t; -#elif (defined(__clang__) || defined(__GNUC__)) && (__cplusplus < 201100) -#include -typedef int64_t khronos_int64_t; -typedef uint64_t khronos_uint64_t; -#else -typedef signed long long khronos_int64_t; -typedef unsigned long long khronos_uint64_t; -#endif +#include #ifndef __gl_glcorearb_h_ #define __gl_glcorearb_h_ 1 diff --git a/lib/libimhex/include/hex/helpers/opengl.hpp b/lib/libimhex/include/hex/helpers/opengl.hpp index 1083cb7c7..00588d5fc 100644 --- a/lib/libimhex/include/hex/helpers/opengl.hpp +++ b/lib/libimhex/include/hex/helpers/opengl.hpp @@ -4,6 +4,8 @@ #include +#include +#include #include #include @@ -33,11 +35,14 @@ namespace hex::gl { void bind() const; void unbind() const; + void setUniform(const std::string &name, const float &value); + private: void compile(GLuint shader, const std::string &source); private: GLuint m_program; + std::map m_uniforms; }; enum class BufferType { @@ -72,9 +77,10 @@ namespace hex::gl { ~VertexArray(); template - void addBuffer(const Buffer &buffer) const { - glVertexAttribPointer(0, buffer.getSize() / sizeof(T), getType(), GL_FALSE, 3 * sizeof(T), nullptr); - glEnableVertexAttribArray(0); + void addBuffer(u32 index, const Buffer &buffer) const { + glEnableVertexAttribArray(index); + buffer.bind(); + glVertexAttribPointer(index, 3, getType(), GL_FALSE, 3 * sizeof(T), nullptr); } void bind() const; @@ -116,5 +122,57 @@ namespace hex::gl { GLuint m_frameBuffer, m_renderBuffer; }; + template + class Vector { + public: + Vector() = default; + Vector(std::array 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(); } + + size_t size() const { return this->m_data.size(); } + + auto operator+(const Vector& other) { + auto copy = *this; + for (size_t i = 0; i < Size; i++) + copy[i] += other[i]; + return copy; + } + + auto operator-(const Vector& other) { + auto copy = *this; + for (size_t i = 0; i < Size; i++) + copy[i] -= other[i]; + return copy; + } + + 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; + } + + auto cross(const Vector& other) { + static_assert(Size == 3, "Cross product is only defined for 3D vectors"); + 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; + } + + private: + std::array m_data; + }; + } \ No newline at end of file diff --git a/lib/libimhex/source/helpers/opengl.cpp b/lib/libimhex/source/helpers/opengl.cpp index 9417455f5..2e2f24d17 100644 --- a/lib/libimhex/source/helpers/opengl.cpp +++ b/lib/libimhex/source/helpers/opengl.cpp @@ -41,6 +41,22 @@ namespace hex::gl { glUseProgram(0); } + void Shader::setUniform(const std::string &name, const float &value) { + auto uniform = this->m_uniforms.find(name); + if (uniform == this->m_uniforms.end()) { + auto location = glGetUniformLocation(this->m_program, name.c_str()); + if (location == -1) { + log::warn("Uniform '{}' not found in shader", name); + return; + } + + this->m_uniforms[name] = location; + uniform = this->m_uniforms.find(name); + } + + glUniform1f(uniform->second, value); + } + void Shader::compile(GLuint shader, const std::string &source) { auto sourcePtr = source.c_str(); @@ -86,7 +102,14 @@ namespace hex::gl { template void Buffer::draw() const { - glDrawElements(GL_TRIANGLES, this->m_size, getType(), nullptr); + switch (this->m_type) { + case GL_ARRAY_BUFFER: + glDrawArrays(GL_TRIANGLES, 0, this->m_size); + break; + case GL_ELEMENT_ARRAY_BUFFER: + glDrawElements(GL_TRIANGLES, this->m_size, getType(), nullptr); + break; + } } template class Buffer; diff --git a/plugins/builtin/source/content/pl_visualizers.cpp b/plugins/builtin/source/content/pl_visualizers.cpp index 13f4a6e5e..21aea20c7 100644 --- a/plugins/builtin/source/content/pl_visualizers.cpp +++ b/plugins/builtin/source/content/pl_visualizers.cpp @@ -122,14 +122,29 @@ namespace hex::plugin::builtin { void draw3DVisualizer(pl::ptrn::Pattern &pattern, pl::ptrn::Iteratable &, bool shouldReset, const std::vector &) { static ImGui::Texture texture; - if (shouldReset) { + if (!shouldReset) { std::vector vertices; vertices.resize(pattern.getSize() / sizeof(float)); pattern.getEvaluator()->readData(pattern.getOffset(), vertices.data(), vertices.size() * sizeof(float), pattern.getSection()); - std::vector indices; - indices.resize(vertices.size() / 3); - std::iota(indices.begin(), indices.end(), 0); + std::vector normals; + normals.resize(vertices.size()); + for (u32 i = 0; i < normals.size(); i += 9) { + auto v1 = gl::Vector({ vertices[i + 0], vertices[i + 1], vertices[i + 2] }); + auto v2 = gl::Vector({ vertices[i + 3], vertices[i + 4], vertices[i + 5] }); + auto v3 = gl::Vector({ vertices[i + 6], vertices[i + 7], vertices[i + 8] }); + + auto normal = ((v2 - v1).cross(v3 - v1)).normalize(); + normals[i + 0] = normal[0]; + normals[i + 1] = normal[1]; + normals[i + 2] = normal[2]; + normals[i + 3] = normal[0]; + normals[i + 4] = normal[1]; + normals[i + 5] = normal[2]; + normals[i + 6] = normal[0]; + normals[i + 7] = normal[1]; + normals[i + 8] = normal[2]; + } { gl::FrameBuffer frameBuffer; @@ -142,41 +157,70 @@ namespace hex::plugin::builtin { constexpr static const char *VertexShaderSource = R"glsl( #version 330 core layout (location = 0) in vec3 in_Position; + layout (location = 1) in vec3 in_Normal; + + uniform float time; + out vec3 normal; + + mat4 rotationMatrix(vec3 axis, float angle) { + axis = normalize(axis); + float s = sin(angle); + float c = cos(angle); + float oc = 1.0 - c; + + return mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0, + oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0, + oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0, + 0.0, 0.0, 0.0, 1.0); + } void main() { - gl_Position = vec4(in_Position.x, in_Position.y, in_Position.z, 1.0); + mat4 rotation = rotationMatrix(vec3(1.0, 0.0, 0.0), time / 2) * rotationMatrix(vec3(0.0, 1.0, 0.0), time / 3); + normal = (vec4(in_Normal, 1.0) * rotation).xyz; + gl_Position = vec4(in_Position * 0.5, 1.0) * rotation; } )glsl"; constexpr static const char *FragmentShaderSource = R"glsl( #version 330 core - out vec4 out_Color; + in vec3 normal; + out vec4 color; void main() { - out_Color = vec4(1.0f, 0.5f, 0.2f, 1.0f); + vec3 norm = normalize(normal); + vec3 lightDir = normalize(vec3(0, 0, -1)); + float diff = max(dot(norm, lightDir), 0.0); + vec3 diffuse = diff * vec3(1.0, 1.0, 1.0); + + color = vec4(1.0f, 0.5f, 0.2f, 1.0f) * vec4(diffuse, 1.0) + 0.1; } )glsl"; + glEnable(GL_DEPTH_TEST); + gl::Shader shader(VertexShaderSource, FragmentShaderSource); gl::VertexArray vertexArray; vertexArray.bind(); gl::Buffer vertexBuffer(gl::BufferType::Vertex, vertices); - gl::Buffer indexBuffer(gl::BufferType::Index, indices); + gl::Buffer normalBuffer(gl::BufferType::Vertex, normals); - vertexArray.addBuffer(vertexBuffer); + vertexArray.addBuffer(0, vertexBuffer); + vertexArray.addBuffer(1, normalBuffer); vertexBuffer.unbind(); vertexArray.unbind(); shader.bind(); + shader.setUniform("time", glfwGetTime()); + vertexArray.bind(); glViewport(0, 0, renderTexture.getWidth(), renderTexture.getHeight()); glClearColor(0.00F, 0.00F, 0.00F, 0.00f); - glClear(GL_COLOR_BUFFER_BIT); - indexBuffer.draw(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + vertexBuffer.draw(); vertexArray.unbind(); shader.unbind();