diff --git a/packages/ludic.render3d/terrain_ltt2_read.ludic b/packages/ludic.render3d/terrain_ltt2_read.ludic index fbbc1a0e..99b7f7a0 100644 --- a/packages/ludic.render3d/terrain_ltt2_read.ludic +++ b/packages/ludic.render3d/terrain_ltt2_read.ludic @@ -74,6 +74,7 @@ function tt_decode(render3d_st: mut Render3dState, t: int, s: int) -> void { render3d_st.tt_nm[s * n2 + i] = gvk_half(float_bits(lt_oct_dec(e, false))) | (gvk_half(float_bits(lt_oct_dec(e, true))) << 16) } let side = render3d_st.tt_oside + if side == 0 { return } let o2 = side * side file_seek(f, render3d_st.tt_ooff + t * o2 * 3, 0) file_read(f, data_of(sc), o2 * 3) @@ -100,21 +101,31 @@ function ltt2_gpu_coarse(render3d_st: mut Render3dState) -> void { let nm = tex_target(render3d_st, c, c, GL_RG16F, GL_RG, GL_FLOAT, GL_LINEAR) gpu_tex_fill(render3d_st, nm, GL_RG16F, c, c, GL_RG, GL_FLOAT, data_of(xz)) free(xz) - file_seek(f, render3d_st.tt_cooff, 0) - file_read(f, data_of(raw), c * c * 3) + # no photograph (side 0): none on the GPU either, as a map without one has always had + var o = 0 + if render3d_st.tt_oside > 0 { o = ltt2_gpu_coarse_ortho(render3d_st, raw) } + free(raw) + if render3d_st.ter_height_tex != 0 { gpu_tex_free(render3d_st, render3d_st.ter_height_tex) } + if render3d_st.ter_normal_tex != 0 { gpu_tex_free(render3d_st, render3d_st.ter_normal_tex) } + if render3d_st.ter_ortho_tex != 0 { gpu_tex_free(render3d_st, render3d_st.ter_ortho_tex) } + render3d_st.ter_height_tex = h; render3d_st.ter_normal_tex = nm + if o != 0 { render3d_st.ter_ortho_tex = o } + render3d_st.gvk_tag = was + tp_pool(render3d_st) +} + +# the coarse photograph from the file into an sRGB texture with mips (raw: c * c * 3 bytes of scratch) +function ltt2_gpu_coarse_ortho(render3d_st: mut Render3dState, raw: []byte) -> int { + let c = TT_COARSE + file_seek(render3d_st.tt_file, render3d_st.tt_cooff, 0) + file_read(render3d_st.tt_file, data_of(raw), c * c * 3) let o = tex_target(render3d_st, c, c, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR) gpu_tex_fill(render3d_st, o, GL_SRGB8_ALPHA8, c, c, GL_RGB, GL_UNSIGNED_BYTE, data_of(raw)) - free(raw) 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) - if render3d_st.ter_height_tex != 0 { gpu_tex_free(render3d_st, render3d_st.ter_height_tex) } - if render3d_st.ter_normal_tex != 0 { gpu_tex_free(render3d_st, render3d_st.ter_normal_tex) } - if render3d_st.ter_ortho_tex != 0 { 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 - render3d_st.gvk_tag = was - tp_pool(render3d_st) + return o } # ---- the bake ------------------------------------------------------------------------------- @@ -123,7 +134,7 @@ function ltt2_gpu_coarse(render3d_st: mut Render3dState) -> void { # The whole copy is left holding the quantized values, as everything will read them. @alloc_ok("a bake: once, at build time") export function terrain_tiles_bake(render3d_st: mut Render3dState, path: string, key: string, version: int, inputs_hash: long) -> bool { - if render3d_st.ter_heights == null or render3d_st.ter_ortho_px == null or render3d_st.ter_normal_tex == 0 { return false } + if render3d_st.ter_heights == null or render3d_st.ter_normal_tex == 0 { return false } Fs.mkdir(Path.dir(path)) let f = file_open(path, "wb") if f == null { return false } diff --git a/packages/ludic.render3d/terrain_ltt2_write.ludic b/packages/ludic.render3d/terrain_ltt2_write.ludic index da418855..75dca194 100644 --- a/packages/ludic.render3d/terrain_ltt2_write.ludic +++ b/packages/ludic.render3d/terrain_ltt2_write.ludic @@ -12,7 +12,9 @@ const LT_HEAD: int = 128 # 32 words @alloc_ok("a map being made or baked: the tiles written once") function ltt2_write(render3d_st: mut Render3dState, f: pointer, base: int) -> int { let n = TERRAIN_RES / TT_TEX - let side = render3d_st.ter_ortho_w / n + # a map with no photograph (Lamar's ground is painted by its materials) has no photograph sections + var side = 0 + if render3d_st.ter_ortho_px != null { side = render3d_st.ter_ortho_w / n } let head = words(32) for k in 0 .. 32 { head[k] = 0 } file_write(f, data_of(head), LT_HEAD) @@ -20,11 +22,13 @@ function ltt2_write(render3d_st: mut Render3dState, f: pointer, base: int) -> in head[8] = at; at += ltt2_write_heights(render3d_st, f, n) let nrm = ltt2_normals_back(render3d_st) head[10] = at; at += ltt2_write_normals(f, nrm, n) - head[11] = at; at += ltt2_write_ortho(render3d_st, f, n, side) + head[11] = at + if side > 0 { at += ltt2_write_ortho(render3d_st, f, n, side) } head[12] = at; at += ltt2_write_coarse_h(render3d_st, f) head[13] = at; at += ltt2_write_coarse_n(f, nrm) free(nrm) - head[14] = at; at += ltt2_write_coarse_o(render3d_st, f) + head[14] = at + if side > 0 { at += ltt2_write_coarse_o(render3d_st, f) } head[0] = LT_MAGIC; head[1] = LT_VERSION; head[2] = TT_TEX; head[3] = n; head[4] = side head[5] = TERRAIN_RES; head[6] = render3d_st.ter_ortho_w; head[7] = TT_COARSE; head[15] = at file_seek(f, base, 0) diff --git a/packages/ludic.render3d/terrain_tiles.ludic b/packages/ludic.render3d/terrain_tiles.ludic index 04804ff0..87b2364a 100644 --- a/packages/ludic.render3d/terrain_tiles.ludic +++ b/packages/ludic.render3d/terrain_tiles.ludic @@ -28,6 +28,7 @@ function ter_h(render3d_st: mut Render3dState, tx: int, tz: int) -> float { # the photograph's texel (px, pz) as 0xRRGGBB function ter_o(render3d_st: mut Render3dState, px: int, pz: int) -> int { let side = render3d_st.tt_oside + if side == 0 { return 0 } let s = tt_slot(render3d_st, (pz / side) * render3d_st.tt_n + (px / side)) if s < 0 { return 0 } return render3d_st.tt_o[s * side * side + (pz % side) * side + (px % side)] diff --git a/packages/ludic.render3d/terrain_tiles_cut.ludic b/packages/ludic.render3d/terrain_tiles_cut.ludic index 36899fbe..3a099a5c 100644 --- a/packages/ludic.render3d/terrain_tiles_cut.ludic +++ b/packages/ludic.render3d/terrain_tiles_cut.ludic @@ -9,7 +9,7 @@ const TT_HEAD: int = 64 # bytes: 16 words @alloc_ok("a map being made: its tiles' file and their pools, once, not a frame") function terrain_tiles_cut(render3d_st: mut Render3dState) -> void { - if render3d_st.tt_baked or render3d_st.tt_dir == "" or render3d_st.ter_heights == null or render3d_st.ter_ortho_px == null { return } + if render3d_st.tt_baked or render3d_st.tt_dir == "" or render3d_st.ter_heights == null { return } let t0 = gl_now_us() tt_close(render3d_st) let path = `{render3d_st.tt_dir}/{render3d_st.tt_key}.tiles`