idk shitload of stuff
This commit is contained in:
+17
-12
@@ -1,38 +1,40 @@
|
||||
// Szenen-Pipeline: die PS1-Eigenheiten aus dem Renderer-Plan, authentisch
|
||||
// gerechnet statt nachgestellt:
|
||||
// - Pixel-Snap im Vertex-Shader → Vertex-Jitter
|
||||
// - @interpolate(linear) → affine (nicht perspektivkorrigierte) Varyings
|
||||
// - @interpolate(linear) → affine (nicht perspektivkorrigierte) UVs
|
||||
// - RGB555-Quantisierung + 4×4-Bayer-Dither im Fragment-Shader
|
||||
// - 1-Bit-Alpha-Test (Cutouts), kein Blending
|
||||
|
||||
struct Uniforms {
|
||||
mvp: mat4x4f,
|
||||
// Halbe interne Auflösung (NDC läuft -1..1, Spanne 2 → Skalierung mit
|
||||
// der halben Auflösung trifft das Pixelraster). Kommt aus dem Renderer.
|
||||
half_res: vec2f,
|
||||
};
|
||||
@group(0) @binding(0) var<uniform> u: Uniforms;
|
||||
|
||||
@group(1) @binding(0) var tex: texture_2d<f32>;
|
||||
@group(1) @binding(1) var smp: sampler;
|
||||
|
||||
struct VsOut {
|
||||
@builtin(position) pos: vec4f,
|
||||
// linear = affin interpoliert; Vertex-Colors (und später UVs)
|
||||
// wobbeln dadurch wie auf der PS1.
|
||||
@location(0) @interpolate(linear) color: vec3f,
|
||||
// linear = affin interpoliert → das Textur-Wobbeln der PS1.
|
||||
@location(0) @interpolate(linear) uv: vec2f,
|
||||
};
|
||||
|
||||
// Halbe interne Auflösung (320×240). Bei umschaltbarer Auflösung später
|
||||
// in die Uniforms verschieben.
|
||||
const HALF_RES = vec2f(160.0, 120.0);
|
||||
|
||||
@vertex
|
||||
fn vs_main(@location(0) pos: vec3f, @location(1) color: vec3f) -> VsOut {
|
||||
fn vs_main(@location(0) pos: vec3f, @location(1) uv: vec2f) -> VsOut {
|
||||
var clip = u.mvp * vec4f(pos, 1.0);
|
||||
// Pixel-Snap: xy nach der Projektion aufs interne Raster runden und
|
||||
// zurück in den Clip-Raum. Nur vor der Kamera (w>0) — dahinter würde
|
||||
// die Division Unsinn liefern, das Hardware-Clipping übernimmt.
|
||||
if clip.w > 0.0 {
|
||||
let ndc = clip.xy / clip.w;
|
||||
clip = vec4f(round(ndc * HALF_RES) / HALF_RES * clip.w, clip.zw);
|
||||
clip = vec4f(round(ndc * u.half_res) / u.half_res * clip.w, clip.zw);
|
||||
}
|
||||
var out: VsOut;
|
||||
out.pos = clip;
|
||||
out.color = color;
|
||||
out.uv = uv;
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -49,9 +51,12 @@ fn bayer4(px: vec2u) -> f32 {
|
||||
|
||||
@fragment
|
||||
fn fs_main(in: VsOut) -> @location(0) vec4f {
|
||||
let texel = textureSample(tex, smp, in.uv);
|
||||
if texel.a < 0.5 { discard; } // 1-Bit-Alpha (Cutouts), noch ungenutzt
|
||||
|
||||
// RGB555: 31 Stufen pro Kanal. Bayer-Schwelle vor dem Abrunden →
|
||||
// Verläufe zerfallen ins typische Dither-Muster.
|
||||
let t = (bayer4(vec2u(in.pos.xy)) + 0.5) / 16.0;
|
||||
let c = clamp(in.color, vec3f(0.0), vec3f(1.0));
|
||||
let c = clamp(texel.rgb, vec3f(0.0), vec3f(1.0));
|
||||
return vec4f(floor(c * 31.0 + t) / 31.0, 1.0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user