From bc8b7e2842a9aa68635eb770aae7b28cd98b3802 Mon Sep 17 00:00:00 2001 From: BlazingTwist Date: Thu, 11 Nov 2021 16:22:00 +0100 Subject: [PATCH 01/12] meshStripper implemented --- resources/shader/demo.frag | 8 + resources/shader/demo.vert | 8 + src/engine/graphics/core/geometrybuffer.cpp | 10 +- src/engine/utils/meshstripper.cpp | 217 ++++++++++++++++++++ src/engine/utils/meshstripper.hpp | 37 ++++ src/main.cpp | 163 ++++++++++++--- 6 files changed, 416 insertions(+), 27 deletions(-) create mode 100644 resources/shader/demo.frag create mode 100644 resources/shader/demo.vert create mode 100644 src/engine/utils/meshstripper.cpp create mode 100644 src/engine/utils/meshstripper.hpp diff --git a/resources/shader/demo.frag b/resources/shader/demo.frag new file mode 100644 index 00000000..ac63cad8 --- /dev/null +++ b/resources/shader/demo.frag @@ -0,0 +1,8 @@ +#version 330 + +layout(location = 0) out vec3 out_color; + +void main() +{ + out_color = vec3(1.f,1.f,1.f); +} \ No newline at end of file diff --git a/resources/shader/demo.vert b/resources/shader/demo.vert new file mode 100644 index 00000000..d4d321eb --- /dev/null +++ b/resources/shader/demo.vert @@ -0,0 +1,8 @@ +#version 330 + +layout(location = 0) in vec2 in_position; + +void main() +{ + gl_Position = vec4(in_position,0.f,1.f); +} \ No newline at end of file diff --git a/src/engine/graphics/core/geometrybuffer.cpp b/src/engine/graphics/core/geometrybuffer.cpp index f2ed4f67..1cd68acb 100644 --- a/src/engine/graphics/core/geometrybuffer.cpp +++ b/src/engine/graphics/core/geometrybuffer.cpp @@ -42,7 +42,9 @@ namespace graphics { m_indexSize(_indexed), m_vertexCount(0), m_indexCount(0), - m_instanceCount(0) + m_instanceCount(0), + m_vao(0), + m_vbo(0) { // Analyze vertex data (vertexsize, instancesize) for(int i = 0; i < _numAttributes; ++i) @@ -80,13 +82,13 @@ namespace graphics { glCall(glBufferData, GL_ARRAY_BUFFER, m_instanceCapacity, nullptr, GL_STATIC_DRAW); // Bind Attributes - unsigned offset = 0; + unsigned offset2 = 0; for(int i = 0; i < _numAttributes; ++i) if(_attributes[i].perInstance) { // Also set this attribute to be instanced glCall(glVertexAttribDivisor, attribIndex, 1); - enableAttribute(attribIndex++, _attributes[i], m_instanceVertexSize, offset); - offset += attributeSize(_attributes[i]); + enableAttribute(attribIndex++, _attributes[i], m_instanceVertexSize, offset2); + offset2 += attributeSize(_attributes[i]); } } diff --git a/src/engine/utils/meshstripper.cpp b/src/engine/utils/meshstripper.cpp new file mode 100644 index 00000000..0ab1aac1 --- /dev/null +++ b/src/engine/utils/meshstripper.cpp @@ -0,0 +1,217 @@ +#include +#include "meshstripper.hpp" + +namespace utils { + TriangleStrip *TriangleStrip::create(utils::MeshData::FaceData face1, utils::MeshData::FaceData face2, std::array vertices) { + auto *strip = new TriangleStrip; + strip->triangles.push_back(face1); + strip->triangles.push_back(face2); + for (const auto &vertexIndex: vertices) { + strip->vertexIndices.push_back(vertexIndex); + } + return strip; + } + + TriangleStrip * + TriangleStrip::create(utils::MeshData::FaceData face1, utils::MeshData::FaceData face2, utils::MeshData::FaceData face3, std::array vertices) { + auto *strip = new TriangleStrip; + strip->triangles.push_back(face1); + strip->triangles.push_back(face2); + strip->triangles.push_back(face3); + for (const auto &vertexIndex: vertices) { + strip->vertexIndices.push_back(vertexIndex); + } + return strip; + } + + TriangleStrip::~TriangleStrip() { + vertexIndices.clear(); + triangles.clear(); + } + + bool findConnectedTriangle(std::array firstFace, std::vector *remainingFaces, utils::MeshData::FaceData &face2, + std::array &result) { + int connectedVertexIndex; + for (auto iterator = remainingFaces->begin(); iterator != remainingFaces->end(); ++iterator) { + connectedVertexIndex = 1; // reset index + for (const auto &vertexB: (*iterator).indices) { + bool didMatch = false; + for (const auto &indexA: firstFace) { + if (indexA == vertexB.positionIdx) { + didMatch = true; + result[connectedVertexIndex] = indexA; + connectedVertexIndex++; + } + } + if (!didMatch) { + result[3] = vertexB.positionIdx; + } + } + + if (connectedVertexIndex > 2) { + // find unique vertex of first face + for (const auto &indexA: firstFace) { + if (indexA != result[1] && indexA != result[2]) { + result[0] = indexA; + break; + } + } + + remainingFaces->erase(iterator); + return true; + } + } + return false; + } + + bool findConnectedTriangle(std::array stripOfTwo, std::vector *remainingFaces, utils::MeshData::FaceData &face3, + std::array &result) { + for (auto iterator = remainingFaces->begin(); iterator != remainingFaces->end(); ++iterator) { + int outerMatchIndex = -1; // marks which end of the strip the triangle connects to + int innerMatchIndex = -1; // marks which inner vertex the triangle connects to + int uniqueVertex = 0; // the one vertex of the triangle that doesn't connect to the strip + for (const auto &vertexB: (*iterator).indices) { + int vertexIndex = vertexB.positionIdx; + if (vertexIndex == stripOfTwo[0]) { + outerMatchIndex = 0; + } else if (vertexIndex == stripOfTwo[3]) { + outerMatchIndex = 3; + } else if (vertexIndex == stripOfTwo[1]) { + innerMatchIndex = 1; + } else if (vertexIndex == stripOfTwo[2]) { + innerMatchIndex = 2; + } else { + uniqueVertex = vertexIndex; + } + } + + // only consider triangles that have an outer and inner match + if (outerMatchIndex < 0 || innerMatchIndex < 0) { + continue; + } + + // make sure the inner and outer matching vertices are directly connected + if ((outerMatchIndex == 0 && innerMatchIndex == 2) + || (outerMatchIndex == 3 && innerMatchIndex == 1)) { + int temp = stripOfTwo[2]; + stripOfTwo[2] = stripOfTwo[1]; + stripOfTwo[1] = temp; + } + + if (outerMatchIndex == 0) { + result[0] = uniqueVertex; + std::copy(stripOfTwo.begin(), stripOfTwo.begin() + 4, result.begin() + 1); + } else if (outerMatchIndex == 3) { + std::copy(stripOfTwo.begin(), stripOfTwo.begin() + 4, result.begin()); + result[4] = uniqueVertex; + } + remainingFaces->erase(iterator); + return true; + } + return false; + } + + bool areFacesConnected(int vertex1, int vertex2, utils::MeshData::FaceData face, int &foundVertex) { + int matches = 0; + for (const auto &index: face.indices) { + if (index.positionIdx == vertex1 || index.positionIdx == vertex2) { + matches++; + } else { + foundVertex = index.positionIdx; + } + } + return matches >= 2; + } + + void expandTriangleStrip(TriangleStrip *stripToExpand, std::vector *remainingFaces) { + int vertA1 = stripToExpand->vertexIndices[0]; + int vertA2 = stripToExpand->vertexIndices[1]; + const auto vertIteratorEnd = stripToExpand->vertexIndices.end(); + int vertB1 = *(vertIteratorEnd - 1); + int vertB2 = *(vertIteratorEnd - 2); + + int count = 0; + while (!remainingFaces->empty()) { + int foundConnectedFace = false; + for (auto iterator = remainingFaces->begin(); iterator != remainingFaces->end(); ++iterator) { + int foundVertex; + if (areFacesConnected(vertA1, vertA2, *iterator, foundVertex)) { + vertA2 = vertA1; + vertA1 = foundVertex; + stripToExpand->vertexIndices.insert(stripToExpand->vertexIndices.begin(), foundVertex); + stripToExpand->triangles.insert(stripToExpand->triangles.begin(), *iterator); + remainingFaces->erase(iterator); + foundConnectedFace = true; + count++; + break; + } + if (areFacesConnected(vertB1, vertB2, *iterator, foundVertex)) { + vertB2 = vertB1; + vertB1 = foundVertex; + stripToExpand->vertexIndices.push_back(foundVertex); + stripToExpand->triangles.push_back(*iterator); + remainingFaces->erase(iterator); + foundConnectedFace = true; + count++; + break; + } + } + + if (!foundConnectedFace) { + break; + } + } + } + + MeshStripData::Handle MeshStripData::createFromMeshData(const utils::MeshData *data) { + auto *result = new MeshStripData; + + std::vector remainingFaces = data->faces; + while (!remainingFaces.empty()) { + utils::MeshData::FaceData face1 = *remainingFaces.begin(); + remainingFaces.erase(remainingFaces.begin()); + + utils::MeshData::FaceData face2; + std::array twoTriangleStrip = {}; + bool foundFace2 = findConnectedTriangle( + { + face1.indices[0].positionIdx, + face1.indices[1].positionIdx, + face1.indices[2].positionIdx + }, + &remainingFaces, + face2, + twoTriangleStrip + ); + if (!foundFace2) { + result->floatingTriangles.push_back(face1); + continue; + } + + utils::MeshData::FaceData face3; + std::array threeTriangleStrip = {}; + bool foundFace3 = findConnectedTriangle( + twoTriangleStrip, + &remainingFaces, + face3, + threeTriangleStrip + ); + + if (!foundFace3) { + result->triangleStrips.push_back(*TriangleStrip::create(face1, face2, twoTriangleStrip)); + continue; + } + + TriangleStrip *strip = TriangleStrip::create(face1, face2, face3, threeTriangleStrip); + expandTriangleStrip(strip, &remainingFaces); + result->triangleStrips.push_back(*strip); + } + + return result; + } + + MeshStripData::~MeshStripData() { + triangleStrips.clear(); + floatingTriangles.clear(); + } +} \ No newline at end of file diff --git a/src/engine/utils/meshstripper.hpp b/src/engine/utils/meshstripper.hpp new file mode 100644 index 00000000..f900e7e8 --- /dev/null +++ b/src/engine/utils/meshstripper.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include +#include +#include + +namespace utils { + + /** + * @brief describes a single triangle strip of a mesh + */ + struct TriangleStrip { + std::vector vertexIndices = {}; + std::vector triangles = {}; + + virtual ~TriangleStrip(); + + static TriangleStrip* create(utils::MeshData::FaceData face1, utils::MeshData::FaceData face2, std::array vertices); + + static TriangleStrip* + create(utils::MeshData::FaceData face1, utils::MeshData::FaceData face2, utils::MeshData::FaceData face3, std::array vertices); + }; + + /** + * @brief contains the MeshData split into triangle strips + */ + struct MeshStripData { + std::vector floatingTriangles = {}; + std::vector triangleStrips = {}; + + virtual ~MeshStripData(); + + using Handle = const MeshStripData *; + + static Handle createFromMeshData(const utils::MeshData *data); + }; +} diff --git a/src/main.cpp b/src/main.cpp index 4b53e1f5..cef01857 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,49 +1,166 @@ #include #include -#include #include #include -#include #include #include +#include +#include +#include +#include #include // CRT's memory leak detection -#ifndef NDEBUG +#ifndef NDEBUG #if defined(_MSC_VER) #define _CRTDBG_MAP_ALLOC + #include + #endif #endif using namespace std::chrono_literals; -int main(int argc, char *argv[]) -{ -#ifndef NDEBUG +graphics::GeometryBuffer *createStripBuffer(graphics::VertexAttribute *vertexAttribute) { + auto *buffer = new graphics::GeometryBuffer( + graphics::GLPrimitiveType::TRIANGLE_STRIPE, + vertexAttribute, + 1, + 0 + ); + return buffer; +} + +graphics::GeometryBuffer *createTriangleBuffer(graphics::VertexAttribute *vertexAttribute) { + auto *buffer = new graphics::GeometryBuffer( + graphics::GLPrimitiveType::TRIANGLES, + vertexAttribute, + 1, + 0 + ); + return buffer; +} + +int main(int argc, char *argv[]) { +#ifndef NDEBUG #if defined(_MSC_VER) - _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); - // _CrtSetBreakAlloc(2760); + _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); + // _CrtSetBreakAlloc(2760); #endif #endif - graphics::Device::initialize(1366, 768,false); - GLFWwindow* window = graphics::Device::getWindow(); - input::InputManager::initialize(window); + glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE); - graphics::glCall(glClearColor,0.f, 1.f, 0.f, 1.f); + graphics::Device::initialize(1366, 1366, false); + GLFWwindow *window = graphics::Device::getWindow(); + input::InputManager::initialize(window); - while (!glfwWindowShouldClose(window) && !input::InputManager::isKeyPressed(input::Key::ESCAPE)) - { - graphics::glCall(glClear, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + utils::MeshData::Handle data = utils::MeshLoader::get("models/sphere.obj"); + utils::MeshStripData::Handle meshStripData = utils::MeshStripData::createFromMeshData(data); - glfwPollEvents(); - glfwSwapBuffers(window); - std::this_thread::sleep_for(16ms); - } + graphics::VertexAttribute vertexAttribute{ + graphics::PrimitiveFormat::FLOAT, + 3, + false, + false + }; - utils::MeshLoader::clear(); - graphics::Device::close(); - return EXIT_SUCCESS; -} + glm::vec3 triangles_tri[] = { + glm::vec3(-1.0f, -1.0f, 0.0f), + glm::vec3(1.0f, -1.0f, 0.0f), + glm::vec3(0.0f, 1.0f, 0.0f), + }; + glm::vec3 triangles_rect[] = { + glm::vec3(-0.75f, -0.75f, 0.0f), + glm::vec3(0.75f, -0.75f, 0.0f), + glm::vec3(-0.75f, 0.75f, 0.0f), + glm::vec3(0.75f, 0.75f, 0.0f), + }; + + std::vector buffers = {}; + + { + graphics::GeometryBuffer *buffer = createStripBuffer(&vertexAttribute); + buffer->setData(&triangles_rect, sizeof(triangles_rect)); + buffers.push_back(buffer); + } + + graphics::Shader::Handle fragmentShader = graphics::ShaderManager::get("shader/demo.frag", graphics::ShaderType::FRAGMENT); + graphics::Shader::Handle vertexShader = graphics::ShaderManager::get("shader/demo.vert", graphics::ShaderType::VERTEX); + + graphics::Program program; + program.attach(vertexShader); + program.attach(fragmentShader); + program.link(); + program.use(); + + graphics::glCall(glClearColor, 0.f, 1.f, 0.f, 1.f); + + bool wasSPressed = false; + + while (!glfwWindowShouldClose(window) && !input::InputManager::isKeyPressed(input::Key::ESCAPE)) { + graphics::glCall(glClear, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + if (input::InputManager::isKeyPressed(input::Key::T)) { + buffers.clear(); + graphics::GeometryBuffer *buffer = createStripBuffer(&vertexAttribute); + buffer->setData(&triangles_tri, sizeof(triangles_tri)); + buffers.push_back(buffer); + } + if (input::InputManager::isKeyPressed(input::Key::R)) { + buffers.clear(); + graphics::GeometryBuffer *buffer = createStripBuffer(&vertexAttribute); + buffer->setData(&triangles_rect, sizeof(triangles_rect)); + buffers.push_back(buffer); + } + if (input::InputManager::isKeyPressed(input::Key::S)) { + if (!wasSPressed) { + wasSPressed = true; + buffers.clear(); + + graphics::GeometryBuffer *triBuffer = createTriangleBuffer(&vertexAttribute); + { + auto *triBufferData = new glm::vec3[meshStripData->floatingTriangles.size() * 3]; + int dataIndex = 0; + for (const auto &floatingTriangle: meshStripData->floatingTriangles) { + triBufferData[dataIndex] = data->positions[floatingTriangle.indices[0].positionIdx]; + triBufferData[dataIndex + 1] = data->positions[floatingTriangle.indices[1].positionIdx]; + triBufferData[dataIndex + 2] = data->positions[floatingTriangle.indices[2].positionIdx]; + dataIndex += 3; + } + triBuffer->setData(triBufferData, sizeof(glm::vec3) * meshStripData->floatingTriangles.size() * 3); + } + buffers.push_back(triBuffer); + + for (const auto &strip: meshStripData->triangleStrips) { + auto *stripBuffer = createStripBuffer(&vertexAttribute); + unsigned int vertexCount = strip.vertexIndices.size(); + auto *stripBufferData = new glm::vec3[vertexCount]; + int dataIndex = 0; + for (const auto &vertexIndex: strip.vertexIndices) { + stripBufferData[dataIndex] = data->positions[vertexIndex]; + dataIndex++; + } + stripBuffer->setData(stripBufferData, sizeof(glm::vec3) * vertexCount); + buffers.push_back(stripBuffer); + } + } + } else { + wasSPressed = false; + } + + for (const auto &buffer: buffers) { + buffer->draw(); + } + + glfwPollEvents(); + glfwSwapBuffers(window); + std::this_thread::sleep_for(16ms); + } + + utils::MeshLoader::clear(); + graphics::Device::close(); + return EXIT_SUCCESS; +} \ No newline at end of file From 9feee6a35dcb923c3d9567a9b4b311f8d95e2ad5 Mon Sep 17 00:00:00 2001 From: BlazingTwist Date: Fri, 12 Nov 2021 13:10:03 +0100 Subject: [PATCH 02/12] started implementing uv mapping --- resources/shader/demo.frag | 8 ++-- resources/shader/demo.vert | 9 +++-- src/main.cpp | 79 ++++++++++++++++++++++++++++---------- 3 files changed, 69 insertions(+), 27 deletions(-) diff --git a/resources/shader/demo.frag b/resources/shader/demo.frag index ac63cad8..62ee5e8a 100644 --- a/resources/shader/demo.frag +++ b/resources/shader/demo.frag @@ -1,8 +1,10 @@ -#version 330 +#version 450 -layout(location = 0) out vec3 out_color; +layout(location = 0) in vec2 tex_coord; +layout(binding = 0) uniform sampler2D tx_color; +layout(location = 0) out vec4 out_color; void main() { - out_color = vec3(1.f,1.f,1.f); + out_color = texture(tx_color, tex_coord); } \ No newline at end of file diff --git a/resources/shader/demo.vert b/resources/shader/demo.vert index d4d321eb..173a795a 100644 --- a/resources/shader/demo.vert +++ b/resources/shader/demo.vert @@ -1,8 +1,11 @@ -#version 330 +#version 450 -layout(location = 0) in vec2 in_position; +layout(location = 0) in vec3 in_position; +layout(location = 1) in vec2 uv_coord; +layout(location = 0) out vec2 tex_coord; void main() { - gl_Position = vec4(in_position,0.f,1.f); + gl_Position = vec4(in_position,1.f); + tex_coord = uv_coord; } \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index cef01857..79ac6fb5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,32 +17,38 @@ #define _CRTDBG_MAP_ALLOC #include +#include #endif #endif using namespace std::chrono_literals; -graphics::GeometryBuffer *createStripBuffer(graphics::VertexAttribute *vertexAttribute) { +graphics::GeometryBuffer *createStripBuffer(graphics::VertexAttribute *vertexAttribute, int numAttributes) { auto *buffer = new graphics::GeometryBuffer( graphics::GLPrimitiveType::TRIANGLE_STRIPE, vertexAttribute, - 1, + numAttributes, 0 ); return buffer; } -graphics::GeometryBuffer *createTriangleBuffer(graphics::VertexAttribute *vertexAttribute) { +graphics::GeometryBuffer *createTriangleBuffer(graphics::VertexAttribute *vertexAttribute, int numAttributes) { auto *buffer = new graphics::GeometryBuffer( graphics::GLPrimitiveType::TRIANGLES, vertexAttribute, - 1, + numAttributes, 0 ); return buffer; } +struct VertexData { + glm::vec3 positionData; + glm::vec2 uvData; +}; + int main(int argc, char *argv[]) { #ifndef NDEBUG #if defined(_MSC_VER) @@ -57,14 +63,26 @@ int main(int argc, char *argv[]) { GLFWwindow *window = graphics::Device::getWindow(); input::InputManager::initialize(window); + static graphics::Sampler sampler(graphics::Sampler::Filter::LINEAR, graphics::Sampler::Filter::LINEAR, + graphics::Sampler::Filter::LINEAR, graphics::Sampler::Border::MIRROR); + auto texture = graphics::Texture2DManager::get("textures/planet1.png", sampler); + texture->bind(0); utils::MeshData::Handle data = utils::MeshLoader::get("models/sphere.obj"); utils::MeshStripData::Handle meshStripData = utils::MeshStripData::createFromMeshData(data); - graphics::VertexAttribute vertexAttribute{ - graphics::PrimitiveFormat::FLOAT, - 3, - false, - false + graphics::VertexAttribute vertexAttribute[] = { + { + graphics::PrimitiveFormat::FLOAT, + 3, + false, + false + }, + { + graphics::PrimitiveFormat::FLOAT, + 2, + false, + false + } }; glm::vec3 triangles_tri[] = { @@ -79,10 +97,10 @@ int main(int argc, char *argv[]) { glm::vec3(0.75f, 0.75f, 0.0f), }; - std::vector buffers = {}; + std::vector < graphics::GeometryBuffer * > buffers = {}; { - graphics::GeometryBuffer *buffer = createStripBuffer(&vertexAttribute); + graphics::GeometryBuffer *buffer = createStripBuffer(vertexAttribute, 1); buffer->setData(&triangles_rect, sizeof(triangles_rect)); buffers.push_back(buffer); } @@ -105,13 +123,13 @@ int main(int argc, char *argv[]) { if (input::InputManager::isKeyPressed(input::Key::T)) { buffers.clear(); - graphics::GeometryBuffer *buffer = createStripBuffer(&vertexAttribute); + graphics::GeometryBuffer *buffer = createStripBuffer(vertexAttribute, 1); buffer->setData(&triangles_tri, sizeof(triangles_tri)); buffers.push_back(buffer); } if (input::InputManager::isKeyPressed(input::Key::R)) { buffers.clear(); - graphics::GeometryBuffer *buffer = createStripBuffer(&vertexAttribute); + graphics::GeometryBuffer *buffer = createStripBuffer(vertexAttribute, 1); buffer->setData(&triangles_rect, sizeof(triangles_rect)); buffers.push_back(buffer); } @@ -120,22 +138,41 @@ int main(int argc, char *argv[]) { wasSPressed = true; buffers.clear(); - graphics::GeometryBuffer *triBuffer = createTriangleBuffer(&vertexAttribute); + graphics::GeometryBuffer *triBuffer = createTriangleBuffer(vertexAttribute, 2); { - auto *triBufferData = new glm::vec3[meshStripData->floatingTriangles.size() * 3]; + auto *triBufferData = new VertexData[meshStripData->floatingTriangles.size() * 3]; int dataIndex = 0; for (const auto &floatingTriangle: meshStripData->floatingTriangles) { - triBufferData[dataIndex] = data->positions[floatingTriangle.indices[0].positionIdx]; - triBufferData[dataIndex + 1] = data->positions[floatingTriangle.indices[1].positionIdx]; - triBufferData[dataIndex + 2] = data->positions[floatingTriangle.indices[2].positionIdx]; + auto tex0 = data->textureCoordinates.at(floatingTriangle.indices[0].textureCoordinateIdx.value()); + auto tex1 = data->textureCoordinates.at(floatingTriangle.indices[1].textureCoordinateIdx.value()); + auto tex2 = data->textureCoordinates.at(floatingTriangle.indices[2].textureCoordinateIdx.value()); + + std::cout << "uv coord 0 is " << tex0.x << "/" << tex0.y << " for vertex " << floatingTriangle.indices[0].positionIdx << std::endl; + std::cout << "uv coord 1 is " << tex1.x << "/" << tex1.y << " for vertex " << floatingTriangle.indices[1].positionIdx << std::endl; + std::cout << "uv coord 2 is " << tex2.x << "/" << tex2.y << " for vertex " << floatingTriangle.indices[2].positionIdx << std::endl; + triBufferData[dataIndex] = { + data->positions[floatingTriangle.indices[0].positionIdx], + data->textureCoordinates.at(floatingTriangle.indices[0].textureCoordinateIdx.value()) + }; + + triBufferData[dataIndex] = { + data->positions[floatingTriangle.indices[1].positionIdx], + data->textureCoordinates.at(floatingTriangle.indices[1].textureCoordinateIdx.value()) + }; + + triBufferData[dataIndex] = { + data->positions[floatingTriangle.indices[2].positionIdx], + data->textureCoordinates.at(floatingTriangle.indices[2].textureCoordinateIdx.value()) + }; + dataIndex += 3; } triBuffer->setData(triBufferData, sizeof(glm::vec3) * meshStripData->floatingTriangles.size() * 3); } buffers.push_back(triBuffer); - for (const auto &strip: meshStripData->triangleStrips) { - auto *stripBuffer = createStripBuffer(&vertexAttribute); + /*for (const auto &strip: meshStripData->triangleStrips) { + auto *stripBuffer = createStripBuffer(vertexAttribute, 1); unsigned int vertexCount = strip.vertexIndices.size(); auto *stripBufferData = new glm::vec3[vertexCount]; int dataIndex = 0; @@ -145,7 +182,7 @@ int main(int argc, char *argv[]) { } stripBuffer->setData(stripBufferData, sizeof(glm::vec3) * vertexCount); buffers.push_back(stripBuffer); - } + }*/ } } else { wasSPressed = false; From 8118b5bfb74f2492525d1b4dc67fdacb02eb518f Mon Sep 17 00:00:00 2001 From: BlazingTwist Date: Sat, 13 Nov 2021 20:34:43 +0100 Subject: [PATCH 03/12] implemented uv-mapping, camera controls and phong shading --- .gitignore | 1 + resources/shader/demo.frag | 43 ++++- resources/shader/demo.vert | 16 +- resources/textures/Planet1_phong.png | Bin 0 -> 10676 bytes src/engine/utils/meshstripper.cpp | 83 ++++---- src/engine/utils/meshstripper.hpp | 7 +- src/main.cpp | 279 +++++++++++++++++++++------ 7 files changed, 312 insertions(+), 117 deletions(-) create mode 100644 resources/textures/Planet1_phong.png diff --git a/.gitignore b/.gitignore index c482431c..42df0183 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ .* !.gitignore !.gitmodules +out \ No newline at end of file diff --git a/resources/shader/demo.frag b/resources/shader/demo.frag index 62ee5e8a..e0281ec2 100644 --- a/resources/shader/demo.frag +++ b/resources/shader/demo.frag @@ -1,10 +1,49 @@ #version 450 -layout(location = 0) in vec2 tex_coord; +#define LIGHT_TYPE_DIRECTIONAL 0 +#define LIGHT_TYPE_SPOT 1 +#define LIGHT_TYPE_POINT 2 + +layout(location = 0) in vec2 uv_coord_frag; +layout(location = 1) in vec3 normal_vec_frag; +layout(location = 2) in vec3 render_position_frag; + layout(binding = 0) uniform sampler2D tx_color; +layout(binding = 1) uniform sampler2D tx_phong;// stores ambient/diffuse/specular/shinyness weights in r/g/b/a respectively + layout(location = 0) out vec4 out_color; +uniform vec3 camera_position; +uniform vec3 ambient_light; + +// TODO figure out what to do about multiple light sources (ideally with variable length - "Shader Storage Buffer Objects" ? ) +uniform int light_type; +uniform vec3 light_position; +uniform vec3 light_direction; +uniform float light_range; +uniform float light_spot_angle; +uniform vec3 light_color; +uniform float light_intensity; + void main() { - out_color = texture(tx_color, tex_coord); + vec4 texColor = texture(tx_color, uv_coord_frag); + vec4 phongData = texture(tx_phong, uv_coord_frag); + vec3 ambientColor = max(phongData.r * ambient_light, 0f); + vec3 diffuseColor; + vec3 specularColor; + + // TODO light bounces? occlusion? + if (light_type == LIGHT_TYPE_DIRECTIONAL){ + // direction, color, intensity + diffuseColor = max(phongData.g * dot(-light_direction, normal_vec_frag) * light_color, 0f); + specularColor = max(phongData.b * pow(dot(reflect(light_direction, normal_vec_frag), normalize(camera_position - render_position_frag)), phongData.a * 255) * light_color, 0f); + } else if (light_type == LIGHT_TYPE_SPOT){ + // TODO implement spot lights + } else if (light_type == LIGHT_TYPE_POINT){ + // TODO implement point lights + } + + out_color = texColor * vec4(ambientColor + diffuseColor + specularColor, 1f); + //out_color = vec4(normal_vec_frag, 1f); } \ No newline at end of file diff --git a/resources/shader/demo.vert b/resources/shader/demo.vert index 173a795a..6ea3907f 100644 --- a/resources/shader/demo.vert +++ b/resources/shader/demo.vert @@ -2,10 +2,20 @@ layout(location = 0) in vec3 in_position; layout(location = 1) in vec2 uv_coord; -layout(location = 0) out vec2 tex_coord; +layout(location = 2) in vec3 normal_vec; + +layout(location = 0) out vec2 uv_coord_frag; +layout(location = 1) out vec3 normal_vec_frag; +layout(location = 2) out vec3 render_position_frag; + +uniform mat4 world_to_camera_matrix; void main() { - gl_Position = vec4(in_position,1.f); - tex_coord = uv_coord; + //gl_Position = vec4(in_position, 1f); + gl_Position = world_to_camera_matrix * vec4(in_position, 1f); + render_position_frag = in_position; + + uv_coord_frag = uv_coord; + normal_vec_frag = normal_vec; } \ No newline at end of file diff --git a/resources/textures/Planet1_phong.png b/resources/textures/Planet1_phong.png new file mode 100644 index 0000000000000000000000000000000000000000..f0f55ca29414761566038fddbdbc8a6c3f255d59 GIT binary patch literal 10676 zcmeHLJxjw-6g|;ULp7K}sYR(2C*7)pb1IRVrHZ(@M4TMNNhoyaqu`)}{s-Mf$8HfS zPPz)6#Kpx$(B1o*Tql3Rc}q@SUNT(n`N%!rX}A31d=Y>jZ$-O+C(wmgkjv@RAOcpp zan#)Fj6O%JCDeoTZtkJ)mzQd_@3mq0@iOQ-a@4NgLMa1y>)F@G%WEhKjUL3rjBW;r zB7;eVZdFk|RRo8hWG%ra0@(vlHbA`;pQ2IFA;D-Msf{s<(SXrF{uUSw7!9Ni7!AN^ zz-S;$U^L*=K-z#axBsF+diZ*IB-MfYb87?5%)pexW7=n8ZNx&pufTc!kN{i5}? fy!d$2DPO%G80T#Nx^ch#T(M8%&31IVk@SB7E7_0i literal 0 HcmV?d00001 diff --git a/src/engine/utils/meshstripper.cpp b/src/engine/utils/meshstripper.cpp index 0ab1aac1..b2c32498 100644 --- a/src/engine/utils/meshstripper.cpp +++ b/src/engine/utils/meshstripper.cpp @@ -1,11 +1,10 @@ #include #include "meshstripper.hpp" +using VertexIndices = utils::MeshData::FaceData::VertexIndices; namespace utils { - TriangleStrip *TriangleStrip::create(utils::MeshData::FaceData face1, utils::MeshData::FaceData face2, std::array vertices) { + TriangleStrip *TriangleStrip::create(std::array vertices) { auto *strip = new TriangleStrip; - strip->triangles.push_back(face1); - strip->triangles.push_back(face2); for (const auto &vertexIndex: vertices) { strip->vertexIndices.push_back(vertexIndex); } @@ -13,11 +12,8 @@ namespace utils { } TriangleStrip * - TriangleStrip::create(utils::MeshData::FaceData face1, utils::MeshData::FaceData face2, utils::MeshData::FaceData face3, std::array vertices) { + TriangleStrip::create(std::array vertices) { auto *strip = new TriangleStrip; - strip->triangles.push_back(face1); - strip->triangles.push_back(face2); - strip->triangles.push_back(face3); for (const auto &vertexIndex: vertices) { strip->vertexIndices.push_back(vertexIndex); } @@ -26,33 +22,32 @@ namespace utils { TriangleStrip::~TriangleStrip() { vertexIndices.clear(); - triangles.clear(); } - bool findConnectedTriangle(std::array firstFace, std::vector *remainingFaces, utils::MeshData::FaceData &face2, - std::array &result) { + bool findConnectedTriangle(utils::MeshData::FaceData *firstFace, std::vector *remainingFaces, + std::array &result) { int connectedVertexIndex; for (auto iterator = remainingFaces->begin(); iterator != remainingFaces->end(); ++iterator) { connectedVertexIndex = 1; // reset index for (const auto &vertexB: (*iterator).indices) { bool didMatch = false; - for (const auto &indexA: firstFace) { - if (indexA == vertexB.positionIdx) { + for (const auto &vertexA: firstFace->indices) { + if (vertexA.positionIdx == vertexB.positionIdx) { didMatch = true; - result[connectedVertexIndex] = indexA; + result[connectedVertexIndex] = vertexA; connectedVertexIndex++; } } if (!didMatch) { - result[3] = vertexB.positionIdx; + result[3] = vertexB; } } if (connectedVertexIndex > 2) { // find unique vertex of first face - for (const auto &indexA: firstFace) { - if (indexA != result[1] && indexA != result[2]) { - result[0] = indexA; + for (const auto &vertexA: firstFace->indices) { + if (vertexA.positionIdx != result[1].positionIdx && vertexA.positionIdx != result[2].positionIdx) { + result[0] = vertexA; break; } } @@ -64,24 +59,24 @@ namespace utils { return false; } - bool findConnectedTriangle(std::array stripOfTwo, std::vector *remainingFaces, utils::MeshData::FaceData &face3, - std::array &result) { + bool findConnectedTriangle(std::array stripOfTwo, std::vector *remainingFaces, + std::array &result) { for (auto iterator = remainingFaces->begin(); iterator != remainingFaces->end(); ++iterator) { int outerMatchIndex = -1; // marks which end of the strip the triangle connects to int innerMatchIndex = -1; // marks which inner vertex the triangle connects to - int uniqueVertex = 0; // the one vertex of the triangle that doesn't connect to the strip + VertexIndices uniqueVertex; // the one vertex of the triangle that doesn't connect to the strip for (const auto &vertexB: (*iterator).indices) { int vertexIndex = vertexB.positionIdx; - if (vertexIndex == stripOfTwo[0]) { + if (vertexIndex == stripOfTwo[0].positionIdx) { outerMatchIndex = 0; - } else if (vertexIndex == stripOfTwo[3]) { + } else if (vertexIndex == stripOfTwo[3].positionIdx) { outerMatchIndex = 3; - } else if (vertexIndex == stripOfTwo[1]) { + } else if (vertexIndex == stripOfTwo[1].positionIdx) { innerMatchIndex = 1; - } else if (vertexIndex == stripOfTwo[2]) { + } else if (vertexIndex == stripOfTwo[2].positionIdx) { innerMatchIndex = 2; } else { - uniqueVertex = vertexIndex; + uniqueVertex = vertexB; } } @@ -93,7 +88,7 @@ namespace utils { // make sure the inner and outer matching vertices are directly connected if ((outerMatchIndex == 0 && innerMatchIndex == 2) || (outerMatchIndex == 3 && innerMatchIndex == 1)) { - int temp = stripOfTwo[2]; + VertexIndices temp = stripOfTwo[2]; stripOfTwo[2] = stripOfTwo[1]; stripOfTwo[1] = temp; } @@ -111,35 +106,34 @@ namespace utils { return false; } - bool areFacesConnected(int vertex1, int vertex2, utils::MeshData::FaceData face, int &foundVertex) { + bool areFacesConnected(VertexIndices vertex1, VertexIndices vertex2, utils::MeshData::FaceData face, VertexIndices &foundVertex) { int matches = 0; for (const auto &index: face.indices) { - if (index.positionIdx == vertex1 || index.positionIdx == vertex2) { + if (index.positionIdx == vertex1.positionIdx || index.positionIdx == vertex2.positionIdx) { matches++; } else { - foundVertex = index.positionIdx; + foundVertex = index; } } return matches >= 2; } void expandTriangleStrip(TriangleStrip *stripToExpand, std::vector *remainingFaces) { - int vertA1 = stripToExpand->vertexIndices[0]; - int vertA2 = stripToExpand->vertexIndices[1]; + VertexIndices vertA1 = stripToExpand->vertexIndices[0]; + VertexIndices vertA2 = stripToExpand->vertexIndices[1]; const auto vertIteratorEnd = stripToExpand->vertexIndices.end(); - int vertB1 = *(vertIteratorEnd - 1); - int vertB2 = *(vertIteratorEnd - 2); + VertexIndices vertB1 = *(vertIteratorEnd - 1); + VertexIndices vertB2 = *(vertIteratorEnd - 2); int count = 0; while (!remainingFaces->empty()) { int foundConnectedFace = false; for (auto iterator = remainingFaces->begin(); iterator != remainingFaces->end(); ++iterator) { - int foundVertex; + VertexIndices foundVertex; if (areFacesConnected(vertA1, vertA2, *iterator, foundVertex)) { vertA2 = vertA1; vertA1 = foundVertex; stripToExpand->vertexIndices.insert(stripToExpand->vertexIndices.begin(), foundVertex); - stripToExpand->triangles.insert(stripToExpand->triangles.begin(), *iterator); remainingFaces->erase(iterator); foundConnectedFace = true; count++; @@ -149,7 +143,6 @@ namespace utils { vertB2 = vertB1; vertB1 = foundVertex; stripToExpand->vertexIndices.push_back(foundVertex); - stripToExpand->triangles.push_back(*iterator); remainingFaces->erase(iterator); foundConnectedFace = true; count++; @@ -171,16 +164,10 @@ namespace utils { utils::MeshData::FaceData face1 = *remainingFaces.begin(); remainingFaces.erase(remainingFaces.begin()); - utils::MeshData::FaceData face2; - std::array twoTriangleStrip = {}; + std::array twoTriangleStrip = {}; bool foundFace2 = findConnectedTriangle( - { - face1.indices[0].positionIdx, - face1.indices[1].positionIdx, - face1.indices[2].positionIdx - }, + &face1, &remainingFaces, - face2, twoTriangleStrip ); if (!foundFace2) { @@ -188,21 +175,19 @@ namespace utils { continue; } - utils::MeshData::FaceData face3; - std::array threeTriangleStrip = {}; + std::array threeTriangleStrip = {}; bool foundFace3 = findConnectedTriangle( twoTriangleStrip, &remainingFaces, - face3, threeTriangleStrip ); if (!foundFace3) { - result->triangleStrips.push_back(*TriangleStrip::create(face1, face2, twoTriangleStrip)); + result->triangleStrips.push_back(*TriangleStrip::create(twoTriangleStrip)); continue; } - TriangleStrip *strip = TriangleStrip::create(face1, face2, face3, threeTriangleStrip); + TriangleStrip *strip = TriangleStrip::create(threeTriangleStrip); expandTriangleStrip(strip, &remainingFaces); result->triangleStrips.push_back(*strip); } diff --git a/src/engine/utils/meshstripper.hpp b/src/engine/utils/meshstripper.hpp index f900e7e8..c729aa9f 100644 --- a/src/engine/utils/meshstripper.hpp +++ b/src/engine/utils/meshstripper.hpp @@ -10,15 +10,14 @@ namespace utils { * @brief describes a single triangle strip of a mesh */ struct TriangleStrip { - std::vector vertexIndices = {}; - std::vector triangles = {}; + std::vector vertexIndices = {}; virtual ~TriangleStrip(); - static TriangleStrip* create(utils::MeshData::FaceData face1, utils::MeshData::FaceData face2, std::array vertices); + static TriangleStrip* create(std::array vertices); static TriangleStrip* - create(utils::MeshData::FaceData face1, utils::MeshData::FaceData face2, utils::MeshData::FaceData face3, std::array vertices); + create(std::array vertices); }; /** diff --git a/src/main.cpp b/src/main.cpp index 79ac6fb5..cf82b70d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,6 +18,7 @@ #include #include +#include #endif #endif @@ -47,6 +48,45 @@ graphics::GeometryBuffer *createTriangleBuffer(graphics::VertexAttribute *vertex struct VertexData { glm::vec3 positionData; glm::vec2 uvData; + glm::vec3 normalData; +}; + +struct LightData { + inline static const int LIGHT_TYPE_DIRECTIONAL = 0; + inline static const int LIGHT_TYPE_SPOT = 1; + inline static const int LIGHT_TYPE_POINT = 2; + + /** + * Directional Light: + * position - + * direction direction the light is emitted in + * range - + * spot_angle - + * color color of the emitted light + * intensity simple multiplier for emitted light + * Spot-Light: + * position position of the light source in world space + * direction direction the spot-light is facing + * range maximum range of emitted light + * spot_angle max angle the light is emitted at in degrees (e.g. 5° means light is emitted in a cone of 2.5° from the spot-light's direction) + * color color of the emitted light + * intensity resulting light-intensity at a given point is `intensity * ( 1 - ([point_to_light_distance] / [range]) )²` + * Point-Light: + * position position of the light source in world space + * direction - + * range maximum range of emitted light + * spot_angle - + * color color of the emitted light + * intensity resulting light-intensity at a given point is `intensity * ( 1 - ([point_to_light_distance] / [range]) )²` + */ + + int light_type; + glm::vec3 light_position; + glm::vec3 light_direction; + float light_range; + float light_spot_angle; + glm::vec3 light_color; + float light_intensity; }; int main(int argc, char *argv[]) { @@ -62,45 +102,66 @@ int main(int argc, char *argv[]) { graphics::Device::initialize(1366, 1366, false); GLFWwindow *window = graphics::Device::getWindow(); input::InputManager::initialize(window); + input::InputManager::setCursorMode(input::InputManager::CursorMode::NORMAL); + + glm::vec3 ambientLightData = {0.3f, 0.3f, 0.3f}; + // TODO create light type specific constructors + LightData lightData = { + LightData::LIGHT_TYPE_DIRECTIONAL, + glm::vec3(0.0f, 0.0f, 0.0f), + glm::normalize(glm::vec3(-1.0f, -1.0f, 0.0f)), + 0.0f, 0.0f, + glm::vec3(1.0f, 1.0f, 1.0f), + 1.0f + }; + graphics::Camera camera(90.0f, 0.1f, 300.0f); static graphics::Sampler sampler(graphics::Sampler::Filter::LINEAR, graphics::Sampler::Filter::LINEAR, graphics::Sampler::Filter::LINEAR, graphics::Sampler::Border::MIRROR); - auto texture = graphics::Texture2DManager::get("textures/planet1.png", sampler); - texture->bind(0); + auto planetTexture = graphics::Texture2DManager::get("textures/planet1.png", sampler); + auto planetPhong = graphics::Texture2DManager::get("textures/Planet1_phong.png", sampler); + planetTexture->bind(0); + planetPhong->bind(1); utils::MeshData::Handle data = utils::MeshLoader::get("models/sphere.obj"); utils::MeshStripData::Handle meshStripData = utils::MeshStripData::createFromMeshData(data); - graphics::VertexAttribute vertexAttribute[] = { - { + std::array vertexAttributes = { + graphics::VertexAttribute{ graphics::PrimitiveFormat::FLOAT, 3, false, false }, - { + graphics::VertexAttribute{ graphics::PrimitiveFormat::FLOAT, 2, false, false + }, + graphics::VertexAttribute{ + graphics::PrimitiveFormat::FLOAT, + 3, + false, + false } }; - glm::vec3 triangles_tri[] = { - glm::vec3(-1.0f, -1.0f, 0.0f), - glm::vec3(1.0f, -1.0f, 0.0f), - glm::vec3(0.0f, 1.0f, 0.0f), + VertexData triangles_tri[] = { + {glm::vec3(-1.0f, -1.0f, 0.0f), glm::vec2(-1.0f, -1.0f)}, + {glm::vec3(1.0f, -1.0f, 0.0f), glm::vec2(1.0f, -1.0f)}, + {glm::vec3(0.0f, 1.0f, 0.0f), glm::vec2(0.0f, 1.0f)}, }; - glm::vec3 triangles_rect[] = { - glm::vec3(-0.75f, -0.75f, 0.0f), - glm::vec3(0.75f, -0.75f, 0.0f), - glm::vec3(-0.75f, 0.75f, 0.0f), - glm::vec3(0.75f, 0.75f, 0.0f), + VertexData triangles_rect[] = { + {glm::vec3(-0.75f, -0.75f, 0.0f), glm::vec2(0.0f, -0.75f)}, + {glm::vec3(0.75f, -0.75f, 0.0f), glm::vec2(0.75f, -0.75f)}, + {glm::vec3(-0.75f, 0.75f, 0.0f), glm::vec2(-0.75f, 0.75f)}, + {glm::vec3(0.75f, 0.75f, 0.0f), glm::vec2(0.75f, 0.75f)}, }; - std::vector < graphics::GeometryBuffer * > buffers = {}; + std::vector buffers = {}; { - graphics::GeometryBuffer *buffer = createStripBuffer(vertexAttribute, 1); + graphics::GeometryBuffer *buffer = createStripBuffer(vertexAttributes.data(), vertexAttributes.size()); buffer->setData(&triangles_rect, sizeof(triangles_rect)); buffers.push_back(buffer); } @@ -114,86 +175,186 @@ int main(int argc, char *argv[]) { program.link(); program.use(); - graphics::glCall(glClearColor, 0.f, 1.f, 0.f, 1.f); + const glm::vec4 rightVector = {1.0f, 0.0f, 0.0f, 0.0f}; + const glm::vec4 forwardVector = {0.0f, 0.0f, 1.0f, 0.0f}; + const glm::vec4 upVector = {0.0f, 1.0f, 0.0f, 0.0f}; + glm::vec4 cameraPosition = {0.0f, 0.0f, -3.0f, 0.0f}; + glm::vec4 cameraForwardVector = forwardVector; + glm::vec4 cameraUpVector = upVector; + glm::vec4 cameraRightVector = rightVector; + const float cameraStep = 0.05f; + const float cameraPitchSensitivity = 0.5f; + const float cameraYawSensitivity = 0.5f; + const float cameraRollStep = 0.05f; + float cameraPitch = 0.0f; + float cameraYaw = 0.0f; + float cameraRoll = 0.0f; + glm::mat4 worldToCameraMatrix; + GLint worldToCameraMatrixID = glGetUniformLocation(program.getID(), "world_to_camera_matrix"); + + GLint cameraPositionShaderID = glGetUniformLocation(program.getID(), "camera_position"); + GLint glsl_ambient_light = glGetUniformLocation(program.getID(), "ambient_light"); + + // TODO create a function for binding lightData + GLint glsl_light_type = glGetUniformLocation(program.getID(), "light_type"); + GLint glsl_light_position = glGetUniformLocation(program.getID(), "light_position"); + GLint glsl_light_direction = glGetUniformLocation(program.getID(), "light_direction"); + GLint glsl_light_range = glGetUniformLocation(program.getID(), "light_range"); + GLint glsl_light_spot_angle = glGetUniformLocation(program.getID(), "light_spot_angle"); + GLint glsl_light_color = glGetUniformLocation(program.getID(), "light_color"); + GLint glsl_light_intensity = glGetUniformLocation(program.getID(), "light_intensity"); - bool wasSPressed = false; + graphics::glCall(glEnable, GL_DEPTH_TEST); + graphics::glCall(glClearColor, 0.05f, 0.0f, 0.05f, 1.f); + + glm::vec2 prevCursorPos; + glm::vec2 currentCursorPos = input::InputManager::getCursorPos(); while (!glfwWindowShouldClose(window) && !input::InputManager::isKeyPressed(input::Key::ESCAPE)) { + prevCursorPos = currentCursorPos; + currentCursorPos = input::InputManager::getCursorPos(); graphics::glCall(glClear, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); if (input::InputManager::isKeyPressed(input::Key::T)) { buffers.clear(); - graphics::GeometryBuffer *buffer = createStripBuffer(vertexAttribute, 1); + graphics::GeometryBuffer *buffer = createStripBuffer(vertexAttributes.data(), vertexAttributes.size()); buffer->setData(&triangles_tri, sizeof(triangles_tri)); buffers.push_back(buffer); } if (input::InputManager::isKeyPressed(input::Key::R)) { buffers.clear(); - graphics::GeometryBuffer *buffer = createStripBuffer(vertexAttribute, 1); + graphics::GeometryBuffer *buffer = createStripBuffer(vertexAttributes.data(), vertexAttributes.size()); buffer->setData(&triangles_rect, sizeof(triangles_rect)); buffers.push_back(buffer); } if (input::InputManager::isKeyPressed(input::Key::S)) { - if (!wasSPressed) { - wasSPressed = true; - buffers.clear(); - - graphics::GeometryBuffer *triBuffer = createTriangleBuffer(vertexAttribute, 2); - { - auto *triBufferData = new VertexData[meshStripData->floatingTriangles.size() * 3]; - int dataIndex = 0; - for (const auto &floatingTriangle: meshStripData->floatingTriangles) { - auto tex0 = data->textureCoordinates.at(floatingTriangle.indices[0].textureCoordinateIdx.value()); - auto tex1 = data->textureCoordinates.at(floatingTriangle.indices[1].textureCoordinateIdx.value()); - auto tex2 = data->textureCoordinates.at(floatingTriangle.indices[2].textureCoordinateIdx.value()); - - std::cout << "uv coord 0 is " << tex0.x << "/" << tex0.y << " for vertex " << floatingTriangle.indices[0].positionIdx << std::endl; - std::cout << "uv coord 1 is " << tex1.x << "/" << tex1.y << " for vertex " << floatingTriangle.indices[1].positionIdx << std::endl; - std::cout << "uv coord 2 is " << tex2.x << "/" << tex2.y << " for vertex " << floatingTriangle.indices[2].positionIdx << std::endl; - triBufferData[dataIndex] = { - data->positions[floatingTriangle.indices[0].positionIdx], - data->textureCoordinates.at(floatingTriangle.indices[0].textureCoordinateIdx.value()) - }; - - triBufferData[dataIndex] = { - data->positions[floatingTriangle.indices[1].positionIdx], - data->textureCoordinates.at(floatingTriangle.indices[1].textureCoordinateIdx.value()) - }; + /*std::cout << "floating triangles: " << meshStripData->floatingTriangles.size() << std::endl; + std::cout << "triangle strips: " << meshStripData->triangleStrips.size() << std::endl; + for (const auto &triStrip: meshStripData->triangleStrips) { + std::cout << " vertices: " << triStrip.vertexIndices.size() << std::endl; + }*/ + buffers.clear(); - triBufferData[dataIndex] = { - data->positions[floatingTriangle.indices[2].positionIdx], - data->textureCoordinates.at(floatingTriangle.indices[2].textureCoordinateIdx.value()) + if (input::InputManager::isKeyPressed(input::Key::Num1)) { + graphics::GeometryBuffer *triBuffer = createTriangleBuffer(vertexAttributes.data(), vertexAttributes.size()); + auto *triBufferData = new VertexData[meshStripData->floatingTriangles.size() * 3]; + int dataIndex = 0; + for (const auto &floatingTriangle: meshStripData->floatingTriangles) { + for (int i = 0; i < 3; i++) { + triBufferData[dataIndex + i] = { + data->positions[floatingTriangle.indices[i].positionIdx], + data->textureCoordinates[floatingTriangle.indices[i].textureCoordinateIdx.value_or(0)], + data->normals[floatingTriangle.indices[i].normalIdx.value_or(0)] }; - - dataIndex += 3; } - triBuffer->setData(triBufferData, sizeof(glm::vec3) * meshStripData->floatingTriangles.size() * 3); + dataIndex += 3; } + triBuffer->setData(triBufferData, sizeof(VertexData) * meshStripData->floatingTriangles.size() * 3); buffers.push_back(triBuffer); + } - /*for (const auto &strip: meshStripData->triangleStrips) { - auto *stripBuffer = createStripBuffer(vertexAttribute, 1); + if (input::InputManager::isKeyPressed(input::Key::Num3)) { + for (const auto &strip: meshStripData->triangleStrips) { + auto *stripBuffer = createStripBuffer(vertexAttributes.data(), vertexAttributes.size()); unsigned int vertexCount = strip.vertexIndices.size(); - auto *stripBufferData = new glm::vec3[vertexCount]; + auto *stripBufferData = new VertexData[vertexCount]; int dataIndex = 0; for (const auto &vertexIndex: strip.vertexIndices) { - stripBufferData[dataIndex] = data->positions[vertexIndex]; + stripBufferData[dataIndex] = { + data->positions[vertexIndex.positionIdx], + data->textureCoordinates[vertexIndex.textureCoordinateIdx.value_or(0)], + data->normals[vertexIndex.normalIdx.value_or(0)] + }; dataIndex++; } - stripBuffer->setData(stripBufferData, sizeof(glm::vec3) * vertexCount); + stripBuffer->setData(stripBufferData, sizeof(VertexData) * vertexCount); buffers.push_back(stripBuffer); - }*/ + } } - } else { - wasSPressed = false; } + if (input::InputManager::isKeyPressed(input::Key::KP_8)) { + cameraPosition += cameraForwardVector * cameraStep; + std::cout << "camera position: " << cameraPosition[0] << " / " << cameraPosition[1] << " / " << cameraPosition[2] << std::endl; + } + if (input::InputManager::isKeyPressed(input::Key::KP_2)) { + cameraPosition -= cameraForwardVector * cameraStep; + std::cout << "camera position: " << cameraPosition[0] << " / " << cameraPosition[1] << " / " << cameraPosition[2] << std::endl; + } + if (input::InputManager::isKeyPressed(input::Key::KP_6)) { + cameraPosition += cameraRightVector * cameraStep; + std::cout << "camera position: " << cameraPosition[0] << " / " << cameraPosition[1] << " / " << cameraPosition[2] << std::endl; + } + if (input::InputManager::isKeyPressed(input::Key::KP_4)) { + cameraPosition -= cameraRightVector * cameraStep; + std::cout << "camera position: " << cameraPosition[0] << " / " << cameraPosition[1] << " / " << cameraPosition[2] << std::endl; + } + if (input::InputManager::isKeyPressed(input::Key::KP_9)) { + cameraPosition += cameraUpVector * cameraStep; + std::cout << "camera position: " << cameraPosition[0] << " / " << cameraPosition[1] << " / " << cameraPosition[2] << std::endl; + } + if (input::InputManager::isKeyPressed(input::Key::KP_3)) { + cameraPosition -= cameraUpVector * cameraStep; + std::cout << "camera position: " << cameraPosition[0] << " / " << cameraPosition[1] << " / " << cameraPosition[2] << std::endl; + } + + float cursorDeltaX = currentCursorPos.x - prevCursorPos.x; + float cursorDeltaY = currentCursorPos.y - prevCursorPos.y; + if (cursorDeltaX != 0.0f) { + cameraYaw += cursorDeltaX * cameraYawSensitivity; + if (cameraYaw > 180.0f) { + cameraYaw -= 360.0f; + } else if (cameraYaw < -180.0f) { + cameraYaw += 360.0f; + } + } + if (cursorDeltaY != 0.0f) { + cameraPitch += cursorDeltaY * cameraPitchSensitivity; + if (cameraPitch > 90.0f) { + cameraPitch = 90.0f; + } else if (cameraPitch < -90.0f) { + cameraPitch = -90.0f; + } + } + + // update camera up/forward/right vectors according to camera rotation + // apply yaw, then pitch, then roll + auto identityMat4 = glm::identity(); + auto yawRotationMatrix = glm::rotate(identityMat4, glm::radians(cameraYaw), glm::vec3(cameraUpVector)); + cameraRightVector = yawRotationMatrix * rightVector; + auto pitchRotationMatrix = glm::rotate(identityMat4, glm::radians(cameraPitch), glm::vec3(cameraRightVector)); + cameraForwardVector = pitchRotationMatrix * yawRotationMatrix * forwardVector; + auto rollRotationMatrix = glm::rotate(identityMat4, glm::radians(cameraRoll), glm::vec3(cameraForwardVector)); + cameraRightVector = rollRotationMatrix * cameraRightVector; + cameraUpVector = rollRotationMatrix * pitchRotationMatrix * upVector; + + glUniform3fv(glsl_ambient_light, 1, glm::value_ptr(ambientLightData)); + + // TODO create a function for binding lightData + glUniform1i(glsl_light_type, lightData.light_type); + glUniform3fv(glsl_light_position, 1, glm::value_ptr(lightData.light_position)); + glUniform3fv(glsl_light_direction, 1, glm::value_ptr(lightData.light_direction)); + glUniform1f(glsl_light_range, lightData.light_range); + glUniform1f(glsl_light_spot_angle, lightData.light_spot_angle); + glUniform3fv(glsl_light_color, 1, glm::value_ptr(lightData.light_color)); + glUniform1f(glsl_light_intensity, lightData.light_intensity); + + auto lookAtMatrix = glm::lookAt(glm::vec3(cameraPosition), glm::vec3(cameraPosition + cameraForwardVector), glm::vec3(cameraUpVector)); + // fix x direction + lookAtMatrix[0][0] *= -1.0f; + lookAtMatrix[1][0] *= -1.0f; + lookAtMatrix[2][0] *= -1.0f; + lookAtMatrix[3][0] *= -1.0f; + worldToCameraMatrix = camera.getViewProjection() * lookAtMatrix; + glUniformMatrix4fv(worldToCameraMatrixID, 1, GL_FALSE, glm::value_ptr(worldToCameraMatrix)); + glUniform3fv(cameraPositionShaderID, 1, glm::value_ptr(cameraPosition)); for (const auto &buffer: buffers) { buffer->draw(); } glfwPollEvents(); glfwSwapBuffers(window); + graphics::glCall(glClear, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); std::this_thread::sleep_for(16ms); } From 69166675c8c65399767f4cb22e0a85f91bef8f90 Mon Sep 17 00:00:00 2001 From: BlazingTwist Date: Sat, 27 Nov 2021 11:52:45 +0100 Subject: [PATCH 04/12] export camera behaviour to camera class (and minor fixes) --- resources/shader/demo.frag | 6 +- resources/textures/Planet1_phong.png | Bin 10676 -> 10675 bytes src/engine/graphics/camera.cpp | 155 +++++++++++++++++++++------ src/engine/graphics/camera.hpp | 97 ++++++++++++----- src/main.cpp | 96 ++++++----------- 5 files changed, 229 insertions(+), 125 deletions(-) diff --git a/resources/shader/demo.frag b/resources/shader/demo.frag index e0281ec2..d6c09a6a 100644 --- a/resources/shader/demo.frag +++ b/resources/shader/demo.frag @@ -36,8 +36,8 @@ void main() // TODO light bounces? occlusion? if (light_type == LIGHT_TYPE_DIRECTIONAL){ // direction, color, intensity - diffuseColor = max(phongData.g * dot(-light_direction, normal_vec_frag) * light_color, 0f); - specularColor = max(phongData.b * pow(dot(reflect(light_direction, normal_vec_frag), normalize(camera_position - render_position_frag)), phongData.a * 255) * light_color, 0f); + diffuseColor = max(phongData.g * dot(-light_direction, normal_vec_frag) * light_color, 0f) * light_intensity; + specularColor = max(phongData.b * 8 * pow(dot(reflect(light_direction, normal_vec_frag), normalize(camera_position - render_position_frag)), phongData.a * 255) * light_color, 0f) * light_intensity; } else if (light_type == LIGHT_TYPE_SPOT){ // TODO implement spot lights } else if (light_type == LIGHT_TYPE_POINT){ @@ -45,5 +45,5 @@ void main() } out_color = texColor * vec4(ambientColor + diffuseColor + specularColor, 1f); - //out_color = vec4(normal_vec_frag, 1f); + //out_color = vec4(specularColor, 1f); } \ No newline at end of file diff --git a/resources/textures/Planet1_phong.png b/resources/textures/Planet1_phong.png index f0f55ca29414761566038fddbdbc8a6c3f255d59..af32edfd2202ccc2a2c1dca5b548c66090c70d08 100644 GIT binary patch delta 96 zcmdlIyg7J+igA^vi(^Q|tv9zE1sN204j8yBU}>G)*Z1{PN8`TgduLb~AfU`z3CcQ9 qw>gk;z3}7$)}KrV(l;}S&Jz*2do?+JyT;7RASIrzelF{r5}E+cJR(j2 delta 98 zcmdlSyd`*oib=Jni(^Q|tv9y}1sN0s4r~xV*u*QMBrE&H=!nDfb33aU86couS`f;5 sP`~*hi=4pb3(Q?COb3!TGm6d=5owKHWU$fytQbg*r>mdKI;Vst0C?9QmjD0& diff --git a/src/engine/graphics/camera.cpp b/src/engine/graphics/camera.cpp index 180a5e76..8354bb03 100644 --- a/src/engine/graphics/camera.cpp +++ b/src/engine/graphics/camera.cpp @@ -4,38 +4,125 @@ namespace graphics { - using namespace glm; - - Camera::Camera(float _fov, float _zNear, float zFar) - : m_projection(glm::perspective(glm::radians(_fov), Device::getAspectRatio(), _zNear, zFar)), - m_view(glm::identity()) - { - updateMatrices(); - } - - Camera::Camera(glm::vec2 _size, glm::vec2 _origin, float _zNear, float _zFar) - : m_projection(glm::ortho(-_size.x*_origin.x, _size.x*(1.f-_origin.x), - -_size.y * _origin.y, _size.y* (1.f - _origin.y), - _zNear, _zFar)), - m_view(glm::identity()) - { - updateMatrices(); - } - - vec3 Camera::toWorldSpace(const vec2& _screenSpace) const - { - vec2 clipSpace = _screenSpace / vec2(Device::getBufferSize()); - clipSpace.y = 1.f - clipSpace.y; - clipSpace = clipSpace * 2.f - vec2(1.f, 1.f); - - const vec4 worldSpace = m_viewProjectionInv * vec4(clipSpace, -1.f, 1.f); - - return vec3(worldSpace) / worldSpace.w; - } - - void Camera::updateMatrices() - { - m_viewProjection = m_projection * m_view; - m_viewProjectionInv = glm::inverse(m_viewProjection); - } + using namespace glm; + constexpr glm::vec3 RIGHT_VECTOR = glm::vec3(1.0f, 0.0f, 0.0f); + constexpr glm::vec3 UP_VECTOR = glm::vec3(0.0f, 1.0f, 0.0f); + constexpr glm::vec3 FORWARD_VECTOR = glm::vec3(0.0f, 0.0f, 1.0f); + + Camera::Camera(float _fov, float _zNear, float zFar) + : m_projection(glm::perspective(glm::radians(_fov), Device::getAspectRatio(), _zNear, zFar)), + m_view(glm::identity()) { + updateMatrices(); + } + + Camera::Camera(glm::vec2 _size, glm::vec2 _origin, float _zNear, float _zFar) + : m_projection(glm::ortho(-_size.x * _origin.x, _size.x * (1.f - _origin.x), + -_size.y * _origin.y, _size.y * (1.f - _origin.y), + _zNear, _zFar)), + m_view(glm::identity()) { + updateMatrices(); + } + + vec3 Camera::toWorldSpace(const vec2 &_screenSpace) const { + vec2 clipSpace = _screenSpace / vec2(Device::getBufferSize()); + clipSpace.y = 1.f - clipSpace.y; + clipSpace = clipSpace * 2.f - vec2(1.f, 1.f); + + const vec4 worldSpace = m_viewProjectionInv * vec4(clipSpace, -1.f, 1.f); + + return vec3(worldSpace) / worldSpace.w; + } + + void Camera::updateMatrices() { + m_viewProjection = m_projection * m_view; + m_viewProjectionInv = glm::inverse(m_viewProjection); + updateTransform(); + } + + void Camera::updateTransform() { + lookAtMatrix = glm::lookAt(cameraPosition, cameraPosition + cameraForward, cameraUp); + // fix x direction (gets inverted due to RHS / cross product) + lookAtMatrix[0][0] *= -1.0f; + lookAtMatrix[1][0] *= -1.0f; + lookAtMatrix[2][0] *= -1.0f; + lookAtMatrix[3][0] *= -1.0f; + worldToCameraMatrix = m_viewProjection * lookAtMatrix; + } + + void Camera::moveRelative(const float &right, const float &up, const float &forward) { + if (right == 0.0f && up == 0.0f && forward == 0.0f) { + return; + } + + if (right != 0.0f) { + cameraPosition += cameraRight * right; + } + if (up != 0.0f) { + cameraPosition += cameraUp * up; + } + if (forward != 0.0f) { + cameraPosition += cameraForward * forward; + } + updateTransform(); + } + + void Camera::moveAbsolute(const vec3 &direction) { + cameraPosition += direction; + updateTransform(); + } + + void Camera::setRotation(const float &yawAngle, const float &pitchAngle, const float &rollAngle) { + cameraRight = RIGHT_VECTOR; + cameraUp = UP_VECTOR; + cameraForward = FORWARD_VECTOR; + rotate(yawAngle, pitchAngle, rollAngle); + } + + void Camera::setRotation(const glm::mat3 &rotationMatrix) { + cameraRight = rotationMatrix * RIGHT_VECTOR; + cameraUp = rotationMatrix * UP_VECTOR; + cameraForward = rotationMatrix * FORWARD_VECTOR; + updateTransform(); + } + + void Camera::rotate(const float &yawAngle, const float &pitchAngle, const float &rollAngle) { + if (yawAngle == 0.0f && pitchAngle == 0.0f && rollAngle == 0.0f) { + return; + } + + if (yawAngle != 0.0f) { + auto yawRotationMatrix = glm::mat3(glm::rotate( + glm::identity(), + glm::radians(yawAngle), + cameraUp)); + cameraRight = yawRotationMatrix * cameraRight; + cameraForward = yawRotationMatrix * cameraForward; + } + if (pitchAngle != 0.0f) { + auto pitchRotationMatrix = glm::mat3(glm::rotate( + glm::identity(), + glm::radians(pitchAngle), + cameraRight)); + cameraForward = pitchRotationMatrix * cameraForward; + cameraUp = pitchRotationMatrix * cameraUp; + } + if (rollAngle != 0.0f) { + auto rollRotationMatrix = glm::mat3(glm::rotate( + glm::identity(), + glm::radians(rollAngle), + cameraForward)); + cameraRight = rollRotationMatrix * cameraRight; + cameraUp = rollRotationMatrix * cameraUp; + } + + updateTransform(); + } + + void Camera::rotate(const mat3 &rotationMatrix) { + cameraRight = rotationMatrix * cameraRight; + cameraUp = rotationMatrix * cameraUp; + cameraForward = rotationMatrix * cameraForward; + updateTransform(); + } + } \ No newline at end of file diff --git a/src/engine/graphics/camera.hpp b/src/engine/graphics/camera.hpp index f357ad3f..38f9af0f 100644 --- a/src/engine/graphics/camera.hpp +++ b/src/engine/graphics/camera.hpp @@ -4,29 +4,76 @@ namespace graphics { - class Camera - { - public: - // Perspective - // @param _fov as angle - Camera(float _fov, float _zNear, float zFar); - // Orthogonal - Camera(glm::vec2 _size, glm::vec2 _origin = glm::vec2(0.f), float _zNear = 0.f, float _zFar = 1.f); - - const glm::mat4& getView() const { return m_view; } - const glm::mat4& getProjection() const { return m_projection; } - const glm::mat4& getViewProjection() const { return m_viewProjection; } - - void setView(const glm::mat4& _view) { m_view = _view; updateMatrices(); } - - // @Return the position of the point _screenSpace on the near plane of this camera - glm::vec3 toWorldSpace(const glm::vec2& _sceenSpace) const; - private: - void updateMatrices(); - - glm::mat4 m_projection; - glm::mat4 m_view; - glm::mat4 m_viewProjection; - glm::mat4 m_viewProjectionInv; - }; + class Camera { + public: + // Perspective + // @param _fov as angle + Camera(float _fov, float _zNear, float zFar); + + // Orthogonal + Camera(glm::vec2 _size, glm::vec2 _origin = glm::vec2(0.f), float _zNear = 0.f, float _zFar = 1.f); + + [[nodiscard]] const glm::mat4 &getView() const { return m_view; } + + [[nodiscard]] const glm::mat4 &getProjection() const { return m_projection; } + + [[nodiscard]] const glm::mat4 &getViewProjection() const { return m_viewProjection; } + + void setView(const glm::mat4 &_view) { + m_view = _view; + updateMatrices(); + } + + // @Return the position of the point _screenSpace on the near plane of this camera + [[nodiscard]] glm::vec3 toWorldSpace(const glm::vec2 &_screenSpace) const; + + [[nodiscard]] const glm::vec3 &getPosition() const { return cameraPosition; } + + void setPosition(const glm::vec3 &position) { + cameraPosition = position; + updateTransform(); + } + + void moveRelative(const float &right, const float &up, const float &forward); + + void moveAbsolute(const glm::vec3 &direction); + + [[nodiscard]] const glm::vec3 &forwardVector() const { return cameraForward; } + + [[nodiscard]] const glm::vec3 &upVector() const { return cameraUp; } + + [[nodiscard]] const glm::vec3 &rightVector() const { return cameraRight; } + + // sets the camera rotation + void setRotation(const float &yawAngle, const float &pitchAngle, const float &rollAngle); + + // sets the camera rotation + void setRotation(const glm::mat3 &rotationMatrix); + + // rotates the camera based on its current rotation + void rotate(const float &yawAngle, const float &pitchAngle, const float &rollAngle); + + // rotates the camera based on its current rotation + void rotate(const glm::mat3 &rotationMatrix); + + [[nodiscard]] const glm::mat4 &getWorldToCamera() const { return worldToCameraMatrix; } + + private: + void updateMatrices(); + + void updateTransform(); + + glm::mat4 m_projection; + glm::mat4 m_view; + glm::mat4 m_viewProjection; + glm::mat4 m_viewProjectionInv; + + glm::vec3 cameraPosition = {0.0f, 0.0f, 0.0f}; + glm::vec3 cameraForward = {0.0f, 0.0f, 1.0f}; + glm::vec3 cameraUp = {0.0f, 1.0f, 0.0f}; + glm::vec3 cameraRight = {1.0f, 0.0f, 0.0f}; + glm::mat4 lookAtMatrix; + + glm::mat4 worldToCameraMatrix; + }; } \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index cf82b70d..2ec9cbae 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -51,11 +51,13 @@ struct VertexData { glm::vec3 normalData; }; -struct LightData { - inline static const int LIGHT_TYPE_DIRECTIONAL = 0; - inline static const int LIGHT_TYPE_SPOT = 1; - inline static const int LIGHT_TYPE_POINT = 2; +enum LightType : int { + directional = 0, + spot = 1, + point = 2 +}; +struct LightData { /** * Directional Light: * position - @@ -80,7 +82,7 @@ struct LightData { * intensity resulting light-intensity at a given point is `intensity * ( 1 - ([point_to_light_distance] / [range]) )²` */ - int light_type; + LightType light_type; glm::vec3 light_position; glm::vec3 light_direction; float light_range; @@ -104,15 +106,15 @@ int main(int argc, char *argv[]) { input::InputManager::initialize(window); input::InputManager::setCursorMode(input::InputManager::CursorMode::NORMAL); - glm::vec3 ambientLightData = {0.3f, 0.3f, 0.3f}; + glm::vec3 ambientLightData = {0.7f, 0.7f, 0.7f}; // TODO create light type specific constructors LightData lightData = { - LightData::LIGHT_TYPE_DIRECTIONAL, + LightType::directional, glm::vec3(0.0f, 0.0f, 0.0f), - glm::normalize(glm::vec3(-1.0f, -1.0f, 0.0f)), + glm::normalize(glm::vec3(-1.0f, -1.0f, 0.5f)), 0.0f, 0.0f, glm::vec3(1.0f, 1.0f, 1.0f), - 1.0f + 2.0f }; graphics::Camera camera(90.0f, 0.1f, 300.0f); @@ -147,15 +149,15 @@ int main(int argc, char *argv[]) { }; VertexData triangles_tri[] = { - {glm::vec3(-1.0f, -1.0f, 0.0f), glm::vec2(-1.0f, -1.0f)}, - {glm::vec3(1.0f, -1.0f, 0.0f), glm::vec2(1.0f, -1.0f)}, - {glm::vec3(0.0f, 1.0f, 0.0f), glm::vec2(0.0f, 1.0f)}, + {glm::vec3(-1.0f, -1.0f, 0.0f), glm::vec2(-1.0f, -1.0f), glm::vec3(0.0f, 0.0f, -1.0f)}, + {glm::vec3(1.0f, -1.0f, 0.0f), glm::vec2(1.0f, -1.0f), glm::vec3(0.0f, 0.0f, -1.0f)}, + {glm::vec3(0.0f, 1.0f, 0.0f), glm::vec2(0.0f, 1.0f), glm::vec3(0.0f, 0.0f, -1.0f)}, }; VertexData triangles_rect[] = { - {glm::vec3(-0.75f, -0.75f, 0.0f), glm::vec2(0.0f, -0.75f)}, - {glm::vec3(0.75f, -0.75f, 0.0f), glm::vec2(0.75f, -0.75f)}, - {glm::vec3(-0.75f, 0.75f, 0.0f), glm::vec2(-0.75f, 0.75f)}, - {glm::vec3(0.75f, 0.75f, 0.0f), glm::vec2(0.75f, 0.75f)}, + {glm::vec3(-0.75f, -0.75f, 0.0f), glm::vec2(0.0f, -0.75f), glm::vec3(0.0f, 0.0f, -1.0f)}, + {glm::vec3(0.75f, -0.75f, 0.0f), glm::vec2(0.75f, -0.75f), glm::vec3(0.0f, 0.0f, -1.0f)}, + {glm::vec3(-0.75f, 0.75f, 0.0f), glm::vec2(-0.75f, 0.75f), glm::vec3(0.0f, 0.0f, -1.0f)}, + {glm::vec3(0.75f, 0.75f, 0.0f), glm::vec2(0.75f, 0.75f), glm::vec3(0.0f, 0.0f, -1.0f)}, }; std::vector buffers = {}; @@ -174,14 +176,7 @@ int main(int argc, char *argv[]) { program.attach(fragmentShader); program.link(); program.use(); - - const glm::vec4 rightVector = {1.0f, 0.0f, 0.0f, 0.0f}; - const glm::vec4 forwardVector = {0.0f, 0.0f, 1.0f, 0.0f}; - const glm::vec4 upVector = {0.0f, 1.0f, 0.0f, 0.0f}; - glm::vec4 cameraPosition = {0.0f, 0.0f, -3.0f, 0.0f}; - glm::vec4 cameraForwardVector = forwardVector; - glm::vec4 cameraUpVector = upVector; - glm::vec4 cameraRightVector = rightVector; + const float cameraStep = 0.05f; const float cameraPitchSensitivity = 0.5f; const float cameraYawSensitivity = 0.5f; @@ -189,7 +184,6 @@ int main(int argc, char *argv[]) { float cameraPitch = 0.0f; float cameraYaw = 0.0f; float cameraRoll = 0.0f; - glm::mat4 worldToCameraMatrix; GLint worldToCameraMatrixID = glGetUniformLocation(program.getID(), "world_to_camera_matrix"); GLint cameraPositionShaderID = glGetUniformLocation(program.getID(), "camera_position"); @@ -228,11 +222,6 @@ int main(int argc, char *argv[]) { buffers.push_back(buffer); } if (input::InputManager::isKeyPressed(input::Key::S)) { - /*std::cout << "floating triangles: " << meshStripData->floatingTriangles.size() << std::endl; - std::cout << "triangle strips: " << meshStripData->triangleStrips.size() << std::endl; - for (const auto &triStrip: meshStripData->triangleStrips) { - std::cout << " vertices: " << triStrip.vertexIndices.size() << std::endl; - }*/ buffers.clear(); if (input::InputManager::isKeyPressed(input::Key::Num1)) { @@ -273,30 +262,28 @@ int main(int argc, char *argv[]) { } } + float rightInput = 0.0f; + float forwardInput = 0.0f; + float upInput = 0.0f; if (input::InputManager::isKeyPressed(input::Key::KP_8)) { - cameraPosition += cameraForwardVector * cameraStep; - std::cout << "camera position: " << cameraPosition[0] << " / " << cameraPosition[1] << " / " << cameraPosition[2] << std::endl; + forwardInput += cameraStep; } if (input::InputManager::isKeyPressed(input::Key::KP_2)) { - cameraPosition -= cameraForwardVector * cameraStep; - std::cout << "camera position: " << cameraPosition[0] << " / " << cameraPosition[1] << " / " << cameraPosition[2] << std::endl; + forwardInput -= cameraStep; } if (input::InputManager::isKeyPressed(input::Key::KP_6)) { - cameraPosition += cameraRightVector * cameraStep; - std::cout << "camera position: " << cameraPosition[0] << " / " << cameraPosition[1] << " / " << cameraPosition[2] << std::endl; + rightInput += cameraStep; } if (input::InputManager::isKeyPressed(input::Key::KP_4)) { - cameraPosition -= cameraRightVector * cameraStep; - std::cout << "camera position: " << cameraPosition[0] << " / " << cameraPosition[1] << " / " << cameraPosition[2] << std::endl; + rightInput -= cameraStep; } if (input::InputManager::isKeyPressed(input::Key::KP_9)) { - cameraPosition += cameraUpVector * cameraStep; - std::cout << "camera position: " << cameraPosition[0] << " / " << cameraPosition[1] << " / " << cameraPosition[2] << std::endl; + upInput += cameraStep; } if (input::InputManager::isKeyPressed(input::Key::KP_3)) { - cameraPosition -= cameraUpVector * cameraStep; - std::cout << "camera position: " << cameraPosition[0] << " / " << cameraPosition[1] << " / " << cameraPosition[2] << std::endl; + upInput -= cameraStep; } + camera.moveRelative(rightInput, upInput, forwardInput); float cursorDeltaX = currentCursorPos.x - prevCursorPos.x; float cursorDeltaY = currentCursorPos.y - prevCursorPos.y; @@ -316,18 +303,8 @@ int main(int argc, char *argv[]) { cameraPitch = -90.0f; } } + camera.setRotation(cameraYaw, cameraPitch, cameraRoll); - // update camera up/forward/right vectors according to camera rotation - // apply yaw, then pitch, then roll - auto identityMat4 = glm::identity(); - auto yawRotationMatrix = glm::rotate(identityMat4, glm::radians(cameraYaw), glm::vec3(cameraUpVector)); - cameraRightVector = yawRotationMatrix * rightVector; - auto pitchRotationMatrix = glm::rotate(identityMat4, glm::radians(cameraPitch), glm::vec3(cameraRightVector)); - cameraForwardVector = pitchRotationMatrix * yawRotationMatrix * forwardVector; - auto rollRotationMatrix = glm::rotate(identityMat4, glm::radians(cameraRoll), glm::vec3(cameraForwardVector)); - cameraRightVector = rollRotationMatrix * cameraRightVector; - cameraUpVector = rollRotationMatrix * pitchRotationMatrix * upVector; - glUniform3fv(glsl_ambient_light, 1, glm::value_ptr(ambientLightData)); // TODO create a function for binding lightData @@ -338,16 +315,9 @@ int main(int argc, char *argv[]) { glUniform1f(glsl_light_spot_angle, lightData.light_spot_angle); glUniform3fv(glsl_light_color, 1, glm::value_ptr(lightData.light_color)); glUniform1f(glsl_light_intensity, lightData.light_intensity); - - auto lookAtMatrix = glm::lookAt(glm::vec3(cameraPosition), glm::vec3(cameraPosition + cameraForwardVector), glm::vec3(cameraUpVector)); - // fix x direction - lookAtMatrix[0][0] *= -1.0f; - lookAtMatrix[1][0] *= -1.0f; - lookAtMatrix[2][0] *= -1.0f; - lookAtMatrix[3][0] *= -1.0f; - worldToCameraMatrix = camera.getViewProjection() * lookAtMatrix; - glUniformMatrix4fv(worldToCameraMatrixID, 1, GL_FALSE, glm::value_ptr(worldToCameraMatrix)); - glUniform3fv(cameraPositionShaderID, 1, glm::value_ptr(cameraPosition)); + + glUniformMatrix4fv(worldToCameraMatrixID, 1, GL_FALSE, glm::value_ptr(camera.getWorldToCamera())); + glUniform3fv(cameraPositionShaderID, 1, glm::value_ptr(camera.getPosition())); for (const auto &buffer: buffers) { buffer->draw(); } From 9a858ebd0b22a854070b7e0a5061fea24065b3bc Mon Sep 17 00:00:00 2001 From: BlazingTwist Date: Sat, 27 Nov 2021 12:59:04 +0100 Subject: [PATCH 05/12] reformat shader --- resources/shader/demo.frag | 2 +- resources/shader/demo.vert | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/shader/demo.frag b/resources/shader/demo.frag index d6c09a6a..77752b5a 100644 --- a/resources/shader/demo.frag +++ b/resources/shader/demo.frag @@ -43,7 +43,7 @@ void main() } else if (light_type == LIGHT_TYPE_POINT){ // TODO implement point lights } - + out_color = texColor * vec4(ambientColor + diffuseColor + specularColor, 1f); //out_color = vec4(specularColor, 1f); } \ No newline at end of file diff --git a/resources/shader/demo.vert b/resources/shader/demo.vert index 6ea3907f..fc50b91c 100644 --- a/resources/shader/demo.vert +++ b/resources/shader/demo.vert @@ -15,7 +15,7 @@ void main() //gl_Position = vec4(in_position, 1f); gl_Position = world_to_camera_matrix * vec4(in_position, 1f); render_position_frag = in_position; - + uv_coord_frag = uv_coord; normal_vec_frag = normal_vec; } \ No newline at end of file From 63da27acb17cd53d797e9d43594b5c9d9a7889b9 Mon Sep 17 00:00:00 2001 From: BlazingTwist Date: Sat, 27 Nov 2021 12:59:33 +0100 Subject: [PATCH 06/12] move LightData into separate file --- src/engine/graphics/lightdata.cpp | 29 ++++++++ src/engine/graphics/lightdata.h | 111 ++++++++++++++++++++++++++++++ src/main.cpp | 81 +++------------------- 3 files changed, 150 insertions(+), 71 deletions(-) create mode 100644 src/engine/graphics/lightdata.cpp create mode 100644 src/engine/graphics/lightdata.h diff --git a/src/engine/graphics/lightdata.cpp b/src/engine/graphics/lightdata.cpp new file mode 100644 index 00000000..fec5c406 --- /dev/null +++ b/src/engine/graphics/lightdata.cpp @@ -0,0 +1,29 @@ +#include "lightdata.h" + +namespace graphics { + + void LightData::prepareBinding(const unsigned int &programID) { + currentProgramID = programID; + glsl_light_type = glGetUniformLocation(programID, "light_type"); + glsl_light_position = glGetUniformLocation(programID, "light_position"); + glsl_light_direction = glGetUniformLocation(programID, "light_direction"); + glsl_light_range = glGetUniformLocation(programID, "light_range"); + glsl_light_spot_angle = glGetUniformLocation(programID, "light_spot_angle"); + glsl_light_color = glGetUniformLocation(programID, "light_color"); + glsl_light_intensity = glGetUniformLocation(programID, "light_intensity"); + } + + void LightData::bindData(const unsigned int &programID) { + if (currentProgramID != programID) { + prepareBinding(programID); + } + + glUniform1i(glsl_light_type, light_type); + glUniform3fv(glsl_light_position, 1, glm::value_ptr(light_position)); + glUniform3fv(glsl_light_direction, 1, glm::value_ptr(light_direction)); + glUniform1f(glsl_light_range, light_range); + glUniform1f(glsl_light_spot_angle, light_spot_angle); + glUniform3fv(glsl_light_color, 1, glm::value_ptr(light_color)); + glUniform1f(glsl_light_intensity, light_intensity); + } +} \ No newline at end of file diff --git a/src/engine/graphics/lightdata.h b/src/engine/graphics/lightdata.h new file mode 100644 index 00000000..eeabeee3 --- /dev/null +++ b/src/engine/graphics/lightdata.h @@ -0,0 +1,111 @@ +#ifndef ACAENGINE_LIGHTDATA_H +#define ACAENGINE_LIGHTDATA_H + +#include +#include +#include + +namespace graphics { + enum LightType : int { + directional = 0, + spot = 1, + point = 2 + }; + + struct LightData { + /** + * Directional Light: + * position - + * direction direction the light is emitted in + * range - + * spot_angle - + * color color of the emitted light + * intensity simple multiplier for emitted light + * Spot-Light: + * position position of the light source in world space + * direction direction the spot-light is facing + * range maximum range of emitted light + * spot_angle max angle the light is emitted at in degrees (e.g. 5° means light is emitted in a cone of 2.5° from the spot-light's direction) + * color color of the emitted light + * intensity resulting light-intensity at a given point is `intensity * ( 1 - ([point_to_light_distance] / [range]) )²` + * Point-Light: + * position position of the light source in world space + * direction - + * range maximum range of emitted light + * spot_angle - + * color color of the emitted light + * intensity resulting light-intensity at a given point is `intensity * ( 1 - ([point_to_light_distance] / [range]) )²` + */ + + LightType light_type; + glm::vec3 light_position; + glm::vec3 light_direction; + float light_range; + float light_spot_angle; + glm::vec3 light_color; + float light_intensity; + + static constexpr LightData directional(glm::vec3 direction, glm::vec3 lightColor, float lightIntensity) { + return LightData{ + LightType::directional, + glm::vec3(0.0f, 0.0f, 0.0f), + direction, + 0.0f, + 0.0f, + lightColor, + lightIntensity + }; + } + + static constexpr LightData spot(glm::vec3 position, glm::vec3 direction, float range, float spotAngle, glm::vec3 lightColor, float lightIntensity) { + return LightData{ + LightType::directional, + position, + direction, + range, + spotAngle, + lightColor, + lightIntensity + }; + } + + static constexpr LightData point(glm::vec3 position, float range, glm::vec3 lightColor, float lightIntensity) { + return LightData{ + LightType::directional, + position, + glm::vec3(0.0f, 0.0f, 0.0f), + range, + 0.0f, + lightColor, + lightIntensity + }; + } + + void bindData(const unsigned int &programID); + + private: + constexpr LightData(LightType lightType, glm::vec3 lightPosition, glm::vec3 lightDirection, float lightRange, float lightSpotAngle, + glm::vec3 lightColor, float lightIntensity) : + light_type(lightType), + light_position(lightPosition), + light_direction(lightDirection), + light_range(lightRange), + light_spot_angle(lightSpotAngle), + light_color(lightColor), + light_intensity(lightIntensity) {} + + void prepareBinding(const unsigned int &programID); + + unsigned int currentProgramID = -1; + GLint glsl_light_type = 0; + GLint glsl_light_position = 0; + GLint glsl_light_direction = 0; + GLint glsl_light_range = 0; + GLint glsl_light_spot_angle = 0; + GLint glsl_light_color = 0; + GLint glsl_light_intensity = 0; + }; +} + + +#endif //ACAENGINE_LIGHTDATA_H diff --git a/src/main.cpp b/src/main.cpp index 2ec9cbae..f2ca6027 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -17,7 +18,6 @@ #define _CRTDBG_MAP_ALLOC #include -#include #include #endif @@ -51,46 +51,6 @@ struct VertexData { glm::vec3 normalData; }; -enum LightType : int { - directional = 0, - spot = 1, - point = 2 -}; - -struct LightData { - /** - * Directional Light: - * position - - * direction direction the light is emitted in - * range - - * spot_angle - - * color color of the emitted light - * intensity simple multiplier for emitted light - * Spot-Light: - * position position of the light source in world space - * direction direction the spot-light is facing - * range maximum range of emitted light - * spot_angle max angle the light is emitted at in degrees (e.g. 5° means light is emitted in a cone of 2.5° from the spot-light's direction) - * color color of the emitted light - * intensity resulting light-intensity at a given point is `intensity * ( 1 - ([point_to_light_distance] / [range]) )²` - * Point-Light: - * position position of the light source in world space - * direction - - * range maximum range of emitted light - * spot_angle - - * color color of the emitted light - * intensity resulting light-intensity at a given point is `intensity * ( 1 - ([point_to_light_distance] / [range]) )²` - */ - - LightType light_type; - glm::vec3 light_position; - glm::vec3 light_direction; - float light_range; - float light_spot_angle; - glm::vec3 light_color; - float light_intensity; -}; - int main(int argc, char *argv[]) { #ifndef NDEBUG #if defined(_MSC_VER) @@ -107,17 +67,13 @@ int main(int argc, char *argv[]) { input::InputManager::setCursorMode(input::InputManager::CursorMode::NORMAL); glm::vec3 ambientLightData = {0.7f, 0.7f, 0.7f}; - // TODO create light type specific constructors - LightData lightData = { - LightType::directional, - glm::vec3(0.0f, 0.0f, 0.0f), + graphics::LightData lightData = graphics::LightData::directional( glm::normalize(glm::vec3(-1.0f, -1.0f, 0.5f)), - 0.0f, 0.0f, glm::vec3(1.0f, 1.0f, 1.0f), - 2.0f - }; + 2.0f); graphics::Camera camera(90.0f, 0.1f, 300.0f); + camera.setPosition(glm::vec3(0.0f, 0.0f, -3.0f)); static graphics::Sampler sampler(graphics::Sampler::Filter::LINEAR, graphics::Sampler::Filter::LINEAR, graphics::Sampler::Filter::LINEAR, graphics::Sampler::Border::MIRROR); auto planetTexture = graphics::Texture2DManager::get("textures/planet1.png", sampler); @@ -150,14 +106,14 @@ int main(int argc, char *argv[]) { VertexData triangles_tri[] = { {glm::vec3(-1.0f, -1.0f, 0.0f), glm::vec2(-1.0f, -1.0f), glm::vec3(0.0f, 0.0f, -1.0f)}, - {glm::vec3(1.0f, -1.0f, 0.0f), glm::vec2(1.0f, -1.0f), glm::vec3(0.0f, 0.0f, -1.0f)}, - {glm::vec3(0.0f, 1.0f, 0.0f), glm::vec2(0.0f, 1.0f), glm::vec3(0.0f, 0.0f, -1.0f)}, + {glm::vec3(1.0f, -1.0f, 0.0f), glm::vec2(1.0f, -1.0f), glm::vec3(0.0f, 0.0f, -1.0f)}, + {glm::vec3(0.0f, 1.0f, 0.0f), glm::vec2(0.0f, 1.0f), glm::vec3(0.0f, 0.0f, -1.0f)}, }; VertexData triangles_rect[] = { - {glm::vec3(-0.75f, -0.75f, 0.0f), glm::vec2(0.0f, -0.75f), glm::vec3(0.0f, 0.0f, -1.0f)}, + {glm::vec3(-0.75f, -0.75f, 0.0f), glm::vec2(0.0f, -0.75f), glm::vec3(0.0f, 0.0f, -1.0f)}, {glm::vec3(0.75f, -0.75f, 0.0f), glm::vec2(0.75f, -0.75f), glm::vec3(0.0f, 0.0f, -1.0f)}, {glm::vec3(-0.75f, 0.75f, 0.0f), glm::vec2(-0.75f, 0.75f), glm::vec3(0.0f, 0.0f, -1.0f)}, - {glm::vec3(0.75f, 0.75f, 0.0f), glm::vec2(0.75f, 0.75f), glm::vec3(0.0f, 0.0f, -1.0f)}, + {glm::vec3(0.75f, 0.75f, 0.0f), glm::vec2(0.75f, 0.75f), glm::vec3(0.0f, 0.0f, -1.0f)}, }; std::vector buffers = {}; @@ -177,6 +133,8 @@ int main(int argc, char *argv[]) { program.link(); program.use(); + lightData.bindData(program.getID()); + const float cameraStep = 0.05f; const float cameraPitchSensitivity = 0.5f; const float cameraYawSensitivity = 0.5f; @@ -189,15 +147,6 @@ int main(int argc, char *argv[]) { GLint cameraPositionShaderID = glGetUniformLocation(program.getID(), "camera_position"); GLint glsl_ambient_light = glGetUniformLocation(program.getID(), "ambient_light"); - // TODO create a function for binding lightData - GLint glsl_light_type = glGetUniformLocation(program.getID(), "light_type"); - GLint glsl_light_position = glGetUniformLocation(program.getID(), "light_position"); - GLint glsl_light_direction = glGetUniformLocation(program.getID(), "light_direction"); - GLint glsl_light_range = glGetUniformLocation(program.getID(), "light_range"); - GLint glsl_light_spot_angle = glGetUniformLocation(program.getID(), "light_spot_angle"); - GLint glsl_light_color = glGetUniformLocation(program.getID(), "light_color"); - GLint glsl_light_intensity = glGetUniformLocation(program.getID(), "light_intensity"); - graphics::glCall(glEnable, GL_DEPTH_TEST); graphics::glCall(glClearColor, 0.05f, 0.0f, 0.05f, 1.f); @@ -306,16 +255,6 @@ int main(int argc, char *argv[]) { camera.setRotation(cameraYaw, cameraPitch, cameraRoll); glUniform3fv(glsl_ambient_light, 1, glm::value_ptr(ambientLightData)); - - // TODO create a function for binding lightData - glUniform1i(glsl_light_type, lightData.light_type); - glUniform3fv(glsl_light_position, 1, glm::value_ptr(lightData.light_position)); - glUniform3fv(glsl_light_direction, 1, glm::value_ptr(lightData.light_direction)); - glUniform1f(glsl_light_range, lightData.light_range); - glUniform1f(glsl_light_spot_angle, lightData.light_spot_angle); - glUniform3fv(glsl_light_color, 1, glm::value_ptr(lightData.light_color)); - glUniform1f(glsl_light_intensity, lightData.light_intensity); - glUniformMatrix4fv(worldToCameraMatrixID, 1, GL_FALSE, glm::value_ptr(camera.getWorldToCamera())); glUniform3fv(cameraPositionShaderID, 1, glm::value_ptr(camera.getPosition())); for (const auto &buffer: buffers) { From 255e1fc4a148f867611f52aae669acc93201e5e6 Mon Sep 17 00:00:00 2001 From: BlazingTwist Date: Sat, 27 Nov 2021 13:56:17 +0100 Subject: [PATCH 07/12] fix lightdata "constructor" --- src/engine/graphics/lightdata.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/engine/graphics/lightdata.h b/src/engine/graphics/lightdata.h index eeabeee3..8e7d4f31 100644 --- a/src/engine/graphics/lightdata.h +++ b/src/engine/graphics/lightdata.h @@ -59,7 +59,7 @@ namespace graphics { static constexpr LightData spot(glm::vec3 position, glm::vec3 direction, float range, float spotAngle, glm::vec3 lightColor, float lightIntensity) { return LightData{ - LightType::directional, + LightType::spot, position, direction, range, @@ -71,7 +71,7 @@ namespace graphics { static constexpr LightData point(glm::vec3 position, float range, glm::vec3 lightColor, float lightIntensity) { return LightData{ - LightType::directional, + LightType::point, position, glm::vec3(0.0f, 0.0f, 0.0f), range, From 6504aa259808402a960e7f66fd782b228dd03790 Mon Sep 17 00:00:00 2001 From: BlazingTwist Date: Sat, 27 Nov 2021 13:56:43 +0100 Subject: [PATCH 08/12] implement point light --- resources/shader/demo.frag | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/resources/shader/demo.frag b/resources/shader/demo.frag index 77752b5a..dccb4006 100644 --- a/resources/shader/demo.frag +++ b/resources/shader/demo.frag @@ -29,21 +29,35 @@ void main() { vec4 texColor = texture(tx_color, uv_coord_frag); vec4 phongData = texture(tx_phong, uv_coord_frag); - vec3 ambientColor = max(phongData.r * ambient_light, 0f); + vec3 ambientColor = max(phongData.r * ambient_light, 0.0f); vec3 diffuseColor; vec3 specularColor; // TODO light bounces? occlusion? if (light_type == LIGHT_TYPE_DIRECTIONAL){ // direction, color, intensity - diffuseColor = max(phongData.g * dot(-light_direction, normal_vec_frag) * light_color, 0f) * light_intensity; - specularColor = max(phongData.b * 8 * pow(dot(reflect(light_direction, normal_vec_frag), normalize(camera_position - render_position_frag)), phongData.a * 255) * light_color, 0f) * light_intensity; + + float diffuseDot = max(dot(-light_direction, normal_vec_frag), 0.0f); + float specularDot = max(dot(reflect(light_direction, normal_vec_frag), normalize(camera_position - render_position_frag)), 0.0f); + diffuseColor = phongData.g * diffuseDot * light_color * light_intensity; + specularColor = phongData.b * 8 * pow(specularDot, phongData.a * 255) * light_color * light_intensity; + } else if (light_type == LIGHT_TYPE_SPOT){ // TODO implement spot lights } else if (light_type == LIGHT_TYPE_POINT){ - // TODO implement point lights + // position, range, color, intensity + // light intensity should diminish proportionally to `1 / distance_squared` + vec3 pointLightDirection = normalize(render_position_frag - light_position); + float lightDistance = length(render_position_frag - light_position); + if(lightDistance <= light_range){ + float distanceFactor = 0.01f / pow(lightDistance / light_range, 2); + + float diffuseDot = max(dot(-pointLightDirection, normal_vec_frag), 0.0f); + float specularDot = max(dot(reflect(pointLightDirection, normal_vec_frag), normalize(camera_position - render_position_frag)), 0.0f); + diffuseColor = phongData.g * diffuseDot * light_color * light_intensity * distanceFactor; + specularColor = phongData.b * 8 * pow(specularDot, phongData.a * 255) * light_color * light_intensity * distanceFactor; + } } - out_color = texColor * vec4(ambientColor + diffuseColor + specularColor, 1f); - //out_color = vec4(specularColor, 1f); + out_color = texColor * vec4(ambientColor + diffuseColor + specularColor, 1.0f); } \ No newline at end of file From 2ec58eca0ced31cff1bb7b49254aa7fe06fac021 Mon Sep 17 00:00:00 2001 From: BlazingTwist Date: Sat, 27 Nov 2021 14:28:18 +0100 Subject: [PATCH 09/12] implement spot light --- resources/shader/demo.frag | 25 ++++++++++++++++++------- src/engine/graphics/lightdata.cpp | 2 +- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/resources/shader/demo.frag b/resources/shader/demo.frag index dccb4006..2b02c502 100644 --- a/resources/shader/demo.frag +++ b/resources/shader/demo.frag @@ -36,22 +36,33 @@ void main() // TODO light bounces? occlusion? if (light_type == LIGHT_TYPE_DIRECTIONAL){ // direction, color, intensity - + float diffuseDot = max(dot(-light_direction, normal_vec_frag), 0.0f); float specularDot = max(dot(reflect(light_direction, normal_vec_frag), normalize(camera_position - render_position_frag)), 0.0f); diffuseColor = phongData.g * diffuseDot * light_color * light_intensity; specularColor = phongData.b * 8 * pow(specularDot, phongData.a * 255) * light_color * light_intensity; - + } else if (light_type == LIGHT_TYPE_SPOT){ - // TODO implement spot lights + // position, direction, range, spot_angle, color, intensity + vec3 spotLightDirection = normalize(render_position_frag - light_position); + // here we're (ab-)using the fact that the dot product of two normalized vectors is the cosine of their angle + float spotLightAngle = dot(light_direction, spotLightDirection); + float spotLightDistance = length(render_position_frag - light_position); + if (spotLightAngle > light_spot_angle && spotLightDistance <= light_range){ + float distanceFactor = 0.01f / pow(spotLightDistance / light_range, 2); + float diffuseDot = max(dot(-spotLightDirection, normal_vec_frag), 0.0f); + float specularDot = max(dot(reflect(spotLightDirection, normal_vec_frag), normalize(camera_position - render_position_frag)), 0.0f); + diffuseColor = phongData.g * diffuseDot * light_color * light_intensity * distanceFactor; + specularColor = phongData.b * 8 * pow(specularDot, phongData.a * 255) * light_color * light_intensity * distanceFactor; + } + } else if (light_type == LIGHT_TYPE_POINT){ // position, range, color, intensity // light intensity should diminish proportionally to `1 / distance_squared` vec3 pointLightDirection = normalize(render_position_frag - light_position); - float lightDistance = length(render_position_frag - light_position); - if(lightDistance <= light_range){ - float distanceFactor = 0.01f / pow(lightDistance / light_range, 2); - + float pointLightDistance = length(render_position_frag - light_position); + if (pointLightDistance <= light_range){ + float distanceFactor = 0.01f / pow(pointLightDistance / light_range, 2); float diffuseDot = max(dot(-pointLightDirection, normal_vec_frag), 0.0f); float specularDot = max(dot(reflect(pointLightDirection, normal_vec_frag), normalize(camera_position - render_position_frag)), 0.0f); diffuseColor = phongData.g * diffuseDot * light_color * light_intensity * distanceFactor; diff --git a/src/engine/graphics/lightdata.cpp b/src/engine/graphics/lightdata.cpp index fec5c406..c7d908b2 100644 --- a/src/engine/graphics/lightdata.cpp +++ b/src/engine/graphics/lightdata.cpp @@ -22,7 +22,7 @@ namespace graphics { glUniform3fv(glsl_light_position, 1, glm::value_ptr(light_position)); glUniform3fv(glsl_light_direction, 1, glm::value_ptr(light_direction)); glUniform1f(glsl_light_range, light_range); - glUniform1f(glsl_light_spot_angle, light_spot_angle); + glUniform1f(glsl_light_spot_angle, light_type == LightType::spot ? glm::cos(glm::radians(light_spot_angle)) : 0.0f); glUniform3fv(glsl_light_color, 1, glm::value_ptr(light_color)); glUniform1f(glsl_light_intensity, light_intensity); } From 36674f3f4161b55894d65ad7583715e3f3b65ed0 Mon Sep 17 00:00:00 2001 From: BlazingTwist Date: Sat, 27 Nov 2021 14:28:26 +0100 Subject: [PATCH 10/12] add spotLight demo --- src/main.cpp | 49 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index f2ca6027..ff7a4ba8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -67,10 +67,24 @@ int main(int argc, char *argv[]) { input::InputManager::setCursorMode(input::InputManager::CursorMode::NORMAL); glm::vec3 ambientLightData = {0.7f, 0.7f, 0.7f}; - graphics::LightData lightData = graphics::LightData::directional( + /*graphics::LightData lightData = graphics::LightData::directional( glm::normalize(glm::vec3(-1.0f, -1.0f, 0.5f)), glm::vec3(1.0f, 1.0f, 1.0f), - 2.0f); + 2.0f);*/ + /*graphics::LightData lightData = graphics::LightData::point( + glm::vec3(3.0f, 0.0f, 0.0f), + 10.0f, + glm::vec3(1.0f, 1.0f, 1.0f), + 5.0f + );*/ + graphics::LightData lightData = graphics::LightData::spot( + glm::vec3(3.0f, 0.0f, 0.0f), + glm::vec3(-1.0f, 0.0f, 0.0f), + 10.0f, + 10.0f, + glm::vec3(1.0f, 1.0f, 1.0f), + 5.0f + ); graphics::Camera camera(90.0f, 0.1f, 300.0f); camera.setPosition(glm::vec3(0.0f, 0.0f, -3.0f)); @@ -132,7 +146,7 @@ int main(int argc, char *argv[]) { program.attach(fragmentShader); program.link(); program.use(); - + lightData.bindData(program.getID()); const float cameraStep = 0.05f; @@ -254,6 +268,35 @@ int main(int argc, char *argv[]) { } camera.setRotation(cameraYaw, cameraPitch, cameraRoll); + bool lightChanged = false; + if (input::InputManager::isKeyPressed(input::Key::J)){ + lightData.light_position += glm::vec3(-0.05f, 0.0f, 0.0f); + lightChanged = true; + } + if (input::InputManager::isKeyPressed(input::Key::L)){ + lightData.light_position += glm::vec3(0.05f, 0.0f, 0.0f); + lightChanged = true; + } + if (input::InputManager::isKeyPressed(input::Key::I)){ + lightData.light_position += glm::vec3(0.0f, 0.05f, 0.0f); + lightChanged = true; + } + if (input::InputManager::isKeyPressed(input::Key::K)){ + lightData.light_position += glm::vec3(0.0f, -0.05f, 0.0f); + lightChanged = true; + } + if(input::InputManager::isKeyPressed(input::Key::U)){ + lightData.light_spot_angle -= 0.1f; + lightChanged = true; + } + if(input::InputManager::isKeyPressed(input::Key::O)){ + lightData.light_spot_angle += 0.1f; + lightChanged = true; + } + if(lightChanged){ + lightData.bindData(program.getID()); + } + glUniform3fv(glsl_ambient_light, 1, glm::value_ptr(ambientLightData)); glUniformMatrix4fv(worldToCameraMatrixID, 1, GL_FALSE, glm::value_ptr(camera.getWorldToCamera())); glUniform3fv(cameraPositionShaderID, 1, glm::value_ptr(camera.getPosition())); From 94e7e5edb2b945a06aa66421e71554f280a5ccf6 Mon Sep 17 00:00:00 2001 From: BlazingTwist Date: Sat, 27 Nov 2021 16:03:26 +0100 Subject: [PATCH 11/12] implement janky mesh and meshrenderer classes --- resources/shader/demo.vert | 7 +- src/engine/graphics/renderer/mesh.cpp | 56 +++++++- src/engine/graphics/renderer/mesh.hpp | 44 +++++- src/engine/graphics/renderer/meshrenderer.cpp | 30 +++- src/engine/graphics/renderer/meshrenderer.hpp | 37 +++-- src/main.cpp | 136 ++---------------- 6 files changed, 166 insertions(+), 144 deletions(-) diff --git a/resources/shader/demo.vert b/resources/shader/demo.vert index fc50b91c..28579417 100644 --- a/resources/shader/demo.vert +++ b/resources/shader/demo.vert @@ -8,13 +8,14 @@ layout(location = 0) out vec2 uv_coord_frag; layout(location = 1) out vec3 normal_vec_frag; layout(location = 2) out vec3 render_position_frag; +uniform mat4 object_to_world_matrix; uniform mat4 world_to_camera_matrix; void main() { - //gl_Position = vec4(in_position, 1f); - gl_Position = world_to_camera_matrix * vec4(in_position, 1f); - render_position_frag = in_position; + vec4 worldPosition = object_to_world_matrix * vec4(in_position, 1.0f); + gl_Position = world_to_camera_matrix * worldPosition; + render_position_frag = worldPosition.xyz; uv_coord_frag = uv_coord; normal_vec_frag = normal_vec; diff --git a/src/engine/graphics/renderer/mesh.cpp b/src/engine/graphics/renderer/mesh.cpp index f98423c2..734c795d 100644 --- a/src/engine/graphics/renderer/mesh.cpp +++ b/src/engine/graphics/renderer/mesh.cpp @@ -1,6 +1,60 @@ #include "mesh.hpp" -#include "mesh.hpp" namespace graphics { + static graphics::GeometryBuffer *createStripBuffer(const graphics::VertexAttribute *vertexAttribute, int numAttributes) { + auto *buffer = new graphics::GeometryBuffer( + graphics::GLPrimitiveType::TRIANGLE_STRIPE, + vertexAttribute, + numAttributes, + 0 + ); + return buffer; + } + + static graphics::GeometryBuffer *createTriangleBuffer(const graphics::VertexAttribute *vertexAttribute, int numAttributes) { + auto *buffer = new graphics::GeometryBuffer( + graphics::GLPrimitiveType::TRIANGLES, + vertexAttribute, + numAttributes, + 0 + ); + return buffer; + } + + Mesh::Mesh(const utils::MeshData::Handle &_meshData) { + utils::MeshStripData::Handle meshStripData = utils::MeshStripData::createFromMeshData(_meshData); + graphics::GeometryBuffer *triBuffer = createTriangleBuffer(VERTEX_ATTRIBUTES.data(), VERTEX_ATTRIBUTES.size()); + auto *triBufferData = new VertexData[meshStripData->floatingTriangles.size() * 3]; + int dataIndex = 0; + for (const auto &floatingTriangle: meshStripData->floatingTriangles) { + for (int i = 0; i < 3; i++) { + triBufferData[dataIndex + i] = { + _meshData->positions[floatingTriangle.indices[i].positionIdx], + _meshData->textureCoordinates[floatingTriangle.indices[i].textureCoordinateIdx.value_or(0)], + _meshData->normals[floatingTriangle.indices[i].normalIdx.value_or(0)] + }; + } + dataIndex += 3; + } + triBuffer->setData(triBufferData, sizeof(VertexData) * meshStripData->floatingTriangles.size() * 3); + buffers.push_back(triBuffer); + + for (const auto &strip: meshStripData->triangleStrips) { + auto *stripBuffer = createStripBuffer(VERTEX_ATTRIBUTES.data(), VERTEX_ATTRIBUTES.size()); + unsigned int vertexCount = strip.vertexIndices.size(); + auto *stripBufferData = new VertexData[vertexCount]; + dataIndex = 0; + for (const auto &vertexIndex: strip.vertexIndices) { + stripBufferData[dataIndex] = { + _meshData->positions[vertexIndex.positionIdx], + _meshData->textureCoordinates[vertexIndex.textureCoordinateIdx.value_or(0)], + _meshData->normals[vertexIndex.normalIdx.value_or(0)] + }; + dataIndex++; + } + stripBuffer->setData(stripBufferData, sizeof(VertexData) * vertexCount); + buffers.push_back(stripBuffer); + } + } } \ No newline at end of file diff --git a/src/engine/graphics/renderer/mesh.hpp b/src/engine/graphics/renderer/mesh.hpp index 6fa50a8a..d2603424 100644 --- a/src/engine/graphics/renderer/mesh.hpp +++ b/src/engine/graphics/renderer/mesh.hpp @@ -1,12 +1,46 @@ #pragma once +#include #include "../../utils/meshloader.hpp" +#include namespace graphics { - class Mesh - { - public: - Mesh(const utils::MeshData& _meshData) {} - }; + struct VertexData { + glm::vec3 positionData; + glm::vec2 uvData; + glm::vec3 normalData; + }; + + class Mesh { + public: + Mesh(const utils::MeshData::Handle &_meshData); + + static constexpr std::array VERTEX_ATTRIBUTES = { + graphics::VertexAttribute{ + graphics::PrimitiveFormat::FLOAT, + 3, + false, + false + }, + graphics::VertexAttribute{ + graphics::PrimitiveFormat::FLOAT, + 2, + false, + false + }, + graphics::VertexAttribute{ + graphics::PrimitiveFormat::FLOAT, + 3, + false, + false + } + }; + + const std::vector &getGeometryBuffers() { return buffers; } + + private: + std::vector buffers = {}; + + }; } diff --git a/src/engine/graphics/renderer/meshrenderer.cpp b/src/engine/graphics/renderer/meshrenderer.cpp index b740e7a5..3a5d2179 100644 --- a/src/engine/graphics/renderer/meshrenderer.cpp +++ b/src/engine/graphics/renderer/meshrenderer.cpp @@ -1,8 +1,36 @@ #include "meshrenderer.hpp" -#include "../core/opengl.hpp" #include "../core/texture.hpp" namespace graphics { + void MeshRenderer::draw(const Mesh &_mesh, const Texture2D &_texture, const Texture2D &phongData, const glm::mat4 &_transform) { + auto *renderData = new MeshRenderData{ + _mesh, + _texture, + phongData, + _transform + }; + meshBuffer.push_back(renderData); + } + + void MeshRenderer::present(const unsigned int &programID) { + if (currentProgramID != programID){ + currentProgramID = programID; + glsl_object_to_world_matrix = glGetUniformLocation(programID, "object_to_world_matrix"); + } + + for (const auto &meshRenderData: meshBuffer){ + meshRenderData->textureData.bind(0); + meshRenderData->phongData.bind(1); + glUniformMatrix4fv(glsl_object_to_world_matrix, 1, false, glm::value_ptr(meshRenderData->transform)); + for (const auto &geometryBuffer : meshRenderData->meshData.getGeometryBuffers()){ + geometryBuffer->draw(); + } + } + } + + void MeshRenderer::clear() { + meshBuffer.clear(); + } } diff --git a/src/engine/graphics/renderer/meshrenderer.hpp b/src/engine/graphics/renderer/meshrenderer.hpp index 520b886a..d3583cb0 100644 --- a/src/engine/graphics/renderer/meshrenderer.hpp +++ b/src/engine/graphics/renderer/meshrenderer.hpp @@ -3,22 +3,37 @@ #include "../core/shader.hpp" #include "../camera.hpp" #include "glm/glm.hpp" +#include "mesh.hpp" #include +#include +#include namespace graphics { - class Mesh; - class Texture2D; + class Texture2D; - class MeshRenderer - { - public: - MeshRenderer() {} + class MeshRenderer { + public: + MeshRenderer() = default; - void draw(const Mesh& _mesh, const Texture2D& _texture, const glm::mat4& _transform) {} + void draw(const Mesh &_mesh, const Texture2D &_texture, const Texture2D &phongData, const glm::mat4 &_transform); - void present(const Camera& _camera) {} - void clear() {} - private: - }; + void present(const unsigned int &programID); + + void clear(); + + private: + unsigned int currentProgramID = -1; + GLint glsl_object_to_world_matrix = 0; + + struct MeshRenderData{ + Mesh meshData; + const Texture2D &textureData; + const Texture2D &phongData; + const glm::mat4 &transform; + }; + + std::vector meshBuffer = {}; + + }; } \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index ff7a4ba8..472a3bd6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,9 +5,7 @@ #include #include #include -#include #include -#include #include #include @@ -25,32 +23,6 @@ using namespace std::chrono_literals; -graphics::GeometryBuffer *createStripBuffer(graphics::VertexAttribute *vertexAttribute, int numAttributes) { - auto *buffer = new graphics::GeometryBuffer( - graphics::GLPrimitiveType::TRIANGLE_STRIPE, - vertexAttribute, - numAttributes, - 0 - ); - return buffer; -} - -graphics::GeometryBuffer *createTriangleBuffer(graphics::VertexAttribute *vertexAttribute, int numAttributes) { - auto *buffer = new graphics::GeometryBuffer( - graphics::GLPrimitiveType::TRIANGLES, - vertexAttribute, - numAttributes, - 0 - ); - return buffer; -} - -struct VertexData { - glm::vec3 positionData; - glm::vec2 uvData; - glm::vec3 normalData; -}; - int main(int argc, char *argv[]) { #ifndef NDEBUG #if defined(_MSC_VER) @@ -91,52 +63,12 @@ int main(int argc, char *argv[]) { static graphics::Sampler sampler(graphics::Sampler::Filter::LINEAR, graphics::Sampler::Filter::LINEAR, graphics::Sampler::Filter::LINEAR, graphics::Sampler::Border::MIRROR); auto planetTexture = graphics::Texture2DManager::get("textures/planet1.png", sampler); + auto crateTexture = graphics::Texture2DManager::get("textures/cratetex.png", sampler); auto planetPhong = graphics::Texture2DManager::get("textures/Planet1_phong.png", sampler); - planetTexture->bind(0); - planetPhong->bind(1); - utils::MeshData::Handle data = utils::MeshLoader::get("models/sphere.obj"); - utils::MeshStripData::Handle meshStripData = utils::MeshStripData::createFromMeshData(data); - - std::array vertexAttributes = { - graphics::VertexAttribute{ - graphics::PrimitiveFormat::FLOAT, - 3, - false, - false - }, - graphics::VertexAttribute{ - graphics::PrimitiveFormat::FLOAT, - 2, - false, - false - }, - graphics::VertexAttribute{ - graphics::PrimitiveFormat::FLOAT, - 3, - false, - false - } - }; - - VertexData triangles_tri[] = { - {glm::vec3(-1.0f, -1.0f, 0.0f), glm::vec2(-1.0f, -1.0f), glm::vec3(0.0f, 0.0f, -1.0f)}, - {glm::vec3(1.0f, -1.0f, 0.0f), glm::vec2(1.0f, -1.0f), glm::vec3(0.0f, 0.0f, -1.0f)}, - {glm::vec3(0.0f, 1.0f, 0.0f), glm::vec2(0.0f, 1.0f), glm::vec3(0.0f, 0.0f, -1.0f)}, - }; - VertexData triangles_rect[] = { - {glm::vec3(-0.75f, -0.75f, 0.0f), glm::vec2(0.0f, -0.75f), glm::vec3(0.0f, 0.0f, -1.0f)}, - {glm::vec3(0.75f, -0.75f, 0.0f), glm::vec2(0.75f, -0.75f), glm::vec3(0.0f, 0.0f, -1.0f)}, - {glm::vec3(-0.75f, 0.75f, 0.0f), glm::vec2(-0.75f, 0.75f), glm::vec3(0.0f, 0.0f, -1.0f)}, - {glm::vec3(0.75f, 0.75f, 0.0f), glm::vec2(0.75f, 0.75f), glm::vec3(0.0f, 0.0f, -1.0f)}, - }; - - std::vector buffers = {}; - - { - graphics::GeometryBuffer *buffer = createStripBuffer(vertexAttributes.data(), vertexAttributes.size()); - buffer->setData(&triangles_rect, sizeof(triangles_rect)); - buffers.push_back(buffer); - } + utils::MeshData::Handle meshData = utils::MeshLoader::get("models/sphere.obj"); + + auto mesh = graphics::Mesh(meshData); + auto meshRenderer = graphics::MeshRenderer(); graphics::Shader::Handle fragmentShader = graphics::ShaderManager::get("shader/demo.frag", graphics::ShaderType::FRAGMENT); graphics::Shader::Handle vertexShader = graphics::ShaderManager::get("shader/demo.vert", graphics::ShaderType::VERTEX); @@ -157,7 +89,6 @@ int main(int argc, char *argv[]) { float cameraYaw = 0.0f; float cameraRoll = 0.0f; GLint worldToCameraMatrixID = glGetUniformLocation(program.getID(), "world_to_camera_matrix"); - GLint cameraPositionShaderID = glGetUniformLocation(program.getID(), "camera_position"); GLint glsl_ambient_light = glGetUniformLocation(program.getID(), "ambient_light"); @@ -173,56 +104,17 @@ int main(int argc, char *argv[]) { graphics::glCall(glClear, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); if (input::InputManager::isKeyPressed(input::Key::T)) { - buffers.clear(); - graphics::GeometryBuffer *buffer = createStripBuffer(vertexAttributes.data(), vertexAttributes.size()); - buffer->setData(&triangles_tri, sizeof(triangles_tri)); - buffers.push_back(buffer); + // TODO triangles } if (input::InputManager::isKeyPressed(input::Key::R)) { - buffers.clear(); - graphics::GeometryBuffer *buffer = createStripBuffer(vertexAttributes.data(), vertexAttributes.size()); - buffer->setData(&triangles_rect, sizeof(triangles_rect)); - buffers.push_back(buffer); + // TODO rectangle + meshRenderer.clear(); + meshRenderer.draw(mesh, *crateTexture, *planetPhong, glm::translate(glm::identity(), glm::vec3(1.5f, 0.0f, 0.0f))); + meshRenderer.draw(mesh, *planetTexture, *planetPhong, glm::translate(glm::identity(), glm::vec3(-1.5f, 0.0f, 0.0f))); } if (input::InputManager::isKeyPressed(input::Key::S)) { - buffers.clear(); - - if (input::InputManager::isKeyPressed(input::Key::Num1)) { - graphics::GeometryBuffer *triBuffer = createTriangleBuffer(vertexAttributes.data(), vertexAttributes.size()); - auto *triBufferData = new VertexData[meshStripData->floatingTriangles.size() * 3]; - int dataIndex = 0; - for (const auto &floatingTriangle: meshStripData->floatingTriangles) { - for (int i = 0; i < 3; i++) { - triBufferData[dataIndex + i] = { - data->positions[floatingTriangle.indices[i].positionIdx], - data->textureCoordinates[floatingTriangle.indices[i].textureCoordinateIdx.value_or(0)], - data->normals[floatingTriangle.indices[i].normalIdx.value_or(0)] - }; - } - dataIndex += 3; - } - triBuffer->setData(triBufferData, sizeof(VertexData) * meshStripData->floatingTriangles.size() * 3); - buffers.push_back(triBuffer); - } - - if (input::InputManager::isKeyPressed(input::Key::Num3)) { - for (const auto &strip: meshStripData->triangleStrips) { - auto *stripBuffer = createStripBuffer(vertexAttributes.data(), vertexAttributes.size()); - unsigned int vertexCount = strip.vertexIndices.size(); - auto *stripBufferData = new VertexData[vertexCount]; - int dataIndex = 0; - for (const auto &vertexIndex: strip.vertexIndices) { - stripBufferData[dataIndex] = { - data->positions[vertexIndex.positionIdx], - data->textureCoordinates[vertexIndex.textureCoordinateIdx.value_or(0)], - data->normals[vertexIndex.normalIdx.value_or(0)] - }; - dataIndex++; - } - stripBuffer->setData(stripBufferData, sizeof(VertexData) * vertexCount); - buffers.push_back(stripBuffer); - } - } + meshRenderer.clear(); + meshRenderer.draw(mesh, *planetTexture, *planetPhong, glm::identity()); } float rightInput = 0.0f; @@ -300,9 +192,7 @@ int main(int argc, char *argv[]) { glUniform3fv(glsl_ambient_light, 1, glm::value_ptr(ambientLightData)); glUniformMatrix4fv(worldToCameraMatrixID, 1, GL_FALSE, glm::value_ptr(camera.getWorldToCamera())); glUniform3fv(cameraPositionShaderID, 1, glm::value_ptr(camera.getPosition())); - for (const auto &buffer: buffers) { - buffer->draw(); - } + meshRenderer.present(program.getID()); glfwPollEvents(); glfwSwapBuffers(window); From 4b08f87ab4043a0b48494fff18ccbfc8c3676f3d Mon Sep 17 00:00:00 2001 From: BlazingTwist Date: Sat, 27 Nov 2021 16:05:32 +0100 Subject: [PATCH 12/12] change to WASD controls --- src/main.cpp | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 472a3bd6..52f35a20 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -43,20 +43,20 @@ int main(int argc, char *argv[]) { glm::normalize(glm::vec3(-1.0f, -1.0f, 0.5f)), glm::vec3(1.0f, 1.0f, 1.0f), 2.0f);*/ - /*graphics::LightData lightData = graphics::LightData::point( - glm::vec3(3.0f, 0.0f, 0.0f), + graphics::LightData lightData = graphics::LightData::point( + glm::vec3(0.0f, 0.0f, 0.0f), 10.0f, glm::vec3(1.0f, 1.0f, 1.0f), 5.0f - );*/ - graphics::LightData lightData = graphics::LightData::spot( + ); + /*graphics::LightData lightData = graphics::LightData::spot( glm::vec3(3.0f, 0.0f, 0.0f), glm::vec3(-1.0f, 0.0f, 0.0f), 10.0f, 10.0f, glm::vec3(1.0f, 1.0f, 1.0f), 5.0f - ); + );*/ graphics::Camera camera(90.0f, 0.1f, 300.0f); camera.setPosition(glm::vec3(0.0f, 0.0f, -3.0f)); @@ -103,16 +103,12 @@ int main(int argc, char *argv[]) { currentCursorPos = input::InputManager::getCursorPos(); graphics::glCall(glClear, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - if (input::InputManager::isKeyPressed(input::Key::T)) { - // TODO triangles - } - if (input::InputManager::isKeyPressed(input::Key::R)) { - // TODO rectangle + if (input::InputManager::isKeyPressed(input::Key::Num1)) { meshRenderer.clear(); meshRenderer.draw(mesh, *crateTexture, *planetPhong, glm::translate(glm::identity(), glm::vec3(1.5f, 0.0f, 0.0f))); meshRenderer.draw(mesh, *planetTexture, *planetPhong, glm::translate(glm::identity(), glm::vec3(-1.5f, 0.0f, 0.0f))); } - if (input::InputManager::isKeyPressed(input::Key::S)) { + if (input::InputManager::isKeyPressed(input::Key::Num2)) { meshRenderer.clear(); meshRenderer.draw(mesh, *planetTexture, *planetPhong, glm::identity()); } @@ -120,22 +116,22 @@ int main(int argc, char *argv[]) { float rightInput = 0.0f; float forwardInput = 0.0f; float upInput = 0.0f; - if (input::InputManager::isKeyPressed(input::Key::KP_8)) { + if (input::InputManager::isKeyPressed(input::Key::W)) { forwardInput += cameraStep; } - if (input::InputManager::isKeyPressed(input::Key::KP_2)) { + if (input::InputManager::isKeyPressed(input::Key::S)) { forwardInput -= cameraStep; } - if (input::InputManager::isKeyPressed(input::Key::KP_6)) { + if (input::InputManager::isKeyPressed(input::Key::D)) { rightInput += cameraStep; } - if (input::InputManager::isKeyPressed(input::Key::KP_4)) { + if (input::InputManager::isKeyPressed(input::Key::A)) { rightInput -= cameraStep; } - if (input::InputManager::isKeyPressed(input::Key::KP_9)) { + if (input::InputManager::isKeyPressed(input::Key::E)) { upInput += cameraStep; } - if (input::InputManager::isKeyPressed(input::Key::KP_3)) { + if (input::InputManager::isKeyPressed(input::Key::Q)) { upInput -= cameraStep; } camera.moveRelative(rightInput, upInput, forwardInput);