small changes to fix the lighting (+ added logo for later.)

This commit is contained in:
Anemunt
2025-12-10 17:59:57 -05:00
parent cdb781262f
commit d35d000dd7
4 changed files with 176 additions and 13 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 KiB

View File

@@ -21,7 +21,7 @@ uniform float specularStrength = 0.5;
uniform float shininess = 32.0; uniform float shininess = 32.0;
const int MAX_LIGHTS = 10; const int MAX_LIGHTS = 10;
uniform int lightCount = 0; // up to MAX_LIGHTS uniform int lightCount = 0; // up to MAX_LIGHTS
// type: 0 dir, 1 point, 2 spot // type: 0 dir, 1 point, 2 spot, 3 area (rect)
uniform int lightTypeArr[MAX_LIGHTS]; uniform int lightTypeArr[MAX_LIGHTS];
uniform vec3 lightDirArr[MAX_LIGHTS]; uniform vec3 lightDirArr[MAX_LIGHTS];
uniform vec3 lightPosArr[MAX_LIGHTS]; uniform vec3 lightPosArr[MAX_LIGHTS];
@@ -30,6 +30,7 @@ uniform float lightIntensityArr[MAX_LIGHTS];
uniform float lightRangeArr[MAX_LIGHTS]; uniform float lightRangeArr[MAX_LIGHTS];
uniform float lightInnerCosArr[MAX_LIGHTS]; uniform float lightInnerCosArr[MAX_LIGHTS];
uniform float lightOuterCosArr[MAX_LIGHTS]; uniform float lightOuterCosArr[MAX_LIGHTS];
uniform vec2 lightAreaSizeArr[MAX_LIGHTS];
// Single directional light controlled by hierarchy (fallback if none set) // Single directional light controlled by hierarchy (fallback if none set)
uniform vec3 lightDir = normalize(vec3(0.3, 1.0, 0.5)); uniform vec3 lightDir = normalize(vec3(0.3, 1.0, 0.5));
@@ -69,12 +70,59 @@ void main()
int count = min(lightCount, MAX_LIGHTS); int count = min(lightCount, MAX_LIGHTS);
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
int ltype = lightTypeArr[i]; int ltype = lightTypeArr[i];
vec3 ldir = (ltype == 0) ? -normalize(lightDirArr[i]) : lightPosArr[i] - FragPos; float intensity = lightIntensityArr[i];
float dist = length(ldir); if (intensity <= 0.0) continue;
vec3 lDirN = normalize(ldir);
vec3 lDirN;
float attenuation = 1.0; float attenuation = 1.0;
if (ltype != 0) {
if (ltype == 0) {
lDirN = -normalize(lightDirArr[i]);
} else if (ltype == 3) { // area light approximate
vec3 n = normalize(lightDirArr[i]);
vec3 up = abs(n.y) > 0.9 ? vec3(1.0, 0.0, 0.0) : vec3(0.0, 1.0, 0.0);
vec3 tangent = normalize(cross(up, n));
vec3 bitangent = cross(n, tangent);
vec3 center = lightPosArr[i];
vec3 rel = FragPos - center;
float distPlane = dot(rel, n);
vec3 onPlane = FragPos - distPlane * n;
vec2 halfSize = lightAreaSizeArr[i] * 0.5;
vec2 local;
local.x = dot(onPlane - center, tangent);
local.y = dot(onPlane - center, bitangent);
vec2 clamped = clamp(local, -halfSize, halfSize);
vec3 closest = center + tangent * clamped.x + bitangent * clamped.y;
vec3 lvec = closest - FragPos;
float dist = length(lvec);
if (dist < 1e-4) continue;
lDirN = normalize(lvec);
float range = lightRangeArr[i];
if (range > 0.0 && dist > range) continue;
if (range > 0.0) {
float falloff = clamp(1.0 - (dist / range), 0.0, 1.0);
attenuation = falloff * falloff;
}
// Lambert against area normal for softer look
float nl = max(dot(norm, lDirN), 0.0);
float facing = max(dot(n, -lDirN), 0.0);
attenuation *= facing;
vec3 diffuse = nl * lightColorArr[i] * intensity;
vec3 halfwayDir = normalize(lDirN + viewDir);
float spec = pow(max(dot(norm, halfwayDir), 0.0), shininess);
vec3 specular = specularStrength * spec * lightColorArr[i] * intensity;
lighting += attenuation * (diffuse + specular) * baseColor;
continue;
} else {
vec3 ldir = lightPosArr[i] - FragPos;
float dist = length(ldir);
lDirN = normalize(ldir);
float range = lightRangeArr[i]; float range = lightRangeArr[i];
if (range > 0.0 && dist > range) continue; if (range > 0.0 && dist > range) continue;
if (range > 0.0) { if (range > 0.0) {
@@ -83,9 +131,6 @@ void main()
} }
} }
float intensity = lightIntensityArr[i];
if (intensity <= 0.0) continue;
float diff = max(dot(norm, lDirN), 0.0); float diff = max(dot(norm, lDirN), 0.0);
vec3 diffuse = diff * lightColorArr[i] * intensity; vec3 diffuse = diff * lightColorArr[i] * intensity;

