From 9ce4b41e39b49749ff725be4f4e50d8a47f1a730 Mon Sep 17 00:00:00 2001 From: Anemunt <69436164+darkresident55@users.noreply.github.com> Date: Sun, 28 Dec 2025 16:01:45 -0500 Subject: [PATCH] fixed up a few lighting issues + made modularity boot quicker without taking past 100 MB of ram. --- src/EditorWindows/ViewportWindows.cpp | 2 +- src/Engine.cpp | 12 +-- src/Rendering.cpp | 133 +++++++++++++++++++++++++- src/Rendering.h | 4 +- src/Shaders/Shader_Manager/Shader.cpp | 22 +++++ src/main.cpp | 48 ++++++++++ 6 files changed, 207 insertions(+), 14 deletions(-) diff --git a/src/EditorWindows/ViewportWindows.cpp b/src/EditorWindows/ViewportWindows.cpp index 5f0c219..9527658 100644 --- a/src/EditorWindows/ViewportWindows.cpp +++ b/src/EditorWindows/ViewportWindows.cpp @@ -614,7 +614,7 @@ void Engine::renderViewport() { glm::mat4 view = camera.getViewMatrix(); renderer.beginRender(view, proj, camera.position); - renderer.renderScene(camera, sceneObjects, selectedObjectId); + renderer.renderScene(camera, sceneObjects, selectedObjectId, FOV, NEAR_PLANE, FAR_PLANE, collisionWireframe); unsigned int tex = renderer.getViewportTexture(); ImGui::Image((void*)(intptr_t)tex, imageSize, ImVec2(0, 1), ImVec2(1, 0)); diff --git a/src/Engine.cpp b/src/Engine.cpp index ad90069..088517a 100644 --- a/src/Engine.cpp +++ b/src/Engine.cpp @@ -379,19 +379,9 @@ void Engine::run() { if (aspect <= 0.0f) aspect = 1.0f; glm::mat4 proj = glm::perspective(glm::radians(FOV), aspect, NEAR_PLANE, FAR_PLANE); -#ifdef GL_POLYGON_MODE - GLint prevPoly[2] = { GL_FILL, GL_FILL }; - glGetIntegerv(GL_POLYGON_MODE, prevPoly); - glPolygonMode(GL_FRONT_AND_BACK, collisionWireframe ? GL_LINE : GL_FILL); -#endif - renderer.beginRender(view, proj, camera.position); - renderer.renderScene(camera, sceneObjects, selectedObjectId); + renderer.renderScene(camera, sceneObjects, selectedObjectId, FOV, NEAR_PLANE, FAR_PLANE, collisionWireframe); renderer.endRender(); - -#ifdef GL_POLYGON_MODE - glPolygonMode(GL_FRONT_AND_BACK, prevPoly[0]); -#endif } if (firstFrame) { diff --git a/src/Rendering.cpp b/src/Rendering.cpp index aa3054f..7becedb 100644 --- a/src/Rendering.cpp +++ b/src/Rendering.cpp @@ -537,6 +537,7 @@ Renderer::~Renderer() { if (rbo) glDeleteRenderbuffers(1, &rbo); if (quadVBO) glDeleteBuffers(1, &quadVBO); if (quadVAO) glDeleteVertexArrays(1, &quadVAO); + if (debugWhiteTexture) glDeleteTextures(1, &debugWhiteTexture); } Texture* Renderer::getTexture(const std::string& path) { @@ -619,6 +620,17 @@ void Renderer::initialize() { texture1 = new Texture("Resources/Textures/container.jpg"); texture2 = new Texture("Resources/Textures/awesomeface.png"); + if (debugWhiteTexture == 0) { + unsigned char white[4] = { 255, 255, 255, 255 }; + glGenTextures(1, &debugWhiteTexture); + glBindTexture(GL_TEXTURE_2D, debugWhiteTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, white); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glBindTexture(GL_TEXTURE_2D, 0); + } cubeMesh = new Mesh(vertices, sizeof(vertices)); @@ -1449,9 +1461,15 @@ unsigned int Renderer::applyPostProcessing(const std::vector& scene return target.texture; } -void Renderer::renderScene(const Camera& camera, const std::vector& sceneObjects, int /*selectedId*/, float fovDeg, float nearPlane, float farPlane) { +void Renderer::renderScene(const Camera& camera, const std::vector& sceneObjects, int /*selectedId*/, float fovDeg, float nearPlane, float farPlane, bool drawColliders) { updateMirrorTargets(camera, sceneObjects, currentWidth, currentHeight, fovDeg, nearPlane, farPlane); renderSceneInternal(camera, sceneObjects, currentWidth, currentHeight, true, fovDeg, nearPlane, farPlane, true); + if (drawColliders) { + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); + glViewport(0, 0, currentWidth, currentHeight); + renderCollisionOverlay(camera, sceneObjects, currentWidth, currentHeight, fovDeg, nearPlane, farPlane); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + } unsigned int result = applyPostProcessing(sceneObjects, viewportTexture, currentWidth, currentHeight, true); displayTexture = result ? result : viewportTexture; } @@ -1474,6 +1492,119 @@ unsigned int Renderer::renderScenePreview(const Camera& camera, const std::vecto return processed ? processed : previewTarget.texture; } +void Renderer::renderCollisionOverlay(const Camera& camera, const std::vector& sceneObjects, int width, int height, float fovDeg, float nearPlane, float farPlane) { + if (!defaultShader || width <= 0 || height <= 0) return; + + GLint prevPoly[2] = { GL_FILL, GL_FILL }; + glGetIntegerv(GL_POLYGON_MODE, prevPoly); + GLboolean depthTest = glIsEnabled(GL_DEPTH_TEST); + GLboolean cullFace = glIsEnabled(GL_CULL_FACE); + GLboolean polyOffsetLine = glIsEnabled(GL_POLYGON_OFFSET_LINE); + + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + glDisable(GL_CULL_FACE); + glEnable(GL_POLYGON_OFFSET_LINE); + glPolygonOffset(-1.0f, -1.0f); + + Shader* active = defaultShader; + active->use(); + active->setMat4("view", camera.getViewMatrix()); + active->setMat4("projection", glm::perspective(glm::radians(fovDeg), (float)width / (float)height, nearPlane, farPlane)); + active->setVec3("viewPos", camera.position); + active->setBool("unlit", true); + active->setBool("hasOverlay", false); + active->setBool("hasNormalMap", false); + active->setInt("lightCount", 0); + active->setFloat("mixAmount", 0.0f); + active->setVec3("materialColor", glm::vec3(0.2f, 1.0f, 0.2f)); + active->setFloat("ambientStrength", 1.0f); + active->setFloat("specularStrength", 0.0f); + active->setFloat("shininess", 1.0f); + active->setInt("texture1", 0); + active->setInt("overlayTex", 1); + active->setInt("normalMap", 2); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, debugWhiteTexture ? debugWhiteTexture : (texture1 ? texture1->GetID() : 0)); + + for (const auto& obj : sceneObjects) { + if (!obj.enabled) continue; + if (!(obj.hasCollider && obj.collider.enabled) && !(obj.hasRigidbody && obj.rigidbody.enabled)) continue; + + Mesh* meshToDraw = nullptr; + glm::vec3 scale = obj.scale; + glm::vec3 position = obj.position; + glm::vec3 rotation = obj.rotation; + + if (obj.hasCollider && obj.collider.enabled) { + switch (obj.collider.type) { + case ColliderType::Box: + meshToDraw = cubeMesh; + scale = obj.collider.boxSize; + break; + case ColliderType::Capsule: + meshToDraw = capsuleMesh; + scale = obj.collider.boxSize; + break; + case ColliderType::Mesh: + case ColliderType::ConvexMesh: + if (obj.type == ObjectType::OBJMesh && obj.meshId >= 0) { + meshToDraw = g_objLoader.getMesh(obj.meshId); + } else if (obj.type == ObjectType::Model && obj.meshId >= 0) { + meshToDraw = getModelLoader().getMesh(obj.meshId); + } else { + meshToDraw = nullptr; + } + scale = obj.scale; + break; + } + } else { + switch (obj.type) { + case ObjectType::Cube: + meshToDraw = cubeMesh; + break; + case ObjectType::Sphere: + meshToDraw = sphereMesh; + break; + case ObjectType::Capsule: + meshToDraw = capsuleMesh; + break; + case ObjectType::Plane: + meshToDraw = planeMesh; + break; + case ObjectType::Torus: + meshToDraw = sphereMesh; + break; + case ObjectType::OBJMesh: + if (obj.meshId >= 0) meshToDraw = g_objLoader.getMesh(obj.meshId); + break; + case ObjectType::Model: + if (obj.meshId >= 0) meshToDraw = getModelLoader().getMesh(obj.meshId); + break; + default: + break; + } + } + + if (!meshToDraw) continue; + + glm::mat4 model = glm::mat4(1.0f); + model = glm::translate(model, position); + model = glm::rotate(model, glm::radians(rotation.x), glm::vec3(1.0f, 0.0f, 0.0f)); + model = glm::rotate(model, glm::radians(rotation.y), glm::vec3(0.0f, 1.0f, 0.0f)); + model = glm::rotate(model, glm::radians(rotation.z), glm::vec3(0.0f, 0.0f, 1.0f)); + model = glm::scale(model, scale); + active->setMat4("model", model); + + meshToDraw->draw(); + } + + if (!polyOffsetLine) glDisable(GL_POLYGON_OFFSET_LINE); + if (cullFace) glEnable(GL_CULL_FACE); + if (depthTest) glEnable(GL_DEPTH_TEST); + glPolygonMode(GL_FRONT_AND_BACK, prevPoly[0]); +} + void Renderer::endRender() { glBindFramebuffer(GL_FRAMEBUFFER, 0); } diff --git a/src/Rendering.h b/src/Rendering.h index e9d711b..cc67855 100644 --- a/src/Rendering.h +++ b/src/Rendering.h @@ -84,6 +84,7 @@ private: Shader* blurShader = nullptr; Texture* texture1 = nullptr; Texture* texture2 = nullptr; + unsigned int debugWhiteTexture = 0; std::unordered_map> textureCache; std::unordered_map> previewTextureCacheLinear; std::unordered_map> previewTextureCacheNearest; @@ -145,8 +146,9 @@ public: void beginRender(const glm::mat4& view, const glm::mat4& proj, const glm::vec3& cameraPos); void renderSkybox(const glm::mat4& view, const glm::mat4& proj); void renderObject(const SceneObject& obj); - void renderScene(const Camera& camera, const std::vector& sceneObjects, int selectedId = -1, float fovDeg = FOV, float nearPlane = NEAR_PLANE, float farPlane = FAR_PLANE); + void renderScene(const Camera& camera, const std::vector& sceneObjects, int selectedId = -1, float fovDeg = FOV, float nearPlane = NEAR_PLANE, float farPlane = FAR_PLANE, bool drawColliders = false); unsigned int renderScenePreview(const Camera& camera, const std::vector& sceneObjects, int width, int height, float fovDeg, float nearPlane, float farPlane, bool applyPostFX = false); + void renderCollisionOverlay(const Camera& camera, const std::vector& sceneObjects, int width, int height, float fovDeg, float nearPlane, float farPlane); void endRender(); Skybox* getSkybox() { return skybox; } diff --git a/src/Shaders/Shader_Manager/Shader.cpp b/src/Shaders/Shader_Manager/Shader.cpp index 9f184ce..6160e13 100644 --- a/src/Shaders/Shader_Manager/Shader.cpp +++ b/src/Shaders/Shader_Manager/Shader.cpp @@ -46,12 +46,34 @@ void Shader::compileShaders(const char* vertexSource, const char* fragmentSource glShaderSource(fragment, 1, &fragmentSource, NULL); glCompileShader(fragment); checkCompileErrors(fragment, "FRAGMENT"); + + int success = 0; + glGetShaderiv(vertex, GL_COMPILE_STATUS, &success); + if (!success) { + glDeleteShader(vertex); + glDeleteShader(fragment); + ID = 0; + return; + } + glGetShaderiv(fragment, GL_COMPILE_STATUS, &success); + if (!success) { + glDeleteShader(vertex); + glDeleteShader(fragment); + ID = 0; + return; + } ID = glCreateProgram(); glAttachShader(ID, vertex); glAttachShader(ID, fragment); glLinkProgram(ID); checkCompileErrors(ID, "PROGRAM"); + + glGetProgramiv(ID, GL_LINK_STATUS, &success); + if (!success) { + glDeleteProgram(ID); + ID = 0; + } glDeleteShader(vertex); glDeleteShader(fragment); diff --git a/src/main.cpp b/src/main.cpp index c858783..dd066b2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,55 @@ #include "Engine.h" +#include #include +#include +#include + +#if defined(_WIN32) +#include +#elif defined(__APPLE__) +#include +#else +#include +#endif + +static std::filesystem::path getExecutableDir() { +#if defined(_WIN32) + char pathBuf[MAX_PATH] = {}; + DWORD len = GetModuleFileNameA(nullptr, pathBuf, MAX_PATH); + if (len == 0 || len == MAX_PATH) { + return {}; + } + return std::filesystem::path(pathBuf).parent_path(); +#elif defined(__APPLE__) + uint32_t size = 0; + if (_NSGetExecutablePath(nullptr, &size) != -1 || size == 0) { + return {}; + } + std::string buf(size, '\0'); + if (_NSGetExecutablePath(buf.data(), &size) != 0) { + return {}; + } + return std::filesystem::path(buf).lexically_normal().parent_path(); +#else + std::vector buf(4096, '\0'); + ssize_t len = readlink("/proc/self/exe", buf.data(), buf.size() - 1); + if (len <= 0) { + return {}; + } + buf[static_cast(len)] = '\0'; + return std::filesystem::path(buf.data()).parent_path(); +#endif +} int main() { + if (auto exeDir = getExecutableDir(); !exeDir.empty()) { + std::error_code ec; + std::filesystem::current_path(exeDir, ec); + if (ec) { + std::cerr << "[WARN] Failed to set working dir to executable: " + << ec.message() << std::endl; + } + } std::cerr << "[DEBUG] Starting engine initialization..." << std::endl; Engine engine;