Hi Hzzzln, thanks for giving it a try. I also wish there was more but a lot of my ideas came far too late and I just needed to close the game loop as short as it was.
Someone else asked in the comments so I'm going to copy/paste my response from that:
Since my game mostly takes place on the X axis I have a global shader value for that position and another global shader for an edge thickness. I check the world position of the current pixel and if within the edge value I blend between grass and snow while applying a noise texture and TIME for some randomness
I'll throw the fragment part of the shader in since that's the only part doing anything.
vec3 p = (INV_VIEW_MATRIX * vec4(VERTEX, 1.0)).rgb;
bool in_danger = thaw_position >= p.x;
float noise = mod(texture(noise_texture, UV * (uv_scale / 2.0)).r + (TIME / 2.0), 1.0);
float dist = (p.x - thaw_position) + noise;
if (dist >= 0.0 && dist <= edge_thickness)
{
vec3 ground = texture(ground_texture, UV * uv_scale).rgb;
vec3 snow = texture(snow_texture, UV * uv_scale).rgb;
float blend = mod((dist / edge_thickness), 1.0);
ALBEDO = mix(ground, snow, dist);
NORMAL_MAP = texture(snow_normal, UV * uv_scale).rgb;
}
else
{
// Danger
if (in_danger)
{
ALBEDO = texture(ground_texture, UV * uv_scale).rgb;
NORMAL_MAP = texture(ground_normal, UV * uv_scale).rgb;
}
// Snow
else
{
ALBEDO = texture(snow_texture, UV * uv_scale).rgb;
NORMAL_MAP = texture(snow_normal, UV * uv_scale).rgb;
}
}
As I try to point out in the post this is a very slapped together shader so none of the code is well thought out it simply looked "good enough" haha.