diff --git a/.gitmodules b/.gitmodules new file mode 100755 index 0000000..eeed3b5 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "libraries/include/stb"] + path = libraries/include/stb + url = https://github.com/nothings/stb +[submodule "libraries/include/glm"] + path = libraries/include/glm + url = https://github.com/g-truc/glm diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..c882834 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +z3d \ No newline at end of file diff --git a/.idea/editor.xml b/.idea/editor.xml new file mode 100644 index 0000000..00465ab --- /dev/null +++ b/.idea/editor.xml @@ -0,0 +1,103 @@ + + + + + \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..374fd27 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,91 @@ +{ + "files.associations": { + "*.ipp": "cpp", + "*.tcc": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "csignal": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "any": "cpp", + "array": "cpp", + "atomic": "cpp", + "strstream": "cpp", + "bit": "cpp", + "bitset": "cpp", + "cfenv": "cpp", + "charconv": "cpp", + "chrono": "cpp", + "cinttypes": "cpp", + "codecvt": "cpp", + "compare": "cpp", + "complex": "cpp", + "concepts": "cpp", + "condition_variable": "cpp", + "coroutine": "cpp", + "cstdint": "cpp", + "deque": "cpp", + "forward_list": "cpp", + "list": "cpp", + "map": "cpp", + "set": "cpp", + "string": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", + "regex": "cpp", + "source_location": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "hash_map": "cpp", + "hash_set": "cpp", + "format": "cpp", + "fstream": "cpp", + "future": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "mutex": "cpp", + "new": "cpp", + "numbers": "cpp", + "ostream": "cpp", + "ranges": "cpp", + "semaphore": "cpp", + "shared_mutex": "cpp", + "span": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "stdfloat": "cpp", + "stop_token": "cpp", + "streambuf": "cpp", + "text_encoding": "cpp", + "thread": "cpp", + "typeindex": "cpp", + "typeinfo": "cpp", + "valarray": "cpp", + "variant": "cpp" + } +} diff --git a/data/images/logo.png b/data/images/logo.png new file mode 100644 index 0000000..c3f292d Binary files /dev/null and b/data/images/logo.png differ diff --git a/data/images/spinner.png b/data/images/spinner.png new file mode 100644 index 0000000..c58b5f0 Binary files /dev/null and b/data/images/spinner.png differ diff --git a/include/assets/data_loaders/generic/generic_3dtk_loader.hpp b/include/assets/data_loaders/generic/generic_3dtk_loader.hpp new file mode 100644 index 0000000..9b457d1 --- /dev/null +++ b/include/assets/data_loaders/generic/generic_3dtk_loader.hpp @@ -0,0 +1,58 @@ +#pragma once + +#include +#include +#include + +#include "glm/mat4x4.hpp" +#include "util/result.hpp" +#include "util/string_list.hpp" +#include "assets/prefetch_queue.hpp" + +#include "assets/dynamic_read_buffers/dynamic_point_cloud_buffer.hpp" +#include "assets/dynamic_data_stores/dynamic_point_cloud_store.hpp" +#include "assets/prefetch_lookup.hpp" + + + +template +struct generic_3dtk_loader +{ + [[nodiscard]] static std::error_code prefetch( + const ztu::string_list& filenames, + prefetch_queue& queue + ); + + [[nodiscard]] static std::error_code load( + dynamic_point_cloud_buffer& buffer, + const file_dir_list& paths, + prefetch_lookup& asset_lookup, + dynamic_point_cloud_store& store, + bool pedantic = false + ); + +protected: + + [[nodiscard]] static ztu::result parse_index( + std::string_view filename + ); + + ztu::result> analyze_component_format( + std::string_view line + ); + + void transform_point_cloud( + std::span points, + const glm::mat4& pose + ); + +private: + std::error_code read_point_file( + const std::filesystem::path& filename, + dynamic_point_cloud_buffer& point_cloud + ); +}; + +#define INCLUDE_GENERIC_3DTK_LOADER_IMPLEMENTATION +#include "assets/data_loaders/generic/generic_3dtk_loader.ipp" +#undef INCLUDE_GENERIC_3DTK_LOADER_IMPLEMENTATION diff --git a/include/geometry/aabb.hpp b/include/geometry/aabb.hpp new file mode 100755 index 0000000..de3ee64 --- /dev/null +++ b/include/geometry/aabb.hpp @@ -0,0 +1,91 @@ +#pragma once + +#include "glm/glm.hpp" + +#include +#include +#include +#include + +struct aabb +{ + using vector_type = glm::vec3; + using scalar_type = vector_type::value_type; + using index_type = vector_type::length_type; + + static constexpr auto default_min = std::numeric_limits::max(); + static constexpr auto default_max =-std::numeric_limits::max(); + + vector_type min { default_min, default_min, default_min }; + vector_type max { default_max, default_max, default_max }; + + [[nodiscard]] vector_type size() const + { + return max - min; + } + + [[nodiscard]] vector_type center() const + { + return min + 0.5f * size(); + } + + [[nodiscard]] vector_type closest_point_inside(const vector_type& point) const { + return { + std::clamp(point.x, min.x, max.x), + std::clamp(point.y, min.y, max.y), + std::clamp(point.z, min.z, max.z) + }; + } + + aabb& add_aabb(const aabb& other) + { + for (index_type i{}; i != min.length(); ++i) + { + min[i] = std::min(min[i], other.min[i]); + max[i] = std::max(max[i], other.max[i]); + } + return *this; + } + + aabb& add_point(const auto& point) + { + for (index_type i{}; i != min.length(); ++i) + { + min[i] = std::min(min[i], point[i]); + max[i] = std::max(max[i], point[i]); + } + return *this; + } + + template + aabb& add_points(std::span points) + { + for (const auto& point : points) + { + add_point(point); + } + return *this; + } + + aabb& join(const aabb& other) + { + min = glm::min(min, other.min); + max = glm::max(max, other.max); + return *this; + } + + [[nodiscard]] aabb transformed(const glm::mat4x4& matrix) const + { + const auto vertices = std::array{ + vector_type{ matrix * glm::vec4{ min.x, min.y, min.z, 1 } }, + vector_type{ matrix * glm::vec4{ min.x, min.y, max.z, 1 } }, + vector_type{ matrix * glm::vec4{ min.x, max.y, min.z, 1 } }, + vector_type{ matrix * glm::vec4{ min.x, max.y, max.z, 1 } }, + vector_type{ matrix * glm::vec4{ max.x, min.y, min.z, 1 } }, + vector_type{ matrix * glm::vec4{ max.x, min.y, max.z, 1 } }, + vector_type{ matrix * glm::vec4{ max.x, max.y, min.z, 1 } }, + vector_type{ matrix * glm::vec4{ max.x, max.y, max.z, 1 } } + }; + return aabb{}.add_points(vertices); + } +}; diff --git a/include/geometry/normal_estimation.hpp b/include/geometry/normal_estimation.hpp new file mode 100644 index 0000000..4d8bbb0 --- /dev/null +++ b/include/geometry/normal_estimation.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include +#include +#include + +#include "util/uix.hpp" +#include "assets/components/mesh_vertex_components.hpp" + +void estimate_normals( + std::span vertices, + std::span> triangles, + std::vector& normals +); \ No newline at end of file diff --git a/include/opengl/data/shader_program_data.hpp b/include/opengl/data/shader_program_data.hpp new file mode 100755 index 0000000..e94f79d --- /dev/null +++ b/include/opengl/data/shader_program_data.hpp @@ -0,0 +1,45 @@ +#pragma once + + +#include "GL/glew.h" +#include + +#include "opengl/handles/shader_handle.hpp" +#include "opengl/handles/shader_program_handle.hpp" + +namespace zgl +{ +class shader_program_data +{ +private: + explicit shader_program_data(GLuint program_id); + +public: + + shader_program_data() = default; + + [[nodiscard]] static std::error_code build_from( + const shader_handle& vertex_shader, + const shader_handle& geometry_shader, + const shader_handle& fragment_shader, + shader_program_data& data + ); + + shader_program_data(const shader_program_data& other) = delete; + shader_program_data& operator=(const shader_program_data& other) = delete; + + shader_program_data(shader_program_data&& other) noexcept ; + shader_program_data& operator=(shader_program_data&& other) noexcept; + + [[nodiscard]] shader_program_handle handle() const; + + ~shader_program_data(); + +private: + shader_program_handle m_handle{}; +}; +} + +#define INCLUDE_SHADER_PROGRAM_DATA_IMPLEMENTATION +#include "opengl/data/shader_program_data.ipp" +#undef INCLUDE_SHADER_PROGRAM_DATA_IMPLEMENTATION diff --git a/include/opengl/error.hpp b/include/opengl/error.hpp new file mode 100644 index 0000000..8b2b620 --- /dev/null +++ b/include/opengl/error.hpp @@ -0,0 +1,74 @@ +#pragma once + +#include +#include "GL/glew.h" + +namespace zgl +{ +namespace error +{ + +enum class codes : GLenum { + ok = GL_NO_ERROR, + invalid_enum = GL_INVALID_ENUM, + invalid_value = GL_INVALID_VALUE, + invalid_operation = GL_INVALID_OPERATION, + invalid_framebuffer_operation = GL_INVALID_FRAMEBUFFER_OPERATION, + out_of_memory = GL_OUT_OF_MEMORY, + stack_overflow = GL_STACK_OVERFLOW, + stack_underflow = GL_STACK_UNDERFLOW, + context_lost = GL_CONTEXT_LOST +}; + +struct category : std::error_category +{ + [[nodiscard]] const char* name() const noexcept override + { + return "opengl"; + } + + [[nodiscard]] std::string message(int ev) const override + { + switch (static_cast(ev)) { + using enum codes; + case ok: + return "No error has been recorded."; + case invalid_enum: + return "An unacceptable value is specified for an enumerated argument."; + case invalid_value: + return "A numeric argument is out of range."; + case invalid_operation: + return "The specified operation is not allowed in the current state."; + case invalid_framebuffer_operation: + return "The framebuffer object is not complete."; + case out_of_memory: + return "There is not enough memory left to execute the command."; + case stack_overflow: + return "An attempt has been made to perform an operation that would cause an internal stack to underflow."; + case stack_underflow: + return "An attempt has been made to perform an operation that would cause an internal stack to overflow."; + case context_lost: + return "The OpenGL context has been lost."; + default: + return ""; + } + } +}; + +} // namespace error + +[[nodiscard]] inline std::error_category& error_category() noexcept +{ + static error::category category; + return category; +} + +[[nodiscard]] inline std::error_code make_error_code(const GLenum e) noexcept +{ + return { static_cast(e), error_category() }; +} + +} // namespace zgl + +template<> +struct std::is_error_code_enum : std::true_type {}; diff --git a/include/opengl/handles/alpha_handle.hpp b/include/opengl/handles/alpha_handle.hpp new file mode 100644 index 0000000..0a49f9e --- /dev/null +++ b/include/opengl/handles/alpha_handle.hpp @@ -0,0 +1,8 @@ +#pragma once + +namespace zgl +{ + +using alpha_handle = float; + +} // namespace zgl diff --git a/include/opengl/handles/material_handle.hpp b/include/opengl/handles/material_handle.hpp new file mode 100644 index 0000000..ce420df --- /dev/null +++ b/include/opengl/handles/material_handle.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include +#include "opengl/handles/texture_handle.hpp" +#include "opengl/handles/surface_properties_handle.hpp" +#include "opengl/handles/alpha_handle.hpp" + +namespace zgl +{ +struct material_handle +{ + std::optional texture{ std::nullopt }; + std::optional surface_properties{ std::nullopt }; + std::optional alpha{ std::nullopt }; +}; +} diff --git a/include/opengl/handles/matrix_handles.hpp b/include/opengl/handles/matrix_handles.hpp new file mode 100644 index 0000000..ba646fb --- /dev/null +++ b/include/opengl/handles/matrix_handles.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "glm/glm.hpp" + +namespace zgl +{ +using model_matrix_handle = glm::mat4x4; + +using view_matrix_handle = glm::mat4x4; + +using projection_matrix_handle = glm::mat4x4; +} \ No newline at end of file diff --git a/include/opengl/handles/mesh_handle.hpp b/include/opengl/handles/mesh_handle.hpp new file mode 100755 index 0000000..8f5088c --- /dev/null +++ b/include/opengl/handles/mesh_handle.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "GL/glew.h" +#include "util/uix.hpp" + +namespace zgl +{ +struct mesh_handle +{ + inline void bind() const; + inline static void unbind(); + + GLuint vao_id{ 0 }; + GLsizei index_count{ 0 }; +}; +} + +#define INCLUDE_MESH_INSTANCE_IMPLEMENTATION +#include "opengl/handles/mesh_handle.ipp" +#undef INCLUDE_MESH_INSTANCE_IMPLEMENTATION \ No newline at end of file diff --git a/include/opengl/handles/point_cloud_handle.hpp b/include/opengl/handles/point_cloud_handle.hpp new file mode 100755 index 0000000..49dd4af --- /dev/null +++ b/include/opengl/handles/point_cloud_handle.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "GL/glew.h" +#include "util/uix.hpp" + +namespace zgl +{ +struct point_cloud_handle +{ + inline void bind() const; + inline static void unbind(); + + GLuint vao_id{ 0 }; + GLsizei point_count{ 0 }; +}; +} + +#define INCLUDE_POINT_CLOUD_INSTANCE_IMPLEMENTATION +#include "opengl/handles/point_cloud_handle.ipp" +#undef INCLUDE_POINT_CLOUD_INSTANCE_IMPLEMENTATION \ No newline at end of file diff --git a/include/opengl/handles/shader_program_handle.hpp b/include/opengl/handles/shader_program_handle.hpp new file mode 100644 index 0000000..59fa5fc --- /dev/null +++ b/include/opengl/handles/shader_program_handle.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include "GL/glew.h" +#include "opengl/shader_program_variable.hpp" + +#include "opengl/shader_program_variable.hpp" +#include "util/uix.hpp" +#include + +namespace zgl +{ +struct shader_program_handle +{ + using attribute_support_type = ztu::u32; + using uniform_support_type = ztu::u32; + + inline void bind() const; + static void unbind(); + + template + void set_uniform(const T& value) const; + + [[nodiscard]] attribute_support_type check_attribute_support(std::span attributes) const; + + [[nodiscard]] uniform_support_type check_uniform_support(std::span uniforms) const; + + GLuint program_id{ 0 }; +}; +} + +#define INCLUDE_GL_SHADER_PROGRAM_INSTANCE_IMPLEMENTATION +#include "opengl/handles/shader_program_handle.ipp" +#undef INCLUDE_GL_SHADER_PROGRAM_INSTANCE_IMPLEMENTATION diff --git a/include/opengl/handles/surface_properties_handle.hpp b/include/opengl/handles/surface_properties_handle.hpp new file mode 100644 index 0000000..8780217 --- /dev/null +++ b/include/opengl/handles/surface_properties_handle.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "glm/glm.hpp" + +namespace zgl +{ +struct surface_properties_handle +{ + glm::mat3 filters{ + 0.1986f, 0.0000f, 0.0000f, + 0.5922f, 0.0166f, 0.0000f, + 0.5974f, 0.2084f, 0.2084f + }; + float shininess{ 100.2237f }; +}; +} diff --git a/include/opengl/handles/texture_handle.hpp b/include/opengl/handles/texture_handle.hpp new file mode 100644 index 0000000..084efc2 --- /dev/null +++ b/include/opengl/handles/texture_handle.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include "GL/glew.h" + +namespace zgl { +struct texture_handle +{ + inline void bind() const; + inline static void unbind(); + + GLuint texture_id{ 0 }; +}; +} + +#define INCLUDE_TEXTURE_INSTANCE_IMPLEMENTATION +#include "opengl/handles/texture_handle.ipp" +#undef INCLUDE_TEXTURE_INSTANCE_IMPLEMENTATION diff --git a/include/opengl/shader_program_variable.hpp b/include/opengl/shader_program_variable.hpp new file mode 100644 index 0000000..63def71 --- /dev/null +++ b/include/opengl/shader_program_variable.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "GL/glew.h" + +namespace zgl +{ +struct shader_program_variable +{ + struct info_type + { + GLenum type; + GLint location; + } info; + const char* name; +}; +} diff --git a/include/opengl/type_utils.hpp b/include/opengl/type_utils.hpp new file mode 100755 index 0000000..9956830 --- /dev/null +++ b/include/opengl/type_utils.hpp @@ -0,0 +1,71 @@ +#pragma once + +#include +#include "GL/glew.h" +#include "util/uix.hpp" + +namespace zgl::type_utils +{ +constexpr bool is_valid_type(GLenum type) { + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_FLOAT: + case GL_DOUBLE: + return true; + default: + return false; + } +} + +template +consteval GLenum to_gl_type() { + if constexpr (std::same_as) { + return GL_BYTE; + } else if constexpr (std::same_as) { + return GL_UNSIGNED_BYTE; + } else if constexpr (std::same_as) { + return GL_SHORT; + } else if constexpr (std::same_as) { + return GL_UNSIGNED_SHORT; + } else if constexpr (std::same_as) { + return GL_INT; + } else if constexpr (std::same_as) { + return GL_UNSIGNED_INT; + } else if constexpr (std::same_as) { + return GL_FLOAT; + } else if constexpr (std::same_as) { + return GL_DOUBLE; + } else { + T::___unknown_type; + return GL_INVALID_ENUM; + } +} + +constexpr GLsizei size_of(GLenum type) { + switch (type) { + case GL_BYTE: + return sizeof(ztu::i8); + case GL_UNSIGNED_BYTE: + return sizeof(ztu::u8); + case GL_SHORT: + return sizeof(ztu::i16); + case GL_UNSIGNED_SHORT: + return sizeof(ztu::u16); + case GL_INT: + return sizeof(ztu::i32); + case GL_UNSIGNED_INT: + return sizeof(ztu::u32); + case GL_FLOAT: + return sizeof(float); + case GL_DOUBLE: + return sizeof(double); + default: + return 0; + } +} +} // namespace zgl::type_utils diff --git a/include/scene/camera_view.hpp b/include/scene/camera_view.hpp new file mode 100644 index 0000000..c31b5ab --- /dev/null +++ b/include/scene/camera_view.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include "glm/glm.hpp" +#include "glm/gtc/matrix_transform.hpp" +#include + +struct camera_view +{ + glm::vec3 position; + glm::vec3 front; + glm::vec3 right; + glm::vec3 up; + float aspect_ratio; + float fov; + + [[nodiscard]] glm::mat4 create_view_matrix() const { + return glm::lookAt(position, position + front, up); + } + + [[nodiscard]] glm::mat4 create_projection_matrix() const { + return glm::perspective( + fov, + aspect_ratio, + 0.1f, 1000.0f + ); + } +}; diff --git a/libraries/include/glm b/libraries/include/glm new file mode 160000 index 0000000..33b4a62 --- /dev/null +++ b/libraries/include/glm @@ -0,0 +1 @@ +Subproject commit 33b4a621a697a305bc3a7610d290677b96beb181 diff --git a/shaders/mesh/fragment_face.glsl b/shaders/mesh/fragment_face.glsl new file mode 100644 index 0000000..4d7fedc --- /dev/null +++ b/shaders/mesh/fragment_face.glsl @@ -0,0 +1,64 @@ +#ifdef TEXTURE +#ifdef U_COLOR +#error Texture and color attribute are mutually exclusive. +#endif +#endif + +out vec4 pixel_color; + +#ifdef TEXTURE +layout (location = 3) uniform sampler2D tex; +layout (location = 2) in vec2 frag_tex_coord; +#endif + +#ifdef U_COLOR +layout (location = 3) uniform vec4 color; +#endif + +#ifdef LIGHTING +layout (location = 4) uniform vec3 view_pos; +layout (location = 5) uniform vec3 point_light_direction; +layout (location = 6) uniform vec3 point_light_color; +layout (location = 7) uniform vec3 ambient_light_color; +layout (location = 8) uniform vec3 ambient_filter; +layout (location = 9) uniform vec3 diffuse_filter; +layout (location = 10) uniform vec3 specular_filter; +layout (location = 11) uniform float shininess; +layout (location = 0) in vec3 frag_position; +layout (location = 1) in vec3 frag_normal; +#endif + +#ifdef U_ALPHA +layout (location = 12) uniform float alpha; +#endif + +void main() { + + pixel_color = vec4(1); + +#ifdef TEXTURE + pixel_color *= texture(tex, frag_tex_coord); +#endif + +#ifdef U_COLOR + pixel_color *= color; +#endif + +#ifdef U_ALPHA + pixel_color.w *= alpha; +#endif + +#ifdef LIGHTING + vec3 ambient = pixel_color.rgb * ambient_filter * ambient_light_color; + + float point_light_alignment = max(dot(frag_normal, point_light_direction), 0.0); + vec3 diffuse = pixel_color.rgb * diffuse_filter * point_light_color * point_light_alignment; + + vec3 reflection_dir = reflect(-point_light_direction, frag_normal); + vec3 view_dir = normalize(frag_position - view_pos); + float specular_strength = pow(max(dot(view_dir, reflection_dir), 0.0), shininess); + vec3 specular = specular_filter * point_light_color * specular_strength; + + pixel_color.rgb *= ambient + diffuse + specular; +#endif +} diff --git a/shaders/mesh/fragment_point.glsl b/shaders/mesh/fragment_point.glsl new file mode 100644 index 0000000..fc4fbfd --- /dev/null +++ b/shaders/mesh/fragment_point.glsl @@ -0,0 +1,7 @@ +layout (location = 0) in vec4 frag_color; + +out vec4 pixel_color; + +void main() { + pixel_color = frag_color; +} diff --git a/shaders/mesh/vertex_face.glsl b/shaders/mesh/vertex_face.glsl new file mode 100644 index 0000000..cbae90f --- /dev/null +++ b/shaders/mesh/vertex_face.glsl @@ -0,0 +1,27 @@ +layout (location = 0) uniform mat4 mvp_matrix; +layout (location = 0) in vec3 vertex_position; + +#ifdef LIGHTING +layout (location = 1) uniform mat4 model_matrix; +layout (location = 1) in vec3 vertex_normal; +layout (location = 0) out vec3 frag_position; +layout (location = 1) out vec3 frag_normal; +#endif + +#ifdef TEXTURE +layout (location = 2) in vec2 vertex_tex_coord; +layout (location = 2) out vec2 frag_tex_coord; +#endif + +void main() { + gl_Position = mvp_matrix * vec4(vertex_position, 1.0); + +#ifdef LIGHTING + frag_position = (model_matrix * vec4(vertex_position, 1.0)).xyz; + frag_normal = normalize(mat3(model_matrix) * vertex_normal); +#endif + +#ifdef TEXTURE + frag_tex_coord = vertex_tex_coord; +#endif +} diff --git a/shaders/mesh/vertex_point.glsl b/shaders/mesh/vertex_point.glsl new file mode 100644 index 0000000..ce9a662 --- /dev/null +++ b/shaders/mesh/vertex_point.glsl @@ -0,0 +1,59 @@ +layout (location = 0) uniform mat4 mvp_matrix; +layout (location = 2) uniform float point_size; +layout (location = 0) in vec3 vertex_position; +layout (location = 0) out vec4 frag_color; + +#ifdef TEXTURE +layout (location = 3) uniform sampler2D tex; +layout (location = 2) in vec2 vertex_tex_coord; +#endif + +#ifdef LIGHTING +layout (location = 1) uniform mat4 model_matrix; +layout (location = 4) uniform vec3 view_pos; +layout (location = 5) uniform vec3 point_light_direction; +layout (location = 6) uniform vec3 point_light_color; +layout (location = 7) uniform vec3 ambient_light_color; +layout (location = 8) uniform vec3 ambient_filter; +layout (location = 9) uniform vec3 diffuse_filter; +layout (location = 10) uniform vec3 specular_filter; +layout (location = 11) uniform float shininess; +layout (location = 1) in vec3 vertex_normal; +#endif + +#ifdef U_ALPHA +layout (location = 12) uniform float alpha; +#endif + +void main() { + + gl_Position = mvp_matrix * vec4(vertex_position, 1.0); + gl_PointSize = point_size / gl_Position.w; + + frag_color = vec4(1); + +#ifdef TEXTURE + frag_color *= texture(tex, vertex_tex_coord); +#endif + +#ifdef U_ALPHA + frag_color.w *= alpha; +#endif + +#ifdef LIGHTING + vec3 position = (model_matrix * vec4(vertex_position, 1.0)).xyz; + vec3 normal = normalize(mat3(model_matrix) * vertex_normal); + + vec3 ambient = frag_color.rgb * ambient_filter * ambient_light_color; + + float point_light_alignment = max(dot(normal, point_light_direction), 0.0); + vec3 diffuse = frag_color.rgb * diffuse_filter * point_light_color * point_light_alignment; + + vec3 reflection_dir = reflect(-point_light_direction, normal); + vec3 view_dir = normalize(position - view_pos); + float specular_strength = pow(max(dot(view_dir, reflection_dir), 0.0), shininess); + vec3 specular = specular_filter * point_light_color * specular_strength; + + frag_color.rgb *= ambient + diffuse + specular; +#endif +} diff --git a/shaders/point_cloud/fragment.glsl b/shaders/point_cloud/fragment.glsl new file mode 100644 index 0000000..fc4fbfd --- /dev/null +++ b/shaders/point_cloud/fragment.glsl @@ -0,0 +1,7 @@ +layout (location = 0) in vec4 frag_color; + +out vec4 pixel_color; + +void main() { + pixel_color = frag_color; +} diff --git a/shaders/point_cloud/vertex.glsl b/shaders/point_cloud/vertex.glsl new file mode 100644 index 0000000..7edaeb7 --- /dev/null +++ b/shaders/point_cloud/vertex.glsl @@ -0,0 +1,51 @@ +layout (location = 0) in vec3 vertex_position; +layout (location = 0) uniform mat4 mvp_matrix; +layout (location = 2) uniform float point_size; +layout (location = 0) out vec4 frag_color; + +#ifdef LIGHTING +layout (location = 4) uniform mat4 model_matrix; +layout (location = 5) uniform vec3 camera_position; +layout (location = 1) in vec3 vertex_normal; +#endif + +#ifdef RAINBOW +layout (location = 6) uniform float rainbow_offset_y; +layout (location = 7) uniform float rainbow_scale_y; + +// taken from 'https://github.com/hughsk/glsl-hsv2rgb' +vec3 hue2rgb(float hue) +{ + vec4 offsets = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); + vec3 p = abs(fract(vec3(hue) + offsets.xyz) * 6.0 - offsets.www); + return clamp(p - offsets.xxx, 0.0, 1.0); +} +#endif + +#ifdef REFLECTANCE +layout (location = 2) in float vertex_reflectance; +#endif + +void main() +{ + gl_Position = mvp_matrix * vec4(vertex_position, 1.0); + gl_PointSize = point_size / gl_Position.w; + + frag_color = vec4(1); + +#ifdef LIGHTING + vec3 world_position = vec3(model_matrix * vec4(vertex_position, 1.0)); + vec3 world_normal = normalize(mat3(model_matrix) * vertex_normal); + vec3 view_direction = normalize(camera_position - world_position); + frag_color.rgb *= max(dot(world_normal, view_direction), 0.0); +#endif + +#ifdef RAINBOW + float rainbow_pos = rainbow_scale_y * (vertex_position.y + rainbow_offset_y); + frag_color.rgb *= hue2rgb(mod(rainbow_pos, 1.0f)); +#endif + +#ifdef REFLECTANCE + frag_color.rgb *= vertex_reflectance; +#endif +} diff --git a/source/opengl/handles/mesh_handle.ipp b/source/opengl/handles/mesh_handle.ipp new file mode 100644 index 0000000..7e7ae7d --- /dev/null +++ b/source/opengl/handles/mesh_handle.ipp @@ -0,0 +1,16 @@ +#ifndef INCLUDE_MESH_INSTANCE_IMPLEMENTATION +#error Never include this file directly include 'mesh_handle.hpp' +#endif + +namespace zgl +{ +inline void mesh_handle::bind() const +{ + glBindVertexArray(vao_id); +} + +inline void mesh_handle::unbind() +{ + glBindVertexArray(0); +} +} \ No newline at end of file diff --git a/source/opengl/handles/point_cloud_handle.ipp b/source/opengl/handles/point_cloud_handle.ipp new file mode 100644 index 0000000..a773a5f --- /dev/null +++ b/source/opengl/handles/point_cloud_handle.ipp @@ -0,0 +1,16 @@ +#ifndef INCLUDE_POINT_CLOUD_INSTANCE_IMPLEMENTATION +#error Never include this file directly include 'point_cloud_handle.hpp' +#endif + +namespace zgl +{ +inline void point_cloud_handle::bind() const +{ + glBindVertexArray(vao_id); +} + +inline void point_cloud_handle::unbind() +{ + glBindVertexArray(0); +} +} diff --git a/source/opengl/handles/shader_program_handle.ipp b/source/opengl/handles/shader_program_handle.ipp new file mode 100755 index 0000000..537dbbd --- /dev/null +++ b/source/opengl/handles/shader_program_handle.ipp @@ -0,0 +1,63 @@ +#ifndef INCLUDE_GL_SHADER_PROGRAM_INSTANCE_IMPLEMENTATION +#error Never include this file directly include 'shader_program_handle.hpp' +#endif + +#include "glm/glm.hpp" +#include "glm/gtc/type_ptr.hpp" + +namespace zgl +{ +inline void shader_program_handle::bind() const +{ + glUseProgram(program_id); +} + +inline void shader_program_handle::unbind() +{ + glUseProgram(0); +} + +template +void shader_program_handle::set_uniform(const T& value) const +{ + if constexpr (std::same_as) + { + static_assert(VariableInfo.type == GL_FLOAT_MAT4); + glUniformMatrix4fv(VariableInfo.location, 1, false, glm::value_ptr(value)); + } + else if constexpr (std::same_as) + { + static_assert(VariableInfo.type == GL_FLOAT_MAT3); + glUniformMatrix3fv(VariableInfo.location, 1, false, glm::value_ptr(value)); + } + else if constexpr (std::same_as) + { + static_assert(VariableInfo.type == GL_FLOAT_VEC4); + glUniform4fv(VariableInfo.location, 1, glm::value_ptr(value)); + } + else if constexpr (std::same_as) + { + static_assert(VariableInfo.type == GL_FLOAT_VEC3); + glUniform3fv(VariableInfo.location, 1, glm::value_ptr(value)); + } + else if constexpr (std::same_as) + { + static_assert(VariableInfo.type == GL_FLOAT_VEC2); + glUniform2fv(VariableInfo.location, 1, glm::value_ptr(value)); + } + else if constexpr (std::same_as) + { + static_assert(VariableInfo.type == GL_FLOAT); + glUniform1f(VariableInfo.location, value); + } + else if constexpr (std::same_as) + { + static_assert(VariableInfo.type == GL_INT or VariableInfo.type == GL_SAMPLER_2D); + glUniform1i(VariableInfo.location, value); + } + else + { + T::_unknown_shader_uniform_type_; + } +} +} \ No newline at end of file diff --git a/source/opengl/handles/texture_handle.ipp b/source/opengl/handles/texture_handle.ipp new file mode 100644 index 0000000..0693a93 --- /dev/null +++ b/source/opengl/handles/texture_handle.ipp @@ -0,0 +1,16 @@ +#ifndef INCLUDE_TEXTURE_INSTANCE_IMPLEMENTATION +#error Never include this file directly include 'texture_handle.hpp' +#endif + +namespace zgl +{ +inline void texture_handle::bind() const +{ + glBindTexture(GL_TEXTURE_2D, texture_id); +} + +inline void texture_handle::unbind() +{ + glBindTexture(GL_TEXTURE_2D, 0); +} +} // namespace zgl