Added Mirror, it kinda works..?
This commit is contained in:
@@ -11,6 +11,7 @@ uniform sampler2D normalMap;
|
|||||||
uniform float mixAmount = 0.2;
|
uniform float mixAmount = 0.2;
|
||||||
uniform bool hasOverlay = false;
|
uniform bool hasOverlay = false;
|
||||||
uniform bool hasNormalMap = false;
|
uniform bool hasNormalMap = false;
|
||||||
|
uniform bool unlit = false;
|
||||||
|
|
||||||
uniform vec3 viewPos;
|
uniform vec3 viewPos;
|
||||||
uniform vec3 materialColor = vec3(1.0);
|
uniform vec3 materialColor = vec3(1.0);
|
||||||
@@ -52,6 +53,11 @@ void main()
|
|||||||
}
|
}
|
||||||
vec3 baseColor = texColor * materialColor;
|
vec3 baseColor = texColor * materialColor;
|
||||||
|
|
||||||
|
if (unlit) {
|
||||||
|
FragColor = vec4(baseColor, tex1.a);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Normal map (tangent-space)
|
// Normal map (tangent-space)
|
||||||
if (hasNormalMap) {
|
if (hasNormalMap) {
|
||||||
vec3 mapN = texture(normalMap, TexCoord).xyz * 2.0 - 1.0;
|
vec3 mapN = texture(normalMap, TexCoord).xyz * 2.0 - 1.0;
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ void Engine::renderHierarchyPanel() {
|
|||||||
if (ImGui::MenuItem("Cube")) addObject(ObjectType::Cube, "Cube");
|
if (ImGui::MenuItem("Cube")) addObject(ObjectType::Cube, "Cube");
|
||||||
if (ImGui::MenuItem("Sphere")) addObject(ObjectType::Sphere, "Sphere");
|
if (ImGui::MenuItem("Sphere")) addObject(ObjectType::Sphere, "Sphere");
|
||||||
if (ImGui::MenuItem("Capsule")) addObject(ObjectType::Capsule, "Capsule");
|
if (ImGui::MenuItem("Capsule")) addObject(ObjectType::Capsule, "Capsule");
|
||||||
|
if (ImGui::MenuItem("Mirror")) addObject(ObjectType::Mirror, "Mirror");
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,6 +139,7 @@ void Engine::renderObjectNode(SceneObject& obj, const std::string& filter) {
|
|||||||
case ObjectType::SpotLight: icon = "(S)"; break;
|
case ObjectType::SpotLight: icon = "(S)"; break;
|
||||||
case ObjectType::AreaLight: icon = "(L)"; break;
|
case ObjectType::AreaLight: icon = "(L)"; break;
|
||||||
case ObjectType::PostFXNode: icon = "(FX)"; break;
|
case ObjectType::PostFXNode: icon = "(FX)"; break;
|
||||||
|
case ObjectType::Mirror: icon = "[R]"; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nodeOpen = ImGui::TreeNodeEx((void*)(intptr_t)obj.id, flags, "%s %s", icon, obj.name.c_str());
|
bool nodeOpen = ImGui::TreeNodeEx((void*)(intptr_t)obj.id, flags, "%s %s", icon, obj.name.c_str());
|
||||||
@@ -613,6 +615,7 @@ void Engine::renderInspectorPanel() {
|
|||||||
case ObjectType::SpotLight: typeLabel = "Spot Light"; break;
|
case ObjectType::SpotLight: typeLabel = "Spot Light"; break;
|
||||||
case ObjectType::AreaLight: typeLabel = "Area Light"; break;
|
case ObjectType::AreaLight: typeLabel = "Area Light"; break;
|
||||||
case ObjectType::PostFXNode: typeLabel = "Post FX Node"; break;
|
case ObjectType::PostFXNode: typeLabel = "Post FX Node"; break;
|
||||||
|
case ObjectType::Mirror: typeLabel = "Mirror"; break;
|
||||||
}
|
}
|
||||||
ImGui::TextColored(ImVec4(0.5f, 0.8f, 1.0f, 1.0f), "%s", typeLabel);
|
ImGui::TextColored(ImVec4(0.5f, 0.8f, 1.0f, 1.0f), "%s", typeLabel);
|
||||||
|
|
||||||
|
|||||||
@@ -1576,6 +1576,9 @@ void Engine::renderViewport() {
|
|||||||
case ObjectType::Capsule:
|
case ObjectType::Capsule:
|
||||||
hit = rayAabb(localOrigin, localDir, glm::vec3(-0.35f, -0.9f, -0.35f), glm::vec3(0.35f, 0.9f, 0.35f), hitT);
|
hit = rayAabb(localOrigin, localDir, glm::vec3(-0.35f, -0.9f, -0.35f), glm::vec3(0.35f, 0.9f, 0.35f), hitT);
|
||||||
break;
|
break;
|
||||||
|
case ObjectType::Mirror:
|
||||||
|
hit = rayAabb(localOrigin, localDir, glm::vec3(-0.5f, -0.5f, -0.02f), glm::vec3(0.5f, 0.5f, 0.02f), hitT);
|
||||||
|
break;
|
||||||
case ObjectType::OBJMesh: {
|
case ObjectType::OBJMesh: {
|
||||||
const auto* info = g_objLoader.getMeshInfo(obj.meshId);
|
const auto* info = g_objLoader.getMeshInfo(obj.meshId);
|
||||||
if (info && info->boundsMin.x < info->boundsMax.x) {
|
if (info && info->boundsMin.x < info->boundsMax.x) {
|
||||||
|
|||||||
@@ -1107,6 +1107,11 @@ void Engine::addObject(ObjectType type, const std::string& baseName) {
|
|||||||
} else if (type == ObjectType::Camera) {
|
} else if (type == ObjectType::Camera) {
|
||||||
sceneObjects.back().camera.type = SceneCameraType::Player;
|
sceneObjects.back().camera.type = SceneCameraType::Player;
|
||||||
sceneObjects.back().camera.fov = 60.0f;
|
sceneObjects.back().camera.fov = 60.0f;
|
||||||
|
} else if (type == ObjectType::Mirror) {
|
||||||
|
sceneObjects.back().useOverlay = true;
|
||||||
|
sceneObjects.back().material.textureMix = 1.0f;
|
||||||
|
sceneObjects.back().material.color = glm::vec3(1.0f);
|
||||||
|
sceneObjects.back().scale = glm::vec3(2.0f, 2.0f, 0.05f);
|
||||||
}
|
}
|
||||||
setPrimarySelection(id);
|
setPrimarySelection(id);
|
||||||
if (projectManager.currentProject.isLoaded) {
|
if (projectManager.currentProject.isLoaded) {
|
||||||
|
|||||||
@@ -258,7 +258,7 @@ bool SceneSerializer::saveScene(const fs::path& filePath,
|
|||||||
if (!file.is_open()) return false;
|
if (!file.is_open()) return false;
|
||||||
|
|
||||||
file << "# Scene File\n";
|
file << "# Scene File\n";
|
||||||
file << "version=8\n";
|
file << "version=9\n";
|
||||||
file << "nextId=" << nextId << "\n";
|
file << "nextId=" << nextId << "\n";
|
||||||
file << "objectCount=" << objects.size() << "\n";
|
file << "objectCount=" << objects.size() << "\n";
|
||||||
file << "\n";
|
file << "\n";
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "Camera.h"
|
#include "Camera.h"
|
||||||
#include "ModelLoader.h"
|
#include "ModelLoader.h"
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
#define TINYOBJLOADER_IMPLEMENTATION
|
#define TINYOBJLOADER_IMPLEMENTATION
|
||||||
#include "../include/ThirdParty/tiny_obj_loader.h"
|
#include "../include/ThirdParty/tiny_obj_loader.h"
|
||||||
@@ -60,6 +61,17 @@ float vertices[] = {
|
|||||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f
|
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f
|
||||||
};
|
};
|
||||||
|
|
||||||
|
float mirrorPlaneVertices[] = {
|
||||||
|
// positions // normals // texcoords
|
||||||
|
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
|
||||||
|
0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f,
|
||||||
|
0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
|
||||||
|
|
||||||
|
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
|
||||||
|
0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
|
||||||
|
-0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f
|
||||||
|
};
|
||||||
|
|
||||||
std::vector<float> generateSphere(int segments, int rings) {
|
std::vector<float> generateSphere(int segments, int rings) {
|
||||||
std::vector<float> vertices;
|
std::vector<float> vertices;
|
||||||
|
|
||||||
@@ -422,6 +434,7 @@ Renderer::~Renderer() {
|
|||||||
delete cubeMesh;
|
delete cubeMesh;
|
||||||
delete sphereMesh;
|
delete sphereMesh;
|
||||||
delete capsuleMesh;
|
delete capsuleMesh;
|
||||||
|
delete planeMesh;
|
||||||
delete skybox;
|
delete skybox;
|
||||||
delete postShader;
|
delete postShader;
|
||||||
delete brightShader;
|
delete brightShader;
|
||||||
@@ -441,6 +454,11 @@ Renderer::~Renderer() {
|
|||||||
if (bloomTargetB.fbo) glDeleteFramebuffers(1, &bloomTargetB.fbo);
|
if (bloomTargetB.fbo) glDeleteFramebuffers(1, &bloomTargetB.fbo);
|
||||||
if (bloomTargetB.texture) glDeleteTextures(1, &bloomTargetB.texture);
|
if (bloomTargetB.texture) glDeleteTextures(1, &bloomTargetB.texture);
|
||||||
if (bloomTargetB.rbo) glDeleteRenderbuffers(1, &bloomTargetB.rbo);
|
if (bloomTargetB.rbo) glDeleteRenderbuffers(1, &bloomTargetB.rbo);
|
||||||
|
for (auto& entry : mirrorTargets) {
|
||||||
|
releaseRenderTarget(entry.second);
|
||||||
|
}
|
||||||
|
mirrorTargets.clear();
|
||||||
|
mirrorSmooth.clear();
|
||||||
if (framebuffer) glDeleteFramebuffers(1, &framebuffer);
|
if (framebuffer) glDeleteFramebuffers(1, &framebuffer);
|
||||||
if (viewportTexture) glDeleteTextures(1, &viewportTexture);
|
if (viewportTexture) glDeleteTextures(1, &viewportTexture);
|
||||||
if (rbo) glDeleteRenderbuffers(1, &rbo);
|
if (rbo) glDeleteRenderbuffers(1, &rbo);
|
||||||
@@ -519,6 +537,7 @@ void Renderer::initialize() {
|
|||||||
|
|
||||||
auto capsuleVerts = generateCapsule();
|
auto capsuleVerts = generateCapsule();
|
||||||
capsuleMesh = new Mesh(capsuleVerts.data(), capsuleVerts.size() * sizeof(float));
|
capsuleMesh = new Mesh(capsuleVerts.data(), capsuleVerts.size() * sizeof(float));
|
||||||
|
planeMesh = new Mesh(mirrorPlaneVertices, sizeof(mirrorPlaneVertices));
|
||||||
|
|
||||||
skybox = new Skybox();
|
skybox = new Skybox();
|
||||||
|
|
||||||
@@ -668,6 +687,105 @@ void Renderer::ensureRenderTarget(RenderTarget& target, int w, int h) {
|
|||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Renderer::releaseRenderTarget(RenderTarget& target) {
|
||||||
|
if (target.texture) {
|
||||||
|
glDeleteTextures(1, &target.texture);
|
||||||
|
}
|
||||||
|
if (target.rbo) {
|
||||||
|
glDeleteRenderbuffers(1, &target.rbo);
|
||||||
|
}
|
||||||
|
if (target.fbo) {
|
||||||
|
glDeleteFramebuffers(1, &target.fbo);
|
||||||
|
}
|
||||||
|
target = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::updateMirrorTargets(const Camera& camera, const std::vector<SceneObject>& sceneObjects, int width, int height, float fovDeg, float nearPlane, float farPlane) {
|
||||||
|
if (sceneObjects.empty() || width <= 0 || height <= 0) return;
|
||||||
|
|
||||||
|
std::unordered_set<int> active;
|
||||||
|
GLint prevFBO = 0;
|
||||||
|
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prevFBO);
|
||||||
|
|
||||||
|
auto planeNormal = [](const SceneObject& obj) {
|
||||||
|
glm::quat q = glm::quat(glm::radians(obj.rotation));
|
||||||
|
glm::vec3 n = q * glm::vec3(0.0f, 0.0f, 1.0f);
|
||||||
|
if (!std::isfinite(n.x) || glm::length(n) < 1e-3f) {
|
||||||
|
n = glm::vec3(0.0f, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
return glm::normalize(n);
|
||||||
|
};
|
||||||
|
auto planeUp = [](const SceneObject& obj) {
|
||||||
|
glm::quat q = glm::quat(glm::radians(obj.rotation));
|
||||||
|
glm::vec3 u = q * glm::vec3(0.0f, 1.0f, 0.0f);
|
||||||
|
if (!std::isfinite(u.x) || glm::length(u) < 1e-3f) {
|
||||||
|
u = glm::vec3(0.0f, 1.0f, 0.0f);
|
||||||
|
}
|
||||||
|
return glm::normalize(u);
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const auto& obj : sceneObjects) {
|
||||||
|
if (!obj.enabled || obj.type != ObjectType::Mirror) continue;
|
||||||
|
active.insert(obj.id);
|
||||||
|
|
||||||
|
RenderTarget& target = mirrorTargets[obj.id];
|
||||||
|
ensureRenderTarget(target, width, height);
|
||||||
|
if (target.fbo == 0 || target.texture == 0) continue;
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, target.fbo);
|
||||||
|
glViewport(0, 0, target.width, target.height);
|
||||||
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
glm::vec3 n = planeNormal(obj);
|
||||||
|
glm::vec3 planePoint = obj.position;
|
||||||
|
glm::vec3 upVec = planeUp(obj);
|
||||||
|
glm::vec3 tangent = glm::normalize(glm::cross(upVec, n));
|
||||||
|
if (!std::isfinite(tangent.x) || glm::length(tangent) < 1e-3f) {
|
||||||
|
tangent = glm::vec3(1.0f, 0.0f, 0.0f);
|
||||||
|
}
|
||||||
|
glm::vec3 bitangent = glm::cross(n, tangent);
|
||||||
|
|
||||||
|
Camera mirrorCam = camera;
|
||||||
|
glm::vec3 relToPlane = camera.position - planePoint;
|
||||||
|
float alongT = glm::dot(relToPlane, tangent);
|
||||||
|
float alongB = glm::dot(relToPlane, bitangent);
|
||||||
|
MirrorSmoothing& sm = mirrorSmooth[obj.id];
|
||||||
|
if (!sm.initialized) {
|
||||||
|
sm.planar = glm::vec2(alongT, alongB);
|
||||||
|
sm.initialized = true;
|
||||||
|
} else {
|
||||||
|
float lerp = 0.2f; // slow the planar tracking slightly
|
||||||
|
sm.planar = glm::mix(sm.planar, glm::vec2(alongT, alongB), lerp);
|
||||||
|
}
|
||||||
|
|
||||||
|
float fixedDepth = 0.05f; // keep a small offset off the plane; ignore viewer local Z movement
|
||||||
|
mirrorCam.position = planePoint + tangent * sm.planar.x + bitangent * sm.planar.y + n * fixedDepth;
|
||||||
|
mirrorCam.front = n; // Look straight out from the mirror face
|
||||||
|
mirrorCam.up = upVec;
|
||||||
|
if (!std::isfinite(mirrorCam.front.x) || glm::length(mirrorCam.front) < 1e-3f) {
|
||||||
|
mirrorCam.front = glm::vec3(0.0f, 0.0f, -1.0f);
|
||||||
|
}
|
||||||
|
if (!std::isfinite(mirrorCam.up.x) || glm::length(mirrorCam.up) < 1e-3f) {
|
||||||
|
mirrorCam.up = glm::vec3(0.0f, 1.0f, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderSceneInternal(mirrorCam, sceneObjects, target.width, target.height, false, fovDeg, nearPlane, farPlane, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, prevFBO);
|
||||||
|
|
||||||
|
for (auto it = mirrorTargets.begin(); it != mirrorTargets.end(); ) {
|
||||||
|
if (active.find(it->first) == active.end()) {
|
||||||
|
releaseRenderTarget(it->second);
|
||||||
|
mirrorSmooth.erase(it->first);
|
||||||
|
it = mirrorTargets.erase(it);
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Renderer::ensureQuad() {
|
void Renderer::ensureQuad() {
|
||||||
if (quadVAO != 0) return;
|
if (quadVAO != 0) return;
|
||||||
|
|
||||||
@@ -790,6 +908,7 @@ void Renderer::renderObject(const SceneObject& obj) {
|
|||||||
shader->setFloat("specularStrength", obj.material.specularStrength);
|
shader->setFloat("specularStrength", obj.material.specularStrength);
|
||||||
shader->setFloat("shininess", obj.material.shininess);
|
shader->setFloat("shininess", obj.material.shininess);
|
||||||
shader->setFloat("mixAmount", obj.material.textureMix);
|
shader->setFloat("mixAmount", obj.material.textureMix);
|
||||||
|
shader->setBool("unlit", obj.type == ObjectType::Mirror);
|
||||||
|
|
||||||
Texture* baseTex = texture1;
|
Texture* baseTex = texture1;
|
||||||
if (!obj.albedoTexturePath.empty()) {
|
if (!obj.albedoTexturePath.empty()) {
|
||||||
@@ -798,7 +917,15 @@ void Renderer::renderObject(const SceneObject& obj) {
|
|||||||
if (baseTex) baseTex->Bind(GL_TEXTURE0);
|
if (baseTex) baseTex->Bind(GL_TEXTURE0);
|
||||||
|
|
||||||
bool overlayUsed = false;
|
bool overlayUsed = false;
|
||||||
if (obj.useOverlay && !obj.overlayTexturePath.empty()) {
|
if (obj.type == ObjectType::Mirror) {
|
||||||
|
auto it = mirrorTargets.find(obj.id);
|
||||||
|
if (it != mirrorTargets.end() && it->second.texture != 0) {
|
||||||
|
glActiveTexture(GL_TEXTURE1);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, it->second.texture);
|
||||||
|
overlayUsed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!overlayUsed && obj.useOverlay && !obj.overlayTexturePath.empty()) {
|
||||||
if (auto* t = getTexture(obj.overlayTexturePath)) {
|
if (auto* t = getTexture(obj.overlayTexturePath)) {
|
||||||
t->Bind(GL_TEXTURE1);
|
t->Bind(GL_TEXTURE1);
|
||||||
overlayUsed = true;
|
overlayUsed = true;
|
||||||
@@ -828,6 +955,9 @@ void Renderer::renderObject(const SceneObject& obj) {
|
|||||||
case ObjectType::Capsule:
|
case ObjectType::Capsule:
|
||||||
capsuleMesh->draw();
|
capsuleMesh->draw();
|
||||||
break;
|
break;
|
||||||
|
case ObjectType::Mirror:
|
||||||
|
if (planeMesh) planeMesh->draw();
|
||||||
|
break;
|
||||||
case ObjectType::OBJMesh:
|
case ObjectType::OBJMesh:
|
||||||
if (obj.meshId >= 0) {
|
if (obj.meshId >= 0) {
|
||||||
Mesh* objMesh = g_objLoader.getMesh(obj.meshId);
|
Mesh* objMesh = g_objLoader.getMesh(obj.meshId);
|
||||||
@@ -860,7 +990,7 @@ void Renderer::renderObject(const SceneObject& obj) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::renderSceneInternal(const Camera& camera, const std::vector<SceneObject>& sceneObjects, int width, int height, bool unbindFramebuffer, float fovDeg, float nearPlane, float farPlane) {
|
void Renderer::renderSceneInternal(const Camera& camera, const std::vector<SceneObject>& sceneObjects, int width, int height, bool unbindFramebuffer, float fovDeg, float nearPlane, float farPlane, bool drawMirrorObjects) {
|
||||||
if (!defaultShader || width <= 0 || height <= 0) return;
|
if (!defaultShader || width <= 0 || height <= 0) return;
|
||||||
|
|
||||||
struct LightUniform {
|
struct LightUniform {
|
||||||
@@ -958,6 +1088,7 @@ void Renderer::renderSceneInternal(const Camera& camera, const std::vector<Scene
|
|||||||
|
|
||||||
for (const auto& obj : sceneObjects) {
|
for (const auto& obj : sceneObjects) {
|
||||||
if (!obj.enabled) continue;
|
if (!obj.enabled) continue;
|
||||||
|
if (!drawMirrorObjects && obj.type == ObjectType::Mirror) continue;
|
||||||
// Skip light gizmo-only types and camera helpers
|
// Skip light gizmo-only types and camera helpers
|
||||||
if (obj.type == ObjectType::PointLight || obj.type == ObjectType::SpotLight || obj.type == ObjectType::AreaLight || obj.type == ObjectType::Camera || obj.type == ObjectType::PostFXNode) {
|
if (obj.type == ObjectType::PointLight || obj.type == ObjectType::SpotLight || obj.type == ObjectType::AreaLight || obj.type == ObjectType::Camera || obj.type == ObjectType::PostFXNode) {
|
||||||
continue;
|
continue;
|
||||||
@@ -971,6 +1102,7 @@ void Renderer::renderSceneInternal(const Camera& camera, const std::vector<Scene
|
|||||||
shader->setMat4("view", camera.getViewMatrix());
|
shader->setMat4("view", camera.getViewMatrix());
|
||||||
shader->setMat4("projection", glm::perspective(glm::radians(fovDeg), (float)width / (float)height, nearPlane, farPlane));
|
shader->setMat4("projection", glm::perspective(glm::radians(fovDeg), (float)width / (float)height, nearPlane, farPlane));
|
||||||
shader->setVec3("viewPos", camera.position);
|
shader->setVec3("viewPos", camera.position);
|
||||||
|
shader->setBool("unlit", obj.type == ObjectType::Mirror);
|
||||||
shader->setVec3("ambientColor", ambientColor);
|
shader->setVec3("ambientColor", ambientColor);
|
||||||
shader->setVec3("ambientColor", ambientColor);
|
shader->setVec3("ambientColor", ambientColor);
|
||||||
|
|
||||||
@@ -1011,7 +1143,15 @@ void Renderer::renderSceneInternal(const Camera& camera, const std::vector<Scene
|
|||||||
if (baseTex) baseTex->Bind(GL_TEXTURE0);
|
if (baseTex) baseTex->Bind(GL_TEXTURE0);
|
||||||
|
|
||||||
bool overlayUsed = false;
|
bool overlayUsed = false;
|
||||||
if (obj.useOverlay && !obj.overlayTexturePath.empty()) {
|
if (obj.type == ObjectType::Mirror) {
|
||||||
|
auto it = mirrorTargets.find(obj.id);
|
||||||
|
if (it != mirrorTargets.end() && it->second.texture != 0) {
|
||||||
|
glActiveTexture(GL_TEXTURE1);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, it->second.texture);
|
||||||
|
overlayUsed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!overlayUsed && obj.useOverlay && !obj.overlayTexturePath.empty()) {
|
||||||
if (auto* t = getTexture(obj.overlayTexturePath)) {
|
if (auto* t = getTexture(obj.overlayTexturePath)) {
|
||||||
t->Bind(GL_TEXTURE1);
|
t->Bind(GL_TEXTURE1);
|
||||||
overlayUsed = true;
|
overlayUsed = true;
|
||||||
@@ -1035,6 +1175,7 @@ void Renderer::renderSceneInternal(const Camera& camera, const std::vector<Scene
|
|||||||
if (obj.type == ObjectType::Cube) meshToDraw = cubeMesh;
|
if (obj.type == ObjectType::Cube) meshToDraw = cubeMesh;
|
||||||
else if (obj.type == ObjectType::Sphere) meshToDraw = sphereMesh;
|
else if (obj.type == ObjectType::Sphere) meshToDraw = sphereMesh;
|
||||||
else if (obj.type == ObjectType::Capsule) meshToDraw = capsuleMesh;
|
else if (obj.type == ObjectType::Capsule) meshToDraw = capsuleMesh;
|
||||||
|
else if (obj.type == ObjectType::Mirror) meshToDraw = planeMesh;
|
||||||
else if (obj.type == ObjectType::OBJMesh && obj.meshId != -1) {
|
else if (obj.type == ObjectType::OBJMesh && obj.meshId != -1) {
|
||||||
meshToDraw = g_objLoader.getMesh(obj.meshId);
|
meshToDraw = g_objLoader.getMesh(obj.meshId);
|
||||||
} else if (obj.type == ObjectType::Model && obj.meshId != -1) {
|
} else if (obj.type == ObjectType::Model && obj.meshId != -1) {
|
||||||
@@ -1211,7 +1352,8 @@ unsigned int Renderer::applyPostProcessing(const std::vector<SceneObject>& scene
|
|||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
renderSceneInternal(camera, sceneObjects, currentWidth, currentHeight, true, fovDeg, nearPlane, farPlane);
|
updateMirrorTargets(camera, sceneObjects, currentWidth, currentHeight, fovDeg, nearPlane, farPlane);
|
||||||
|
renderSceneInternal(camera, sceneObjects, currentWidth, currentHeight, true, fovDeg, nearPlane, farPlane, true);
|
||||||
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;
|
||||||
}
|
}
|
||||||
@@ -1225,7 +1367,8 @@ unsigned int Renderer::renderScenePreview(const Camera& camera, const std::vecto
|
|||||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
renderSceneInternal(camera, sceneObjects, width, height, true, fovDeg, nearPlane, farPlane);
|
updateMirrorTargets(camera, sceneObjects, width, height, fovDeg, nearPlane, farPlane);
|
||||||
|
renderSceneInternal(camera, sceneObjects, width, height, true, fovDeg, nearPlane, farPlane, true);
|
||||||
if (!applyPostFX) {
|
if (!applyPostFX) {
|
||||||
return previewTarget.texture;
|
return previewTarget.texture;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,11 @@ private:
|
|||||||
RenderTarget historyTarget;
|
RenderTarget historyTarget;
|
||||||
RenderTarget bloomTargetA;
|
RenderTarget bloomTargetA;
|
||||||
RenderTarget bloomTargetB;
|
RenderTarget bloomTargetB;
|
||||||
|
struct MirrorSmoothing {
|
||||||
|
glm::vec2 planar = glm::vec2(0.0f);
|
||||||
|
bool initialized = false;
|
||||||
|
};
|
||||||
|
std::unordered_map<int, MirrorSmoothing> mirrorSmooth;
|
||||||
Shader* shader = nullptr;
|
Shader* shader = nullptr;
|
||||||
Shader* defaultShader = nullptr;
|
Shader* defaultShader = nullptr;
|
||||||
Shader* postShader = nullptr;
|
Shader* postShader = nullptr;
|
||||||
@@ -100,19 +105,23 @@ private:
|
|||||||
Mesh* cubeMesh = nullptr;
|
Mesh* cubeMesh = nullptr;
|
||||||
Mesh* sphereMesh = nullptr;
|
Mesh* sphereMesh = nullptr;
|
||||||
Mesh* capsuleMesh = nullptr;
|
Mesh* capsuleMesh = nullptr;
|
||||||
|
Mesh* planeMesh = nullptr;
|
||||||
Skybox* skybox = nullptr;
|
Skybox* skybox = nullptr;
|
||||||
unsigned int quadVAO = 0;
|
unsigned int quadVAO = 0;
|
||||||
unsigned int quadVBO = 0;
|
unsigned int quadVBO = 0;
|
||||||
unsigned int displayTexture = 0;
|
unsigned int displayTexture = 0;
|
||||||
bool historyValid = false;
|
bool historyValid = false;
|
||||||
|
std::unordered_map<int, RenderTarget> mirrorTargets;
|
||||||
|
|
||||||
void setupFBO();
|
void setupFBO();
|
||||||
void ensureRenderTarget(RenderTarget& target, int w, int h);
|
void ensureRenderTarget(RenderTarget& target, int w, int h);
|
||||||
|
void releaseRenderTarget(RenderTarget& target);
|
||||||
|
void updateMirrorTargets(const Camera& camera, const std::vector<SceneObject>& sceneObjects, int width, int height, float fovDeg, float nearPlane, float farPlane);
|
||||||
void ensureQuad();
|
void ensureQuad();
|
||||||
void drawFullscreenQuad();
|
void drawFullscreenQuad();
|
||||||
void clearHistory();
|
void clearHistory();
|
||||||
void clearTarget(RenderTarget& target);
|
void clearTarget(RenderTarget& target);
|
||||||
void renderSceneInternal(const Camera& camera, const std::vector<SceneObject>& sceneObjects, int width, int height, bool unbindFramebuffer, float fovDeg, float nearPlane, float farPlane);
|
void renderSceneInternal(const Camera& camera, const std::vector<SceneObject>& sceneObjects, int width, int height, bool unbindFramebuffer, float fovDeg, float nearPlane, float farPlane, bool drawMirrorObjects);
|
||||||
unsigned int applyPostProcessing(const std::vector<SceneObject>& sceneObjects, unsigned int sourceTexture, int width, int height, bool allowHistory);
|
unsigned int applyPostProcessing(const std::vector<SceneObject>& sceneObjects, unsigned int sourceTexture, int width, int height, bool allowHistory);
|
||||||
PostFXSettings gatherPostFX(const std::vector<SceneObject>& sceneObjects) const;
|
PostFXSettings gatherPostFX(const std::vector<SceneObject>& sceneObjects) const;
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ enum class ObjectType {
|
|||||||
SpotLight,
|
SpotLight,
|
||||||
AreaLight,
|
AreaLight,
|
||||||
Camera,
|
Camera,
|
||||||
PostFXNode
|
PostFXNode,
|
||||||
|
Mirror
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MaterialProperties {
|
struct MaterialProperties {
|
||||||
|
|||||||
Reference in New Issue
Block a user