From 0226819a46621b8c49e09c2b2e59751586134d59 Mon Sep 17 00:00:00 2001 From: SeanOMik Date: Thu, 18 Aug 2022 11:34:05 -0400 Subject: [PATCH] Implement batched rendering with multiple textures --- CMake/Findsoil2.cmake | 28 +++++ CMakeLists.txt | 17 ++- cmrc | 2 +- examples/dev_testing/resources/.gitignore | 3 + examples/dev_testing/src/main.cpp | 113 +++++++++--------- include/simpleengine/camera.h | 12 +- include/simpleengine/game.h | 14 ++- include/simpleengine/gfx/model.h | 2 +- include/simpleengine/gfx/shader.h | 6 + .../simpleengine/gfx/shaders/core_3d_shader.h | 4 +- include/simpleengine/gfx/ssbo.h | 60 ++++++++++ include/simpleengine/gfx/texture.h | 16 +++ include/simpleengine/gfx/textured_model.h | 8 +- .../objects/3d/{obj_model.h => mesh.h} | 6 +- include/simpleengine/objects/3d/terrain.h | 104 ++++++++++++++++ include/simpleengine/transformable.h | 4 +- include/simpleengine/vertex.h | 14 ++- .../shaders/{ => core/3d}/fragment_core.glsl | 41 ++++--- .../shaders/{ => core/3d}/vertex_core.glsl | 16 ++- src/camera.cpp | 71 +++++++++-- src/game.cpp | 30 +++-- src/gfx/model.cpp | 22 ++-- src/gfx/shader.cpp | 29 +++++ src/gfx/texture.cpp | 4 + src/gfx/textured_model.cpp | 40 +++++-- src/objects/3d/{obj_model.cpp => mesh.cpp} | 34 +++--- 26 files changed, 557 insertions(+), 143 deletions(-) create mode 100644 CMake/Findsoil2.cmake create mode 100644 examples/dev_testing/resources/.gitignore create mode 100644 include/simpleengine/gfx/ssbo.h rename include/simpleengine/objects/3d/{obj_model.h => mesh.h} (88%) create mode 100644 include/simpleengine/objects/3d/terrain.h rename resources/shaders/{ => core/3d}/fragment_core.glsl (51%) rename resources/shaders/{ => core/3d}/vertex_core.glsl (73%) rename src/objects/3d/{obj_model.cpp => mesh.cpp} (76%) diff --git a/CMake/Findsoil2.cmake b/CMake/Findsoil2.cmake new file mode 100644 index 0000000..7b9d355 --- /dev/null +++ b/CMake/Findsoil2.cmake @@ -0,0 +1,28 @@ +# Find SOIL2 +# Find the SOIL2 includes and library +# +# SOIL2_INCLUDE_DIRS - where to find SOIL2.h, etc. +# SOIL2_LIBRARIES - List of libraries when using SOIL2. +# SOIL2_FOUND - True if SOIL2 found. +# +# Based on the FindZLIB.cmake module. + +IF (SOIL2_INCLUDE_DIR) + # Already in cache, be silent + SET(SOIL2_FIND_QUIETLY TRUE) +ENDIF (SOIL2_INCLUDE_DIR) + +FIND_PATH(SOIL2_INCLUDE_DIR SOIL2.h PATH_SUFFIXES include/SOIL2 include) + +SET(SOIL2_NAMES SOIL2 SOIL2 soil2) +FIND_LIBRARY(SOIL2_LIBRARY NAMES ${SOIL2_NAMES} ) +MARK_AS_ADVANCED( SOIL2_LIBRARY SOIL2_INCLUDE_DIR ) + +# Per-recommendation +SET(SOIL2_INCLUDE_DIRS "${SOIL2_INCLUDE_DIR}") +SET(SOIL2_LIBRARIES "${SOIL2_LIBRARY}") + +# handle the QUIETLY and REQUIRED arguments and set SOIL2_FOUND to TRUE if +# all listed variables are TRUE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(soil2 DEFAULT_MSG SOIL2_LIBRARIES SOIL2_INCLUDE_DIRS) \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index c2933aa..b9139a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,14 +3,24 @@ set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}") project(SimpleEngine) include(cmrc/CMakeRC.cmake) +include(CMake/Findsoil2.cmake) # Add some CMake options: option(SIMPLE_ENGINE_BUILD_EXAMPLES "Build example projects" ON) +# By default use OpenGL GLVND +option(SIMPLE_ENGINE_USE_GL_LEGACY "Use OpenGL legacy, or use BLVND" OFF) +if (SIMPLE_ENGINE_USE_GL_LEGACY) + set(OpenGL_GL_PREFERENCE "LEGACY") +else() + set(OpenGL_GL_PREFERENCE "GLVND") +endif() + find_package(GLEW REQUIRED) find_package(glfw3 CONFIG REQUIRED) find_package(glm CONFIG REQUIRED) -find_package(soil2 CONFIG REQUIRED) +find_package(soil2 REQUIRED) +find_package(OpenGL REQUIRED) # Link sources file(GLOB_RECURSE source_list src/*.cpp) @@ -32,10 +42,13 @@ cmrc_add_resource_library( # Link dependencies target_link_libraries(simpleengine PUBLIC GLEW::GLEW) target_link_libraries(simpleengine PUBLIC glfw) -target_link_libraries(simpleengine PUBLIC glm::glm) +target_link_libraries(simpleengine PUBLIC glm) target_link_libraries(simpleengine PUBLIC soil2) +target_link_libraries(simpleengine PUBLIC ${OPENGL_LIBRARIES}) target_link_libraries(simpleengine PRIVATE simpleengine_resources) +# Include some dependencies' include directories +include_directories(${OPENGL_INCLUDE_DIR}) include_directories(${GLM_INCLUDE_DIRS}) # Add examples as a target if the user has them enabled diff --git a/cmrc b/cmrc index a64bea5..e386a62 160000 --- a/cmrc +++ b/cmrc @@ -1 +1 @@ -Subproject commit a64bea50c05594c8e7cf1f08e441bb9507742e2e +Subproject commit e386a629eb537d384811e598a3c96b9ca928f65e diff --git a/examples/dev_testing/resources/.gitignore b/examples/dev_testing/resources/.gitignore new file mode 100644 index 0000000..69bf9b6 --- /dev/null +++ b/examples/dev_testing/resources/.gitignore @@ -0,0 +1,3 @@ +*.blend +*.obj +*.png \ No newline at end of file diff --git a/examples/dev_testing/src/main.cpp b/examples/dev_testing/src/main.cpp index c89a833..f5f0143 100644 --- a/examples/dev_testing/src/main.cpp +++ b/examples/dev_testing/src/main.cpp @@ -2,16 +2,18 @@ #include "simpleengine/gfx/light.h" #include "simpleengine/gfx/model.h" #include "simpleengine/gfx/texture.h" +#include "simpleengine/objects/3d/terrain.h" #include "simpleengine/vector.h" #include #include +#include #include #include #include #include #include #include -#include +#include #include #include @@ -22,7 +24,11 @@ #include CMRC_DECLARE(resource_shaders); +#ifdef __linux__ +#include +#else #include +#endif namespace se = simpleengine; @@ -39,23 +45,33 @@ int main(int argc, char *argv[]) { /* se::gfx::Texture wall_texture("resources/wall.jpg"); se::gfx::Texture crate_texture("resources/container.jpg", true, true); */ - // Load core shaders from simpleengine resources + // Load core shaders from SimpleEngine resources se::gfx::shaders::Core3dShader core_shader; - auto light = std::make_shared(core_shader, glm::vec3(0.f, 0.f, -20.f), glm::vec3(1.f, 1.f, 1.f)); + auto light = std::make_shared(core_shader, glm::vec3(0.f, 1.f, -10.f), glm::vec3(1.f, 1.f, 1.f)); game.add_event(light); se::gfx::Texture white_texture("examples/dev_testing/resources/white_texture.png"); - /* white_texture.shine_damper = 10; - white_texture.reflectivity = 1; */ - auto dragon = std::make_shared(game.get_window(), core_shader, white_texture, "examples/dev_testing/resources/dragon.obj"); - dragon->translate(0.f, -5.f, -25.f); - game.add_event(dragon); + // white_texture.shine_damper = 10; + //white_texture.reflectivity = 1; + /* auto dragon = std::make_shared(game.get_window(), core_shader, white_texture, "examples/dev_testing/resources/dragon.obj"); + dragon->translate(0.f, -5.f, -15.f); + game.add_event(dragon); */ - /* se::gfx::Texture stall_texture("resources/stallTexture.png"); - auto stall = std::make_shared(game.get_window(), core_shader, stall_texture, "resources/stall.obj"); - stall->translate(0.f, -4.f, -25.f); - game.add_event(stall); */ + /* auto cube = std::make_shared(game.get_window(), core_shader, white_texture, "examples/dev_testing/resources/cube.obj"); + cube->translate(0.f, -5.f, -15.f); + game.add_event(cube); + + se::gfx::Texture grass("examples/dev_testing/resources/grass.png"); + auto terrain = std::make_shared(game.get_window(), core_shader, grass, 0, 0); + terrain->translate(0.f, -5.f, -15.f); + game.add_event(terrain); */ + + se::gfx::Texture stall_texture("examples/dev_testing/resources/stallTextureb.png"); + auto stall = std::make_shared(game.get_window(), core_shader, stall_texture, "examples/dev_testing/resources/stall.obj"); + stall->translate(10.f, -5.f, 0.f); + stall->rotate_y(90.f); + game.add_event(stall); /* std::vector square_vertices = { { se::Vectorf(0.5f, 0.5f, -1.f), glm::vec3(1.f, 0.f, 0.f), glm::vec2(0.f, 0.f) }, // top right @@ -71,10 +87,16 @@ int main(int argc, char *argv[]) { auto square = std::make_shared(game.get_window(), core_shader, square_vertices, indicies); square->translate(1.25f, 0.f, -1.f); - square->scale(.75f); - game.add_event(square); + //square->rotate_y(90.f); + //square->scale(.75f); + game.add_event(square); */ - std::vector tri_vertices = { + /* se::gfx::Texture white_texture("examples/dev_testing/resources/white_texture.png"); + auto cube = std::make_shared(game.get_window(), core_shader, white_texture, "examples/dev_testing/resources/cube.obj"); + cube->translate(-1.25f, 0.f, -1.f); + game.add_event(cube); */ + + /* std::vector tri_vertices = { { se::Vectorf(-0.5f, -0.5f, -1.f), glm::vec3(1.f, 0.f, 0.f), glm::vec2(0.f, 0.f) }, // top right { se::Vectorf(0.5f, -0.5f, -1.f), glm::vec3(0.f, 1.f, 0.f), glm::vec2(1.f, 0.f) }, // bottom right { se::Vectorf(0.f, 0.5f, -1.f), glm::vec3(0.f, 0.f, 1.f), glm::vec2(0.5f, 1.0f) }, // bottom left @@ -86,56 +108,39 @@ int main(int argc, char *argv[]) { game.add_event(tri); */ /* std::vector cube_vertices = { - { se::Vectorf(-0.5f,0.5f,-0.5f), glm::vec3(1.f, 0.f, 0.f), glm::vec2(1.f, 1.f) }, - { se::Vectorf(-0.5f,-0.5f,-0.5f), glm::vec3(0.f, 1.f, 0.f), glm::vec2(1.f, 0.f) }, - { se::Vectorf(0.5f,-0.5f,-0.5f), glm::vec3(0.f, 0.f, 1.f), glm::vec2(0.f, 0.f) }, - { se::Vectorf(0.5f,0.5f,-0.5f), glm::vec3(1.f, 1.f, 0.f), glm::vec2(0.f, 1.f) }, + { se::Vectorf(-1.f, -1.f, -1.f), glm::vec3(1.f, 0.f, 0.f), glm::vec2(0.f, 0.f) }, + { se::Vectorf(1.f, -1.f, -1.f), glm::vec3(0.f, 1.f, 0.f), glm::vec2(1.f, 0.f) }, + { se::Vectorf(1.f, 1.f, -1.f), glm::vec3(0.f, 0.f, 1.f), glm::vec2(2.f, 0.f) }, + { se::Vectorf(-1.f, 1.f, -1.f), glm::vec3(1.f, 1.f, 0.f), glm::vec2(3.f, 0.f) }, + { se::Vectorf(-1, -1, -1), glm::vec3(1.f, 1.f, 0.f), glm::vec2(4.f, 0.f) }, - { se::Vectorf(-0.5f,0.5f,0.5f), glm::vec3(1.f, 0.f, 0.f), glm::vec2(1.f, 1.f) }, - { se::Vectorf(-0.5f,-0.5f,0.5f), glm::vec3(0.f, 1.f, 0.f), glm::vec2(1.f, 0.f) }, - { se::Vectorf(0.5f,-0.5f,0.5f), glm::vec3(0.f, 0.f, 1.f), glm::vec2(0.f, 0.f) }, - { se::Vectorf(0.5f,0.5f,0.5f), glm::vec3(1.f, 1.f, 0.f), glm::vec2(0.f, 1.f) }, + { se::Vectorf(-1, -1, 1), glm::vec3(1.f, 0.f, 0.f), glm::vec2(0.f, 1.f) }, + { se::Vectorf(1, -1, 1), glm::vec3(0.f, 1.f, 0.f), glm::vec2(1.f, 1.f) }, + { se::Vectorf(1, 1, 1), glm::vec3(0.f, 0.f, 1.f), glm::vec2(2.f, 1.f) }, + { se::Vectorf(-1, 1, 1), glm::vec3(1.f, 1.f, 0.f), glm::vec2(3.f, 1.f) }, + { se::Vectorf(-1, -1, 1), glm::vec3(1.f, 1.f, 0.f), glm::vec2(4.f, 1.f) }, - { se::Vectorf(0.5f,0.5f,-0.5f), glm::vec3(1.f, 0.f, 0.f), glm::vec2(1.f, 1.f) }, - { se::Vectorf(0.5f,-0.5f,-0.5f), glm::vec3(0.f, 1.f, 0.f), glm::vec2(1.f, 0.f) }, - { se::Vectorf(0.5f,-0.5f,0.5f), glm::vec3(0.f, 0.f, 1.f), glm::vec2(0.f, 0.f) }, - { se::Vectorf(0.5f,0.5f,0.5f), glm::vec3(1.f, 1.f, 0.f), glm::vec2(0.f, 1.f) }, + { se::Vectorf(-1, 1, -1), glm::vec3(1.f, 0.f, 0.f), glm::vec2(0.f, -1.f) }, + { se::Vectorf(1, 1, -1), glm::vec3(0.f, 1.f, 0.f), glm::vec2(1.f, -1.f) }, - { se::Vectorf(-0.5f,0.5f,-0.5f), glm::vec3(1.f, 0.f, 0.f), glm::vec2(1.f, 1.f) }, - { se::Vectorf(-0.5f,-0.5f,-0.5f), glm::vec3(0.f, 1.f, 0.f), glm::vec2(1.f, 0.f) }, - { se::Vectorf(-0.5f,-0.5f,0.5f), glm::vec3(0.f, 0.f, 1.f), glm::vec2(0.f, 0.f) }, - { se::Vectorf(-0.5f,0.5f,0.5f), glm::vec3(1.f, 1.f, 0.f), glm::vec2(0.f, 1.f) }, - - { se::Vectorf(-0.5f,0.5f,0.5f), glm::vec3(1.f, 0.f, 0.f), glm::vec2(1.f, 1.f) }, - { se::Vectorf(-0.5f,0.5f,-0.5f), glm::vec3(0.f, 1.f, 0.f), glm::vec2(1.f, 0.f) }, - { se::Vectorf(0.5f,0.5f,-0.5f), glm::vec3(0.f, 0.f, 1.f), glm::vec2(0.f, 0.f) }, - { se::Vectorf(0.5f,0.5f,0.5f), glm::vec3(1.f, 1.f, 0.f), glm::vec2(0.f, 1.f) }, - - { se::Vectorf(-0.5f,-0.5f,0.5f), glm::vec3(1.f, 0.f, 0.f), glm::vec2(1.f, 1.f) }, - { se::Vectorf(-0.5f,-0.5f,-0.5f), glm::vec3(0.f, 1.f, 0.f), glm::vec2(1.f, 0.f) }, - { se::Vectorf(0.5f,-0.5f,-0.5f), glm::vec3(0.f, 0.f, 1.f), glm::vec2(0.f, 0.f) }, - { se::Vectorf(0.5f,-0.5f,0.5f), glm::vec3(1.f, 1.f, 0.f), glm::vec2(0.f, 1.f) }, + { se::Vectorf(-1, 1, 1), glm::vec3(1.f, 0.f, 0.f), glm::vec2(0.f, 2.f) }, + { se::Vectorf(1, 1, 1), glm::vec3(0.f, 1.f, 0.f), glm::vec2(1.f, 2.f) }, }; std::vector cube_indicies = { - 0,1,3, - 3,1,2, - 4,5,7, - 7,5,6, - 8,9,11, - 11,9,10, - 12,13,15, - 15,13,14, - 16,17,19, - 19,17,18, - 20,21,23, - 23,21,22 + 0, 1, 5, 5, 1, 6, + 1, 2, 6, 6, 2, 7, + 2, 3, 7, 7, 3, 8, + 3, 4, 8, 8, 4, 9, + 10, 11, 0, 0, 11, 1, + 5, 6, 12, 12, 6, 13 }; auto cube = std::make_shared(game.get_window(), core_shader, cube_vertices, cube_indicies); + cube->translate(3.f, 0.f, 0.f); game.add_event(cube); */ - auto camera = std::make_shared(game.get_window(), core_shader, 70, glm::vec3(0, 0, -10)); + auto camera = std::make_shared(game.get_window(), core_shader, 70, glm::vec3(0, 0, 0)); game.add_event(camera); return game.run(); diff --git a/include/simpleengine/camera.h b/include/simpleengine/camera.h index a78c850..4dfa9f0 100644 --- a/include/simpleengine/camera.h +++ b/include/simpleengine/camera.h @@ -12,7 +12,7 @@ namespace simpleengine { class Camera : public simpleengine::Event { private: - + //glm::vec3 camera_forward; public: glm::vec3 position; glm::vec3 rotation; @@ -20,12 +20,16 @@ namespace simpleengine { glm::mat4 projection_matrix; glm::mat4 view_matrix; - glm::vec3 world_up = glm::vec3(0.f, 1.f, 0.f); - glm::vec3 cam_front = glm::vec3(0.f, 0.f, -1.f); + //glm::vec3 camera_rotation; + /* glm::vec3 world_up = glm::vec3(0.f, 1.f, 0.f); + glm::vec3 cam_front = glm::vec3(0.f, 0.f, -1.f); */ + glm::vec3 camera_front = glm::vec3(0.0f, 0.0f, -1.0f); + glm::vec3 camera_up = glm::vec3(0.0f, 1.0f, 0.0f); float fov; - float near_plane ; + float near_plane; float far_plane; + float movement_speed = 2.5f; Camera(GLFWwindow* window, gfx::Shader shader, float fov = 70, glm::vec3 position = glm::vec3(0.f), glm::vec3 rotation = glm::vec3(0.f), float near_plane = 0.1f, float far_plane = 1000.f, glm::vec3 world_up = glm::vec3(0.f, 1.f, 0.f), diff --git a/include/simpleengine/game.h b/include/simpleengine/game.h index 9a87ee4..a9c6f5e 100644 --- a/include/simpleengine/game.h +++ b/include/simpleengine/game.h @@ -35,10 +35,10 @@ namespace simpleengine { void add_event(std::shared_ptr event); - void update(); - void handle_input(); - void render_window(); - void render_items(); + void update(const float& delta_time); + void handle_input(const float& delta_time); + void render_window(const float& delta_time); + void render_items(const float& delta_time); void exit(); int run(); @@ -53,5 +53,11 @@ namespace simpleengine { GLFWwindow* window; std::vector> events; const bool& window_resizeable; + + float get_delta_time(); + + float last_frame_time; + /* float currentFrameTime; + float deltaTime; */ }; } \ No newline at end of file diff --git a/include/simpleengine/gfx/model.h b/include/simpleengine/gfx/model.h index 4ab41b5..0cc7bc2 100644 --- a/include/simpleengine/gfx/model.h +++ b/include/simpleengine/gfx/model.h @@ -24,7 +24,7 @@ namespace simpleengine::gfx { Model(GLFWwindow* window, GLuint shader_program, std::vector vertices, std::vector indicies = std::vector()); protected: - void setup_vertexes(); + virtual void setup_vertices(); public: virtual void update(const float& delta_time) override; diff --git a/include/simpleengine/gfx/shader.h b/include/simpleengine/gfx/shader.h index 8fc581a..b6defe9 100644 --- a/include/simpleengine/gfx/shader.h +++ b/include/simpleengine/gfx/shader.h @@ -183,6 +183,9 @@ namespace simpleengine::gfx { void set_uniform_float(GLint location, GLfloat fl, bool bind_shader = true); void set_uniform_float(const char* uniform_name, GLfloat fl, bool bind_shader = true); + + void set_uniform_float_array(GLint location, int count, GLfloat* arr, bool bind_shader = true); + void set_uniform_float_array(const char* uniform_name, int count, GLfloat* arr, bool bind_shader = true); void set_uniform_float_vec2(GLint location, glm::vec2 vec, bool bind_shader = true); void set_uniform_float_vec2(const char* uniform_name, glm::vec2 vec, bool bind_shader = true); @@ -195,6 +198,9 @@ namespace simpleengine::gfx { void set_uniform_int(GLint location, GLint i, bool bind_shader = true); void set_uniform_int(const char* uniform_name, GLint i, bool bind_shader = true); + + void set_uniform_int_array(GLint location, int count, GLint* arr, bool bind_shader = true); + void set_uniform_int_array(const char* uniform_name, int count, GLint* arr, bool bind_shader = true); void set_uniform_int_vec2(GLint location, glm::ivec2 vec, bool bind_shader = true); void set_uniform_int_vec2(const char* uniform_name, glm::ivec2 vec, bool bind_shader = true); diff --git a/include/simpleengine/gfx/shaders/core_3d_shader.h b/include/simpleengine/gfx/shaders/core_3d_shader.h index f68aa80..b8a0650 100644 --- a/include/simpleengine/gfx/shaders/core_3d_shader.h +++ b/include/simpleengine/gfx/shaders/core_3d_shader.h @@ -14,13 +14,13 @@ namespace simpleengine::gfx::shaders { this->program = glCreateProgram(); auto vertex_fs = cmrc::simpleengine_resources::get_filesystem(); - cmrc::file vertex_file = vertex_fs.open("resources/shaders/vertex_core.glsl"); + cmrc::file vertex_file = vertex_fs.open("resources/shaders/core/3d/vertex_core.glsl"); std::string vertex_source(vertex_file.begin()); Shader vertex = gfx::Shader::from_source(program, ShaderType::ST_Vertex, vertex_source); this->shader = vertex.shader; auto fragment_fs = cmrc::simpleengine_resources::get_filesystem(); - cmrc::file fragment_file = fragment_fs.open("resources/shaders/fragment_core.glsl"); + cmrc::file fragment_file = fragment_fs.open("resources/shaders/core/3d/fragment_core.glsl"); std::string fragment_source(fragment_file.begin()); fragment_shader = gfx::Shader::from_source(program, ShaderType::ST_Fragment, fragment_source); diff --git a/include/simpleengine/gfx/ssbo.h b/include/simpleengine/gfx/ssbo.h new file mode 100644 index 0000000..292642a --- /dev/null +++ b/include/simpleengine/gfx/ssbo.h @@ -0,0 +1,60 @@ +#pragma once + +#ifdef __linux__ +#include +#include +#else +#include +#include +#endif + +#include "shader.h" + +#include + +namespace simpleengine::gfx { + /** + * @brief Shader Storage buffer Object + * + * https://www.khronos.org/opengl/wiki/Shader_Storage_Buffer_Object + */ + class SSBO { + private: + GLuint bind_index; + + void gen_buffer() { + glGenBuffers(1, &handle); + } + public: + GLuint handle; + gfx::Shader& shader; + + SSBO(gfx::Shader& shader, GLuint bind_index) : bind_index(bind_index), shader(shader) { + gen_buffer(); + } + + SSBO(gfx::Shader& shader, const std::string& ssbo_name) : shader(shader) { + bind_index = glGetProgramResourceIndex(shader.program, GL_SHADER_STORAGE_BLOCK, ssbo_name.c_str()); + + gen_buffer(); + } + + void bind_buffer() { + glBindBuffer(GL_SHADER_STORAGE_BUFFER, handle); + } + + void bind_ssbo() { + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, bind_index, handle); + } + + void buffer(void* data, size_t offset, size_t size) { + bind_buffer(); + + glBufferData(GL_SHADER_STORAGE_BUFFER, size - offset, data, GL_DYNAMIC_COPY); + } + + void unbind() { + glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + } + }; +} \ No newline at end of file diff --git a/include/simpleengine/gfx/texture.h b/include/simpleengine/gfx/texture.h index 5194c60..efeed9f 100644 --- a/include/simpleengine/gfx/texture.h +++ b/include/simpleengine/gfx/texture.h @@ -12,7 +12,11 @@ #include +#ifdef __linux__ +#include +#else #include +#endif #include #include @@ -26,11 +30,21 @@ namespace simpleengine::gfx { unsigned int image_type; public: + /** + * @brief The type of the texture + * + */ + enum Type { + TexT_DIFFUSE, + TexT_SPECULAR + }; + int height; int width; int channels; float shine_damper = 1.f; float reflectivity = 0.f; + Type type; /** * @brief Construct a new Texture object from a path. @@ -61,5 +75,7 @@ namespace simpleengine::gfx { Texture(std::vector buffer, bool img_2d = true, bool mipmap = true); void bind() const; + + unsigned int get_texture_id() const; }; } \ No newline at end of file diff --git a/include/simpleengine/gfx/textured_model.h b/include/simpleengine/gfx/textured_model.h index bba943b..8bbea41 100644 --- a/include/simpleengine/gfx/textured_model.h +++ b/include/simpleengine/gfx/textured_model.h @@ -7,6 +7,7 @@ #include "../renderable.h" #include "../transformable.h" */ +#include "ssbo.h" #include "shader.h" #include "model.h" #include "texture.h" @@ -18,13 +19,18 @@ namespace simpleengine::gfx { class TexturedModel : public simpleengine::gfx::Model { public: - gfx::Texture texture; + std::vector textures; TexturedModel(GLFWwindow* window, gfx::Shader shader, gfx::Texture texture, std::vector vertices, std::vector indicies = std::vector()); TexturedModel(GLFWwindow* window, GLuint shader_program, gfx::Texture texture, std::vector vertices, std::vector indicies = std::vector()); + TexturedModel(GLFWwindow* window, gfx::Shader shader, std::vector textures, std::vector vertices, + std::vector indicies = std::vector()); + TexturedModel(GLFWwindow* window, GLuint shader_program, std::vector textures, std::vector vertices, + std::vector indicies = std::vector()); + virtual void update(const float& delta_time) override; virtual void render(GLFWwindow* target) override; }; diff --git a/include/simpleengine/objects/3d/obj_model.h b/include/simpleengine/objects/3d/mesh.h similarity index 88% rename from include/simpleengine/objects/3d/obj_model.h rename to include/simpleengine/objects/3d/mesh.h index 5dd4664..410ecfe 100644 --- a/include/simpleengine/objects/3d/obj_model.h +++ b/include/simpleengine/objects/3d/mesh.h @@ -17,7 +17,7 @@ #include "../../gfx/textured_model.h" namespace simpleengine::objects_3d { - class ObjModel : public simpleengine::gfx::TexturedModel { + class Mesh : public simpleengine::gfx::TexturedModel { private: /** * @brief Split a string multiple times (if possible) with a character delimiter. @@ -49,8 +49,8 @@ namespace simpleengine::objects_3d { public: std::vector lit_vertices; - ObjModel(GLFWwindow *window, gfx::Shader shader, gfx::Texture texture, std::string filename); - ObjModel(GLFWwindow *window, gfx::Shader shader, gfx::Texture texture, std::ifstream file_stream); + Mesh(GLFWwindow *window, gfx::Shader shader, gfx::Texture texture, std::string filename); + Mesh(GLFWwindow *window, gfx::Shader shader, gfx::Texture texture, std::ifstream file_stream); virtual void update(const float& delta_time) override; }; diff --git a/include/simpleengine/objects/3d/terrain.h b/include/simpleengine/objects/3d/terrain.h new file mode 100644 index 0000000..3dcb664 --- /dev/null +++ b/include/simpleengine/objects/3d/terrain.h @@ -0,0 +1,104 @@ +#pragma once + +#include "../../gfx/model.h" +#include "../../gfx/texture.h" +#include "../../gfx/textured_model.h" +#include "../../renderable.h" +#include "../../vertex.h" +#include + +namespace simpleengine::objects_3d { + class Terrain : public simpleengine::gfx::TexturedModel { + private: + /** + * @brief DO NOT USE!!! Replaced with lit_vertices + * + */ + using gfx::Model::vertices; + public: + std::vector lit_vertices; + const float size; + const int vertex_count; + + float x; + float y; + + gfx::Texture texture; + + Terrain(GLFWwindow* window, gfx::Shader shader, gfx::Texture texture, int grid_x, int grid_y, float size = 800.f, int vertex_count = 128) : + simpleengine::gfx::TexturedModel(window, shader, { texture }, std::vector()), x(grid_x * size), y(grid_y * size), + texture(texture), size(size), vertex_count(vertex_count) { + + generate_terrain(); + } + + protected: + virtual void setup_vertices() override { + vao.bind(); + vbo.buffer(lit_vertices.data(), 0, sizeof(LitVertex) * lit_vertices.size()); + ebo.buffer(indicies.data(), 0, indicies.size() * sizeof(GLuint)); + + // Enable VAO attributes + vao.enable_attrib(vbo, 0, 3, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, position)); + //vao.enable_attrib(vbo, 1, 3, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, color)); + vao.enable_attrib(vbo, 1, 2, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, tex_coord)); + vao.enable_attrib(vbo, 2, 3, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, normal)); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + } + public: + void generate_terrain() { + lit_vertices.clear(); + indicies.clear(); + + // Reserve space for vertices and indicies before hand. + int count = pow(vertex_count, 2); + lit_vertices.reserve(count); + indicies.reserve(6 * pow(vertex_count - 1, 2)); + + int vertex_index = 0; + for (int i = 0; i < vertex_count; i++) { + for (int j = 0; j < vertex_count; j++) { + Vectorf pos( (float) j / ((float) vertex_count - 1) * size, 0, (float) i / ((float) vertex_count - 1) * size); + glm::vec2 tex( (float) j / (float) vertex_count - 1, (float) i / (float) vertex_count - 1); + glm::vec3 normals(0, 1, 0); + lit_vertices.emplace_back(pos, tex, normals); + + vertex_index++; + } + } + + int indicies_index = 0; + for (int i = 0; i < vertex_count; i++) { + for (int j = 0; j < vertex_count; j++) { + int top_left = (i * vertex_count) + j; + int top_right = top_left + 1; + int bottom_left = ((i + 1) * vertex_count) + j; + int bottom_right = bottom_left + 1; + + indicies.push_back(top_left); + indicies.push_back(bottom_left); + indicies.push_back(top_right); + indicies.push_back(top_right); + indicies.push_back(bottom_left); + indicies.push_back(bottom_right); + } + } + + std::cout << "========= New terrain generated =========" << std::endl; + std::cout << " Lit vertices count: " << lit_vertices.size() << std::endl; + std::cout << " Indicies count: " << indicies.size() << std::endl; + + setup_vertices(); + } + + virtual void update(const float& delta_time) override { + + } + + /* virtual void render(GLFWwindow* target) override { + + } */ + }; +} \ No newline at end of file diff --git a/include/simpleengine/transformable.h b/include/simpleengine/transformable.h index 3623acc..d661e22 100644 --- a/include/simpleengine/transformable.h +++ b/include/simpleengine/transformable.h @@ -52,9 +52,9 @@ namespace simpleengine { transform_matrix = glm::translate(transform_matrix, glm::vec3(x, y, z)); } - virtual void translate(const glm::vec3& vec) { + /* virtual void translate(const glm::vec3& vec) { transform_matrix = glm::translate(transform_matrix, vec); - } + } */ virtual glm::mat4 rotation_matrix(float degrees, glm::vec3 rotation_axis) const { return glm::rotate(transform_matrix, glm::radians(degrees), rotation_axis); diff --git a/include/simpleengine/vertex.h b/include/simpleengine/vertex.h index baf1616..652dc15 100644 --- a/include/simpleengine/vertex.h +++ b/include/simpleengine/vertex.h @@ -19,10 +19,12 @@ namespace simpleengine { simpleengine::Vectorf position; glm::vec3 color; glm::vec2 tex_coord; + float texture_id = 0.f; Vertex() = default; - Vertex(simpleengine::Vectorf position, glm::vec3 color, glm::vec2 tex_coord) : position(position), color(color), tex_coord(tex_coord) { + Vertex(simpleengine::Vectorf position, glm::vec3 color, glm::vec2 tex_coord, int texture_id = 0) : + position(position), color(color), tex_coord(tex_coord), texture_id((float) texture_id) { } }; @@ -37,11 +39,17 @@ namespace simpleengine { glm::vec3 color; glm::vec2 tex_coord; glm::vec3 normal; + float texture_id = 0.f; LitVertex() = default; - LitVertex(simpleengine::Vectorf position, glm::vec3 color, glm::vec2 tex_coord, glm::vec3 normal) : - position(position), color(color), tex_coord(tex_coord), normal(normal) { + LitVertex(simpleengine::Vectorf position, glm::vec3 color, glm::vec2 tex_coord, glm::vec3 normal, int texture_id = 0) : + position(position), color(color), tex_coord(tex_coord), normal(normal), texture_id((float) texture_id) { + + } + + LitVertex(simpleengine::Vectorf position, glm::vec2 tex_coord, glm::vec3 normal, int texture_id = 0) : + position(position), color(glm::vec3(1.f)), tex_coord(tex_coord), normal(normal), texture_id((float) texture_id) { } }; diff --git a/resources/shaders/fragment_core.glsl b/resources/shaders/core/3d/fragment_core.glsl similarity index 51% rename from resources/shaders/fragment_core.glsl rename to resources/shaders/core/3d/fragment_core.glsl index d5fe2e6..3d09bb5 100644 --- a/resources/shaders/fragment_core.glsl +++ b/resources/shaders/core/3d/fragment_core.glsl @@ -1,20 +1,25 @@ #version 440 in vec3 vs_position; -in mat4 vs_transform; -in vec2 vs_texcoord; +in vec3 vs_color; in vec3 vs_normal; +in vec2 vs_texcoord; +flat in float vs_tex_id; // < 0 is reserved for solid colored objects. + +in mat4 vs_transform; in vec3 vs_to_light; in vec3 vs_to_camera; -uniform bool texture_is_set; -uniform sampler2D vs_texture; +uniform sampler2D u_textures[16]; +uniform float u_texture_shine[16]; +uniform float u_texture_reflectivity[16]; + uniform vec3 light_color; -uniform float shine_damper; -uniform float reflectivity; out vec4 fs_color; +vec3 calculate_specular(vec3 unit_normal, float shine_damper, float reflectivity); + void main() { // Lighting vec3 unit_normal = normalize(vs_normal); @@ -24,8 +29,21 @@ void main() { float brightness = max(dot_prod, 0.f); vec3 diffuse = brightness * light_color; - // Specular lighting - // only do all this math is reflectivity is > 0 + if (vs_tex_id > -1) { + int id = int(vs_tex_id); + + float shine_damper = u_texture_shine[id]; + float reflectivity = u_texture_reflectivity[id]; + vec3 final_specular = calculate_specular(unit_normal, shine_damper, reflectivity); + + fs_color = vec4(diffuse, 1.f) * texture(u_textures[1], vs_texcoord) + vec4(final_specular, 1.f); + //fs_color = texture(u_textures[1], vs_texcoord); + } else { + fs_color = vec4(diffuse, 1.f) * vec4(vs_color, 1.f); // We don't add any reflectivity to solid colored vectors. + } +} + +vec3 calculate_specular(vec3 unit_normal, float shine_damper, float reflectivity) { vec3 final_specular = vec3(0.f); if (reflectivity > 0) { vec3 unit_vector_to_camera = normalize(vs_to_camera); @@ -37,10 +55,5 @@ void main() { final_specular = damped_specular * reflectivity * light_color; } - if (texture_is_set) { - //fs_color = vec4(0.5 * unit_normal + vec3(0.5), 1.f); // Visualize normals - fs_color = vec4(diffuse, 1.f) * texture(vs_texture, vs_texcoord) + vec4(final_specular, 1.f); - } else { - fs_color = vec4(diffuse, 1.f) + vec4(final_specular, 1.f); - } + return final_specular; } \ No newline at end of file diff --git a/resources/shaders/vertex_core.glsl b/resources/shaders/core/3d/vertex_core.glsl similarity index 73% rename from resources/shaders/vertex_core.glsl rename to resources/shaders/core/3d/vertex_core.glsl index 42b9be3..cc5d36f 100644 --- a/resources/shaders/vertex_core.glsl +++ b/resources/shaders/core/3d/vertex_core.glsl @@ -1,13 +1,18 @@ #version 440 layout (location = 0) in vec3 vertex_position; -layout (location = 1) in vec2 vertex_texcoord; +layout (location = 1) in vec3 vertex_color; layout (location = 2) in vec3 vertex_normal; +layout (location = 3) in vec2 vertex_texcoord; +layout (location = 4) in float vertex_tex_id; out vec3 vs_position; -out vec2 vs_texcoord; -out mat4 vs_transform; +out vec3 vs_color; out vec3 vs_normal; +out vec2 vs_texcoord; +flat out float vs_tex_id; + +out mat4 vs_transform; out vec3 vs_to_light; out vec3 vs_to_camera; @@ -19,9 +24,14 @@ uniform vec3 light_position; void main() { vec4 world_pos = (transform_matrix * vec4(vertex_position, 1.f)); + // Directly pass things to the fragment shader. vs_position = world_pos.xyz; vs_transform = transform_matrix; vs_texcoord = vertex_texcoord; + vs_color = vertex_color; + + vs_tex_id = vertex_tex_id; + gl_Position = projection_matrix * view_matrix * world_pos; diff --git a/src/camera.cpp b/src/camera.cpp index e56d217..88399a3 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -1,16 +1,20 @@ #include "camera.h" +#include +#include +#include namespace simpleengine { Camera::Camera(GLFWwindow* window, gfx::Shader shader, float fov, glm::vec3 position, glm::vec3 rotation, float near_plane, float far_plane, glm::vec3 world_up, glm::vec3 cam_front) : simpleengine::Event(window), shader(shader), - projection_matrix(1.f), view_matrix(1.f), fov(fov), position(position), rotation(rotation), near_plane(near_plane), far_plane(far_plane), - world_up(world_up), cam_front(cam_front) { + projection_matrix(1.f), view_matrix(1.f), fov(fov), position(position), rotation(rotation), near_plane(near_plane), far_plane(far_plane) { // TODO: Update width and height on window resize. int width, height; glfwGetFramebufferSize(window, &width, &height); projection_matrix = glm::perspective(glm::radians(fov), ((float) width) / height, near_plane, far_plane); + + //rotation = glm::vec3(0.f, 0.f, -1.f); } Camera::Camera(GLFWwindow* window, GLuint shader_prog, float fov, glm::vec3 position, glm::vec3 rotation, @@ -20,23 +24,76 @@ namespace simpleengine { } void Camera::update(const float& delta_time) { + if (glfwGetKey(window, GLFW_KEY_MINUS) == GLFW_PRESS) { + movement_speed -= abs(movement_speed - .2f); + } + + if (glfwGetKey(window, GLFW_KEY_EQUAL) == GLFW_PRESS) { + movement_speed += .2f; + } + + if (glfwGetKey(window, GLFW_KEY_0) == GLFW_PRESS) { + movement_speed = 2.5f; + } + + float camera_speed = movement_speed * delta_time; + if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) { - position.z -= 0.02f; + position += camera_speed * camera_front; } if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) { - position.z += 0.02f; + position -= camera_speed * camera_front; } if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) { - position.x += 0.02f; + position += glm::normalize(glm::cross(camera_front, camera_up)) * camera_speed; } if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) { - position.x -= 0.02f; + position -= glm::normalize(glm::cross(camera_front, camera_up)) * camera_speed; } - view_matrix = glm::lookAt(position, position + cam_front, world_up); + if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS) { + position.y += camera_speed; + } + + if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS) { + position.y -= camera_speed; + } + + if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS) { + rotation.z += camera_speed; + } + + if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS) { + rotation.z -= camera_speed; + } + + if (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS) { + rotation.y -= camera_speed; + } + + if (glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW_PRESS) { + rotation.y += camera_speed; + } + + // Limit the pitch of the camera. + if (rotation.z >= glm::radians(89.f)) { + rotation.z = glm::radians(89.f); + } + + if (rotation.z <= -glm::radians(89.f)) { + rotation.z = -glm::radians(89.f); + } + + glm::vec3 direction; + direction.x = cos(rotation.y) * cos(rotation.z); + direction.y = sin(rotation.z); + direction.z = sin(rotation.y) * cos(rotation.z); + camera_front = glm::normalize(direction); + + view_matrix = glm::lookAt(position, position + camera_front, camera_up); shader.use(); shader.set_uniform_matrix_4f("view_matrix", view_matrix, false); diff --git a/src/game.cpp b/src/game.cpp index 9cc4a3c..29d94e0 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -46,6 +46,7 @@ void simpleengine::Game::enable_default_gl_options() const { glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glCullFace(GL_BACK); + //glFrontFace(GL_CW); } void simpleengine::Game::enable_gl_option(GLenum option) const { @@ -72,39 +73,50 @@ void simpleengine::Game::add_event(std::shared_ptr event) { events.push_back(event); } -void simpleengine::Game::update() { - handle_input(); +void simpleengine::Game::update(const float& delta_time) { + handle_input(delta_time); // Update items for (const std::shared_ptr& event : events) { - event->update(0.f); + event->update(delta_time); } } -void simpleengine::Game::handle_input() { +void simpleengine::Game::handle_input(const float& delta_time) { } -void simpleengine::Game::render_window() { +void simpleengine::Game::render_window(const float& delta_time) { glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - render_items(); + render_items(delta_time); } -void simpleengine::Game::render_items() { +void simpleengine::Game::render_items(const float& delta_time) { for (const std::shared_ptr& event : events) { event->render(window); } } +float simpleengine::Game::get_delta_time() { + float current_frame_time = glfwGetTime(); + float delta_time = current_frame_time - last_frame_time; + last_frame_time = current_frame_time; + + return delta_time; +} + int simpleengine::Game::run() { while (!glfwWindowShouldClose(window)) { + // Get delta time first thing + float delta_time = get_delta_time(); + // Update input glfwPollEvents(); - update(); + update(delta_time); - render_window(); + render_window(delta_time); // End draw glfwSwapBuffers(window); diff --git a/src/gfx/model.cpp b/src/gfx/model.cpp index 0b6e67f..0298773 100644 --- a/src/gfx/model.cpp +++ b/src/gfx/model.cpp @@ -5,7 +5,7 @@ namespace simpleengine::gfx { simpleengine::Renderable(window), shader(shader), vertices(vertices), indicies(indicies), vbo(gfx::VBO(GL_ARRAY_BUFFER, false)), ebo(gfx::VBO(GL_ELEMENT_ARRAY_BUFFER, false)) { - setup_vertexes(); + setup_vertices(); } Model::Model(GLFWwindow* window, GLuint shader_program, std::vector vertices, std::vector indicies) : @@ -13,28 +13,26 @@ namespace simpleengine::gfx { } - void Model::setup_vertexes() { + void Model::setup_vertices() { vao.bind(); vbo.buffer(vertices.data(), 0, sizeof(Vertex) * vertices.size()); if (!indicies.empty()) { ebo.buffer(indicies.data(), 0, indicies.size() * sizeof(GLuint)); } - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, position)); - glEnableVertexAttribArray(0); - - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, color)); - glEnableVertexAttribArray(1); - - glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, tex_coord)); - glEnableVertexAttribArray(2); + // Enable VAO attributes + vao.enable_attrib(vbo, 0, 3, GL_FLOAT, sizeof(Vertex), offsetof(Vertex, position)); + vao.enable_attrib(vbo, 1, 3, GL_FLOAT, sizeof(Vertex), offsetof(Vertex, color)); + // Attribute 2 is used for normals + vao.enable_attrib(vbo, 3, 2, GL_FLOAT, sizeof(Vertex), offsetof(Vertex, tex_coord)); + vao.enable_attrib(vbo, 4, 1, GL_FLOAT, sizeof(Vertex), offsetof(Vertex, texture_id)); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); } void Model::update(const float& delta_time) { - //this->rotate_y(1.f); + this->rotate_y(1.f); } void Model::render(GLFWwindow* target) { @@ -42,7 +40,7 @@ namespace simpleengine::gfx { shader.set_uniform_matrix_4f("transform_matrix", transform_matrix, false); // When binding to the texture, also tell the shader if the texture is set or not. - shader.set_uniform_int("texture_is_set", (GLint) false, false); + //shader.set_uniform_int("texture_is_set", (GLint) false, false); vao.bind(); if (indicies.empty()) { diff --git a/src/gfx/shader.cpp b/src/gfx/shader.cpp index 025cf66..329fa40 100644 --- a/src/gfx/shader.cpp +++ b/src/gfx/shader.cpp @@ -189,6 +189,22 @@ namespace simpleengine::gfx { set_uniform_float(location, fl, bind_shader); } + void Shader::set_uniform_float_array(GLint location, int count, GLfloat* arr, bool bind_shader) { + if (bind_shader) { + use(); + } + glUniform1fv(location, count, arr); + if (bind_shader) { + unuse(); + } + } + + void Shader::set_uniform_float_array(const char* uniform_name, int count, GLfloat* arr, bool bind_shader) { + int location = get_uniform_location(uniform_name); + set_uniform_float_array(location, count, arr, bind_shader); + } + + void Shader::set_uniform_float_vec2(GLint location, glm::vec2 vec, bool bind_shader) { if (bind_shader) { use(); @@ -249,6 +265,19 @@ namespace simpleengine::gfx { set_uniform_int(location, i, bind_shader); } + void Shader::set_uniform_int_array(GLint location, int count, GLint* arr, bool bind_shader) { + if (bind_shader) { + use(); + } + + glUniform1iv(location, count, arr); + } + + void Shader::set_uniform_int_array(const char* uniform_name, int count, GLint* arr, bool bind_shader) { + int location = get_uniform_location(uniform_name); + set_uniform_int_array(location, count, arr, bind_shader); + } + void Shader::set_uniform_int_vec2(GLint location, glm::ivec2 vec, bool bind_shader) { if (bind_shader) { use(); diff --git a/src/gfx/texture.cpp b/src/gfx/texture.cpp index 1add5c8..2dc8c6f 100644 --- a/src/gfx/texture.cpp +++ b/src/gfx/texture.cpp @@ -90,4 +90,8 @@ namespace simpleengine::gfx { void Texture::bind() const { glBindTexture(image_type, texture_id); } + + unsigned int Texture::get_texture_id() const { + return texture_id; + } } \ No newline at end of file diff --git a/src/gfx/textured_model.cpp b/src/gfx/textured_model.cpp index bb7f9b1..cd4cef3 100644 --- a/src/gfx/textured_model.cpp +++ b/src/gfx/textured_model.cpp @@ -1,14 +1,26 @@ #include "gfx/textured_model.h" +#include "gfx/ssbo.h" namespace simpleengine::gfx { TexturedModel::TexturedModel(GLFWwindow* window, gfx::Shader shader, gfx::Texture texture, std::vector vertices, - std::vector indicies) : simpleengine::gfx::Model(window, shader, vertices, indicies), texture(texture) { - + std::vector indicies) : simpleengine::gfx::Model(window, shader, vertices, indicies), + textures(std::vector{texture}) { } TexturedModel::TexturedModel(GLFWwindow* window, GLuint shader_program, gfx::Texture texture, std::vector vertices, std::vector indicies) : TexturedModel(window, gfx::Shader(shader_program), - texture, vertices, indicies) { + std::vector{texture}, vertices, indicies) { + + } + + TexturedModel::TexturedModel(GLFWwindow* window, gfx::Shader shader, std::vector textures, std::vector vertices, + std::vector indicies) : simpleengine::gfx::Model(window, shader, vertices, indicies), + textures(textures) { + } + + TexturedModel::TexturedModel(GLFWwindow* window, GLuint shader_program, std::vector textures, + std::vector vertices, std::vector indicies) : TexturedModel(window, gfx::Shader(shader_program), + textures, vertices, indicies) { } @@ -19,11 +31,25 @@ namespace simpleengine::gfx { void TexturedModel::render(GLFWwindow* target) { shader.use(); shader.set_uniform_matrix_4f("transform_matrix", transform_matrix, false); - shader.set_uniform_float("shine_damper", texture.shine_damper, false); - shader.set_uniform_float("reflectivity", texture.reflectivity, false); - // When binding to the texture, tell the shader if the texture is set or not. - shader.set_uniform_int("texture_is_set", (GLint) true, false); + const int tex_id = 0; + + // On a batch renderer, you would set an array. + shader.set_uniform_int("u_textures", tex_id, false); + shader.set_uniform_float("u_texture_shine", 1.f, false); + shader.set_uniform_float("u_texture_reflectivity", 0.f, false); + + /* int samples[2] = { 0, 1 }; + float shine[2] = { 1.f, 1.f}; + float reflectivity[2] = { 0.f, 0.f}; + + shader.set_uniform_int_array("u_textures", 2, samples, false); + shader.set_uniform_float_array("u_texture_shine", 2, shine, false); + shader.set_uniform_float_array("u_texture_reflectivity", 2, reflectivity, false); */ + + glActiveTexture(GL_TEXTURE0 + tex_id); + glBindTextureUnit(tex_id, textures.front().get_texture_id()); + const auto& texture = textures.front(); texture.bind(); vao.bind(); diff --git a/src/objects/3d/obj_model.cpp b/src/objects/3d/mesh.cpp similarity index 76% rename from src/objects/3d/obj_model.cpp rename to src/objects/3d/mesh.cpp index 046139e..d9bc2f7 100644 --- a/src/objects/3d/obj_model.cpp +++ b/src/objects/3d/mesh.cpp @@ -1,7 +1,7 @@ -#include "objects/3d/obj_model.h" +#include "objects/3d/mesh.h" namespace simpleengine::objects_3d { - std::vector ObjModel::split_string(std::string str, const char delim) { + std::vector Mesh::split_string(std::string str, const char delim) { std::istringstream ss(str); std::vector tokens; @@ -17,8 +17,9 @@ namespace simpleengine::objects_3d { return tokens; } - void ObjModel::process_vertex(const std::vector& vertex_data, const std::vector& in_textures, - const std::vector& in_normals, std::vector& out_indicies, std::vector& out_textures, std::vector& out_normals) { + void Mesh::process_vertex(const std::vector& vertex_data, const std::vector& in_textures, + const std::vector& in_normals, std::vector& out_indicies, + std::vector& out_textures, std::vector& out_normals) { // Get the index the current vertex and put it in indicies int currentVertexIndex = stoi(vertex_data[0]) - 1; @@ -34,13 +35,13 @@ namespace simpleengine::objects_3d { out_normals.at(currentVertexIndex) = current_norm; } - ObjModel::ObjModel(GLFWwindow *window, gfx::Shader shader, gfx::Texture texture, std::string filename) : - ObjModel(window, shader, texture, std::ifstream(filename, std::ios::in | std::ios::binary)) { + Mesh::Mesh(GLFWwindow *window, gfx::Shader shader, gfx::Texture texture, std::string filename) : + Mesh(window, shader, texture, std::ifstream(filename, std::ios::in | std::ios::binary)) { } - ObjModel::ObjModel(GLFWwindow *window, gfx::Shader shader, gfx::Texture texture, std::ifstream file_stream) : - simpleengine::gfx::TexturedModel(window, shader, texture, std::vector()) { + Mesh::Mesh(GLFWwindow *window, gfx::Shader shader, gfx::Texture texture, std::ifstream file_stream) : + simpleengine::gfx::TexturedModel(window, shader, std::vector{texture}, std::vector()) { if (!file_stream.is_open()) { std::cerr << "File stream that was given to ObjModel::ObjModel is not open!" << std::endl; @@ -94,9 +95,13 @@ namespace simpleengine::objects_3d { file_stream.close(); + const int texture_id = 0; + + std::cout << "Texture ID: " << texture_id << std::endl; + // Insert everything into lit_vertices. for (int i = 0; i < obj_vertices.size(); i++) { - lit_vertices.emplace_back(simpleengine::Vectorf(obj_vertices.at(i)), glm::vec3(1.f), textures.at(i), normals.at(i)); + lit_vertices.emplace_back(simpleengine::Vectorf(obj_vertices.at(i)), glm::vec3(1.f), textures.at(i), normals.at(i), texture_id); } // Create VAO and EBO and assign buffers @@ -106,15 +111,16 @@ namespace simpleengine::objects_3d { // Enable VAO attributes vao.enable_attrib(vbo, 0, 3, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, position)); - //vao.enable_attrib(vbo, 1, 3, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, color)); - vao.enable_attrib(vbo, 1, 2, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, tex_coord)); + vao.enable_attrib(vbo, 1, 3, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, color)); vao.enable_attrib(vbo, 2, 3, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, normal)); - + vao.enable_attrib(vbo, 3, 2, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, tex_coord)); + vao.enable_attrib(vbo, 4, 1, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, texture_id)); + glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); } - void ObjModel::update(const float& delta_time) { - this->rotate_y(0.05f); // Slowly rotate (for debugging) + void Mesh::update(const float& delta_time) { + this->rotate_y(0.0005f); // Slowly rotate (for debugging) } } \ No newline at end of file