fixed up a few lighting issues + made modularity boot quicker without taking past 100 MB of ram.

This commit is contained in:
Anemunt
2025-12-28 16:01:45 -05:00
parent 5e1d352289
commit 9ce4b41e39
6 changed files with 207 additions and 14 deletions

View File

@@ -614,7 +614,7 @@ void Engine::renderViewport() {
glm::mat4 view = camera.getViewMatrix(); glm::mat4 view = camera.getViewMatrix();
renderer.beginRender(view, proj, camera.position); 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(); unsigned int tex = renderer.getViewportTexture();
ImGui::Image((void*)(intptr_t)tex, imageSize, ImVec2(0, 1), ImVec2(1, 0)); ImGui::Image((void*)(intptr_t)tex, imageSize, ImVec2(0, 1), ImVec2(1, 0));

View File

@@ -379,19 +379,9 @@ void Engine::run() {
if (aspect <= 0.0f) aspect = 1.0f; if (aspect <= 0.0f) aspect = 1.0f;
glm::mat4 proj = glm::perspective(glm::radians(FOV), aspect, NEAR_PLANE, FAR_PLANE); 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.beginRender(view, proj, camera.position);
renderer.renderScene(camera, sceneObjects, selectedObjectId); renderer.renderScene(camera, sceneObjects, selectedObjectId, FOV, NEAR_PLANE, FAR_PLANE, collisionWireframe);
renderer.endRender(); renderer.endRender();
#ifdef GL_POLYGON_MODE
glPolygonMode(GL_FRONT_AND_BACK, prevPoly[0]);
#endif
} }
if (firstFrame) { if (firstFrame) {

View File

@@ -537,6 +537,7 @@ Renderer::~Renderer() {
if (rbo) glDeleteRenderbuffers(1, &rbo); if (rbo) glDeleteRenderbuffers(1, &rbo);
if (quadVBO) glDeleteBuffers(1, &quadVBO); if (quadVBO) glDeleteBuffers(1, &quadVBO);
if (quadVAO) glDeleteVertexArrays(1, &quadVAO); if (quadVAO) glDeleteVertexArrays(1, &quadVAO);
if (debugWhiteTexture) glDeleteTextures(1, &debugWhiteTexture);
} }
Texture* Renderer::getTexture(const std::string& path) { Texture* Renderer::getTexture(const std::string& path) {
@@ -619,6 +620,17 @@ void Renderer::initialize() {
texture1 = new Texture("Resources/Textures/container.jpg"); texture1 = new Texture("Resources/Textures/container.jpg");
texture2 = new Texture("Resources/Textures/awesomeface.png"); 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)); cubeMesh = new Mesh(vertices, sizeof(vertices));
@@ -1449,9 +1461,15 @@ unsigned int Renderer::applyPostProcessing(const std::vector<SceneObject>& scene
return target.texture; return target.texture;
} }
void Renderer::renderScene(const Camera& camera, const std::vector<SceneObject>& sceneObjects, int /*selectedId*/, float fovDeg, float nearPlane, float farPlane) { void Renderer::renderScene(const Camera& camera, const std::vector<SceneObject>& sceneObjects, int /*selectedId*/, float fovDeg, float nearPlane, float farPlane, bool drawColliders) {
updateMirrorTargets(camera, sceneObjects, currentWidth, currentHeight, fovDeg, nearPlane, farPlane); updateMirrorTargets(camera, sceneObjects, currentWidth, currentHeight, fovDeg, nearPlane, farPlane);
renderSceneInternal(camera, sceneObjects, currentWidth, currentHeight, true, fovDeg, nearPlane, farPlane, true); 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); unsigned int result = applyPostProcessing(sceneObjects, viewportTexture, currentWidth, currentHeight, true);
displayTexture = result ? result : viewportTexture; displayTexture = result ? result : viewportTexture;
} }
@@ -1474,6 +1492,119 @@ unsigned int Renderer::renderScenePreview(const Camera& camera, const std::vecto
return processed ? processed : previewTarget.texture; return processed ? processed : previewTarget.texture;
} }
void Renderer::renderCollisionOverlay(const Camera& camera, const std::vector<SceneObject>& 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() { void Renderer::endRender() {
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
} }

View File

@@ -84,6 +84,7 @@ private:
Shader* blurShader = nullptr; Shader* blurShader = nullptr;
Texture* texture1 = nullptr; Texture* texture1 = nullptr;
Texture* texture2 = nullptr; Texture* texture2 = nullptr;
unsigned int debugWhiteTexture = 0;
std::unordered_map<std::string, std::unique_ptr<Texture>> textureCache; std::unordered_map<std::string, std::unique_ptr<Texture>> textureCache;
std::unordered_map<std::string, std::unique_ptr<Texture>> previewTextureCacheLinear; std::unordered_map<std::string, std::unique_ptr<Texture>> previewTextureCacheLinear;
std::unordered_map<std::string, std::unique_ptr<Texture>> previewTextureCacheNearest; std::unordered_map<std::string, std::unique_ptr<Texture>> previewTextureCacheNearest;
@@ -145,8 +146,9 @@ public:
void beginRender(const glm::mat4& view, const glm::mat4& proj, const glm::vec3& cameraPos); 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 renderSkybox(const glm::mat4& view, const glm::mat4& proj);
void renderObject(const SceneObject& obj); void renderObject(const SceneObject& obj);
void renderScene(const Camera& camera, const std::vector<SceneObject>& sceneObjects, int selectedId = -1, float fovDeg = FOV, float nearPlane = NEAR_PLANE, float farPlane = FAR_PLANE); void renderScene(const Camera& camera, const std::vector<SceneObject>& 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<SceneObject>& sceneObjects, int width, int height, float fovDeg, float nearPlane, float farPlane, bool applyPostFX = false); unsigned int renderScenePreview(const Camera& camera, const std::vector<SceneObject>& sceneObjects, int width, int height, float fovDeg, float nearPlane, float farPlane, bool applyPostFX = false);
void renderCollisionOverlay(const Camera& camera, const std::vector<SceneObject>& sceneObjects, int width, int height, float fovDeg, float nearPlane, float farPlane);
void endRender(); void endRender();
Skybox* getSkybox() { return skybox; } Skybox* getSkybox() { return skybox; }

View File

@@ -47,12 +47,34 @@ void Shader::compileShaders(const char* vertexSource, const char* fragmentSource
glCompileShader(fragment); glCompileShader(fragment);
checkCompileErrors(fragment, "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(); ID = glCreateProgram();
glAttachShader(ID, vertex); glAttachShader(ID, vertex);
glAttachShader(ID, fragment); glAttachShader(ID, fragment);
glLinkProgram(ID); glLinkProgram(ID);
checkCompileErrors(ID, "PROGRAM"); checkCompileErrors(ID, "PROGRAM");
glGetProgramiv(ID, GL_LINK_STATUS, &success);
if (!success) {
glDeleteProgram(ID);
ID = 0;
}
glDeleteShader(vertex); glDeleteShader(vertex);
glDeleteShader(fragment); glDeleteShader(fragment);
} }

View File

@@ -1,7 +1,55 @@
#include "Engine.h" #include "Engine.h"
#include <filesystem>
#include <iostream> #include <iostream>
#include <string>
#include <vector>
#if defined(_WIN32)
#include <windows.h>
#elif defined(__APPLE__)
#include <mach-o/dyld.h>
#else
#include <unistd.h>
#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<char> buf(4096, '\0');
ssize_t len = readlink("/proc/self/exe", buf.data(), buf.size() - 1);
if (len <= 0) {
return {};
}
buf[static_cast<size_t>(len)] = '\0';
return std::filesystem::path(buf.data()).parent_path();
#endif
}
int main() { 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; std::cerr << "[DEBUG] Starting engine initialization..." << std::endl;
Engine engine; Engine engine;