diff --git a/StarterNG.Tests/GraphicsSettingsTests.cs b/StarterNG.Tests/GraphicsSettingsTests.cs index 98f496d..2ba8d20 100644 --- a/StarterNG.Tests/GraphicsSettingsTests.cs +++ b/StarterNG.Tests/GraphicsSettingsTests.cs @@ -402,4 +402,140 @@ public class GraphicsSettingsTests c.Set("b", "9"); Assert.Equal("b 9\nc 3\na 1\n", c.ToText().Replace("\r\n", "\n")); } + + [Fact] + public void The_ao_lighting_and_cab_probe_keys_survive_a_round_trip_in_the_simulators_form() + { + var s = Read("gfx.postfx.ao.lighting no\ngfx.cabprobe high\ngfx.cabprobe.interval 12\ngfx.cabprobe.bounce 2.5\ngfx.cabprobe.reflections no\n"); + + Assert.False(s.AoLighting); + Assert.Equal(3, s.CabProbe); + Assert.Equal(12, s.CabProbeInterval); + Assert.Equal(2.5, s.CabProbeBounce); + Assert.False(s.CabProbeReflections); + + string text = Write(s); + Assert.Equal("gfx.postfx.ao.lighting no", Line(text, "gfx.postfx.ao.lighting")); + Assert.Equal("gfx.cabprobe high", Line(text, "gfx.cabprobe")); + Assert.Equal("gfx.cabprobe.interval 12", Line(text, "gfx.cabprobe.interval")); + Assert.Equal("gfx.cabprobe.bounce 2.5", Line(text, "gfx.cabprobe.bounce")); + Assert.Equal("gfx.cabprobe.reflections no", Line(text, "gfx.cabprobe.reflections")); + + var again = Read(text); + Assert.Equal((s.AoLighting, s.CabProbe, s.CabProbeInterval, s.CabProbeBounce, s.CabProbeReflections), + (again.AoLighting, again.CabProbe, again.CabProbeInterval, again.CabProbeBounce, again.CabProbeReflections)); + } + + [Fact] + public void Missing_ao_lighting_and_cab_probe_keys_take_the_simulators_defaults_and_are_written_like_its_export() + { + var s = Read(""); + + Assert.Equal((true, 2, 4, 1.0, true), (s.AoLighting, s.CabProbe, s.CabProbeInterval, s.CabProbeBounce, s.CabProbeReflections)); + + string text = Write(s); + Assert.Equal("gfx.postfx.ao.lighting yes", Line(text, "gfx.postfx.ao.lighting")); + Assert.Equal("gfx.cabprobe medium", Line(text, "gfx.cabprobe")); + Assert.Equal("gfx.cabprobe.interval 4", Line(text, "gfx.cabprobe.interval")); + Assert.Equal("gfx.cabprobe.bounce 1", Line(text, "gfx.cabprobe.bounce")); + Assert.Equal("gfx.cabprobe.reflections yes", Line(text, "gfx.cabprobe.reflections")); + } + + [Fact] + public void Unknown_ao_lighting_and_cab_probe_values_fall_back_to_the_simulators_defaults() + { + var s = Read("gfx.postfx.ao.lighting maybe\ngfx.cabprobe bogus\ngfx.cabprobe.interval abc\ngfx.cabprobe.bounce x\ngfx.cabprobe.reflections ?\n"); + + Assert.Equal((true, 2, 4, 1.0, true), (s.AoLighting, s.CabProbe, s.CabProbeInterval, s.CabProbeBounce, s.CabProbeReflections)); + } + + [Theory] + [InlineData("no", 0)] + [InlineData("0", 0)] + [InlineData("low", 1)] + [InlineData("1", 1)] + [InlineData("medium", 2)] + [InlineData("yes", 2)] + [InlineData("2", 2)] + [InlineData("high", 3)] + [InlineData("3", 3)] + public void The_cab_probe_level_is_read_with_the_aliases_the_simulator_takes(string value, int expected) + { + Assert.Equal(expected, Read($"gfx.cabprobe {value}\n").CabProbe); + } + + [Fact] + public void The_cab_probe_numbers_are_kept_within_the_simulators_ranges() + { + var s = Read("gfx.cabprobe.interval 500\ngfx.cabprobe.bounce 9\n"); + Assert.Equal((120, 4.0), (s.CabProbeInterval, s.CabProbeBounce)); + + s = Read("gfx.cabprobe.interval 0\ngfx.cabprobe.bounce -1\n"); + Assert.Equal((1, 0.0), (s.CabProbeInterval, s.CabProbeBounce)); + } + + [Fact] + public void The_ao_lighting_counts_with_gtao_only() + { + Assert.True(GraphicsRules.AoLightingUsed(Read("gfx.postfx.ao gtao\n"))); + Assert.False(GraphicsRules.AoLightingUsed(Read("gfx.postfx.ao ssao\n"))); + Assert.False(GraphicsRules.AoLightingUsed(Read("gfx.postfx.ao no\n"))); + } + + [Theory] + [InlineData("gfx.ssr no\ngfx.contactshadows no\n", true)] + [InlineData("gfx.ssr low\ngfx.contactshadows no\n", false)] + [InlineData("gfx.ssr no\ngfx.contactshadows low\n", false)] + [InlineData("gfx.ssr no\ngfx.contactshadows no\ngfx.depthprepass.scene yes\n", false)] + [InlineData("gfx.ssr no\ngfx.contactshadows no\ngfx.postfx.ao.lighting no\n", false)] + [InlineData("gfx.ssr no\ngfx.contactshadows no\ngfx.postfx.ao ssao\n", false)] + public void The_ao_lighting_adds_the_depth_pass_only_when_nothing_else_draws_it(string text, bool expected) + { + Assert.Equal(expected, GraphicsRules.AoLightingAddsDepthPrepass(Read(text))); + } + + [Theory] + [InlineData("gfx.cabprobe medium\n", true, true)] + [InlineData("gfx.cabprobe no\n", false, false)] + [InlineData("gfx.cabprobe low\ngfx.lights.clustered no\n", true, false)] + [InlineData("gfx.cabprobe high\ngfx.lights.cab no\n", true, false)] + public void The_cab_probe_lights_the_cab_only_with_its_lamp_as_a_light(string text, bool used, bool lights) + { + var s = Read(text); + + Assert.Equal(used, GraphicsRules.CabProbeUsed(s)); + Assert.Equal(lights, GraphicsRules.CabProbeLights(s)); + } + + [Theory] + [InlineData(GraphicsPreset.Lowest, false, 0, 4, false)] + [InlineData(GraphicsPreset.Low, false, 0, 4, false)] + [InlineData(GraphicsPreset.Medium, false, 1, 8, true)] + [InlineData(GraphicsPreset.High, true, 2, 4, true)] + [InlineData(GraphicsPreset.Ultra, true, 3, 2, true)] + public void A_preset_sets_the_ao_lighting_and_the_cab_probe(GraphicsPreset preset, bool aoLighting, int probe, int interval, bool reflections) + { + var s = new SimulatorSettings { CabProbeBounce = 2.5 }; + + GraphicsPresets.Apply(s, preset, true); + + Assert.Equal((aoLighting, probe, interval, reflections), (s.AoLighting, s.CabProbe, s.CabProbeInterval, s.CabProbeReflections)); + Assert.Equal(2.5, s.CabProbeBounce); + Assert.Equal(preset, GraphicsPresets.Detect(s, true)); + + string text = Write(s); + Assert.Equal(preset, GraphicsPresets.Detect(Read(text), true)); + } + + [Fact] + public void An_import_keeps_the_lamp_switch_of_the_users_own_file() + { + var installation = WithIni("gfx.lights.cab no\n"); + installation.Files.WithFile("/backup/eu07.ini", "gfx.lights.cab yes\ngfx.cabprobe high\n"); + + Assert.True(installation.SettingsStore.ImportFrom("/backup/eu07.ini")); + + Assert.False(installation.SettingsStore.Settings.CabLampLight); + Assert.Equal(3, installation.SettingsStore.Settings.CabProbe); + } } diff --git a/StarterNG/Application/SettingsStore.cs b/StarterNG/Application/SettingsStore.cs index 718852f..0d16658 100644 --- a/StarterNG/Application/SettingsStore.cs +++ b/StarterNG/Application/SettingsStore.cs @@ -102,6 +102,9 @@ public sealed class SettingsStore string executable = s.ExecutablePath; string lastScenery = s.LastScenery; bool maximized = s.WindowMaximized; + // Only read for the dependencies and never written, so they stay as this user's file has them. + bool cabLampLight = s.CabLampLight; + bool depthPrepassScene = s.DepthPrepassScene; _serializer.Read(s, imported); @@ -109,6 +112,8 @@ public sealed class SettingsStore s.ExecutablePath = executable; s.LastScenery = lastScenery; s.WindowMaximized = maximized; + s.CabLampLight = cabLampLight; + s.DepthPrepassScene = depthPrepassScene; return true; } diff --git a/StarterNG/Domain/Settings/GraphicsPresets.cs b/StarterNG/Domain/Settings/GraphicsPresets.cs index cded183..07ddbd0 100644 --- a/StarterNG/Domain/Settings/GraphicsPresets.cs +++ b/StarterNG/Domain/Settings/GraphicsPresets.cs @@ -8,7 +8,7 @@ public enum GraphicsPreset { Lowest, Low, Medium, High, Ultra, Custom } /// Quality presets of the starter: one set of graphics settings each. A preset /// leaves alone what is a matter of taste or of the machine rather than of quality /// (resolution, render scale, vsync, field of view, motion blur, chromatic -/// aberration) and keeps DLSS when it is on, since that is a choice of the +/// aberration, the strength of the light bounced in the cab) and keeps DLSS when it is on, since that is a choice of the /// anti-aliasing the presets cannot make better. Ray tracing is only for Vulkan. /// public static class GraphicsPresets @@ -23,7 +23,8 @@ public static class GraphicsPresets int Texture, int CabTexture, int Anisotropy, AntiAliasingMode AntiAliasing, int DrawRange, int Spline, int DynamicLights, bool Shadows, int ShadowMap, int ShadowRange, int ShadowRank, int LightShadows, int ContactShadows, - int Ao, int AoSlices, int AoSteps, + int Ao, int AoSlices, int AoSteps, bool AoLighting, + int CabProbe, int CabProbeInterval, bool CabProbeReflections, int ReflectionsFidelity, int ReflectionsFramerate, int Ssr, bool RayTracing, bool VolumetricFog, int FogQuality, int Clouds, bool CloudShadows, bool Grass, int GrassDistance, int GrassDensityPercent, @@ -35,7 +36,8 @@ public static class GraphicsPresets 1024, 1024, 1, AntiAliasingMode.Off, 1, 1, 3, false, 1024, 75, 1, 0, 0, - 0, 3, 4, + 0, 3, 4, false, + 0, 4, false, 0, 5, 0, false, false, 1, 0, false, false, 60, 100, @@ -44,7 +46,8 @@ public static class GraphicsPresets 2048, 2048, 4, AntiAliasingMode.Msaa2, 2, 2, 5, true, 1024, 150, 2, 1, 0, - 1, 3, 4, + 1, 3, 4, false, + 0, 4, false, 0, 10, 1, false, true, 1, 1, false, true, 40, 50, @@ -53,7 +56,8 @@ public static class GraphicsPresets 4096, 4096, 8, AntiAliasingMode.Msaa2, 3, 3, 7, true, 2048, 250, 3, 2, 0, - 2, 3, 4, + 2, 3, 4, false, + 1, 8, true, 1, 30, 2, false, true, 2, 2, true, true, 60, 100, @@ -62,7 +66,8 @@ public static class GraphicsPresets 4096, 4096, 16, AntiAliasingMode.Msaa4, 3, 4, 7, true, 4096, 300, 3, 3, 1, - 2, 4, 6, + 2, 4, 6, true, + 2, 4, true, 2, 30, 2, false, true, 3, 3, true, true, 90, 100, @@ -71,7 +76,8 @@ public static class GraphicsPresets 8192, 8192, 16, AntiAliasingMode.Msaa8, 3, 4, 7, true, 8192, 400, 3, 3, 3, - 2, 6, 8, + 2, 6, 8, true, + 3, 2, true, 2, 60, 3, true, true, 4, 4, true, true, 120, 150, @@ -94,7 +100,8 @@ public static class GraphicsPresets s.MaxTextureSize, s.MaxCabTextureSize, s.TextureFiltering, s.AntiAliasing, (int)Math.Round(s.DrawRangeFactor), s.SplineFidelity, s.DynamicLights, s.RenderShadows, s.ShadowMapResolution, s.ShadowProjectionRange, s.ShadowRankCutoff, s.LightShadows, s.ContactShadows, - s.AmbientOcclusion, s.AoSlices, s.AoSteps, + s.AmbientOcclusion, s.AoSlices, s.AoSteps, s.AoLighting, + s.CabProbe, s.CabProbeInterval, s.CabProbeReflections, s.ReflectionsFidelity, s.ReflectionsFramerate, s.Ssr, s.RayTracing, s.VolumetricFog, s.FogQuality, s.Clouds, s.CloudShadows, s.Grass, s.GrassDistance, (int)Math.Round(s.GrassDensity * 100), @@ -122,6 +129,10 @@ public static class GraphicsPresets s.AmbientOcclusion = q.Ao; s.AoSlices = q.AoSlices; s.AoSteps = q.AoSteps; + s.AoLighting = q.AoLighting; + s.CabProbe = q.CabProbe; + s.CabProbeInterval = q.CabProbeInterval; + s.CabProbeReflections = q.CabProbeReflections; s.ReflectionsFidelity = q.ReflectionsFidelity; s.ReflectionsFramerate = q.ReflectionsFramerate; s.Ssr = q.Ssr; diff --git a/StarterNG/Domain/Settings/GraphicsRules.cs b/StarterNG/Domain/Settings/GraphicsRules.cs index b4830e5..16ae082 100644 --- a/StarterNG/Domain/Settings/GraphicsRules.cs +++ b/StarterNG/Domain/Settings/GraphicsRules.cs @@ -45,6 +45,24 @@ public static class GraphicsRules /// With the clustered lights the headlights come from the clusters; dynamiclights only caps the old path. public static bool DynamicLightsUsed(SimulatorSettings s) => !s.LightsClustered; + /// The ambient occlusion goes into the lighting only with GTAO. + public static bool AoLightingUsed(SimulatorSettings s) => s.AmbientOcclusion == 2; + + /// + /// The AO in the lighting needs the depth of the whole scene drawn before its colour. SSR, contact + /// shadows and gfx.depthprepass.scene draw it anyway; without them it is an extra pass (CPU time on OpenGL). + /// + public static bool AoLightingAddsDepthPrepass(SimulatorSettings s) => + AoLightingUsed(s) && s.AoLighting && s.Ssr == 0 && s.ContactShadows == 0 && !s.DepthPrepassScene; + + public static bool CabProbeUsed(SimulatorSettings s) => s.CabProbe > 0; + + /// + /// The light bounced around the cab comes from the cab lamp as a light, which needs the clustered lights + /// and gfx.lights.cab; without them the probe gives the reflections only. + /// + public static bool CabProbeLights(SimulatorSettings s) => CabProbeUsed(s) && s.LightsClustered && s.CabLampLight; + /// /// Brings the settings to what the simulator would run with: the Vulkan-only /// features off on OpenGL, DLSS falling back to TAA, values within the ranges @@ -72,6 +90,9 @@ public static class GraphicsRules s.AmbientOcclusion = Clamp(s.AmbientOcclusion, 0, 2); s.AoSlices = Clamp(s.AoSlices, 1, 8); s.AoSteps = Clamp(s.AoSteps, 1, 16); + s.CabProbe = Clamp(s.CabProbe, 0, 3); + s.CabProbeInterval = Clamp(s.CabProbeInterval, 1, 120); + s.CabProbeBounce = s.CabProbeBounce < 0 ? 0 : (s.CabProbeBounce > 4 ? 4 : s.CabProbeBounce); s.Ssr = Clamp(s.Ssr, 0, 3); s.RayTracingRange = Clamp(s.RayTracingRange, 10, 5000); s.FogQuality = Clamp(s.FogQuality, 1, 4); diff --git a/StarterNG/Domain/Settings/SimulatorSettings.cs b/StarterNG/Domain/Settings/SimulatorSettings.cs index 90d8918..05b7095 100644 --- a/StarterNG/Domain/Settings/SimulatorSettings.cs +++ b/StarterNG/Domain/Settings/SimulatorSettings.cs @@ -72,6 +72,15 @@ public sealed class SimulatorSettings public int AmbientOcclusion = 2; public int AoSlices = 3; public int AoSteps = 4; + public bool AoLighting = true; + public int CabProbe = 2; + public int CabProbeInterval = 4; + public double CabProbeBounce = 1.0; + public bool CabProbeReflections = true; + + // Read from eu07.ini only, for the dependencies shown: the starter offers no switch for them. + public bool CabLampLight { get; internal set; } = true; + public bool DepthPrepassScene { get; internal set; } public int Ssr = 2; public bool RayTracing; public int RayTracingRange = 500; diff --git a/StarterNG/Infrastructure/Settings/SettingsSerializer.cs b/StarterNG/Infrastructure/Settings/SettingsSerializer.cs index e33cbd9..7b9db59 100644 --- a/StarterNG/Infrastructure/Settings/SettingsSerializer.cs +++ b/StarterNG/Infrastructure/Settings/SettingsSerializer.cs @@ -98,6 +98,13 @@ public sealed class SettingsSerializer var aoQuality = c.GetTokens("gfx.postfx.ao.quality"); s.AoSlices = aoQuality.Length >= 1 ? ParseInt(aoQuality[0], 3) : 3; s.AoSteps = aoQuality.Length >= 2 ? ParseInt(aoQuality[1], 4) : 4; + s.AoLighting = c.GetBool("gfx.postfx.ao.lighting", true); + s.CabProbe = ParseCabProbe(FirstToken(c, "gfx.cabprobe")); + s.CabProbeInterval = c.GetInt("gfx.cabprobe.interval", 4); + s.CabProbeBounce = c.GetDouble("gfx.cabprobe.bounce", 1.0); + s.CabProbeReflections = c.GetBool("gfx.cabprobe.reflections", true); + s.CabLampLight = c.GetBool("gfx.lights.cab", true); + s.DepthPrepassScene = c.GetBool("gfx.depthprepass.scene", false); s.Ssr = ParseLevel(FirstToken(c, "gfx.ssr"), 2, 3); s.RayTracing = c.GetBool("gfx.raytracing", false); s.RayTracingRange = (int)Math.Round(c.GetDouble("gfx.raytracing.range", 500)); @@ -275,6 +282,11 @@ public sealed class SettingsSerializer c.SetBool("gfx.lights.clustered", s.LightsClustered); c.Set("gfx.postfx.ao", s.AmbientOcclusion switch { 1 => "ssao", 2 => "gtao", _ => "no" }); c.Set("gfx.postfx.ao.quality", $"{s.AoSlices} {s.AoSteps}"); + c.SetBool("gfx.postfx.ao.lighting", s.AoLighting); + c.Set("gfx.cabprobe", LevelToken(s.CabProbe)); + c.SetInt("gfx.cabprobe.interval", s.CabProbeInterval); + c.SetDouble("gfx.cabprobe.bounce", s.CabProbeBounce); + c.SetBool("gfx.cabprobe.reflections", s.CabProbeReflections); c.Set("gfx.ssr", LevelToken(s.Ssr)); c.SetBool("gfx.raytracing", s.RayTracing); c.SetInt("gfx.raytracing.range", s.RayTracingRange); @@ -466,6 +478,15 @@ public sealed class SettingsSerializer _ => "no" }; + // As the simulator reads it, but a value it does not know keeps its default (medium) rather than turning the probe off. + private static int ParseCabProbe(string value) => value switch + { + "no" or "false" or "off" or "0" => 0, + "low" or "1" => 1, + "high" or "3" => 3, + _ => 2 + }; + private static int ParseAmbientOcclusion(string value) => value switch { "" => 2, diff --git a/StarterNG/Views/Settings.Graphics.cs b/StarterNG/Views/Settings.Graphics.cs index 60e6fda..eeff4c7 100644 --- a/StarterNG/Views/Settings.Graphics.cs +++ b/StarterNG/Views/Settings.Graphics.cs @@ -84,6 +84,11 @@ public partial class Settings SelectTag(ContactShadowsCb, s.ContactShadows.ToString(Invariant)); SelectTag(AmbientOcclusionCb, s.AmbientOcclusion.ToString(Invariant)); SelectOrAddTag(AoQualityCb, $"{s.AoSlices} {s.AoSteps}", $"{s.AoSlices} / {s.AoSteps}"); + AoLightingCb.IsChecked = s.AoLighting; + SelectTag(CabProbeCb, s.CabProbe.ToString(Invariant)); + CabProbeIntervalNud.Value = s.CabProbeInterval; + CabProbeBounceSlider.Value = s.CabProbeBounce; + CabProbeReflectionsCb.IsChecked = s.CabProbeReflections; ReflectionsCubeMapCb.IsChecked = s.EnvMap; SelectTag(SsrCb, s.Ssr.ToString(Invariant)); @@ -152,6 +157,15 @@ public partial class Settings var ao = (SelectedTag(AoQualityCb) ?? "3 4").Split(' '); s.AoSlices = ao.Length > 0 && int.TryParse(ao[0], NumberStyles.Integer, Invariant, out int slices) ? slices : 3; s.AoSteps = ao.Length > 1 && int.TryParse(ao[1], NumberStyles.Integer, Invariant, out int steps) ? steps : 4; + s.AoLighting = IsChecked(AoLightingCb); + s.CabProbe = TagInt(CabProbeCb, 2); + s.CabProbeInterval = (int)(CabProbeIntervalNud.Value ?? 4); + s.CabProbeBounce = CabProbeBounceSlider.Value; + s.CabProbeReflections = IsChecked(CabProbeReflectionsCb); + // Not on screen: kept as read, for the dependencies. + var read = AppServices.Current.Settings; + s.CabLampLight = read.CabLampLight; + s.DepthPrepassScene = read.DepthPrepassScene; s.EnvMap = IsChecked(ReflectionsCubeMapCb); s.Ssr = TagInt(SsrCb, 2); @@ -263,6 +277,11 @@ public partial class Settings RayTracingRangeRow.IsEnabled = vulkan && s.RayTracing; DynamicLightsRow.IsEnabled = GraphicsRules.DynamicLightsUsed(s); AoQualityRow.IsEnabled = s.AmbientOcclusion > 0; + AoLightingRow.IsEnabled = GraphicsRules.AoLightingUsed(s); + bool probe = GraphicsRules.CabProbeUsed(s); + CabProbeIntervalRow.IsEnabled = probe; + CabProbeReflectionsRow.IsEnabled = probe; + CabProbeBounceRow.IsEnabled = GraphicsRules.CabProbeLights(s); FogQualityRow.IsEnabled = s.VolumetricFog; CloudShadowsRow.IsEnabled = s.Clouds > 0; GrassDistanceRow.IsEnabled = s.Grass; @@ -280,6 +299,8 @@ public partial class Settings SetNote(AntiAliasingNote, AntiAliasingRemark(s, dlss)); SetNote(FrameGenerationNote, FrameGenerationRemark(s, dlss)); SetNote(ReflexNote, GraphicsRules.ReflexForced(s, DlssPlatform) ? App.Loc["ReflexForcedNote"] : ""); + SetNote(AoLightingNote, AoLightingRemark(s)); + SetNote(CabProbeNote, GraphicsRules.CabProbeUsed(s) && !GraphicsRules.CabProbeLights(s) ? App.Loc["CabProbeReflectionsOnlyNote"] : ""); SetNote(RayTracingNote, vulkan ? "" : App.Loc["VulkanOnlyNote"]); SetNote(SkipPipelineNote, GraphicsRules.TemporalWithoutPipeline(s) ? App.Loc["TemporalNeedsPipelineNote"] : ""); @@ -302,6 +323,15 @@ public partial class Settings return ""; } + private static string AoLightingRemark(SimulatorSettings s) + { + if (!GraphicsRules.AoLightingUsed(s) || !s.AoLighting) + return ""; + if (s.SkipPipeline) + return App.Loc["AoNeedsPipelineNote"]; + return GraphicsRules.AoLightingAddsDepthPrepass(s) ? App.Loc["AoLightingPrepassNote"] : ""; + } + private string FrameGenerationRemark(SimulatorSettings s, bool dlss) { if (!dlss) diff --git a/StarterNG/Views/Settings.axaml b/StarterNG/Views/Settings.axaml index 8689adb..a699bde 100644 --- a/StarterNG/Views/Settings.axaml +++ b/StarterNG/Views/Settings.axaml @@ -393,6 +393,12 @@ + + + + + + @@ -401,6 +407,26 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/StarterNG/startercfg/lang/en.xml b/StarterNG/startercfg/lang/en.xml index a015226..4cf17a6 100644 --- a/StarterNG/startercfg/lang/en.xml +++ b/StarterNG/startercfg/lang/en.xml @@ -718,6 +718,23 @@ Ambient occlusion Darkens corners and creases. GTAO is more accurate than the older SSAO. Occlusion quality + AO in the ambient light (not over the image) + GTAO only. The occlusion darkens the ambient light and reflections while the sun, headlights and lamps stay bright. Off: the AO multiplies the finished image – cheaper. + Needs the depth of the whole scene before its colour; without SSR and contact shadows that is an extra pass (CPU cost on OpenGL). + With the post-processing pipeline skipped the AO does not work. + Cab probe (bounced light and interior reflections) + A cubemap of the cab lit by its lamp (64 / 128 / 256 px per face, about 0.5 / 2 / 8 MB). Gives the light bounced off the cab instead of the fixed gfx.lights.cab.bounce, and the interior reflected in the windows and glossy parts. Off: the old behaviour, no cost. + Off + Low + Medium + High + Without the clustered lighting and the cab lamp as a light (gfx.lights.cab) the probe gives the reflections only. + Refresh every N frames + How often the probe is drawn anew (moving parts, desk lamps). More = cheaper. A change of the lamp or the cab refreshes it at once. + Bounced light strength + How much of the lamp light bounced off the cab lights it again. + The cab reflects itself + Windows and glossy parts show the cab interior instead of the sky where SSR finds nothing. Screen space reflections (SSR) Reflections of what is on screen on wet and smooth surfaces. Ray traced reflections diff --git a/StarterNG/startercfg/lang/pl.xml b/StarterNG/startercfg/lang/pl.xml index a7b7664..b5bafae 100644 --- a/StarterNG/startercfg/lang/pl.xml +++ b/StarterNG/startercfg/lang/pl.xml @@ -718,6 +718,23 @@ Okluzja otoczenia Przyciemnia zakamarki i styki powierzchni. GTAO jest dokładniejsze od starszego SSAO. Jakość okluzji + AO w świetle otoczenia (zamiast na obrazie) + Tylko z GTAO. Okluzja przyciemnia światło i odbicia otoczenia, a słońce, reflektory i lampy zostają jasne. Wyłączone: AO mnoży gotowy obraz – taniej. + Wymaga głębi całej sceny przed kolorem; bez SSR i cieni kontaktowych to dodatkowy przebieg (koszt CPU w OpenGL). + Przy pominiętym potoku postprocessingu AO nie działa. + Próbka kabiny (odbite światło i odbicia wnętrza) + Cubemapa kabiny oświetlonej jej lampą (64 / 128 / 256 px na ścianę, ok. 0,5 / 2 / 8 MB). Daje światło odbite od kabiny zamiast stałego gfx.lights.cab.bounce i odbicia wnętrza w szybach i błyszczących elementach. Wyłączona: stare zachowanie, bez kosztu. + Wyłączona + Niska + Średnia + Wysoka + Bez oświetlenia klastrowego i lampy kabiny jako światła (gfx.lights.cab) próbka daje tylko odbicia. + Odświeżanie co N klatek + Jak często próbka jest rysowana na nowo (ruchome elementy, lampki pulpitu). Więcej = taniej. Zmiana lampy lub kabiny odświeża ją od razu. + Siła odbitego światła + Ile światła lampy odbitego od kabiny oświetla ją ponownie. + Kabina odbija siebie + W szybach i błyszczących elementach widać wnętrze kabiny zamiast nieba tam, gdzie SSR nic nie znajduje. Odbicia w przestrzeni ekranu (SSR) Odbicia tego, co widać na ekranie, na mokrych i gładkich powierzchniach. Odbicia ray tracing