feat: Added basic lighting and rotations to 3d visualizer model
This commit is contained in:
parent
8e759d9b5f
commit
d4967018c2
@ -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 <stdint.h>
|
||||
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 <KHR/khrplatform.h>
|
||||
|
||||
#ifndef __gl_glcorearb_h_
|
||||
#define __gl_glcorearb_h_ 1
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
#include <hex/helpers/concepts.hpp>
|
||||
|
||||
#include <cmath>
|
||||
#include <map>
|
||||
#include <span>
|
||||
#include <string>
|
||||
|
||||
@ -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<std::string, GLint> m_uniforms;
|
||||
};
|
||||
|
||||
enum class BufferType {
|
||||
@ -72,9 +77,10 @@ namespace hex::gl {
|
||||
~VertexArray();
|
||||
|
||||
template<typename T>
|
||||
void addBuffer(const Buffer<T> &buffer) const {
|
||||
glVertexAttribPointer(0, buffer.getSize() / sizeof(T), getType<T>(), GL_FALSE, 3 * sizeof(T), nullptr);
|
||||
glEnableVertexAttribArray(0);
|
||||
void addBuffer(u32 index, const Buffer<T> &buffer) const {
|
||||
glEnableVertexAttribArray(index);
|
||||
buffer.bind();
|
||||
glVertexAttribPointer(index, 3, getType<T>(), GL_FALSE, 3 * sizeof(T), nullptr);
|
||||
}
|
||||
|
||||
void bind() const;
|
||||
@ -116,5 +122,57 @@ namespace hex::gl {
|
||||
GLuint m_frameBuffer, m_renderBuffer;
|
||||
};
|
||||
|
||||
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(); }
|
||||
|
||||
size_t size() const { return this->m_data.size(); }
|
||||
|
||||
auto operator+(const Vector<T, Size>& other) {
|
||||
auto copy = *this;
|
||||
for (size_t i = 0; i < Size; i++)
|
||||
copy[i] += other[i];
|
||||
return copy;
|
||||
}
|
||||
|
||||
auto operator-(const Vector<T, Size>& other) {
|
||||
auto copy = *this;
|
||||
for (size_t i = 0; i < Size; i++)
|
||||
copy[i] -= other[i];
|
||||
return copy;
|
||||
}
|
||||
|
||||
auto dot(const Vector<T, Size>& 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<T, Size>& other) {
|
||||
static_assert(Size == 3, "Cross product is only defined for 3D vectors");
|
||||
return Vector<T, Size>({ 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<T, Size> m_data;
|
||||
};
|
||||
|
||||
|
||||
}
|
@ -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<typename T>
|
||||
void Buffer<T>::draw() const {
|
||||
glDrawElements(GL_TRIANGLES, this->m_size, getType<T>(), 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<T>(), nullptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template class Buffer<float>;
|
||||
|
@ -122,14 +122,29 @@ namespace hex::plugin::builtin {
|
||||
void draw3DVisualizer(pl::ptrn::Pattern &pattern, pl::ptrn::Iteratable &, bool shouldReset, const std::vector<pl::core::Token::Literal> &) {
|
||||
static ImGui::Texture texture;
|
||||
|
||||
if (shouldReset) {
|
||||
if (!shouldReset) {
|
||||
std::vector<float> vertices;
|
||||
vertices.resize(pattern.getSize() / sizeof(float));
|
||||
pattern.getEvaluator()->readData(pattern.getOffset(), vertices.data(), vertices.size() * sizeof(float), pattern.getSection());
|
||||
|
||||
std::vector<u32> indices;
|
||||
indices.resize(vertices.size() / 3);
|
||||
std::iota(indices.begin(), indices.end(), 0);
|
||||
std::vector<float> normals;
|
||||
normals.resize(vertices.size());
|
||||
for (u32 i = 0; i < normals.size(); i += 9) {
|
||||
auto v1 = gl::Vector<float, 3>({ vertices[i + 0], vertices[i + 1], vertices[i + 2] });
|
||||
auto v2 = gl::Vector<float, 3>({ vertices[i + 3], vertices[i + 4], vertices[i + 5] });
|
||||
auto v3 = gl::Vector<float, 3>({ 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<float> vertexBuffer(gl::BufferType::Vertex, vertices);
|
||||
gl::Buffer<u32> indexBuffer(gl::BufferType::Index, indices);
|
||||
gl::Buffer<float> 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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user