diff --git a/AimGL/resources/Models/tree/tree.mtl b/AimGL/resources/Models/tree/tree.mtl new file mode 100644 index 0000000..bb2ca7b --- /dev/null +++ b/AimGL/resources/Models/tree/tree.mtl @@ -0,0 +1,22 @@ +# Blender 3.4.1 MTL File: 'None' +# www.blender.org + +newmtl Bark +Ns 256.000031 +Ka 1.000000 1.000000 1.000000 +Kd 0.207595 0.138513 0.055181 +Ks 0.000000 0.000000 0.000000 +Ke 0.000000 0.000000 0.000000 +Ni 1.450000 +d 1.000000 +illum 1 + +newmtl Tree +Ns 256.000031 +Ka 1.000000 1.000000 1.000000 +Kd 0.256861 0.440506 0.110769 +Ks 0.000000 0.000000 0.000000 +Ke 0.000000 0.000000 0.000000 +Ni 1.450000 +d 1.000000 +illum 1 diff --git a/AimGL/resources/Shaders/Graphics/InfiniteGridFloor.fs b/AimGL/resources/Shaders/Graphics/InfiniteGridFloor.fs index ddee668..3bb096e 100644 --- a/AimGL/resources/Shaders/Graphics/InfiniteGridFloor.fs +++ b/AimGL/resources/Shaders/Graphics/InfiniteGridFloor.fs @@ -4,7 +4,7 @@ out vec4 FragColor; float near = 0.01f; -float far = 20.f; +uniform float far = 5.f; in vec3 nearPoint; in vec3 farPoint; diff --git a/AimGL/resources/Shaders/basic3d.fs b/AimGL/resources/Shaders/basic3d.fs new file mode 100644 index 0000000..1600c7e --- /dev/null +++ b/AimGL/resources/Shaders/basic3d.fs @@ -0,0 +1,34 @@ +#version 330 core + +out vec4 FragColor; + +in vec3 FragmentNormal; +in vec3 FragPos; + +uniform vec3 lightPos = vec3(3, 3, 3); +uniform vec3 cameraPosition; +uniform vec3 lightColor = vec3(1,1,1); +uniform vec3 objectColor = vec3(0.3,0.3,0.3); + +void main() +{ + // ambient + float ambientStrength = 0.1; + vec3 ambient = ambientStrength * lightColor; + + // diffuse + vec3 norm = normalize(FragmentNormal); + vec3 lightDir = normalize(lightPos - FragPos); + float diff = max(dot(norm, lightDir), 0.0); + vec3 diffuse = diff * lightColor; + + // specular + float specularStrength = 0.5; + vec3 viewDir = normalize(cameraPosition - FragPos); + vec3 reflectDir = reflect(-lightDir, norm); + float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32); + vec3 specular = specularStrength * spec * lightColor; + + vec3 result = (ambient + diffuse + specular) * objectColor; + FragColor = vec4(result, 1.0); +} \ No newline at end of file diff --git a/AimGL/resources/Shaders/basic3d.vs b/AimGL/resources/Shaders/basic3d.vs new file mode 100644 index 0000000..3c732a4 --- /dev/null +++ b/AimGL/resources/Shaders/basic3d.vs @@ -0,0 +1,21 @@ +#version 330 core + +layout(location = 0) in vec3 position; // Vertex position +layout(location = 1) in vec3 normal; // Norm +layout(location = 2) in vec2 texCoords; // Texture coordinates + +out vec3 FragmentNormal; +out vec3 FragPos; + +uniform mat4 model = mat4(1.0); +uniform mat4 view; +uniform mat4 projection; + +void main() +{ + mat4 mvp = projection * view * model; + FragPos = vec3(model * vec4(normal, 1.0)); + FragmentNormal = mat3(transpose(inverse(model))) * normal; + + gl_Position = mvp * vec4(position, 1.0); +} \ No newline at end of file diff --git a/AimGL/resources/Shaders/veryBasic3d.fs b/AimGL/resources/Shaders/veryBasic3d.fs new file mode 100644 index 0000000..2a7e6e0 --- /dev/null +++ b/AimGL/resources/Shaders/veryBasic3d.fs @@ -0,0 +1,13 @@ +#version 330 core + +out vec4 FragColor; + +uniform vec3 lightPos = vec3(3, 3, 3); +uniform vec3 cameraPosition; +uniform vec3 lightColor = vec3(1,1,1); +uniform vec3 objectColor = vec3(0.3,0.3,0.3); + +void main() +{ + FragColor = vec4(0.5,0.5,0.5, 1.0); +} \ No newline at end of file diff --git a/AimGL/resources/Shaders/veryBasic3d.vs b/AimGL/resources/Shaders/veryBasic3d.vs new file mode 100644 index 0000000..443a3d4 --- /dev/null +++ b/AimGL/resources/Shaders/veryBasic3d.vs @@ -0,0 +1,15 @@ +#version 330 core + +layout(location = 0) in vec3 position; // Vertex position +layout(location = 1) in vec3 normal; // Norm +layout(location = 2) in vec2 texCoords; // Texture coordinates + +uniform mat4 model = mat4(1.0); +uniform mat4 view; +uniform mat4 projection; + +void main() +{ + mat4 mvp = projection * view * model; + gl_Position = mvp * vec4(position, 1.0); +} \ No newline at end of file diff --git a/AimGL/src/CMakeLists_Sources.txt b/AimGL/src/CMakeLists_Sources.txt index 80d47cc..722cd5a 100644 --- a/AimGL/src/CMakeLists_Sources.txt +++ b/AimGL/src/CMakeLists_Sources.txt @@ -11,9 +11,12 @@ set(PROJECT_SOURCES Renderer/Core/OpenglUtils.cpp Renderer/Graphics/Texture.cpp Renderer/Graphics/2D/Sprite2D.cpp - Renderer/Graphics/3D/Sprite3D.cpp Renderer/Graphics/2D/Rectangle2D.cpp + Renderer/Graphics/3D/Sprite3D.cpp + Renderer/Graphics/3D/Core/Mesh.cpp + Renderer/Graphics/3D/Model.cpp Renderer/Renderer.cpp + Resources/ObjLoader.cpp States/State.cpp States/StateStack.cpp States/CustomStates/LogoState.cpp diff --git a/AimGL/src/Game.cpp b/AimGL/src/Game.cpp index b5dd81c..9edd9e4 100644 --- a/AimGL/src/Game.cpp +++ b/AimGL/src/Game.cpp @@ -72,7 +72,7 @@ Game::Game() mAppStack.saveState(State_ID::GameState, *mGameWindow); // Initial state of the statestack is TitleState - mAppStack.push(State_ID::LogoState); + mAppStack.push(State_ID::GameState); } void Game::run() diff --git a/AimGL/src/Renderer/Core/Shader.cpp b/AimGL/src/Renderer/Core/Shader.cpp index b1b4d73..5caf613 100644 --- a/AimGL/src/Renderer/Core/Shader.cpp +++ b/AimGL/src/Renderer/Core/Shader.cpp @@ -38,6 +38,11 @@ void Shader::setUniform(const std::string& name, glm::vec4 vec) const GLCall(glUniform4fv(getUniformLocation(name), 1, glm::value_ptr(vec))); } +void Shader::setUniform(const std::string& name, glm::vec3 vec) const +{ + GLCall(glUniform3fv(getUniformLocation(name), 1, glm::value_ptr(vec))); +} + void Shader::setUniform(const std::string& name, float f1, float f2, float f3, float f4) const { GLCall(glUniform4f(getUniformLocation(name), f1, f2, f3, f4)); diff --git a/AimGL/src/Renderer/Core/Shader.h b/AimGL/src/Renderer/Core/Shader.h index 74fe13c..dbe6834 100644 --- a/AimGL/src/Renderer/Core/Shader.h +++ b/AimGL/src/Renderer/Core/Shader.h @@ -65,6 +65,7 @@ class Shader void setUniform(const std::string& name, glm::mat4 mat) const; void setUniform(const std::string& name, glm::vec4 vec) const; + void setUniform(const std::string& name, glm::vec3 vec) const; void setUniform(const std::string& name, float f1, float f2, float f3, float f4) const; void setUniform(const std::string& name, float f1, float f2, float f3) const; void setUniform(const std::string& name, float f1, float f2) const; diff --git a/AimGL/src/Renderer/Graphics/3D/Core/Mesh.cpp b/AimGL/src/Renderer/Graphics/3D/Core/Mesh.cpp new file mode 100644 index 0000000..2c77391 --- /dev/null +++ b/AimGL/src/Renderer/Graphics/3D/Core/Mesh.cpp @@ -0,0 +1,2 @@ +#include "Mesh.h" +#include "pch.h" \ No newline at end of file diff --git a/AimGL/src/Renderer/Graphics/3D/Core/Mesh.h b/AimGL/src/Renderer/Graphics/3D/Core/Mesh.h new file mode 100644 index 0000000..cd33c0d --- /dev/null +++ b/AimGL/src/Renderer/Graphics/3D/Core/Mesh.h @@ -0,0 +1,47 @@ +#pragma once + +#include "Renderer/Graphics/3D/Core/Vertex.h" + +#include +#include +#include +#include +#include +#include + +class Mesh +{ +public: + Mesh(const std::vector& vertices, const std::vector& indices, + const std::vector& textures) + : vertices(vertices), + indices(indices), + textures(textures) + { + mVBO.setBuffer(vertices.data(), vertices.size()); + mEBO.setBuffer(indices.data(), indices.size()); + + mVAO.bind(); + mVBO.bind(); + mBufferLayout.push(3); + mBufferLayout.push(3); + mBufferLayout.push(2); + mVAO.setBuffer(mVBO, mBufferLayout); + mVAO.unbind(); + } + + void draw(const Renderer& target, const Camera& camera, const Shader& shader) const + { + target.draw3D(mVAO, mEBO, shader, camera); + } + +private: + std::vector vertices; + std::vector indices; + std::vector textures; // TODO: resource manager should be used there + + VertexArray mVAO; + VertexBuffer mVBO; + IndexBuffer mEBO; + BufferLayout mBufferLayout; +}; diff --git a/AimGL/src/Renderer/Graphics/3D/Core/Vertex.h b/AimGL/src/Renderer/Graphics/3D/Core/Vertex.h new file mode 100644 index 0000000..08d411b --- /dev/null +++ b/AimGL/src/Renderer/Graphics/3D/Core/Vertex.h @@ -0,0 +1,8 @@ +#pragma once + +struct Vertex +{ + glm::vec3 position; + glm::vec3 normal; + glm::vec2 textureCoordinates; +}; \ No newline at end of file diff --git a/AimGL/src/Renderer/Graphics/3D/Model.cpp b/AimGL/src/Renderer/Graphics/3D/Model.cpp new file mode 100644 index 0000000..b658f14 --- /dev/null +++ b/AimGL/src/Renderer/Graphics/3D/Model.cpp @@ -0,0 +1,2 @@ +#include "Model.h" +#include "pch.h" \ No newline at end of file diff --git a/AimGL/src/Renderer/Graphics/3D/Model.h b/AimGL/src/Renderer/Graphics/3D/Model.h new file mode 100644 index 0000000..0f6c741 --- /dev/null +++ b/AimGL/src/Renderer/Graphics/3D/Model.h @@ -0,0 +1,27 @@ +#pragma once +#include "Core/Mesh.h" + +#include +#include + +class Model +{ +public: + explicit Model(const std::string objFilePath) + : mShader{{ShaderType::VertexShader, "resources/Shaders/veryBasic3d.vs"}, + {ShaderType::FragmentShader, "resources/Shaders/veryBasic3d.fs"}} + , mObjLoader(objFilePath) + , mMesh(mObjLoader.vertices(), mObjLoader.indices(), std::vector{}) + { + } + + void draw(const Renderer& target, const Camera& camera) const + { + mMesh.draw(target, camera, mShader); + } + +private: + Shader mShader; + ObjLoader mObjLoader; + Mesh mMesh; +}; diff --git a/AimGL/src/Renderer/Renderer.cpp b/AimGL/src/Renderer/Renderer.cpp index a395204..1ec58c4 100644 --- a/AimGL/src/Renderer/Renderer.cpp +++ b/AimGL/src/Renderer/Renderer.cpp @@ -40,6 +40,7 @@ void Renderer::draw3D(const VertexArray& va, const IndexBuffer& ib, const Shader const auto projection = camera.projection(); shader.setUniform("view", view); shader.setUniform("projection", projection); + shader.setUniform("cameraPosition", camera.cameraPosition()); GLCall(glDrawElements(toOpenGl(drawMode), ib.size(), GL_UNSIGNED_INT, nullptr)); #ifdef _DEBUG diff --git a/AimGL/src/Resources/ObjLoader.cpp b/AimGL/src/Resources/ObjLoader.cpp new file mode 100644 index 0000000..7825632 --- /dev/null +++ b/AimGL/src/Resources/ObjLoader.cpp @@ -0,0 +1,2 @@ +#include "ObjLoader.h" +#include "pch.h" \ No newline at end of file diff --git a/AimGL/src/Resources/ObjLoader.h b/AimGL/src/Resources/ObjLoader.h new file mode 100644 index 0000000..6462ea8 --- /dev/null +++ b/AimGL/src/Resources/ObjLoader.h @@ -0,0 +1,126 @@ +#pragma once +#include +#include + + +class ObjLoader +{ +public: + ObjLoader(const std::string& objFilePath) + { + loadObject(objFilePath); + } + + [[nodiscard]] const std::vector& vertices() const + { + return mVertices; + } + [[nodiscard]] const std::vector& indices() const + { + return mIndices; + } + +private: + std::vector mVertices; + std::vector mPositions; + std::vector mNormals; + std::vector mTextureCoordinates; + std::vector mIndices; + + void loadObject(const std::string& objFilePath) + { + std::ifstream file(objFilePath); + std::string line; + while (std::getline(file, line)) + { + parseLine(line); + } + + /* + assert(mPositions.size() == mNormals.size() == mTextureCoordinates.size()); + for (auto i = 0; i < mPositions.size(); ++i) + { + mVertices.push_back(Vertex(mPositions[i], mNormals[i], mTextureCoordinates[i])); + } + + mPositions.clear(); + mNormals.clear(); + mTextureCoordinates.clear(); + */ + } + + void parseVertex(std::istringstream& ss) + { + glm::vec3 position; + ss >> position.x >> position.y >> position.z; + mPositions.push_back(position); + } + + void parseNormal(std::istringstream& ss) + { + glm::vec3 normal; + ss >> normal.x >> normal.y >> normal.z; + mNormals.push_back(normal); + } + + void parseTextureCoordinate(std::istringstream& ss) + { + glm::vec2 textureCoordinate; + ss >> textureCoordinate.x >> textureCoordinate.y; + mTextureCoordinates.push_back(textureCoordinate); + } + + std::tuple parseIndices(const std::string& vertex) + { + std::istringstream vertexStream(vertex); + std::string index; + std::vector indices; + + while (std::getline(vertexStream, index, '/')) + { + if (!index.empty()) + { + indices.push_back(std::stoi(index) - 1); + } + } + + return {indices[0], indices[1], indices[2]}; + } + + void parseFace(std::istringstream& ss) + { + std::string vertex; + while (ss >> vertex) + { + auto [positionIndex, textureIndex, normalIndex] = parseIndices(vertex); + Vertex v{mPositions[positionIndex], + mNormals[normalIndex], mTextureCoordinates[textureIndex]}; + mVertices.push_back(v); + mIndices.push_back(mIndices.size()); + } + } + + void parseLine(const std::string& line) + { + std::istringstream ss(line); + std::string prefix; + ss >> prefix; + + if (prefix == "v") + { + parseVertex(ss); + } + else if (prefix == "vn") + { + parseNormal(ss); + } + else if (prefix == "vt") + { + parseTextureCoordinate(ss); + } + else if (prefix == "f") + { + parseFace(ss); + } + } +}; diff --git a/AimGL/src/States/CustomStates/GameState.cpp b/AimGL/src/States/CustomStates/GameState.cpp index 15609e5..0ab62ff 100644 --- a/AimGL/src/States/CustomStates/GameState.cpp +++ b/AimGL/src/States/CustomStates/GameState.cpp @@ -13,6 +13,7 @@ GameState::GameState(StateStack& stack, WindowToRender& window) , mCamera(window) , mGameBackground(glm::vec2(1280, 720.f), glm::vec4(0.85f, 0.85f, 0.85f, 1.f)) , mPhaseInLogoColor({window.getSize().x, window.getSize().y}, {0.067f, 0.11f, 0.18f, 1.1f}) + , tree("resources/Models/plane.obj") { Mouse::lockMouseAtCenter(mWindow); mLogo.setHeight(2.f); @@ -29,7 +30,8 @@ void GameState::draw(sf::Window& target) const MTR_SCOPE("GameState", "GameState::draw"); mGameBackground.draw(mRenderer); mInfiniteGridFloor.draw(target, mCamera); - mLogo.draw(mRenderer, mCamera); + tree.draw(mRenderer, mCamera); + // mLogo.draw(mRenderer, mCamera); mPhaseInLogoColor.draw(mRenderer); } @@ -71,6 +73,7 @@ bool GameState::updateImGui(const float& deltaTime) { MTR_SCOPE("GameState", "GameState::updateImGui"); mCamera.updateImGui(); + mInfiniteGridFloor.showDebugImGui(); ImGui::ShowDemoWindow(); return true; } diff --git a/AimGL/src/States/CustomStates/GameState.h b/AimGL/src/States/CustomStates/GameState.h index e4d6cd4..a09ec8b 100644 --- a/AimGL/src/States/CustomStates/GameState.h +++ b/AimGL/src/States/CustomStates/GameState.h @@ -7,6 +7,8 @@ #include "World/Camera.h" #include "World/InfiniteGridFloor.h" +#include + class StateStack; /** @@ -58,4 +60,5 @@ class GameState : public State sf::Clock mPhaseInClock; Rectangle2D mPhaseInLogoColor; InfiniteGridFloor mInfiniteGridFloor; + Model tree; }; diff --git a/AimGL/src/World/InfiniteGridFloor.cpp b/AimGL/src/World/InfiniteGridFloor.cpp index 31f74d7..c5e1cff 100644 --- a/AimGL/src/World/InfiniteGridFloor.cpp +++ b/AimGL/src/World/InfiniteGridFloor.cpp @@ -21,3 +21,14 @@ void InfiniteGridFloor::draw(sf::Window& target, const Camera& camera) const glDrawArrays(GL_TRIANGLES, 0, 6); mInfiniteGridShader.unbind(); } + +void InfiniteGridFloor::showDebugImGui(std::string name) +{ + name = "[InfiniteGridFloor] " + name; + ImGui::Begin(name.c_str()); + ImGui::SliderFloat("Far", &mFar, 0.0f, 5.f); + ImGui::End(); + mInfiniteGridShader.bind(); + mInfiniteGridShader.setUniform("far", mFar); + mInfiniteGridShader.unbind(); +} diff --git a/AimGL/src/World/InfiniteGridFloor.h b/AimGL/src/World/InfiniteGridFloor.h index 8b19134..3250144 100644 --- a/AimGL/src/World/InfiniteGridFloor.h +++ b/AimGL/src/World/InfiniteGridFloor.h @@ -25,6 +25,12 @@ class InfiniteGridFloor */ void draw(sf::Window& target, const Camera& camera) const; + /** + * \brief TODO: THIS + */ + void showDebugImGui(std::string name = ""); + private: Shader mInfiniteGridShader; + float mFar = 5.f; }; \ No newline at end of file