Web: plain RGBA blit on wasm (the multi-texture CRT material fights the GL shim); CRT stays native

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
m3ultra 2026-07-29 14:26:51 +10:00
parent f706a9ce55
commit 5286d15892
2 changed files with 64 additions and 36 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@ games/*/saves/
.DS_Store
web/dist/
web/game.bundle.json
.claude/

View File

@ -229,21 +229,25 @@ async fn amain(game_dir: String) {
let mut index_img = Image::gen_image_color(PIC_W as u16, PIC_H as u16, BLACK);
let index_tex = Texture2D::from_image(&index_img);
index_tex.set_filter(FilterMode::Nearest);
let mut pal_img = Image::gen_image_color(256, 1, BLACK);
let pal_tex = Texture2D::from_image(&pal_img);
pal_tex.set_filter(FilterMode::Nearest);
let material = load_material(
ShaderSource::Glsl { vertex: CRT_VERTEX, fragment: CRT_FRAGMENT },
MaterialParams {
textures: vec!["palette_tex".to_string()],
uniforms: vec![
UniformDesc::new("crt", UniformType::Float1),
UniformDesc::new("fade", UniformType::Float1),
],
..Default::default()
},
)
.expect("CRT shader compiles");
#[cfg(not(target_arch = "wasm32"))]
let (mut pal_img, pal_tex, material) = {
let pal_img = Image::gen_image_color(256, 1, BLACK);
let pal_tex = Texture2D::from_image(&pal_img);
pal_tex.set_filter(FilterMode::Nearest);
let material = load_material(
ShaderSource::Glsl { vertex: CRT_VERTEX, fragment: CRT_FRAGMENT },
MaterialParams {
textures: vec!["palette_tex".to_string()],
uniforms: vec![
UniformDesc::new("crt", UniformType::Float1),
UniformDesc::new("fade", UniformType::Float1),
],
..Default::default()
},
)
.expect("CRT shader compiles");
(pal_img, pal_tex, material)
};
let mut last_dir_sent: u8 = 0;
let mut ed = editor::Editor::new();
@ -496,28 +500,51 @@ async fn amain(game_dir: String) {
// --- draw ------------------------------------------------------------
clear_background(Color::from_rgba(12, 12, 16, 255));
// Indices into the R channel; the shader does the palette lookup.
let indices = gs.render_indices(true);
for (i, &idx) in indices.iter().enumerate() {
index_img.bytes[i * 4] = idx;
index_img.bytes[i * 4 + 3] = 255;
}
index_tex.update(&index_img);
pal_img.bytes.copy_from_slice(&gs.effective_palette());
pal_tex.update(&pal_img);
// Native: indices into the R channel; the CRT shader does the
// palette lookup, scanlines, curvature and fades on the GPU.
#[cfg(not(target_arch = "wasm32"))]
{
let indices = gs.render_indices(true);
for (i, &idx) in indices.iter().enumerate() {
index_img.bytes[i * 4] = idx;
index_img.bytes[i * 4 + 3] = 255;
}
index_tex.update(&index_img);
pal_img.bytes.copy_from_slice(&gs.effective_palette());
pal_tex.update(&pal_img);
gl_use_material(&material);
material.set_texture("palette_tex", pal_tex.clone());
material.set_uniform("crt", if ui.scanlines { 1.0f32 } else { 0.0f32 });
material.set_uniform("fade", ui.fade);
draw_texture_ex(
&index_tex,
0.0,
BAR_H,
WHITE,
DrawTextureParams { dest_size: Some(vec2(PIC_W as f32 * SCALE, PIC_H as f32 * SCALE)), ..Default::default() },
);
gl_use_default_material();
gl_use_material(&material);
material.set_texture("palette_tex", pal_tex.clone());
material.set_uniform("crt", if ui.scanlines { 1.0f32 } else { 0.0f32 });
material.set_uniform("fade", ui.fade);
draw_texture_ex(
&index_tex,
0.0,
BAR_H,
WHITE,
DrawTextureParams { dest_size: Some(vec2(PIC_W as f32 * SCALE, PIC_H as f32 * SCALE)), ..Default::default() },
);
gl_use_default_material();
}
// Web: miniquad's GL shim and the multi-texture material don't get
// along (stale-texture binds, frozen frame) — take the MRPGI-proven
// path instead: CPU palette blit, plain textured quad. The CRT stays
// a desktop luxury.
#[cfg(target_arch = "wasm32")]
{
let rgba = gs.render_visual(true);
index_img.bytes.copy_from_slice(&rgba);
index_tex.update(&index_img);
let tint = (ui.fade * 255.0) as u8;
draw_texture_ex(
&index_tex,
0.0,
BAR_H,
Color::from_rgba(tint, tint, tint, 255),
DrawTextureParams { dest_size: Some(vec2(PIC_W as f32 * SCALE, PIC_H as f32 * SCALE)), ..Default::default() },
);
}
if ui.flash > 0.0 {
draw_rectangle(