From e5b66bb8d98b217a958c989cc878b5ec0784f003 Mon Sep 17 00:00:00 2001 From: 4sval Date: Sun, 18 Dec 2022 02:54:28 +0100 Subject: [PATCH] improved maths for point & spot lights to make them look more realistic --- FModel/Resources/default.frag | 93 +++++++++++++++++++++++-------- FModel/Views/Snooper/Light.cs | 8 +-- FModel/Views/Snooper/Renderer.cs | 2 +- FModel/Views/Snooper/Shader.cs | 5 -- FModel/Views/Snooper/SnimGui.cs | 1 + FModel/Views/Snooper/SpotLight.cs | 30 ++++------ 6 files changed, 87 insertions(+), 52 deletions(-) diff --git a/FModel/Resources/default.frag b/FModel/Resources/default.frag index 57bdfac3..2acc8ea4 100644 --- a/FModel/Resources/default.frag +++ b/FModel/Resources/default.frag @@ -48,13 +48,35 @@ struct Parameters float UVScale; }; -struct Light { +struct BaseLight +{ vec4 Color; vec3 Position; float Intensity; +}; - vec2 Direction; - float ConeAngle; +//struct PointLight +//{ +// BaseLight Light; +// +// float Linear; +// float Quadratic; +//}; +// +//struct SpotLight +//{ +// BaseLight Light; +// +// float InnerConeAngle; +// float OuterConeAngle; +// float Attenuation; +//}; + +struct Light { + BaseLight Base; + + float InnerConeAngle; + float OuterConeAngle; float Attenuation; float Linear; @@ -68,9 +90,8 @@ uniform Light uLights[MAX_LIGHT_COUNT]; uniform int uNumLights; uniform int uNumTexCoords; uniform bool uHasVertexColors; -uniform vec3 uViewPos; -uniform vec3 uViewDir; uniform bool bVertexColors[6]; +uniform vec3 uViewPos; out vec4 FragColor; @@ -117,17 +138,16 @@ float geomSmith(float roughness, float dp) return dp / denom; } -vec3 CalcCameraLight(int layer, vec3 normals) +vec3 CalcLight(int layer, vec3 normals, vec3 position, vec3 color, float attenuation, bool global) { vec3 fLambert = SamplerToVector(uParameters.Diffuse[layer].Sampler).rgb * uParameters.Diffuse[layer].Color.rgb; vec3 specular_masks = SamplerToVector(uParameters.SpecularMasks[layer].Sampler).rgb; float roughness = max(0.0f, specular_masks.b * uParameters.Roughness); - vec3 intensity = vec3(1.0f) * 1.0; - vec3 l = -uViewDir; + vec3 l = normalize(uViewPos - fPos); vec3 n = normals; - vec3 v = normalize(uViewPos - fPos); + vec3 v = normalize(position - fPos); vec3 h = normalize(v + l); float nDotH = max(dot(n, h), 0.0); @@ -145,8 +165,43 @@ vec3 CalcCameraLight(int layer, vec3 normals) float specBrdfDenom = 4.0 * nDotV * nDotL + 0.0001; vec3 specBrdf = uParameters.Specular * specular_masks.r * specBrdfNom / specBrdfDenom; - vec3 diffuseBrdf = kD * fLambert / PI; - return (diffuseBrdf + specBrdf) * intensity * nDotL; + vec3 diffuseBrdf = fLambert; + if (!global) diffuseBrdf = kD * fLambert / PI; + return (diffuseBrdf + specBrdf) * color * nDotL * attenuation; +} + +vec3 CalcBaseLight(int layer, vec3 normals, BaseLight base, float attenuation, bool global) +{ + return CalcLight(layer, normals, base.Position, base.Color.rgb * base.Intensity, attenuation, global); +} + +vec3 CalcPointLight(int layer, vec3 normals, Light light) +{ + float distanceToLight = length(light.Base.Position - fPos); + float attenuation = 1.0 / (1.0 + light.Linear * distanceToLight + light.Quadratic * pow(distanceToLight, 2)); + return CalcBaseLight(layer, normals, light.Base, attenuation, true); +} + +vec3 CalcSpotLight(int layer, vec3 normals, Light light) +{ + vec3 v = normalize(light.Base.Position - fPos); + float inner = cos(radians(light.InnerConeAngle)); + float outer = cos(radians(light.OuterConeAngle)); + + float distanceToLight = length(light.Base.Position - fPos); + float theta = dot(v, normalize(-vec3(0, -1, 0))); + float epsilon = inner - outer; + float attenuation = 1.0 / (1.0 + light.Attenuation * pow(distanceToLight, 2)); + light.Base.Intensity *= smoothstep(0.0, 1.0, (theta - outer) / epsilon); + + if(theta > outer) + { + return CalcBaseLight(layer, normals, light.Base, attenuation, false); + } + else + { + return vec3(0.0); + } } void main() @@ -190,29 +245,19 @@ void main() if (!bVertexColors[1]) { - result += CalcCameraLight(layer, normals); + result += CalcLight(layer, normals, uViewPos, vec3(0.75), 1.0, false); vec3 lights = vec3(uNumLights > 0 ? 0 : 1); for (int i = 0; i < uNumLights; i++) { - float attenuation = 0.0; - float distanceToLight = length(uLights[i].Position - fPos); - if (uLights[i].Type == 0) { - attenuation = 1.0 / (1.0 + uLights[i].Linear * distanceToLight + uLights[i].Quadratic * pow(distanceToLight, 2)); + lights += CalcPointLight(layer, normals, uLights[i]); } else if (uLights[i].Type == 1) { - float theta = dot(normalize(uLights[i].Position - fPos), normalize(-vec3(uLights[i].Direction.x, -uLights[i].Attenuation, uLights[i].Direction.y))); - if(theta > uLights[i].ConeAngle) - { - attenuation = 1.0 / (1.0 + uLights[i].Attenuation * pow(distanceToLight, 2)); - } + lights += CalcSpotLight(layer, normals, uLights[i]); } - - vec3 intensity = uLights[i].Color.rgb * uLights[i].Intensity; - lights += result * intensity * attenuation; } result *= lights; // use * to darken the scene, + to lighten it } diff --git a/FModel/Views/Snooper/Light.cs b/FModel/Views/Snooper/Light.cs index 446b62e2..383e0840 100644 --- a/FModel/Views/Snooper/Light.cs +++ b/FModel/Views/Snooper/Light.cs @@ -40,7 +40,7 @@ public abstract class Light : IDisposable var r = light.GetOrDefault("RelativeRotation", parent.GetOrDefault("RelativeRotation", FRotator.ZeroRotator)); Transform = Transform.Identity; - Transform.Scale = new FVector(0.25f); + Transform.Scale = new FVector(0.2f); Transform.Position = position + r.RotateVector(p.ToMapVector()) * Constants.SCALE_DOWN_RATIO; Model = model; @@ -84,9 +84,9 @@ public abstract class Light : IDisposable public virtual void Render(int i, Shader shader) { - shader.SetUniform($"uLights[{i}].Color", Color); - shader.SetUniform($"uLights[{i}].Position", Transform.Position); - shader.SetUniform($"uLights[{i}].Intensity", Intensity); + shader.SetUniform($"uLights[{i}].Base.Color", Color); + shader.SetUniform($"uLights[{i}].Base.Position", Transform.Position); + shader.SetUniform($"uLights[{i}].Base.Intensity", Intensity); } public virtual void ImGuiLight() diff --git a/FModel/Views/Snooper/Renderer.cs b/FModel/Views/Snooper/Renderer.cs index d0123656..b08d6db0 100644 --- a/FModel/Views/Snooper/Renderer.cs +++ b/FModel/Views/Snooper/Renderer.cs @@ -100,7 +100,7 @@ public class Renderer : IDisposable if (ShowSkybox) _skybox.Render(viewMatrix, projMatrix); if (ShowGrid) _grid.Render(viewMatrix, projMatrix, cam.Near, cam.Far); - _shader.Render(viewMatrix, cam.Position, cam.Direction, projMatrix); + _shader.Render(viewMatrix, cam.Position, projMatrix); for (int i = 0; i < 6; i++) _shader.SetUniform($"bVertexColors[{i}]", i == VertexColor); diff --git a/FModel/Views/Snooper/Shader.cs b/FModel/Views/Snooper/Shader.cs index ece9ce27..51660b11 100644 --- a/FModel/Views/Snooper/Shader.cs +++ b/FModel/Views/Snooper/Shader.cs @@ -56,11 +56,6 @@ public class Shader : IDisposable GL.UseProgram(_handle); } - public void Render(Matrix4x4 viewMatrix, Vector3 viewPos, Vector3 viewDir, Matrix4x4 projMatrix) - { - Render(viewMatrix, viewPos, projMatrix); - SetUniform("uViewDir", viewDir); - } public void Render(Matrix4x4 viewMatrix, Vector3 viewPos, Matrix4x4 projMatrix) { Render(viewMatrix, projMatrix); diff --git a/FModel/Views/Snooper/SnimGui.cs b/FModel/Views/Snooper/SnimGui.cs index 6237582a..e2df5cf5 100644 --- a/FModel/Views/Snooper/SnimGui.cs +++ b/FModel/Views/Snooper/SnimGui.cs @@ -587,6 +587,7 @@ hello world! if (ImGui.CollapsingHeader("Textures") && material.ImGuiTextures(icons, model)) { _ti_open = true; + ImGui.SetWindowFocus("Texture Inspector"); } ImGui.SetNextItemOpen(true, ImGuiCond.Appearing); diff --git a/FModel/Views/Snooper/SpotLight.cs b/FModel/Views/Snooper/SpotLight.cs index fae276b7..17ef0659 100644 --- a/FModel/Views/Snooper/SpotLight.cs +++ b/FModel/Views/Snooper/SpotLight.cs @@ -1,6 +1,4 @@ -using System; -using System.Numerics; -using CUE4Parse.UE4.Assets.Exports; +using CUE4Parse.UE4.Assets.Exports; using CUE4Parse.UE4.Objects.Core.Math; using CUE4Parse.UE4.Objects.Core.Misc; using ImGuiNET; @@ -9,9 +7,9 @@ namespace FModel.Views.Snooper; public class SpotLight : Light { - public Vector2 Direction; // ??? public float Attenuation; - public float ConeAngle; + public float InnerConeAngle; + public float OuterConeAngle; public SpotLight(FGuid model, Texture icon, UObject parent, UObject spot, FVector position) : base(model, icon, parent, spot, position) { @@ -19,17 +17,16 @@ public class SpotLight : Light Attenuation = 1.0f; Attenuation *= Constants.SCALE_DOWN_RATIO; - Direction = Vector2.Zero; - ConeAngle = (spot.GetOrDefault("InnerConeAngle", 50.0f) + spot.GetOrDefault("OuterConeAngle", 60.0f)) / 2.0f; - ConeAngle = MathF.Cos(Helper.DegreesToRadians(ConeAngle)); + InnerConeAngle = spot.GetOrDefault("InnerConeAngle", 50.0f); + OuterConeAngle = spot.GetOrDefault("OuterConeAngle", 60.0f); } public override void Render(int i, Shader shader) { base.Render(i, shader); - shader.SetUniform($"uLights[{i}].Direction", Direction); shader.SetUniform($"uLights[{i}].Attenuation", Attenuation); - shader.SetUniform($"uLights[{i}].ConeAngle", ConeAngle); + shader.SetUniform($"uLights[{i}].InnerConeAngle", InnerConeAngle); + shader.SetUniform($"uLights[{i}].OuterConeAngle", OuterConeAngle); shader.SetUniform($"uLights[{i}].Type", 1); } @@ -37,14 +34,11 @@ public class SpotLight : Light public override void ImGuiLight() { base.ImGuiLight(); - SnimGui.Layout("Direction");ImGui.PushID(3); - ImGui.DragFloat2("", ref Direction, 0.01f); - ImGui.PopID();SnimGui.Layout("Attenuation");ImGui.PushID(4); + SnimGui.Layout("Attenuation");ImGui.PushID(3); ImGui.DragFloat("", ref Attenuation, 0.1f);ImGui.PopID(); - - var angle = Helper.RadiansToDegrees(MathF.Acos(ConeAngle)); - SnimGui.Layout("Cone Angle");ImGui.PushID(5); - ImGui.DragFloat("", ref angle, 0.1f, 0.0f, 90.0f, "%.1f°");ImGui.PopID(); - ConeAngle = MathF.Cos(Helper.DegreesToRadians(angle)); + SnimGui.Layout("Inner Cone Angle");ImGui.PushID(4); + ImGui.DragFloat("", ref InnerConeAngle, 0.1f, 0.0f, 90.0f, "%.1f°");ImGui.PopID(); + SnimGui.Layout("Outer Cone Angle");ImGui.PushID(5); + ImGui.DragFloat("", ref OuterConeAngle, 0.1f, 0.0f, 90.0f, "%.1f°");ImGui.PopID(); } }