Skip to content

Commit 6013c81

Browse files
ragojoseclaude
andcommitted
fix: correct upside-down 404 screen and arcade boot image for WebGPU
- Not-found material: change 180° rotation to X-mirror only, since WebGPU render targets have Y=0 at top (no Y negation needed unlike WebGL) - Screen material: add separate uFlipY uniform for render target Y-flip, restoring uFlip to game-mode-only behavior. Two sequential flips cancel when both active (DOOM game + RT inversion) - Arcade screen component: set uFlipY=1 for render targets, 0 for images/video Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 9854208 commit 6013c81

3 files changed

Lines changed: 14 additions & 5 deletions

File tree

src/components/arcade-screen/index.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ export const ArcadeScreen = () => {
9191
if (!hasVisitedArcade) {
9292
if (isLabRoute) {
9393
screenUniforms.map.value = bootTexture
94+
screenUniforms.uFlipY.value = 0
9495
screenUniforms.uRevealProgress.value = 0.0
9596

9697
animate(0, 1, {
@@ -102,18 +103,21 @@ export const ArcadeScreen = () => {
102103
onComplete: () => {
103104
if (screenUniforms.uRevealProgress.value >= 0.99) {
104105
screenUniforms.map.value = renderTarget.texture
106+
screenUniforms.uFlipY.value = 1
105107
setHasVisitedArcade(true)
106108
screenUniforms.uFlip.value = isInGame ? 1 : 0
107109
}
108110
}
109111
})
110112
} else {
111113
screenUniforms.map.value = videoTexture
114+
screenUniforms.uFlipY.value = 0
112115
screenUniforms.uRevealProgress.value = 1.0
113116
screenUniforms.uFlip.value = 0
114117
}
115118
} else {
116119
screenUniforms.map.value = renderTarget.texture
120+
screenUniforms.uFlipY.value = 1
117121
screenUniforms.uFlip.value = isInGame ? 1 : 0
118122
}
119123

src/shaders/material-not-found/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ export const createNotFoundMaterial = () => {
5252
uv2.x.assign(float(1.0).sub(uv2.x))
5353
uv2.subAssign(0.5)
5454

55-
// 180° rotation (cosR=-1, sinR=0) + re-center
56-
const shiftedUv = uv2.mul(-1.0).add(0.5)
55+
// Mirror X only (WebGPU render targets have Y=0 at top, so no Y negate needed)
56+
const shiftedUv = vec2(uv2.x.negate(), uv2.y).add(0.5)
5757

5858
// Texture sampling with color bleeding
5959
const baseColor = tDiffuse.sample(shiftedUv)

src/shaders/material-screen/index.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ export const createScreenMaterial = () => {
7474
const uTime = uniform(0)
7575
const uRevealProgress = uniform(1.0)
7676
const uFlip = uniform(0)
77+
const uFlipY = uniform(0.0)
7778
const uIsGameRunning = uniform(0.0)
7879

7980
const material = new NodeMaterial()
@@ -109,9 +110,13 @@ export const createScreenMaterial = () => {
109110
// CRT curve remap
110111
const remappedUv = curveRemapUV(interferenceUv).toVar()
111112

112-
// Flip y: default flips for WebGPU convention, uFlip=1 un-flips for game mode
113+
// Flip Y for render target textures (WebGPU RT has Y=0 at top vs WebGL Y=0 at bottom)
113114
remappedUv.y.assign(
114-
mix(float(1.0).sub(remappedUv.y), remappedUv.y, uFlip)
115+
mix(remappedUv.y, float(1.0).sub(remappedUv.y), uFlipY)
116+
)
117+
// Game mode flip (DOOM orientation correction — cancels RT flip when both active)
118+
remappedUv.y.assign(
119+
mix(remappedUv.y, float(1.0).sub(remappedUv.y), uFlip)
115120
)
116121

117122
// Pixelation with exclusion zones (only when flipped)
@@ -211,6 +216,6 @@ export const createScreenMaterial = () => {
211216

212217
return {
213218
material,
214-
uniforms: { map: mapTex, uTime, uRevealProgress, uFlip, uIsGameRunning }
219+
uniforms: { map: mapTex, uTime, uRevealProgress, uFlip, uFlipY, uIsGameRunning }
215220
}
216221
}

0 commit comments

Comments
 (0)