View File

@@ -3101,6 +3101,105 @@ void Engine::renderViewport() {
} }
} }
// Light visualization overlays
auto drawLightOverlays = [&](const SceneObject& lightObj) {
if (!lightObj.light.enabled) return;
ImDrawList* dl = ImGui::GetWindowDrawList();
ImU32 col = ImGui::GetColorU32(ImVec4(1.0f, 0.9f, 0.4f, 0.7f));
ImU32 faint = ImGui::GetColorU32(ImVec4(1.0f, 0.9f, 0.4f, 0.25f));
auto forwardFromRotation = [](const SceneObject& obj) {
glm::vec3 f = glm::normalize(glm::vec3(
glm::sin(glm::radians(obj.rotation.y)) * glm::cos(glm::radians(obj.rotation.x)),
glm::sin(glm::radians(obj.rotation.x)),
glm::cos(glm::radians(obj.rotation.y)) * glm::cos(glm::radians(obj.rotation.x))
));
if (glm::length(f) < 1e-3f || !std::isfinite(f.x)) f = glm::vec3(0.0f, -1.0f, 0.0f);
return f;
};
if (lightObj.type == ObjectType::PointLight) {
auto center = projectToScreen(lightObj.position);
glm::vec3 offset = lightObj.position + glm::vec3(lightObj.light.range, 0.0f, 0.0f);
auto edge = projectToScreen(offset);
if (center && edge) {
float r = std::sqrt((center->x - edge->x)*(center->x - edge->x) + (center->y - edge->y)*(center->y - edge->y));
dl->AddCircle(*center, r, faint, 48, 2.0f);
}
} else if (lightObj.type == ObjectType::SpotLight) {
glm::vec3 dir = forwardFromRotation(lightObj);
glm::vec3 tip = lightObj.position;
glm::vec3 end = tip + dir * lightObj.light.range;
float innerRad = glm::tan(glm::radians(lightObj.light.innerAngle)) * lightObj.light.range;
float outerRad = glm::tan(glm::radians(lightObj.light.outerAngle)) * lightObj.light.range;
// Build basis
glm::vec3 up = glm::abs(dir.y) > 0.9f ? glm::vec3(1,0,0) : glm::vec3(0,1,0);
glm::vec3 right = glm::normalize(glm::cross(dir, up));
up = glm::normalize(glm::cross(right, dir));
auto drawConeRing = [&](float radius, ImU32 color) {
const int segments = 24;
ImVec2 prev;
bool first = true;
for (int i = 0; i <= segments; ++i) {
float a = (float)i / segments * 2.0f * PI;
glm::vec3 p = end + right * std::cos(a) * radius + up * std::sin(a) * radius;
auto sp = projectToScreen(p);
if (!sp) continue;
if (first) { prev = *sp; first = false; continue; }
dl->AddLine(prev, *sp, color, 1.5f);
prev = *sp;
}
};
auto sTip = projectToScreen(tip);
auto sEnd = projectToScreen(end);
if (sTip && sEnd) {
dl->AddLine(*sTip, *sEnd, col, 2.0f);
drawConeRing(innerRad, col);
drawConeRing(outerRad, faint);
}
} else if (lightObj.type == ObjectType::AreaLight) {
glm::vec3 n = forwardFromRotation(lightObj);
glm::vec3 up = glm::abs(n.y) > 0.9f ? glm::vec3(1,0,0) : glm::vec3(0,1,0);
glm::vec3 tangent = glm::normalize(glm::cross(up, n));
glm::vec3 bitangent = glm::cross(n, tangent);
glm::vec2 half = lightObj.light.size * 0.5f;
glm::vec3 c = lightObj.position;
glm::vec3 corners[4] = {
c + tangent * half.x + bitangent * half.y,
c - tangent * half.x + bitangent * half.y,
c - tangent * half.x - bitangent * half.y,
c + tangent * half.x - bitangent * half.y
};
ImVec2 projected[4];
bool ok = true;
for (int i = 0; i < 4; ++i) {
auto p = projectToScreen(corners[i]);
if (!p) { ok = false; break; }
projected[i] = *p;
}
if (ok) {
for (int i = 0; i < 4; ++i) {
dl->AddLine(projected[i], projected[(i+1)%4], col, 2.0f);
}
// normal indicator
auto cproj = projectToScreen(c);
auto nproj = projectToScreen(c + n * glm::max(lightObj.light.range, 0.5f));
if (cproj && nproj) {
dl->AddLine(*cproj, *nproj, col, 2.0f);
dl->AddCircleFilled(*nproj, 4.0f, col);
}
}
}
};
for (const auto& obj : sceneObjects) {
if (obj.type == ObjectType::PointLight || obj.type == ObjectType::SpotLight || obj.type == ObjectType::AreaLight) {
drawLightOverlays(obj);
}
}
// Toolbar // Toolbar
const float toolbarPadding = 6.0f; const float toolbarPadding = 6.0f;
const float toolbarSpacing = 5.0f; const float toolbarSpacing = 5.0f;

View File

@@ -864,7 +864,7 @@ void Renderer::renderSceneInternal(const Camera& camera, const std::vector<Scene
if (!defaultShader || width <= 0 || height <= 0) return; if (!defaultShader || width <= 0 || height <= 0) return;
struct LightUniform { struct LightUniform {
int type = 0; // 0 dir,1 point,2 spot int type = 0; // 0 dir,1 point,2 spot,3 area
glm::vec3 dir = glm::vec3(0.0f, -1.0f, 0.0f); glm::vec3 dir = glm::vec3(0.0f, -1.0f, 0.0f);
glm::vec3 pos = glm::vec3(0.0f); glm::vec3 pos = glm::vec3(0.0f);
glm::vec3 color = glm::vec3(1.0f); glm::vec3 color = glm::vec3(1.0f);
@@ -872,6 +872,7 @@ void Renderer::renderSceneInternal(const Camera& camera, const std::vector<Scene
float range = 10.0f; float range = 10.0f;
float inner = glm::cos(glm::radians(15.0f)); float inner = glm::cos(glm::radians(15.0f));
float outer = glm::cos(glm::radians(25.0f)); float outer = glm::cos(glm::radians(25.0f));
glm::vec2 areaSize = glm::vec2(1.0f); // width/height for area lights
}; };
auto forwardFromRotation = [](const SceneObject& obj) { auto forwardFromRotation = [](const SceneObject& obj) {
glm::vec3 f = glm::normalize(glm::vec3( glm::vec3 f = glm::normalize(glm::vec3(
@@ -931,6 +932,23 @@ void Renderer::renderSceneInternal(const Camera& camera, const std::vector<Scene
} }
} }
} }
if (lights.size() < 10) {
for (const auto& obj : sceneObjects) {
if (obj.light.enabled && obj.type == ObjectType::AreaLight) {
LightUniform l;
l.type = 3; // area
l.pos = obj.position;
l.dir = forwardFromRotation(obj); // plane normal
l.color = obj.light.color;
l.intensity = obj.light.intensity;
float sizeHint = glm::max(obj.light.size.x, obj.light.size.y);
l.range = (obj.light.range > 0.0f) ? obj.light.range : glm::max(sizeHint * 2.0f, 1.0f);
l.areaSize = obj.light.size;
lights.push_back(l);
if (lights.size() >= 10) break;
}
}
}
for (const auto& obj : sceneObjects) { for (const auto& obj : sceneObjects) {
// Skip light gizmo-only types and camera helpers // Skip light gizmo-only types and camera helpers
@@ -958,10 +976,11 @@ void Renderer::renderSceneInternal(const Camera& camera, const std::vector<Scene
shader->setVec3("lightPosArr" + idx, l.pos); shader->setVec3("lightPosArr" + idx, l.pos);
shader->setVec3("lightColorArr" + idx, l.color); shader->setVec3("lightColorArr" + idx, l.color);
shader->setFloat("lightIntensityArr" + idx, l.intensity); shader->setFloat("lightIntensityArr" + idx, l.intensity);
shader->setFloat("lightRangeArr" + idx, l.range); shader->setFloat("lightRangeArr" + idx, l.range);
shader->setFloat("lightInnerCosArr" + idx, l.inner); shader->setFloat("lightInnerCosArr" + idx, l.inner);
shader->setFloat("lightOuterCosArr" + idx, l.outer); shader->setFloat("lightOuterCosArr" + idx, l.outer);
} shader->setVec2("lightAreaSizeArr" + idx, l.areaSize);
}
glm::mat4 model = glm::mat4(1.0f); glm::mat4 model = glm::mat4(1.0f);
model = glm::translate(model, obj.position); model = glm::translate(model, obj.position);