mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-17 02:49:19 +02:00
Steady the volumetric fog and add a switch for the old headlight beams
This commit is contained in:
@@ -75,6 +75,7 @@ void gl::glsl_common_setup()
|
||||
"#define MAX_CLOUD_LAYERS " + std::to_string(MAX_CLOUD_LAYERS) + "\n" +
|
||||
"#define FOG_HORIZON_SAMPLES " + std::to_string(FOG_HORIZON_SAMPLES) + "\n" +
|
||||
"#define WEATHER_GROUP_SIZE " + std::to_string(WEATHER_GROUP_SIZE) + "\n" +
|
||||
"#define FOG_VOLUME_BIAS " + std::to_string(FOG_VOLUME_BIAS) + "\n" +
|
||||
R"STRING(
|
||||
const uint LIGHT_SPOT = 0U;
|
||||
const uint LIGHT_POINT = 1U;
|
||||
|
||||
3
gl/ubo.h
3
gl/ubo.h
@@ -410,6 +410,9 @@ namespace gl
|
||||
const size_t FOG_HORIZON_SAMPLES = 32;
|
||||
// work groups of the weather passes: 8x8 for the images, 8x8x1 for the fog volume
|
||||
const GLuint WEATHER_GROUP_SIZE = 8;
|
||||
// the slices of the fog volume are spaced exponentially in the view depth plus this many metres: fewer of them go to the first
|
||||
// metres in front of the camera, more to the distance, where thick slices draw the shafts of light in steps
|
||||
const float FOG_VOLUME_BIAS = 10.0f;
|
||||
|
||||
// layout std140: one layer of clouds (GLSL: cloud_layer_s), see weather_common.glsl
|
||||
struct cloud_layer_ubs
|
||||
|
||||
@@ -823,6 +823,7 @@ void opengl46_renderer::draw_debug_ui()
|
||||
{
|
||||
ImGui::Checkbox("clustered lights (off: the first dynamiclights headlights)", &Global.gfx_lights_clustered);
|
||||
ImGui::Checkbox("heatmap", &Global.gfx_lights_clusterheatmap);
|
||||
ImGui::Checkbox("beams of vehicle headlights (gfx.lights.headlights)", &Global.gfx_lights_headlights);
|
||||
if (auto const &clusters{m_viewports.front()->clusters})
|
||||
{
|
||||
auto const ¶ms{clusters->params()};
|
||||
@@ -6405,8 +6406,8 @@ void opengl46_renderer::Update_Lights(light_array &Lights, bool const Headlights
|
||||
|
||||
for (auto const &scenelight : Lights.data)
|
||||
{
|
||||
if (!Headlights || scenelight.intensity == 0.f) {
|
||||
// all lights past this one are bound to be off
|
||||
if (!Headlights || !Global.gfx_lights_headlights || scenelight.intensity == 0.f) {
|
||||
// all lights past this one are bound to be off (or the beams of the headlights are turned off altogether)
|
||||
break;
|
||||
}
|
||||
auto const lightoffset = glm::vec3{scenelight.position - camera};
|
||||
@@ -6734,7 +6735,7 @@ void opengl46_renderer::Render_headlight_shadows()
|
||||
// the headlights which shine, the most important first (in the order of Update_Lights()), whose beam may be seen within the
|
||||
// reach of the shadows
|
||||
m_headlightshadowpicked.clear();
|
||||
auto const count{(std::clamp(Global.gfx_lights_shadows, 0, 3) > 0) ? std::clamp(Global.gfx_lights_shadows_headlights, 0, static_cast<int>(gl::MAX_HEADLIGHT_SHADOWS)) : 0};
|
||||
auto const count{(Global.gfx_lights_headlights && (std::clamp(Global.gfx_lights_shadows, 0, 3) > 0)) ? std::clamp(Global.gfx_lights_shadows_headlights, 0, static_cast<int>(gl::MAX_HEADLIGHT_SHADOWS)) : 0};
|
||||
if (count > 0)
|
||||
{
|
||||
m_headlightshadowcandidates.clear();
|
||||
|
||||
@@ -519,15 +519,21 @@ void opengl46_weather::render_view(glm::mat4 const &Projection, glm::mat4 const
|
||||
{
|
||||
m_fog_timer.begin();
|
||||
auto const farthest{std::max(Global.gfx_fog_range, FOG_VOLUME_NEAR * 4.f)};
|
||||
// the cells are sampled at another depth in every frame, in the Halton sequence of 2
|
||||
auto const jitter{[](int Frame) {
|
||||
float value{0.f}, fraction{0.5f};
|
||||
for (Frame = (Frame % 64) + 1; Frame > 0; Frame /= 2, fraction *= 0.5f)
|
||||
value += fraction * static_cast<float>(Frame % 2);
|
||||
// the cells are sampled at another point in every frame: along the depth in the Halton sequence of 2, across the view in
|
||||
// those of 3 and 5 (fog_inject.comp moves the point of every cell by a value of its own)
|
||||
auto const halton = [](int Index, int const Base) {
|
||||
float value{0.f}, fraction{1.f};
|
||||
for (; Index > 0; Index /= Base)
|
||||
{
|
||||
fraction /= static_cast<float>(Base);
|
||||
value += fraction * static_cast<float>(Index % Base);
|
||||
}
|
||||
return value;
|
||||
}(m_frame)};
|
||||
};
|
||||
auto const temporal{Global.gfx_fog_temporal && continuity(m_previous_fog)};
|
||||
glm::vec4 const slicing{FOG_VOLUME_NEAR, farthest, static_cast<float>(m_fog_grid.z) / std::log(farthest / FOG_VOLUME_NEAR), temporal ? jitter : 0.5f};
|
||||
auto const sample{(m_frame % 64) + 1};
|
||||
glm::vec3 const jitter{temporal ? glm::vec3{halton(sample, 3), halton(sample, 5), halton(sample, 2)} : glm::vec3{0.5f}};
|
||||
glm::vec4 const slicing{FOG_VOLUME_NEAR, farthest, static_cast<float>(m_fog_grid.z) / std::log((farthest + gl::FOG_VOLUME_BIAS) / (FOG_VOLUME_NEAR + gl::FOG_VOLUME_BIAS)), jitter.z};
|
||||
bind_noise();
|
||||
auto const next{1 - m_fog_current};
|
||||
glBindImageTexture(0, m_fog_scattering[next], 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_RGBA16F);
|
||||
@@ -540,9 +546,11 @@ void opengl46_weather::render_view(glm::mat4 const &Projection, glm::mat4 const
|
||||
auto const previous{glm::vec3{m_previous_fog.camera - Camera}};
|
||||
glProgramUniform3f(*m_inject_program, 5, previous.x, previous.y, previous.z);
|
||||
auto const sunshadows{Global.gfx_fog_shadows && Global.gfx_shadowmap_enabled};
|
||||
glProgramUniform4f(*m_inject_program, 6, temporal ? 0.25f : 1.f, Global.gfx_fog_lights, sunshadows ? 1.f : 0.f, Global.gfx_fog_shadows ? 1.f : 0.f);
|
||||
auto const share{temporal ? std::clamp(Global.gfx_fog_temporal_share, 0.02f, 1.f) : 1.f};
|
||||
glProgramUniform4f(*m_inject_program, 6, share, Global.gfx_fog_lights, sunshadows ? 1.f : 0.f, Global.gfx_fog_shadows ? 1.f : 0.f);
|
||||
glProgramUniform1i(*m_inject_program, 7, Cablamp);
|
||||
glProgramUniform2f(*m_inject_program, 8, m_previous_fog.slicing.x, m_previous_fog.slicing.z);
|
||||
glProgramUniform2f(*m_inject_program, 9, jitter.x, jitter.y);
|
||||
m_inject_program->dispatch(groups(m_fog_grid.x), groups(m_fog_grid.y), static_cast<GLuint>(m_fog_grid.z));
|
||||
glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
|
||||
|
||||
@@ -674,6 +682,7 @@ void opengl46_weather::draw_debug_ui()
|
||||
ImGui::SliderFloat("lamps in the fog (gfx.fog.lights)", &Global.gfx_fog_lights, 0.f, 4.f);
|
||||
ImGui::Checkbox("shadows of the sun and headlights in the fog (gfx.fog.shadows)", &Global.gfx_fog_shadows);
|
||||
ImGui::Checkbox("fog blended over frames (gfx.fog.temporal)", &Global.gfx_fog_temporal);
|
||||
ImGui::SliderFloat("share of a new frame in the fog (gfx.fog.temporal.share)", &Global.gfx_fog_temporal_share, 0.02f, 1.f);
|
||||
char const *cloudlevels[]{"none", "low", "medium", "high", "ultra"};
|
||||
ImGui::Combo("clouds (gfx.clouds)", &Global.gfx_clouds, cloudlevels, IM_ARRAYSIZE(cloudlevels));
|
||||
ImGui::SliderFloat("cloud distance, m (gfx.clouds.distance)", &Global.gfx_clouds_distance, 5000.f, 200000.f, "%.0f", ImGuiSliderFlags_Logarithmic);
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
// depth), how dense the fog is and how much light it scatters towards the camera. the density: the haze, the patches of the
|
||||
// ground fog, the low clouds; the light: the colour the fog has towards the horizon (weather_common.glsl), less what the
|
||||
// shadows of the sun and of the clouds hold back, and the lamps and headlights of the light clusters. blended with the
|
||||
// previous frame, found where the cell was then; the cells are sampled at another depth every frame.
|
||||
// previous frame, found where the cell was then; the cells are sampled at another point every frame, each cell going through
|
||||
// the points from a place of its own, so the volume doesn't flicker as a whole and the blending smooths the edges of the cells.
|
||||
// rgb: light scattered towards the camera per metre, a: extinction per metre
|
||||
|
||||
#include <common>
|
||||
@@ -22,7 +23,8 @@ layout(binding = HEADLIGHT_SHADOW_TEX) uniform sampler2DArrayShadow headlight_sh
|
||||
layout(location = 0) uniform ivec3 grid;
|
||||
layout(location = 1) uniform mat4 inverse_projection;
|
||||
layout(location = 2) uniform mat4 view_to_world;
|
||||
// x: near, y: far, z: slices / log(far / near), w: where in its slice the cell is sampled this frame (0-1)
|
||||
// x: near, y: far, z: slices / log((far + FOG_VOLUME_BIAS) / (near + FOG_VOLUME_BIAS)), w: where in its slice the cell is
|
||||
// sampled this frame (0-1)
|
||||
layout(location = 3) uniform vec4 slicing;
|
||||
// world axes to the clip space of the previous frame, the camera of the previous frame at the origin
|
||||
layout(location = 4) uniform mat4 previous_projection_view;
|
||||
@@ -32,8 +34,41 @@ layout(location = 5) uniform vec3 previous_camera;
|
||||
layout(location = 6) uniform vec4 options;
|
||||
// the light of the cab lamp, which lights no fog (the air of the cab is clear), or -1
|
||||
layout(location = 7) uniform int cablamp;
|
||||
// x: near, y: slices / log(far / near) of the previous frame
|
||||
// x: near, y: slices / log((far + FOG_VOLUME_BIAS) / (near + FOG_VOLUME_BIAS)) of the previous frame
|
||||
layout(location = 8) uniform vec2 previous_slicing;
|
||||
// where in its cell the cell is sampled this frame across the view (0-1), as slicing.w is along the depth
|
||||
layout(location = 9) uniform vec2 jitter;
|
||||
|
||||
// ray of the view space through a point of the view (0-1), one metre of the depth long
|
||||
vec3 view_ray(vec2 coords)
|
||||
{
|
||||
vec4 near = inverse_projection * vec4(coords * 2.0 - 1.0, 1.0, 1.0);
|
||||
vec3 ray = near.xyz / near.w;
|
||||
return ray / -ray.z;
|
||||
}
|
||||
|
||||
// view depth at a place along the slices: slice number and the part of the slice
|
||||
float slice_depth(float slice)
|
||||
{
|
||||
return (slicing.x + FOG_VOLUME_BIAS) * exp(slice / slicing.z) - FOG_VOLUME_BIAS;
|
||||
}
|
||||
|
||||
// where in the cell it is sampled this frame, 0-1 on each axis: the point of the sequence of the frames moved by a value of
|
||||
// the cell's own (pcg3d hash), the middle without the blending
|
||||
vec3 cell_offset(ivec3 cell)
|
||||
{
|
||||
if (options.x >= 1.0)
|
||||
return vec3(0.5);
|
||||
uvec3 v = uvec3(cell) * 1664525U + 1013904223U;
|
||||
v.x += v.y * v.z;
|
||||
v.y += v.z * v.x;
|
||||
v.z += v.x * v.y;
|
||||
v ^= v >> 16U;
|
||||
v.x += v.y * v.z;
|
||||
v.y += v.z * v.x;
|
||||
v.z += v.x * v.y;
|
||||
return fract(vec3(jitter, slicing.w) + vec3(v >> 8U) * (1.0 / 16777216.0));
|
||||
}
|
||||
|
||||
float henyey_greenstein(float cosangle, float g)
|
||||
{
|
||||
@@ -108,12 +143,10 @@ void main()
|
||||
ivec3 cell = ivec3(gl_GlobalInvocationID);
|
||||
if (any(greaterThanEqual(cell, grid)))
|
||||
return;
|
||||
vec2 coords = (vec2(cell.xy) + 0.5) / vec2(grid.xy);
|
||||
vec4 near = inverse_projection * vec4(coords * 2.0 - 1.0, 1.0, 1.0);
|
||||
vec3 ray = near.xyz / near.w;
|
||||
ray /= -ray.z;
|
||||
float depth = slicing.x * exp((float(cell.z) + slicing.w) / slicing.z);
|
||||
vec3 view = ray * depth;
|
||||
vec3 offset = cell_offset(cell);
|
||||
vec2 coords = (vec2(cell.xy) + offset.xy) / vec2(grid.xy);
|
||||
float depth = slice_depth(float(cell.z) + offset.z);
|
||||
vec3 view = view_ray(coords) * depth;
|
||||
vec3 world = mat3(view_to_world) * view;
|
||||
float height = weather_camera.x + world.y;
|
||||
|
||||
@@ -161,14 +194,17 @@ void main()
|
||||
result = vec4(light * fog_haze.w * extinction, extinction);
|
||||
}
|
||||
|
||||
// the previous frame, where the cell was then
|
||||
// the previous frame, where the middle of the cell was then: the cells of the history hold what the cells were on the whole,
|
||||
// not at the point they were sampled at
|
||||
float share = options.x;
|
||||
if (share < 1.0)
|
||||
{
|
||||
vec4 clip = previous_projection_view * vec4(world - previous_camera, 1.0);
|
||||
vec3 centre = mat3(view_to_world) * (view_ray((vec2(cell.xy) + 0.5) / vec2(grid.xy)) * slice_depth(float(cell.z) + 0.5));
|
||||
vec4 clip = previous_projection_view * vec4(centre - previous_camera, 1.0);
|
||||
if (clip.w > 0.0)
|
||||
{
|
||||
vec3 previous = vec3(clip.xy / clip.w * 0.5 + 0.5, log(max(clip.w / previous_slicing.x, 1e-6)) * previous_slicing.y / float(grid.z));
|
||||
float previousslice = log(max((clip.w + FOG_VOLUME_BIAS) / (previous_slicing.x + FOG_VOLUME_BIAS), 1e-6)) * previous_slicing.y;
|
||||
vec3 previous = vec3(clip.xy / clip.w * 0.5 + 0.5, previousslice / float(grid.z));
|
||||
if (all(greaterThanEqual(previous, vec3(0.0))) && all(lessThanEqual(previous, vec3(1.0))))
|
||||
result = mix(textureLod(fog_history, previous, 0.0), result, share);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ layout(rgba16f, binding = 0) uniform writeonly image3D fog_integrated;
|
||||
|
||||
layout(location = 0) uniform ivec3 grid;
|
||||
layout(location = 1) uniform mat4 inverse_projection;
|
||||
// x: near, y: far, z: slices / log(far / near)
|
||||
// x: near, y: far, z: slices / log((far + FOG_VOLUME_BIAS) / (near + FOG_VOLUME_BIAS))
|
||||
layout(location = 3) uniform vec4 slicing;
|
||||
|
||||
void main()
|
||||
@@ -31,7 +31,7 @@ void main()
|
||||
float front = slicing.x;
|
||||
for (int slice = 0; slice < grid.z; slice++)
|
||||
{
|
||||
float back = slicing.x * exp(float(slice + 1) / slicing.z);
|
||||
float back = (slicing.x + FOG_VOLUME_BIAS) * exp(float(slice + 1) / slicing.z) - FOG_VOLUME_BIAS;
|
||||
float span = (back - front) * stretch;
|
||||
front = back;
|
||||
vec4 cell = texelFetch(fog_scattering, ivec3(column, slice), 0);
|
||||
|
||||
@@ -8,6 +8,29 @@
|
||||
|
||||
layout(binding = FOG_VOLUME_TEX) uniform sampler3D fog_volume;
|
||||
|
||||
// the volume at a point of the view (0-1) and a coordinate along the slices, filtered across the view with a cubic B-spline
|
||||
// (four fetches of the linear filter): a cell is several pixels wide, and the linear filter alone draws the shafts of light and
|
||||
// the edges of shadows in the fog as steps
|
||||
vec4 fog_volume_at(vec2 coords, float slice)
|
||||
{
|
||||
vec2 size = vec2(textureSize(fog_volume, 0).xy);
|
||||
vec2 texel = coords * size - 0.5;
|
||||
vec2 base = floor(texel);
|
||||
vec2 f = texel - base;
|
||||
vec2 f2 = f * f;
|
||||
vec2 f3 = f2 * f;
|
||||
vec2 w0 = (1.0 - 3.0 * f + 3.0 * f2 - f3) / 6.0;
|
||||
vec2 w1 = (4.0 - 6.0 * f2 + 3.0 * f3) / 6.0;
|
||||
vec2 w2 = (1.0 + 3.0 * f + 3.0 * f2 - 3.0 * f3) / 6.0;
|
||||
vec2 w3 = f3 / 6.0;
|
||||
vec2 g0 = w0 + w1;
|
||||
vec2 g1 = w2 + w3;
|
||||
vec2 h0 = (base - 0.5 + w1 / g0) / size;
|
||||
vec2 h1 = (base + 1.5 + w3 / g1) / size;
|
||||
return g0.y * (g0.x * textureLod(fog_volume, vec3(h0.x, h0.y, slice), 0.0) + g1.x * textureLod(fog_volume, vec3(h1.x, h0.y, slice), 0.0))
|
||||
+ g1.y * (g0.x * textureLod(fog_volume, vec3(h0.x, h1.y, slice), 0.0) + g1.x * textureLod(fog_volume, vec3(h1.x, h1.y, slice), 0.0));
|
||||
}
|
||||
|
||||
// rgb: light the fog adds, a: what it lets through
|
||||
vec4 fog_along_view(vec3 view, vec2 fragcoord)
|
||||
{
|
||||
@@ -17,16 +40,16 @@ vec4 fog_along_view(vec3 view, vec2 fragcoord)
|
||||
vec3 direction = mat3(inv_view) * (view / span_distance);
|
||||
if (fog_volume_params.x < 0.5)
|
||||
return fog_analytic(direction, 0.0, span_distance, false);
|
||||
// slices are spaced exponentially in the view depth; slice k holds the fog up to its far side
|
||||
// slices are spaced exponentially in the view depth plus FOG_VOLUME_BIAS; slice k holds the fog up to its far side
|
||||
float depth = max(-view.z, 1e-4);
|
||||
float slices = fog_volume_params.w;
|
||||
float slice = log(max(depth / fog_volume_params.y, 1e-6)) * fog_volume_params.z;
|
||||
float slice = log(max((depth + FOG_VOLUME_BIAS) / (fog_volume_params.y + FOG_VOLUME_BIAS), 1e-6)) * fog_volume_params.z;
|
||||
vec2 coords = fragcoord * fog_volume_target.xy;
|
||||
if (slice < 1.0)
|
||||
return mix(vec4(0.0, 0.0, 0.0, 1.0), textureLod(fog_volume, vec3(coords, 0.5 / slices), 0.0), max(slice, 0.0));
|
||||
return mix(vec4(0.0, 0.0, 0.0, 1.0), fog_volume_at(coords, 0.5 / slices), max(slice, 0.0));
|
||||
if (slice < slices)
|
||||
return textureLod(fog_volume, vec3(coords, (slice - 0.5) / slices), 0.0);
|
||||
vec4 volume = textureLod(fog_volume, vec3(coords, (slices - 0.5) / slices), 0.0);
|
||||
return fog_volume_at(coords, (slice - 0.5) / slices);
|
||||
vec4 volume = fog_volume_at(coords, (slices - 0.5) / slices);
|
||||
vec4 rest = fog_analytic(direction, fog_volume_target.z * span_distance / depth, span_distance, false);
|
||||
return vec4(volume.rgb + volume.a * rest.rgb, volume.a * rest.a);
|
||||
}
|
||||
@@ -40,7 +63,7 @@ vec4 fog_sky(vec3 viewdirection, vec2 fragcoord)
|
||||
if (fog_volume_params.x < 0.5 || view.z > -1e-3)
|
||||
return fog_analytic(direction, 0.0, 200000.0, true);
|
||||
float slices = fog_volume_params.w;
|
||||
vec4 volume = textureLod(fog_volume, vec3(fragcoord * fog_volume_target.xy, (slices - 0.5) / slices), 0.0);
|
||||
vec4 volume = fog_volume_at(fragcoord * fog_volume_target.xy, (slices - 0.5) / slices);
|
||||
vec4 rest = fog_analytic(direction, fog_volume_target.z / -view.z, 200000.0, true);
|
||||
return vec4(volume.rgb + volume.a * rest.rgb, volume.a * rest.a);
|
||||
}
|
||||
|
||||
@@ -1613,6 +1613,7 @@ global_settings::ConfigParse_gfx_sky( cParser &Parser, std::string_view const To
|
||||
gfx_postfx_ao_steps = std::clamp( gfx_postfx_ao_steps, 1, 16 ); }
|
||||
else if( Token == "gfx.lights.scenery" ) { readswitch( gfx_lights_scenery ); }
|
||||
else if( Token == "gfx.lights.vehicles" ) { readswitch( gfx_lights_vehicles ); }
|
||||
else if( Token == "gfx.lights.headlights" ) { readswitch( gfx_lights_headlights ); }
|
||||
else if( Token == "gfx.lights.cab" ) { readswitch( gfx_lights_cab ); }
|
||||
else if( Token == "gfx.lights.freespot.intensity" ) { readvalue( gfx_lights_freespot_intensity, 0.f, 1000.f ); }
|
||||
else if( Token == "gfx.lights.compartment.intensity" ) { readvalue( gfx_lights_compartment_intensity, 0.f, 100.f ); }
|
||||
@@ -1659,6 +1660,7 @@ global_settings::ConfigParse_gfx_sky( cParser &Parser, std::string_view const To
|
||||
else if( Token == "gfx.fog.lights" ) { readvalue( gfx_fog_lights, 0.f, 10.f ); }
|
||||
else if( Token == "gfx.fog.shadows" ) { readswitch( gfx_fog_shadows ); }
|
||||
else if( Token == "gfx.fog.temporal" ) { readswitch( gfx_fog_temporal ); }
|
||||
else if( Token == "gfx.fog.temporal.share" ) { readvalue( gfx_fog_temporal_share, 0.02f, 1.f ); }
|
||||
else if( Token == "gfx.clouds" ) {
|
||||
// no, or the quality: low, medium (yes), high, ultra
|
||||
Parser.getTokens( 1 );
|
||||
@@ -1950,6 +1952,7 @@ global_settings::export_as_text( std::ostream &Output ) const {
|
||||
Output << "gfx.postfx.ao.quality " << gfx_postfx_ao_slices << " " << gfx_postfx_ao_steps << "\n";
|
||||
export_as_text( Output, "gfx.lights.scenery", gfx_lights_scenery );
|
||||
export_as_text( Output, "gfx.lights.vehicles", gfx_lights_vehicles );
|
||||
export_as_text( Output, "gfx.lights.headlights", gfx_lights_headlights );
|
||||
export_as_text( Output, "gfx.lights.cab", gfx_lights_cab );
|
||||
export_as_text( Output, "gfx.lights.freespot.intensity", gfx_lights_freespot_intensity );
|
||||
export_as_text( Output, "gfx.lights.compartment.intensity", gfx_lights_compartment_intensity );
|
||||
@@ -1969,6 +1972,7 @@ global_settings::export_as_text( std::ostream &Output ) const {
|
||||
export_as_text( Output, "gfx.fog.lights", gfx_fog_lights );
|
||||
export_as_text( Output, "gfx.fog.shadows", gfx_fog_shadows );
|
||||
export_as_text( Output, "gfx.fog.temporal", gfx_fog_temporal );
|
||||
export_as_text( Output, "gfx.fog.temporal.share", gfx_fog_temporal_share );
|
||||
export_as_text( Output, "gfx.clouds", std::string{ gfx_clouds == 1 ? "low" : gfx_clouds == 2 ? "medium" : gfx_clouds == 3 ? "high" : gfx_clouds == 4 ? "ultra" : "no" } );
|
||||
export_as_text( Output, "gfx.clouds.distance", gfx_clouds_distance );
|
||||
export_as_text( Output, "gfx.clouds.shadows", gfx_clouds_shadows );
|
||||
|
||||
@@ -341,6 +341,9 @@ struct global_settings {
|
||||
// they go through the light clusters, so they need gfx_lights_clustered
|
||||
bool gfx_lights_scenery { true }; // light points (freespot lights) of scenery models light their surroundings
|
||||
bool gfx_lights_vehicles { true }; // light points of vehicles and their lit compartments light their surroundings
|
||||
// the old lighting ahead of vehicles: the beam of their headlights (light_array, the projected texture of the beam), with its
|
||||
// shadows and its light in the fog. off: the vehicles light what is ahead of them only with the light points of their lamps
|
||||
bool gfx_lights_headlights { true };
|
||||
bool gfx_lights_cab { true }; // the lamp of the occupied cab is a point light instead of an addition to the ambient light
|
||||
float gfx_lights_freespot_intensity { 10.f }; // brightness of a light point of a model
|
||||
float gfx_lights_compartment_intensity { 1.f }; // brightness of the light of a lit vehicle compartment
|
||||
@@ -366,13 +369,15 @@ struct global_settings {
|
||||
// environment/weather.h. fog: 1 volumetric (a volume over the view with the shafts of the sun, the shadows of the clouds and
|
||||
// the light of lamps and headlights, worked out along the ray past it), 0 analytic (the same fog along the ray only, the way
|
||||
// the old one was drawn); the quality of the volume 1-4 (low, medium, high, ultra), its depth (metres), the brightness of the
|
||||
// lamps in it (0: none), whether the sun and the headlights cast their shadows into it, blending over frames
|
||||
// lamps in it (0: none), whether the sun and the headlights cast their shadows into it, blending over frames and the share of
|
||||
// a new frame in the blend (lower: smoother, but the light of moving lamps lags more behind them)
|
||||
int gfx_fog { 1 };
|
||||
int gfx_fog_quality { 2 };
|
||||
float gfx_fog_range { 1500.f };
|
||||
float gfx_fog_lights { 1.f };
|
||||
bool gfx_fog_shadows { true };
|
||||
bool gfx_fog_temporal { true };
|
||||
float gfx_fog_temporal_share { 0.1f };
|
||||
// volumetric clouds, 0 none, 1-4 the quality (low, medium, high, ultra); the farthest they are drawn (metres); the shadows
|
||||
// they cast (a map around the camera: its size in texels and in metres)
|
||||
int gfx_clouds { 2 };
|
||||
|
||||
Reference in New Issue
Block a user