diff --git a/shaders/trackblend.glsl b/shaders/trackblend.glsl index a38caf4b..a08e23dd 100644 --- a/shaders/trackblend.glsl +++ b/shaders/trackblend.glsl @@ -82,11 +82,17 @@ vec2 parallax_coord(sampler2D heights, vec2 coord, vec3 viewdir, vec2 dcoorddx, void main() { + // how far the fragment is into the track from the ends, in the lengths of their blending (track_blend::blending::weigh()): + // from -100 down where the track joined there doesn't blend back and its texture goes all the way to the joint, 10000 where + // nothing's blended at the end #ifdef TRACKBLEND_SPECGLOSS - vec3 weights = clamp(vec3(UserData.yz, 0.0), 0.0, 1.0); + vec3 along = vec3(UserData.yz, 10000.0); #else - vec3 weights = clamp(UserData.yzw, 0.0, 1.0); + vec3 along = UserData.yzw; #endif + vec3 single = vec3(lessThan(along, vec3(-50.0))); + vec3 fraction = mix(along, -100.0 - along, single); + vec3 weights = mix(vec3(0.5), vec3(1.0), single) * clamp(1.0 - fraction, 0.0, 1.0); float total = weights.x + weights.y + weights.z; if (total > 1.0) { diff --git a/world/TrackBlend.cpp b/world/TrackBlend.cpp index 84710f4a..4be69152 100644 --- a/world/TrackBlend.cpp +++ b/world/TrackBlend.cpp @@ -22,9 +22,6 @@ namespace track_blend { namespace { -// how far aside of the line of an end its weight reaches, past the widest trackbeds -double constexpr lateral_reach { 6.0 }; - blending const *current { nullptr }; int end_count( TTrack const &Track ) { @@ -194,17 +191,13 @@ void blending::weigh( gfx::vertex_array const &Vertices, gfx::userdata_array &Us auto &data { Userdata[ index ].data }; for( int end = 0; end < 3; ++end ) { auto const &blend { ends[ end ] }; - auto weight { 0.f }; + auto value { none_mark }; if( blend.active ) { - // measured along the line of the end, so both tracks give the vertices of their joint the same weight - auto const offset { position - blend.point }; - auto const along { glm::dot( offset, blend.inward ) }; - auto const aside { glm::length( offset - blend.inward * along ) }; - if( along < blend.length && aside < lateral_reach ) { - weight = blend.peak * static_cast( 1.0 - std::max( 0.0, along ) / blend.length ); - } + // measured along the line of the end, so both tracks give the vertices of their joint the same distance + auto const fraction { static_cast( glm::dot( position - blend.point, blend.inward ) / blend.length ) }; + value = ( blend.peak < 1.f ? fraction : single_mark - fraction ); } - data[ 1 + end ] = weight; + data[ 1 + end ] = value; } } } diff --git a/world/TrackBlend.h b/world/TrackBlend.h index ea9b2b38..b3e2c7c6 100644 --- a/world/TrackBlend.h +++ b/world/TrackBlend.h @@ -20,7 +20,7 @@ http://mozilla.org/MPL/2.0/. class TTrack; // the rails and the ballast of a track blended into those of the tracks joined at its ends, where their textures differ: near -// an end the vertices carry the weight of the track joined there (y, z, w of their user data for the ends p1, p2 and p4 of a +// an end the vertices carry how far they are from it (y, z, w of their user data for the ends p1, p2 and p4 of a // switch) and the track is drawn with a material fading its texture into theirs. a plain track blends its rails and its // ballast, a switch the trackbed made for it namespace track_blend { @@ -47,9 +47,14 @@ struct blending { bool any() const { return material != null_handle; } - // the weights of the ends put in the user data of the vertices (relative to the origin of the track), made as long as the - // vertices where it's shorter; what the user data hold at x is kept + // how far the vertices (relative to the origin of the track) are into it from each end, in the length of its blending, put + // in their user data: distance / length where the track joined blends back, single_mark - distance / length where it doesn't, + // none_mark where nothing's blended at the end. a distance runs straight along the vertices, so it's led between them exactly + // and the shader (trackblend.glsl) works the weight out of it for each fragment, however far apart the vertices are. the user + // data are made as long as the vertices where they're shorter; what they hold at x is kept void weigh( gfx::vertex_array const &Vertices, gfx::userdata_array &Userdata ) const; + static float constexpr single_mark { -100.f }; + static float constexpr none_mark { 10000.f }; }; // how the rails or the ballast of the track blend into those of the tracks joined to it, nothing for the tracks which don't