Skip to content

Commit 20c8417

Browse files
BMagnuGoober5000
andauthored
Fullneb Revamp (scp-fs2open#7352)
* change to new fog system * Fix fog conversion issues * remove unused old neb values * Update scripting API * temporary old-value round trip * Rewrite nebula fog with four explicit parameters Replace the legacy `+Fog Near Mult` / `+Fog Far Mult` model — which depended on fixed engine constants — with four parameters that map directly to renderer behavior: +Fog 1000m Visibility fraction of light surviving 1000m of fog +Fog Near Distance meters from camera where fog begins +Fog Skybox Clip Distance max render distance for the skybox in fog +Fog Clip Distance max render distance for the scene in fog The deferred-lighting fog shader, material system, model renderer, object sort, and the Lua mission API all consume the new parameters directly. The legacy `Neb2_fog_near_mult` / `Neb2_fog_far_mult` globals are removed. Mission parsing accepts either the legacy keys or the modern keys. Legacy values are converted to the modern set at parse time, and a per-mission flag (`Neb2_fog_use_legacy_values`) records which keys to write back on save. The flag is cleared only when something actually changes, so opening and OK'ing an unmodified legacy mission preserves its on-disk format. Saving uses `optional_string_fred` to preserve user comments through edit cycles. FRED2 and QtFRED background editors both expose the four parameters in place of the old multipliers, with friendly labels and tooltips. Both editors validate input (visibility clamped to [0, 1]; near distance must be > 0; skybox and scene clip distances may be 0 to disable fog at that range) and use a snapshot-and-compare at close time so that a no-op open-then-OK never spuriously rewrites a legacy mission in the modern format. FRED2's background dialog is also reorganized so that "Display bg bitmaps in nebula", "Override nebula fog palette", the RGB row, and the four fog parameters all sit inside the Nebula group box; the "Old Nebula" group box is restored below it with its Pattern, Color, Pitch, Bank, and Heading controls back inside the frame. The dialog now overrides PreTranslateMessage so that the new fog tooltips — and the previously broken "Save sun/bitmap angles in correct format" tooltip — actually fire. QtFRED's BackgroundEditor.ui adds four QDoubleSpinBox controls in the existing nebula form layout, with per-field decimals chosen to avoid scientific notation, and per-field min/max declaring the validation rules. The QtFRED help page is updated to describe the new fields. * fix tooltips * restore forward-renderer fog * Clang Tidy * address feedback * Refine nebula fog rewrite - Rename Neb2_fog_use_legacy_values to Neb2_fog_save_legacy_values to reflect that the flag governs save format, not runtime behavior. - Decide both the save flag and the legacy-to-modern conversion purely from whether the file contains modern fog keys, dropping the prior heuristic based on required_fso_version. A mission without modern keys (legacy- or retail-format) converts on load and saves back in legacy format; missions with modern keys are saved as modern. - Snapshot the four fog values as floats at editor open and use fl_equal for the no-change comparison in both FRED2 and QtFRED, replacing the FRED2 CString comparison and the QtFRED strict inequality. - Document the on-disk invariant in missionsave: when not saving legacy keys, the four modern keys must always be written (never gated on "only if non-default"), since the parser uses their presence to decide whether to run the conversion on next load. --------- Co-authored-by: Goober5000 <ipw47@mailbox.org>
1 parent 74dad95 commit 20c8417

26 files changed

Lines changed: 505 additions & 245 deletions

code/def_files/data/effects/fog-f.sdr

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ layout (std140) uniform genericData {
1515
float fog_density;
1616
float zNear;
1717
float zFar;
18+
19+
float clip_inf_dist;
20+
float clip_dist;
1821
};
1922

2023
void main()
@@ -28,6 +31,9 @@ void main()
2831
// Now we compute the depth value in projection space using the clipping plane information
2932
float view_depth = 2.0 * zNear * zFar / (zFar + zNear - depth_normalized * (zFar - zNear));
3033

34+
float skybox_compat_fake = step(1.0, depth_val);
35+
view_depth = clamp(view_depth, 0.0, mix(clip_dist, clip_inf_dist, skybox_compat_fake));
36+
3137
if (isinf(view_depth)) {
3238
fragOut0.rgb = color_in.rgb;
3339
} else {

code/def_files/data/effects/main-f.sdr

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ layout (std140) uniform modelData {
3939
model_light lights[MAX_LIGHTS];
4040

4141
float outlineWidth;
42-
float fogStart;
43-
float fogScale;
42+
float fogNear;
43+
float fogDensity;
4444
int buffer_matrix_offset;
4545

4646
vec4 clip_equation;
@@ -376,9 +376,10 @@ void main()
376376
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_DIFFUSE
377377
// This code will only be used by the forward renderer so we apply the fog effect to both the emissive and the base
378378
// color.
379-
baseColor.rgb = mix(emissiveColor.rgb + baseColor.rgb, finalFogColor, vertIn.fogDist);
379+
float fogDensityFinal = clamp(1 - pow(fogDensity, vertIn.fogDist) , 0.0, 1.0);
380+
baseColor.rgb = mix(emissiveColor.rgb + baseColor.rgb, finalFogColor, fogDensityFinal);
380381
emissiveColor.rgb = vec3(0.0); // Zero the emissive color since it has already been added by the previous line
381-
specColor.rgb *= vertIn.fogDist;
382+
specColor.rgb *= fogDensityFinal;
382383
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_FOG
383384

384385
#prereplace IF_FLAG MODEL_SDR_FLAG_DIFFUSE

code/def_files/data/effects/main-g.sdr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ layout (std140) uniform modelData {
4545
model_light lights[MAX_LIGHTS];
4646

4747
float outlineWidth;
48-
float fogStart;
49-
float fogScale;
48+
float fogNear;
49+
float fogDensity;
5050
int buffer_matrix_offset;
5151

5252
vec4 clip_equation;

code/def_files/data/effects/main-v.sdr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ layout (std140) uniform modelData {
4040
model_light lights[MAX_LIGHTS];
4141

4242
float outlineWidth;
43-
float fogStart;
44-
float fogScale;
43+
float fogNear;
44+
float fogDensity;
4545
int buffer_matrix_offset;
4646

4747
vec4 clip_equation;
@@ -189,7 +189,7 @@ void main()
189189
vertOut.tangentMatrix = mat3(t, b, normal);
190190

191191
#prereplace IF_FLAG MODEL_SDR_FLAG_FOG
192-
vertOut.fogDist = clamp((gl_Position.z - fogStart) * 0.75 * fogScale, 0.0, 1.0);
192+
vertOut.fogDist = gl_Position.z - fogNear;
193193
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_FOG
194194

195195
#prereplace IF_FLAG MODEL_SDR_FLAG_TRANSFORM

code/graphics/material.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -674,14 +674,12 @@ bool model_material::is_batched() const
674674
return Batched;
675675
}
676676

677-
void model_material::set_fog(int r, int g, int b, float _near, float _far)
677+
void model_material::set_fog(int r, int g, int b)
678678
{
679679
Fog_params.enabled = true;
680680
Fog_params.r = r;
681681
Fog_params.g = g;
682682
Fog_params.b = b;
683-
Fog_params.dist_near = _near;
684-
Fog_params.dist_far = _far;
685683
}
686684

687685
void model_material::set_fog()

code/graphics/material.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,6 @@ class model_material : public material
172172
int r = 0;
173173
int g = 0;
174174
int b = 0;
175-
float dist_near = -1.0f;
176-
float dist_far = -1.0f;
177175
};
178176

179177
private:
@@ -255,7 +253,7 @@ class model_material : public material
255253
int get_shader_runtime_early_flags() const;
256254
int get_shader_runtime_flags() const;
257255

258-
void set_fog(int r, int g, int b, float near, float far);
256+
void set_fog(int r, int g, int b);
259257
void set_fog();
260258
bool is_fogged() const;
261259
const fog& get_fog() const;

code/graphics/opengl/gropengldeferred.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -542,8 +542,8 @@ void gr_opengl_deferred_lighting_finish()
542542
GL_state.Texture.Enable(0, GL_TEXTURE_2D, Scene_composite_texture);
543543
GL_state.Texture.Enable(1, GL_TEXTURE_2D, Scene_depth_texture);
544544

545-
float fog_near, fog_far, fog_density;
546-
neb2_get_adjusted_fog_values(&fog_near, &fog_far, &fog_density);
545+
float fog_near, fog_density;
546+
neb2_get_adjusted_fog_values(&fog_near, &fog_density);
547547
unsigned char r, g, b;
548548
neb2_get_fog_color(&r, &g, &b);
549549

@@ -558,6 +558,8 @@ void gr_opengl_deferred_lighting_finish()
558558
data->fog_color.xyz.z = b / 255.f;
559559
data->zNear = Min_draw_distance;
560560
data->zFar = Max_draw_distance;
561+
data->clip_inf_dist = Neb2_fog_skybox_clip_distance;
562+
data->clip_dist = Neb2_fog_clip_distance;
561563
});
562564

563565
opengl_draw_full_screen_textured(0.0f, 0.0f, 1.0f, 1.0f);

code/graphics/uniforms.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "light.h"
77
#include "globalincs/systemvars.h"
88
#include "shadows.h"
9+
#include "nebula/neb.h"
910

1011
#define MODEL_SDR_FLAG_MODE_CPP
1112
#include "def_files/data/effects/model_shader_flags.h"
@@ -218,8 +219,11 @@ void convert_model_material(model_uniform_data* data_out,
218219
auto& fog_params = material.get_fog();
219220

220221
if (fog_params.enabled) {
221-
data_out->fogStart = fog_params.dist_near;
222-
data_out->fogScale = 1.0f / (fog_params.dist_far - fog_params.dist_near);
222+
float fog_near, fog_density;
223+
neb2_get_adjusted_fog_values(&fog_near, &fog_density);
224+
data_out->fogNear = fog_near;
225+
data_out->fogDensity = fog_density;
226+
223227
data_out->fogColor.xyzw.x = i2fl(fog_params.r) / 255.0f;
224228
data_out->fogColor.xyzw.y = i2fl(fog_params.g) / 255.0f;
225229
data_out->fogColor.xyzw.z = i2fl(fog_params.b) / 255.0f;

code/graphics/util/uniform_structs.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ struct model_uniform_data {
8787
model_light lights[MAX_UNIFORM_LIGHTS];
8888

8989
float outlineWidth;
90-
float fogStart;
91-
float fogScale;
90+
float fogNear;
91+
float fogDensity;
9292
int buffer_matrix_offset;
9393

9494
vec4 clip_equation;
@@ -288,8 +288,10 @@ struct fog_data {
288288
float fog_density;
289289
float zNear;
290290
float zFar;
291+
float clip_inf_dist;
292+
float clip_dist;
291293

292-
float pad[1];
294+
float pad[3];
293295
};
294296

295297
struct volumetric_fog_data {

code/mission/missionparse.cpp

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -857,11 +857,45 @@ void parse_mission_info(mission *pm, bool basic = false)
857857
if (!basic)
858858
nebl_set_storm(Mission_parse_storm_name);
859859
}
860-
if(optional_string("+Fog Near Mult:")){
861-
stuff_float(&Neb2_fog_near_mult);
860+
861+
bool found_neb2_modern = false;
862+
863+
if (optional_string("+Fog Near Mult:")) {
864+
stuff_float(&Neb2_fog_legacy_near_mult);
865+
}
866+
if (optional_string("+Fog Far Mult:")) {
867+
stuff_float(&Neb2_fog_legacy_far_mult);
868+
}
869+
870+
// Look for the modern values
871+
if (optional_string("+Fog 1000m Visibility:")) {
872+
stuff_float(&Neb2_fog_1000m_visibility);
873+
found_neb2_modern = true;
874+
}
875+
if (optional_string("+Fog Near Distance:")) {
876+
stuff_float(&Neb2_fog_near_distance);
877+
found_neb2_modern = true;
862878
}
863-
if(optional_string("+Fog Far Mult:")){
864-
stuff_float(&Neb2_fog_far_mult);
879+
if (optional_string("+Fog Skybox Clip Distance:")) {
880+
stuff_float(&Neb2_fog_skybox_clip_distance);
881+
found_neb2_modern = true;
882+
}
883+
if (optional_string("+Fog Clip Distance:")) {
884+
stuff_float(&Neb2_fog_clip_distance);
885+
found_neb2_modern = true;
886+
}
887+
888+
// write legacy values on save if we are compatible with older formats
889+
Neb2_fog_save_legacy_values = !found_neb2_modern;
890+
891+
// Convert legacy values if this mission was made before modern values were introduced
892+
if (!found_neb2_modern) {
893+
//This stems from the weird unchangeable constants of legacy fog
894+
float denom = std::max(75.f * Neb2_fog_legacy_far_mult - Neb2_fog_legacy_near_mult, 1.0f);
895+
Neb2_fog_1000m_visibility = powf(10.f, -100.f / denom);
896+
Neb2_fog_near_distance = 10.f * Neb2_fog_legacy_near_mult;
897+
Neb2_fog_skybox_clip_distance = 0.f; // Apparently, skybox fog was just outright broken...
898+
Neb2_fog_clip_distance = Default_max_draw_distance;
865899
}
866900

867901
// Goober5000 - ship contrail speed threshold
@@ -9614,6 +9648,9 @@ bool check_for_25_1_data()
96149648
if (count_items_with_value(Props) > 0)
96159649
return true;
96169650

9651+
if (The_mission.flags[Mission::Mission_Flags::Fullneb] && !Neb2_fog_save_legacy_values)
9652+
return true;
9653+
96179654
constexpr auto defaultLayer = "Default";
96189655

96199656
for (const auto& so : list_range(&Ship_obj_list))

0 commit comments

Comments
 (0)