At the cut the whole 4096 height, normal and photograph textures go, replaced by a coarse 2048 level (the CPU's tt_coarse uploaded; the normal and photograph blitted down on the GPU, the photograph mipmapped) and a pool of fine tiles in three array textures - heights, normals, photograph, each layer a tile with a one-texel border - addressed through a tt_n^2 page table (u_tp_page: slot + 1, 0 = the coarse level). The pool holds the tiles within the reach (900 m, or the fog wall's when nearer) and a ring, and is made again when the fog wall changes its size (terrain_pages_fog). Once a frame (tp_frame, beside tt_frame) tiles past the reach and two tiles go and the wanted ones come in nearest first, 8 a frame, written into a staging buffer kept for the process (two halves, one per frame in flight) and copied into their layers inside the frame's own command buffer - no submit of their own - with the page table re-uploaded only when it changed. tp_bind binds the pool (or 1-layer stand-in arrays while paging is off, u_tp_on = 0) for every program that reads the ground: terrain_bind_height (models, scatter, shadow_bind, grass), terrain_bind_prog, the sun pass and the shadow bake. grass_cull.comp reads through the same page table. R3D_VKMEM prints the pool's line. Tiles off, nothing changes. Compile-only: not run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
30 lines
1.8 KiB
Text
30 lines
1.8 KiB
Text
# terrain_pages_coarse.ludic — the whole-map level the page pool falls back to (terrain_pages.ludic),
|
|
# made on the GPU from the whole textures at the cut, before they go.
|
|
|
|
# at the cut (terrain_tiles_cut): the coarse level made from the whole textures, which then go - the
|
|
# patch bounds and the sun's bake have already read them - and the pool made
|
|
function tp_cut(render3d_st: mut Render3dState) -> void {
|
|
let was = render3d_st.gvk_tag
|
|
render3d_st.gvk_tag = VKM_TERRAIN
|
|
tp_cut__t(render3d_st)
|
|
render3d_st.gvk_tag = was
|
|
}
|
|
function tp_cut__t(render3d_st: mut Render3dState) -> void {
|
|
if render3d_st.tt_file == null or render3d_st.tt_coarse == null or render3d_st.ter_ortho_tex == 0 { return }
|
|
let c = TT_COARSE
|
|
let h = tex_target(render3d_st, c, c, GL_R32F, GL_RED, GL_FLOAT, GL_LINEAR)
|
|
gpu_tex_fill(render3d_st, h, GL_R32F, c, c, GL_RED, GL_FLOAT, data_of(render3d_st.tt_coarse))
|
|
let nm = tex_target(render3d_st, c, c, GL_RG16F, GL_RG, GL_FLOAT, GL_LINEAR)
|
|
gpu_tex_blit(render3d_st, render3d_st.ter_normal_tex, TERRAIN_RES, TERRAIN_RES, nm, c, c)
|
|
let o = tex_target(render3d_st, c, c, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR)
|
|
gpu_tex_blit(render3d_st, render3d_st.ter_ortho_tex, render3d_st.ter_ortho_w, render3d_st.ter_ortho_w, o, c, c)
|
|
gpu_tex_bind(render3d_st, GPU_TEX2D, o)
|
|
gpu_tex_param(render3d_st, GPU_TEX2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)
|
|
gpu_tex_mips(render3d_st, GPU_TEX2D)
|
|
gpu_tex_paramf(render3d_st, GPU_TEX2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, render3d_st.tex_anisotropy)
|
|
gpu_tex_free(render3d_st, render3d_st.ter_height_tex)
|
|
gpu_tex_free(render3d_st, render3d_st.ter_normal_tex)
|
|
gpu_tex_free(render3d_st, render3d_st.ter_ortho_tex)
|
|
render3d_st.ter_height_tex = h; render3d_st.ter_normal_tex = nm; render3d_st.ter_ortho_tex = o
|
|
tp_pool(render3d_st)
|
|
}
|