diff --git a/Support/steam_versions.json b/Support/steam_versions.json
index 2b6ac85..ccfef35 100644
--- a/Support/steam_versions.json
+++ b/Support/steam_versions.json
@@ -14,5 +14,5 @@
"sn_start_with_seta": "1.1",
"sn_debug_info": "1.1",
"sn_reduce_fog": "1.0",
- "sn_asteroid_fade": "1.1"
+ "sn_asteroid_fade": "1.2"
}
\ No newline at end of file
diff --git a/extensions/sn_asteroid_fade/Customizer_Script.py b/extensions/sn_asteroid_fade/Customizer_Script.py
index 74c8819..53cc6a5 100644
--- a/extensions/sn_asteroid_fade/Customizer_Script.py
+++ b/extensions/sn_asteroid_fade/Customizer_Script.py
@@ -1,5 +1,6 @@
import sys
+import math
from pathlib import Path
this_dir = Path(__file__).resolve().parent
from collections import defaultdict
@@ -276,8 +277,15 @@ def Fadein_Asteroids(empty_diffs = 0):
# Note: render_dist is for the asteroid center point when it shows
# up, but camera distance is per-pixel and will be closer, so have
# fade end a little sooner. Go with 1% for now.
+ # Note: dither effect is more noticeable than proper alpha, do try
+ # to lowball the fading period, and not use the full 20% except for
+ # close stuff.
fade_end = render_dist * 0.99
fade_start = render_dist * 0.8
+ # Cap the fade range. Assuming travel at 5km/s, 15km would still take
+ # 3 seconds to fade in, so might be a decent cap.
+ closest_start = fade_end - 15000
+ fade_start = max(fade_start, closest_start)
# Apply these to the material properties.
for material in materials:
@@ -533,13 +541,41 @@ def Patch_Shader_Files(shader_names, testmode = False):
zoomed in views see more of the asteroid draw (reducing obviousness
of the dither effect when using a zoom hotkey).
- TODO: including camera angle somehow? Maybe compute from the
- cam and object xyz but based on angle?
+ TODO: maybe discard if not gl_FrontFacing; probably not important.
+
+ To stabalize pattern when camera turns:
+ Use the angle from cam pos to object pos.
angles = sin((cam.x - obj.x) / (cam.z - obj.z)) + sin((cam.y - obj.y) / (cam.z - obj.z))
Tweak this based on:
- - Distance; reduced angle between pixels at longer distance.
- - Resolution; reduced angle between pixels at higher res.
- - Round to roughly matching up to pixel density.
+ - Resolution; reduced angle between pixels at higher res.
+ - Round to roughly matching up to pixel density.
+
+ What is the angle between pixels?
+ Guess: 100 fov at 1650 wide, so 5940 pix in full circle, ~6k.
+ Can compute live based on V_viewportpixelsize.x, though fov
+ is unclear (maybe based on x/y ratio?).
+
+ In testing, centering on a nav beacon and counting turns of the
+ camera to get back to it, it takes 4.3 turns, or 84 degrees.
+ Note: trying with the 100 assumption had some dither noise when
+ turning the camera, so that was wrong; maybe 84 is right?
+
+ Scaling by resolution: fov = 84 / (10/16) * x/y = 52.5 * x/y
+
+ Does this even need an actual angle?
+ Can get the xyz vector from the camera to the object, and adjust
+ to be a unit vector:
+ dir = (cam.xyz - obj.xyz)
+ dir = dir / distance(dir)
+ That's probably good enough, but how to round for stability?
+ May need to use atan anyway to get angles.
+
+ Test result:
+ - Looks mostly stable, except some shimmering noticed occasionally,
+ notably near the +x axis center.
+ - Zooming looks bad, but not much to be done about that.
+ - Some shimmer when turning just due to resolution and aliasing,
+ similar to general object edges.
'''
# Pick number of fade stepping bins, used to reduce shimmer.
@@ -598,13 +634,44 @@ def Patch_Shader_Files(shader_names, testmode = False):
# Example of randomizer calculation here:
# https://stackoverflow.com/questions/4200224/random-noise-functions-for-glsl
# Works decently, though dither tracks with camera rotation.
- new_code += '''
+ if 0:
+ new_code += '''
if (ast_fade < 0.999){
float psuedo_rand = fract(sin(dot(gl_FragCoord.xy, vec2(12.9898,78.233))) * 43758.5453);
if( psuedo_rand >= ast_fade)
discard;
}
'''
+
+ # More complex case: compute a rounded angle.
+ # or
+ if 1:
+ # Fov is roughly 52.5 * x/y of the resolution.
+ # angle_per_pixel = fov / x
+ # Want to round based on angle_per_pixel.
+ # roundto = 52.5 * x/y / x = 52.5 / y
+ # Switch to radians.
+ round_y_ratio = math.pi * 2 / 360 * 52.5
+ new_code += f'''
+ if (ast_fade < 0.999){{
+ float roundto = {round_y_ratio} / V_viewportpixelsize.y;
+ vec3 dir = V_cameraposition.xyz - IO_world_pos.xyz;
+ // Note: atan is -pi to pi.
+ vec2 angles = vec2(
+ atan(dir.x, dir.z),
+ atan(dir.y, dir.z)
+ );
+ // Round them.
+ angles = floor((angles / roundto) + 0.5) * roundto;
+ // Get a rand from the angles.
+ // Ideally don't want patterns, eg. circles of discards,
+ // so don't add the angles. Can do what was done above
+ // with xy.
+ float psuedo_rand = fract(sin(dot(angles, vec2(12.9898,78.233))) * 43758.5453);
+ if( psuedo_rand >= ast_fade)
+ discard;
+ }}
+ '''
# Replace a line near the start of main, for fast discard (maybe slightly
# more performant).
diff --git a/extensions/sn_asteroid_fade/change_log.md b/extensions/sn_asteroid_fade/change_log.md
index 6101150..9966208 100644
--- a/extensions/sn_asteroid_fade/change_log.md
+++ b/extensions/sn_asteroid_fade/change_log.md
@@ -5,4 +5,7 @@ Change Log
- Initial version.
* 1.1
- Alternate technique to get xxl asteroids to display in low attention zones.
- - Removed most fps loss, as distant in-sector aiscripts no longer run at higher precision.
\ No newline at end of file
+ - Removed most fps loss, as distant in-sector aiscripts no longer run at higher precision.
+* 1.2
+ - Changed dither algorithm to use absolute angles instead of screen coordinates.
+ - Fade in range limited to 15 km start to end.
\ No newline at end of file
diff --git a/extensions/sn_asteroid_fade/content.xml b/extensions/sn_asteroid_fade/content.xml
index acb0ab5..224a9be 100644
--- a/extensions/sn_asteroid_fade/content.xml
+++ b/extensions/sn_asteroid_fade/content.xml
@@ -8,7 +8,7 @@
description=" "
save="false"
sync="false"
- version="101">
+ version="102">