fix(shaders): varyings meet by name on Vulkan, so the meadow's flowers draw
OpenGL links a vertex output to a fragment input by name; SPIR-V links them by location, and glslang's --auto-map-locations numbered each stage in its own declaration order. The foliage prepass's depth.frag declares v_wpos then v_uv where model.vert writes v_wpos, v_nrm, v_uv, so the prepass read a normal as its texture coordinate, its alpha test cut every flower head and leaf, and the lit pass (depth EQUAL) drew nothing over them. `ludic-dev shaders` now gives both stages explicit locations: the vertex stage's out order numbers them and the fragment stage looks each in up by name. All 45 variants checked: every fragment input sits on its vertex output. Also: - A clear still waiting for its pass when the framebuffer changes now runs on that framebuffer, instead of becoming the load op of whichever pass began next. - R3D_DUMP_ATLAS writes every impostor and card atlas a run bakes (build/atlas_<n>_*.ppm); the 40 baked on Vulkan match OpenGL's. The PC's Vulkan frame now shows the flowers as OpenGL does, validation-clean. ludic-dev test 140 passed; OpenGL frames byte-identical at the five viewpoints; 59 self-tests pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
a674c9b372
commit
66940f9c0a
8 changed files with 81 additions and 4 deletions
|
|
@ -738,7 +738,7 @@ function gpu_debug_check(tag: string) -> void { if gpu_kind == GPU_VK { return }
|
|||
|
||||
function gpu_fb_new() -> int { if gpu_kind == GPU_VK { gvk_fb_counter += 1; return gvk_fb_counter }; return gl_framebuffer() }
|
||||
function gpu_fb_bind(fb: int) -> void {
|
||||
if gpu_kind == GPU_VK { if fb != gvk_fb_cur { gvk_pass_end() }; gvk_fb_cur = fb } else { gl_bind_framebuffer(GL_FRAMEBUFFER, fb) }
|
||||
if gpu_kind == GPU_VK { gvk_rebind(fb) } else { gl_bind_framebuffer(GL_FRAMEBUFFER, fb) }
|
||||
gpu_fb_cur = fb
|
||||
gpu_glcheck_after("fb bind")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -960,6 +960,14 @@ function gvk_clear_color(r: int, g: int, b: int, a: int) -> void {
|
|||
gvk_clear_rgba[0] = r; gvk_clear_rgba[1] = g; gvk_clear_rgba[2] = b; gvk_clear_rgba[3] = a
|
||||
}
|
||||
function gvk_fb_colors(fb: int, n: int) -> void { if gvk_fb_ncolor != null and fb >= 0 and fb < 4096 { gvk_fb_ncolor[fb] = n } }
|
||||
# The framebuffer changes: a clear still waiting for this one's pass runs now, on this target,
|
||||
# rather than becoming the load op of whichever pass begins next.
|
||||
function gvk_rebind(fb: int) -> void {
|
||||
if fb == gvk_fb_cur { return }
|
||||
if not gvk_in_pass and gvk_clear_bits != 0 { gvk_pass_begin(gpu_fb, gpu_fb_at(gvk_fb_cur)) }
|
||||
gvk_pass_end()
|
||||
gvk_fb_cur = fb
|
||||
}
|
||||
function gvk_fb_forget(fb: int) -> void {
|
||||
if fb == gvk_fb_cur { gvk_pass_end() }
|
||||
gvk_fb_colors(fb, 1)
|
||||
|
|
|
|||
|
|
@ -341,6 +341,8 @@ var sc_printed: bool = false
|
|||
var sc_a2c: bool = true
|
||||
|
||||
function scatter_init() -> void {
|
||||
# R3D_DUMP_ATLAS: every impostor and card atlas the run bakes, to build/atlas_<n>_{color,alpha}.ppm
|
||||
sc_debug_dump = Os.has_env("R3D_DUMP_ATLAS")
|
||||
sc_prog = r3d_program("model.vert", "model.frag", "")
|
||||
sc_prog_fol = r3d_program("model.vert", "model.frag", "#define FOLIAGE\n#define WIND\n#define ALPHA_TEST\n")
|
||||
sc_prog_fol_depth = r3d_program("model.vert", "depth.frag", "#define FOLIAGE\n#define WIND\n#define ALPHA_TEST\n")
|
||||
|
|
@ -413,6 +415,7 @@ function layer_add(l: Layer, x: int, y: int, z: int, scale: int, yaw: int, seed:
|
|||
|
||||
# ---- impostors ---------------------------------------------------------------------
|
||||
var sc_bake_flower: bool = false
|
||||
var sc_dump_n: int = 0
|
||||
function impostor_bake(model: Model, tiles: int, tw: int, th: int) -> Impostor {
|
||||
let im = new Impostor
|
||||
im.tiles = tiles
|
||||
|
|
@ -475,7 +478,12 @@ function impostor_bake(model: Model, tiles: int, tw: int, th: int) -> Impostor {
|
|||
gpu_tex_param(GPU_TEX2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)
|
||||
gpu_tex_mips(GPU_TEX2D)
|
||||
gpu_check("impostor bake")
|
||||
if sc_debug_dump { tex_dump_alpha = true; tex_dump(im.albedo, aw, th, "build/atlas_alpha.ppm"); tex_dump_alpha = false }
|
||||
# numbered, so every bake of a run survives to be compared (a card layer per species bakes one)
|
||||
if sc_debug_dump {
|
||||
sc_dump_n += 1
|
||||
tex_dump_alpha = true; tex_dump(im.albedo, aw, th, `build/atlas_{sc_dump_n}_alpha.ppm`); tex_dump_alpha = false
|
||||
tex_dump(im.albedo, aw, th, `build/atlas_{sc_dump_n}_color.ppm`)
|
||||
}
|
||||
return im
|
||||
}
|
||||
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue