refactor(render3d): render targets and passes behind gpu.ludic
Framebuffers and their attachments, renderbuffers (multisampled too), draw and read buffers, completeness checks, blits, viewports, clears, the screen framebuffer, the multisample enable, the wireframe switch and GL error checks now go through gpu_fb_* / gpu_rb_* / gpu_viewport / gpu_clear / gpu_blit / gpu_check, and no other file names them. Each call is the one GL call it replaces, in the same order: the fixed viewpoints render bit-identically and the game's self-tests report exactly what they did. What is attached to each framebuffer - colour slots, a depth texture or one layer of an array, renderbuffers and their samples - is recorded as it is attached, for a backend that builds render passes and image views. gpu_read_screen is the frame read-back a photograph takes. R3D_GLCHECK=1 checks, around every draw, clear and blit, that the bound framebuffer is complete and that no error is left behind, naming the framebuffer. It has already narrowed the old "gl error 1286 at terrain shadow bake": the error is pending before a draw after the map self- test, so it comes from a call that is not a draw, clear or blit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
4d3479d431
commit
78c1f4f9ca
10 changed files with 294 additions and 150 deletions
|
|
@ -34,11 +34,10 @@ function shadow_init() -> void {
|
|||
gl_put(border, 0, 1.0); gl_put(border, 1, 1.0); gl_put(border, 2, 1.0); gl_put(border, 3, 1.0)
|
||||
gpu_tex_border(GPU_TEX2D_ARRAY, border)
|
||||
free(border)
|
||||
sh_fbo = gl_framebuffer()
|
||||
gl_bind_framebuffer(GL_FRAMEBUFFER, sh_fbo)
|
||||
gl_draw_buffer(GL_NONE)
|
||||
gl_read_buffer(GL_NONE)
|
||||
gl_bind_framebuffer(GL_FRAMEBUFFER, 0)
|
||||
sh_fbo = gpu_fb_new()
|
||||
gpu_fb_bind(sh_fbo)
|
||||
gpu_fb_no_color()
|
||||
gpu_fb_bind(0)
|
||||
sh_vp = words(16 * SHADOW_CASCADES)
|
||||
sh_split = words(SHADOW_CASCADES)
|
||||
sh_range = words(SHADOW_CASCADES)
|
||||
|
|
@ -114,8 +113,8 @@ function shadow_cascade_vp(c: int) -> words { return mem_off(sh_vp, c * 64) }
|
|||
# render every cascade; `draw` happens through terrain_draw_shadow + the scene's casters
|
||||
function shadow_pass() -> void {
|
||||
var near = cam_near
|
||||
gl_bind_framebuffer(GL_FRAMEBUFFER, sh_fbo)
|
||||
gl_viewport(0, 0, SHADOW_RES, SHADOW_RES)
|
||||
gpu_fb_bind(sh_fbo)
|
||||
gpu_viewport(0, 0, SHADOW_RES, SHADOW_RES)
|
||||
gpu_depth_test(true)
|
||||
gpu_depth_func(GL_LESS)
|
||||
gpu_depth_bias(2.0, 4.0)
|
||||
|
|
@ -124,9 +123,9 @@ function shadow_pass() -> void {
|
|||
sh_cascade = c
|
||||
shadow_fit(c, near, sh_split[c])
|
||||
near = sh_split[c]
|
||||
gl_framebuffer_texture_layer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, sh_tex, 0, c)
|
||||
if r3d_debug and c == 0 { let st = gl_check_framebuffer_status(GL_FRAMEBUFFER); print(`shadow fbo status {st}`) }
|
||||
gl_clear(GL_DEPTH_BUFFER_BIT)
|
||||
gpu_fb_depth_layer(sh_tex, c)
|
||||
if r3d_debug and c == 0 { let st = gpu_fb_status(); print(`shadow fbo status {st}`) }
|
||||
gpu_clear(GL_DEPTH_BUFFER_BIT)
|
||||
let vp = shadow_cascade_vp(c)
|
||||
# shadows off (a video setting): the cascades stay cleared, so everything reads lit
|
||||
if sh_enabled {
|
||||
|
|
@ -135,7 +134,7 @@ function shadow_pass() -> void {
|
|||
}
|
||||
}
|
||||
gpu_depth_bias(0.0, 0.0)
|
||||
gl_bind_framebuffer(GL_FRAMEBUFFER, 0)
|
||||
gpu_fb_bind(0)
|
||||
if r3d_debug_shadow { shadow_dump() }
|
||||
if r3d_debug_shadow and not sh_printed2 {
|
||||
sh_printed2 = true
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue