small changes to fix the lighting (+ added logo for later.)
This commit is contained in:
BIN
Resources/Engine-Root/Modu-Logo.png
Normal file
BIN
Resources/Engine-Root/Modu-Logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 451 KiB |
@@ -21,7 +21,7 @@ uniform float specularStrength = 0.5;
|
||||
uniform float shininess = 32.0;
|
||||
const int MAX_LIGHTS = 10;
|
||||
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 vec3 lightDirArr[MAX_LIGHTS];
|
||||
uniform vec3 lightPosArr[MAX_LIGHTS];
|
||||
@@ -30,6 +30,7 @@ uniform float lightIntensityArr[MAX_LIGHTS];
|
||||
uniform float lightRangeArr[MAX_LIGHTS];
|
||||
uniform float lightInnerCosArr[MAX_LIGHTS];
|
||||
uniform float lightOuterCosArr[MAX_LIGHTS];
|
||||
uniform vec2 lightAreaSizeArr[MAX_LIGHTS];
|
||||
|
||||
// Single directional light controlled by hierarchy (fallback if none set)
|
||||
uniform vec3 lightDir = normalize(vec3(0.3, 1.0, 0.5));
|
||||
@@ -69,12 +70,59 @@ void main()
|
||||
int count = min(lightCount, MAX_LIGHTS);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
int ltype = lightTypeArr[i];
|
||||
vec3 ldir = (ltype == 0) ? -normalize(lightDirArr[i]) : lightPosArr[i] - FragPos;
|
||||
float dist = length(ldir);
|
||||
vec3 lDirN = normalize(ldir);
|
||||
float intensity = lightIntensityArr[i];
|
||||
if (intensity <= 0.0) continue;
|
||||
|
||||
vec3 lDirN;
|
||||
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];
|
||||
if (range > 0.0 && dist > range) continue;
|
||||
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);
|
||||
vec3 diffuse = diff * lightColorArr[i] * intensity;
|
||||
|
||||
|
||||
@@ -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
|
||||
const float toolbarPadding = 6.0f;
|
||||
const float toolbarSpacing = 5.0f;
|
||||
|
||||
@@ -864,7 +864,7 @@ void Renderer::renderSceneInternal(const Camera& camera, const std::vector<Scene
|
||||
if (!defaultShader || width <= 0 || height <= 0) return;
|
||||
|
||||
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 pos = glm::vec3(0.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 inner = glm::cos(glm::radians(15.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) {
|
||||
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) {
|
||||
// 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("lightColorArr" + idx, l.color);
|
||||
shader->setFloat("lightIntensityArr" + idx, l.intensity);
|
||||
shader->setFloat("lightRangeArr" + idx, l.range);
|
||||
shader->setFloat("lightInnerCosArr" + idx, l.inner);
|
||||
shader->setFloat("lightOuterCosArr" + idx, l.outer);
|
||||
}
|
||||
shader->setFloat("lightRangeArr" + idx, l.range);
|
||||
shader->setFloat("lightInnerCosArr" + idx, l.inner);
|
||||
shader->setFloat("lightOuterCosArr" + idx, l.outer);
|
||||
shader->setVec2("lightAreaSizeArr" + idx, l.areaSize);
|
||||
}
|
||||
|
||||
glm::mat4 model = glm::mat4(1.0f);
|
||||
model = glm::translate(model, obj.position);
|
||||
|
||||
Reference in New Issue
Block a user