Stronger liquid swell, flow along rivers, brighter lava and new lava texture
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a701212299
commit
1094c7c5f2
2 files changed
+63
-29
No files matched your search
+44
-18
@@ -219,9 +219,9 @@ void main() {
|
||||
float a = color0.a;
|
||||
if (a > 96.0 && a < 192.0) {
|
||||
bool lava = a < 128.0;
|
||||
float sp = lava ? 0.55 : 1.6;
|
||||
float amp = lava ? 0.018 : 0.028;
|
||||
w.y += amp * (sin(w.x * 1.7 + Time * sp) * 0.6 + sin(w.z * 2.3 - Time * sp * 1.3) * 0.4);
|
||||
float sp = lava ? 0.8 : 1.6;
|
||||
float amp = lava ? 0.04 : 0.05;
|
||||
w.y += amp * (sin(w.x * 1.3 + w.z * 0.4 + Time * sp) * 0.6 + sin(w.z * 1.9 - w.x * 0.5 - Time * sp * 1.3) * 0.4);
|
||||
}
|
||||
wpos = w.xyz;
|
||||
wnorm = normal.xyz;
|
||||
@@ -250,20 +250,27 @@ void main() {
|
||||
float wave = 0.0;
|
||||
bool liquid = color.a > 0.38 && color.a < 0.75;
|
||||
if (liquid) {
|
||||
// flowing texture: sampled in world space inside the tile's (seamless) atlas cell
|
||||
// flowing texture: sampled in world space inside the tile's (seamless) atlas cell, moving
|
||||
// along the river (its direction comes in the normal's x/z, see liquid_flow)
|
||||
bool lava = color.a < 0.5;
|
||||
vec2 flow = lava ? vec2(0.035, 0.015) : vec2(0.11, 0.045);
|
||||
vec2 p = wpos.xz + flow * Time;
|
||||
p += (lava ? 0.03 : 0.05) * vec2(sin(wpos.z * 3.0 + Time * (lava ? 0.4 : 1.1)), sin(wpos.x * 3.0 + Time * (lava ? 0.3 : 0.9)));
|
||||
vec2 dir = wnorm.xz / max(length(wnorm.xz), 0.001);
|
||||
float speed = lava ? 0.16 : 0.32;
|
||||
float ts = lava ? 0.8 : 1.6; // wave tempo: lava rolls slower
|
||||
// swell: broad moving bands; their slope shades the surface and bends the texture
|
||||
float ph1 = wpos.x * 1.3 + wpos.z * 0.4 + Time * ts;
|
||||
float ph2 = wpos.z * 1.9 - wpos.x * 0.5 - Time * ts * 1.3;
|
||||
vec2 slope = vec2(cos(ph1) * 1.3 * 0.6 - cos(ph2) * 0.5 * 0.4, cos(ph1) * 0.4 * 0.6 + cos(ph2) * 1.9 * 0.4);
|
||||
vec2 p = wpos.xz - dir * speed * Time + slope * (lava ? 0.05 : 0.07);
|
||||
vec2 cell = floor(uv * AtlasSize / 16.0) * 16.0;
|
||||
tuv = (cell + fract(p) * 16.0) / AtlasSize;
|
||||
wave = sin(wpos.x * 5.0 + wpos.z * 3.0 + Time * (lava ? 0.7 : 2.2)) * sin(wpos.z * 4.0 - wpos.x * 2.0 + Time * (lava ? 0.5 : 1.7));
|
||||
float ripple = sin(wpos.x * 5.0 + wpos.z * 3.0 + Time * ts * 1.4) * sin(wpos.z * 4.0 - wpos.x * 2.0 + Time * ts);
|
||||
wave = dot(slope, vec2(0.45, 0.35)) * 0.6 + ripple * 0.4;
|
||||
}
|
||||
vec4 tex = texture2D(Texture, tuv);
|
||||
if (tex.a < 0.5) discard;
|
||||
// see-through units (invisibility): every other pixel left out
|
||||
if (color.a < 0.37 && mod(floor(gl_FragCoord.x) + floor(gl_FragCoord.y), 2.0) < 1.0) discard;
|
||||
vec3 n = normalize(wnorm);
|
||||
vec3 n = liquid ? vec3(0.0, 1.0, 0.0) : normalize(wnorm);
|
||||
vec3 light = color.rgb;
|
||||
for (int i = 0; i < 24; i++) {
|
||||
if (float(i) >= LightCount) break;
|
||||
@@ -274,9 +281,15 @@ void main() {
|
||||
float ndl = max(dot(n, d / max(dist, 0.001)), 0.0) * 0.8 + 0.2;
|
||||
light += LightCol[i].rgb * LightCol[i].a * att * ndl;
|
||||
}
|
||||
// light rippling over the surface: glints on water, a slow pulse of the glow on lava
|
||||
if (liquid) light *= 1.0 + wave * (color.a < 0.5 ? 0.12 : 0.1);
|
||||
gl_FragColor = vec4(tex.rgb * min(light, vec3(1.7)), 1.0);
|
||||
// light rippling over the surface: glints on water; lava glows by itself and pulses
|
||||
if (liquid) {
|
||||
if (color.a < 0.5) {
|
||||
light = max(light, vec3(1.45, 1.3, 1.2)) * (1.0 + wave * 0.18);
|
||||
} else {
|
||||
light *= 1.0 + wave * 0.28;
|
||||
}
|
||||
}
|
||||
gl_FragColor = vec4(tex.rgb * min(light, vec3(1.9)), 1.0);
|
||||
}
|
||||
"#;
|
||||
|
||||
@@ -466,7 +479,7 @@ fn amb_at(f: &[f32], x: f32, z: f32) -> f32 {
|
||||
|
||||
// ---- lava light: an orange glow up to LAVA_REACH tiles around lava, fading with the distance
|
||||
const LAVA_REACH: f32 = 10.0;
|
||||
const LAVA_LIGHT: Vec3 = Vec3::new(0.62, 0.27, 0.05); // added light at full strength (next to the lava)
|
||||
const LAVA_LIGHT: Vec3 = Vec3::new(1.05, 0.45, 0.08); // added light at full strength (next to the lava)
|
||||
|
||||
// glow per tile: 1 on lava, falling to 0 at LAVA_REACH tiles. The light spreads over open ground
|
||||
// (walls are lit on their faces but do not let it through).
|
||||
@@ -507,7 +520,7 @@ fn lava_field(map: &Map) -> Vec<f32> {
|
||||
0.0
|
||||
} else {
|
||||
let k = (1.0 - d as f32 / max as f32).clamp(0.0, 1.0);
|
||||
k * k
|
||||
k.powf(1.6)
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
@@ -528,6 +541,19 @@ fn lava_at(f: &[f32], x: f32, z: f32) -> f32 {
|
||||
a * (1.0 - fz) + b * fz
|
||||
}
|
||||
|
||||
// the direction a river flows at a tile, carried to the shader in the surface normal's x/z
|
||||
// (y stays 1 so the normal still points up): along the longer run of river tiles around it
|
||||
fn liquid_flow(map: &Map, x: i32, z: i32) -> Vec3 {
|
||||
let river = |dx: i32, dz: i32| map.get(x + dx, z + dz).map_or(false, |t| t.river().is_some()) as i32;
|
||||
let along_x: i32 = (-3..=3).map(|d| river(d, 0)).sum();
|
||||
let along_z: i32 = (-3..=3).map(|d| river(0, d)).sum();
|
||||
if along_x > along_z {
|
||||
vec3(0.5, 1.0, 0.0)
|
||||
} else {
|
||||
vec3(0.0, 1.0, 0.5)
|
||||
}
|
||||
}
|
||||
|
||||
// a surface colour with the lava light added
|
||||
fn lava_lit(base: Vec3, glow: f32) -> Vec3 {
|
||||
base + LAVA_LIGHT * glow
|
||||
@@ -550,7 +576,7 @@ const LIQ_D: f32 = 0.3; // depth of the river surface below the floor
|
||||
// vertex alpha that marks river surfaces for the lit shader (waves and flowing texture)
|
||||
const LIQ_WATER_A: f32 = 0.6;
|
||||
const LIQ_LAVA_A: f32 = 0.42;
|
||||
const LIQ_SKIRT: f32 = 0.06; // river banks reach a bit below the surface, so waves leave no gap
|
||||
const LIQ_SKIRT: f32 = 0.1; // river banks reach a bit below the surface, so waves leave no gap
|
||||
const DECK_Y: f32 = 0.03; // height of bridge decks
|
||||
const OUTLINE_C: [u8; 4] = [8, 5, 6, 150];
|
||||
|
||||
@@ -673,7 +699,7 @@ fn build_chunk(map: &Map, amb: &[f32], glow: &[f32], cx: i32, cz: i32, atlas: &T
|
||||
// (its centre, robust even with low precision uvs)
|
||||
[(la + lb) * 0.5; 4],
|
||||
[lc; 4],
|
||||
[Vec3::Y; 4],
|
||||
[liquid_flow(map, x, z); 4],
|
||||
);
|
||||
let (fa, fb) = cell_uv(T_FACE_EARTH);
|
||||
for (d, &(dx, dz)) in DIR4.iter().enumerate() {
|
||||
@@ -1108,7 +1134,7 @@ impl R3d {
|
||||
for x in (ccx - r).max(0)..(ccx + r).min(mw() as i32) {
|
||||
if x % 3 == 0 && g.map.t[idx(x, z)].kind == Kind::Lava {
|
||||
let fl = 0.8 + 0.2 * (t * 2.0 + (x * 7 + z * 3) as f32).sin();
|
||||
push(vec3(x as f32 + 0.5, 0.3, z as f32 + 0.5), 4.0, vec3(1.0, 0.45, 0.12), 0.9 * fl, 0.0);
|
||||
push(vec3(x as f32 + 0.5, 0.3, z as f32 + 0.5), 5.0, vec3(1.0, 0.45, 0.12), 1.3 * fl, 0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2645,7 +2671,7 @@ fn draw_parts_solid(g: &Game) {
|
||||
let life = (p.t / p.max).clamp(0.0, 1.0);
|
||||
let k = 1.0 - life * life;
|
||||
let bob = (p.t * 3.0 + p.x * 2.0).sin() * 0.01;
|
||||
let mid = vec3(p.x, -LIQ_D + 0.04 + bob, p.y); // above the swell of the waves
|
||||
let mid = vec3(p.x, -LIQ_D + 0.07 + bob, p.y); // above the swell of the waves
|
||||
let dir = vec3(p.vx, 0.0, p.vy).normalize_or_zero();
|
||||
let half = dir * (0.17 * k);
|
||||
let wood = vec3(0.45, 0.31, 0.18);
|
||||
|
||||
Reference in new issue
Block a user