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 .DS_Store
web/dist/ web/dist/
web/game.bundle.json web/game.bundle.json
.claude/

View File

@ -229,7 +229,9 @@ async fn amain(game_dir: String) {
let mut index_img = Image::gen_image_color(PIC_W as u16, PIC_H as u16, BLACK); 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); let index_tex = Texture2D::from_image(&index_img);
index_tex.set_filter(FilterMode::Nearest); index_tex.set_filter(FilterMode::Nearest);
let mut pal_img = Image::gen_image_color(256, 1, BLACK); #[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); let pal_tex = Texture2D::from_image(&pal_img);
pal_tex.set_filter(FilterMode::Nearest); pal_tex.set_filter(FilterMode::Nearest);
let material = load_material( let material = load_material(
@ -244,6 +246,8 @@ async fn amain(game_dir: String) {
}, },
) )
.expect("CRT shader compiles"); .expect("CRT shader compiles");
(pal_img, pal_tex, material)
};
let mut last_dir_sent: u8 = 0; let mut last_dir_sent: u8 = 0;
let mut ed = editor::Editor::new(); let mut ed = editor::Editor::new();
@ -496,7 +500,10 @@ async fn amain(game_dir: String) {
// --- draw ------------------------------------------------------------ // --- draw ------------------------------------------------------------
clear_background(Color::from_rgba(12, 12, 16, 255)); clear_background(Color::from_rgba(12, 12, 16, 255));
// Indices into the R channel; the shader does the palette lookup. // 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); let indices = gs.render_indices(true);
for (i, &idx) in indices.iter().enumerate() { for (i, &idx) in indices.iter().enumerate() {
index_img.bytes[i * 4] = idx; index_img.bytes[i * 4] = idx;
@ -518,6 +525,26 @@ async fn amain(game_dir: String) {
DrawTextureParams { dest_size: Some(vec2(PIC_W as f32 * SCALE, PIC_H as f32 * SCALE)), ..Default::default() }, DrawTextureParams { dest_size: Some(vec2(PIC_W as f32 * SCALE, PIC_H as f32 * SCALE)), ..Default::default() },
); );
gl_use_default_material(); 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 { if ui.flash > 0.0 {
draw_rectangle( draw_rectangle(