1054 lines
48 KiB
Text
1054 lines
48 KiB
Text
# env.ludic — the one gate every R3D_* switch goes through.
|
|
# The debug views, feature kills, file writers and hardware fakes are developer
|
|
# tools: a headless build (tests, benchmarks, frame dumps) always honours them, a
|
|
# windowed build - which is what a player runs - only when R3D_DEV is set to
|
|
# anything but "0". Read every R3D_* through r3d_env_has / r3d_env, never
|
|
# Os.has_env / Os.env.
|
|
export state Render3dState {
|
|
ac_lit: AcProg = null
|
|
ac_lit_cut: AcProg = null
|
|
ac_sh: AcProg = null
|
|
ac_sh_cut: AcProg = null
|
|
ac_out: AcProg = null
|
|
ac_out_cut: AcProg = null
|
|
@max(2048) ac_actors: []Actor = null
|
|
ac_next_id: int = 0
|
|
@max(2048) ac_spare: []Actor = null # released actors, taken again by actor_new (actor_release)
|
|
ac_frame: int = 0
|
|
ac_oq: []OutlineReq = null
|
|
ac_oq_n: int = 0 # live entries; the array is kept and reused
|
|
ac_oq_closed: bool = true
|
|
ac_census_at: int = -2
|
|
ac_proxy: Mesh = null # the capsule a figure casts in the far cascades (actor.ludic)
|
|
ac_proxy_s: floats = null # its scale and its world matrix, made with it
|
|
ac_proxy_m: floats = null
|
|
ac_lp0: floats = floats(3)
|
|
ac_lpx: floats = floats(3)
|
|
ac_lpy: floats = floats(3)
|
|
ac_lpz: floats = floats(3)
|
|
ac_cc_actors: int = 0
|
|
ac_cc_draws: int = 0
|
|
ac_cc_skinned: int = 0
|
|
ac_cc_cut: int = 0
|
|
cam_pos: floats = null # x, y, z
|
|
cam_yaw: float = 0.0 # radians, 0 = looking down -z
|
|
cam_pitch: float = 0.0
|
|
cam_fov: float = 0.0 # vertical, radians
|
|
cam_near: float = 0.0
|
|
cam_far: float = 0.0
|
|
cam_aspect: float = 0.0
|
|
cam_view: floats = null
|
|
cam_proj: floats = null
|
|
cam_vp: floats = null
|
|
cam_inv_vp: floats = null
|
|
cam_inv_proj: floats = null
|
|
cam_vp_clean: floats = null # view-projection, kept for depth reconstruction
|
|
cam_inv_vp_clean: floats = null
|
|
cam_fwd: floats = null
|
|
cam_right: floats = null
|
|
cam_planes: floats = floats(16)
|
|
day_on: bool = false
|
|
day_hours: float = 0.0 # float bits, 0 .. 24
|
|
day_light: float = 0.0 # 0 night .. 1 full day (float bits)
|
|
day_ibl: floats = null # rgb scale on the sky's light
|
|
day_sun_base: floats = null # the HDRI's sun radiance, kept
|
|
day_az0: float = 0.0 # the sun's azimuth at the reference hour (radians, yaw convention)
|
|
day_yaw0: float = 0.0 # the sky yaw the scene was tuned at
|
|
day_hour0: float = 0.0 # the hour the photograph was taken (10.5)
|
|
day_dir: float = 0.0 # +1 / -1: which way the sun travels in yaw
|
|
day_az: float = 0.0
|
|
day_el: float = 0.0
|
|
day_gen: int = 0 # bumps when the light moved enough to rebake the terrain shadow
|
|
day_baked_az: float = 0.0
|
|
day_baked_el: float = 0.0
|
|
day_sky_baked: float = 0.0 # the sky yaw the convolutions were baked at
|
|
fire_pos: floats = null
|
|
fire_color: floats = null
|
|
day_moon: bool = false
|
|
day_moon_phase: float = 0.5 # 0.5: full, which is where the game used to be
|
|
day_moon_illum: float = 1.0 # the lit fraction, derived from the phase
|
|
day_moon_dir: floats = null # toward the moon, whether or not it is up
|
|
hand_pos: floats = null
|
|
hand_color: floats = null
|
|
hand_dir: floats = null
|
|
hand_cone: float = 0.0
|
|
hand_reach: float = 0.0 # metres the hand light reaches (float bits)
|
|
day_overcast: float = 0.0 # 0 clear .. 1 a low grey sky (float bits): dims the sun and the sky's light
|
|
day_flash: float = 0.0 # a lightning flash this frame (0..1): the sun brightens for it
|
|
day_fog_mul: float = 1.0 # multiplies the base fog density (rain and snow thicken the air)
|
|
day_fog_base: float = 0.0
|
|
ds_on: int = -1 # -1: not read yet
|
|
ds_counting: bool = false
|
|
ds_from: int = 90
|
|
ds_frames: int = 60
|
|
ds_frame_no: int = 0
|
|
ds_outside: pointer = "(outside passes)"
|
|
ds_pass_names: []pointer = null
|
|
ds_pass_prog: []long = null # program changes inside the pass
|
|
ds_pass_tex: []long = null # texture binds inside the pass
|
|
ds_pass_i: int = 0
|
|
ds_row_pass: []int = null
|
|
ds_row_prog: []int = null
|
|
ds_row_kind: []int = null
|
|
ds_row_draws: []long = null
|
|
ds_row_inst: []long = null
|
|
ds_row_idx: []long = null
|
|
ds_last: int = -1
|
|
r3d_dev_v: int = -1
|
|
gltf_dir: string = null
|
|
gltf_bin: pointer = null
|
|
gltf_doc: Val = null
|
|
gltf_count: int = 0
|
|
gltf_ctype: int = 0
|
|
gltf_comps: int = 0
|
|
gltf_tex_paths: []pointer = null
|
|
gltf_tex_ids: words = null
|
|
gltf_tex_refs: words = null # how many primitives use each cached texture (model_release)
|
|
gltf_tex_n: int = 0
|
|
gltf_white: int = 0
|
|
gltf_flat: int = 0
|
|
gltf_mat_names: []string = null
|
|
gltf_mat_diff: words = null
|
|
gltf_mat_nrm: words = null
|
|
gltf_mat_arm: words = null
|
|
gltf_mat_n: int = 0
|
|
gltf_kept: []Model = null # gltf_cached's: a still model by dir, file and node, loaded once
|
|
gltf_kept_dir: []string = null
|
|
gltf_kept_file: []string = null
|
|
gltf_kept_node: []string = null
|
|
gltf_cutout: bool = false # the material being loaded is alpha-blended (a cut-out atlas)
|
|
gpu_kind: int = 0 # the backend running; 0 until gpu_select
|
|
gpu_wanted: int = 0 # what was asked for (setting or R3D_GFX)
|
|
gpu_fallback_reason: string = null # why the wanted backend is not the one running
|
|
gpu_s_depth_test: int = -1
|
|
gpu_s_depth_func: int = -1
|
|
gpu_s_depth_write: int = -1
|
|
gpu_s_blend: int = -1
|
|
gpu_s_blend_src: int = -1
|
|
gpu_s_blend_dst: int = -1
|
|
gpu_s_cull: int = -1
|
|
gpu_s_cull_face: int = -1
|
|
gpu_s_color_write: int = -1
|
|
gpu_s_a2c: int = -1
|
|
gpu_s_bias: int = -1
|
|
gpu_s_bias_f: float = 0.0 # float bits, for a backend that bakes the bias into a pipeline
|
|
gpu_s_bias_u: float = 0.0
|
|
gpu_s_scissor: int = -1
|
|
gpu_prog_ids: []int = null
|
|
gpu_prog_keys: []string = null
|
|
gpu_prog_cur: int = 0
|
|
gpu_u_tmp: words = words(4)
|
|
gpu_cap_probed: bool = false
|
|
gpu_cap_windows: bool = false # the advanced features exist on this platform at all
|
|
gpu_cap_vulkan: bool = false # a Vulkan loader, an instance and a device
|
|
gpu_cap_floor: bool = false # Vulkan 1.3 with everything the renderer's floor needs
|
|
gpu_cap_rt: bool = false # ray query + acceleration structures
|
|
gpu_cap_mesh: bool = false # VK_EXT_mesh_shader
|
|
gpu_cap_nvidia: bool = false
|
|
gpu_cap_rtx: int = 0 # the RTX generation (20, 30, 40, 50); 0 = not RTX
|
|
gpu_cap_reflex: bool = false # VK_NV_low_latency2
|
|
gpu_cap_hdr: bool = false # the instance offers HDR colour spaces
|
|
gpu_cap_device: string = ""
|
|
gpu_tx: words = null
|
|
gpu_tx_cap: int = 0
|
|
gpu_bound_2d: int = 0
|
|
gpu_bound_array: int = 0
|
|
gpu_unit_2d: words = null
|
|
gpu_unit_cur: int = 0
|
|
gpu_fb: words = null
|
|
gpu_fb_cap: int = 0
|
|
gpu_fb_cur: int = 0
|
|
gpu_rb_samples: int = 0
|
|
gpu_drawbufs: words = null
|
|
gpu_variants: []GpuVariant = null
|
|
gvk_ready: bool = false
|
|
gvk_inst: pointer = null
|
|
gvk_pd: pointer = null
|
|
gvk_dev: pointer = null
|
|
gvk_queue: pointer = null
|
|
gvk_family: int = -1
|
|
gvk_mp: bytes = null # VkPhysicalDeviceMemoryProperties
|
|
gvk_device_name: string = ""
|
|
gvk_sc_dead: int = 0 # textures released since the kept-set cache was emptied
|
|
gvk_read_px: bytes = null # gvk_read_screen's read-back, gvk_read_cap bytes, made again only at a new size
|
|
gvk_read_cap: int = 0
|
|
gvk_renderer_name: string = "" # "<device> (Vulkan)", made once with the device
|
|
gvk_why: string = "" # why the device did not come up, for the fallback notice
|
|
gvk_max_aniso: int = 0x3F800000 # the device's anisotropy limit as float bits; 1.0 when it has none
|
|
gvk_want_surface: bool = false # set before gvk_init when the renderer will present to a window
|
|
gvk_has_surface: bool = false # the instance and device can make a surface and a swapchain
|
|
gvk_errlog: string = null
|
|
gvk_errlog_read: bool = false
|
|
gvk_has_mdi: bool = false # multiDrawIndirect + drawIndirectFirstInstance
|
|
gvk_has_dic: bool = false # drawIndirectCount
|
|
gvk_has_mesh: bool = false # VK_EXT_mesh_shader with its meshShader feature on
|
|
gvk_mesh_fn: pointer = null # vkCmdDrawMeshTasksEXT: the device's own, the interposer exports none
|
|
gvk_n_allocs: int = 0
|
|
gvk_blk_mem: []long = null
|
|
gvk_blk_kind: []int = null # memory type * 2, + 1 for images
|
|
gvk_blk_size: []int = null
|
|
gvk_blk_map: []pointer = null
|
|
@max(4096) gvk_fr_blk: []int = null # free ranges: block, offset, length (0 = an unused slot)
|
|
@max(4096) gvk_fr_off: []int = null
|
|
@max(4096) gvk_fr_len: []int = null
|
|
gvk_al_blk: []int = null # per allocation id: its block, or -1 for its own memory
|
|
gvk_al_mem: []long = null # its own memory when it has one
|
|
gvk_al_off: []int = null
|
|
gvk_al_len: []int = null
|
|
gvk_al_map: []pointer = null
|
|
gvk_al_tag: []int = null # per allocation id: owner * 4 + image * 2 + host (vkmem_report.ludic)
|
|
gvk_tag: int = 0 # the owner allocations are made for now (VKM_*)
|
|
gvk_ring_half: int = 0 # the ring half a frame writes, once it has had to grow (gvk_ring_grow)
|
|
gvk_ring_full: bool = false # a frame ran out of ring: grow it at the next reset
|
|
gvk_ring_peak: int = 0 # the most of a ring half a frame has used (R3D_VKMEM)
|
|
vkmem_at: int = 0 # R3D_VKMEM=<frame>: the report is printed at that frame
|
|
sh_layers: int = 5 # the shadow array's layers: the cascades the fog wall needs (shadow_fog)
|
|
fog_imp_released: int = 0 # impostor atlases let go under a fog wall (fog_impostors.ludic)
|
|
fog_imp_rebaked: int = 0
|
|
fog_imp_rebake_us: int = 0
|
|
fog_at: int = 0 # R3D_FOG_AT=<frame>:<m>, a change of the wall mid-run (a dev switch)
|
|
fog_at_m: float = 0.0
|
|
@max(4096) gvk_al_spare: []int = null # ids to reuse
|
|
gvk_pool: long = 0
|
|
gvk_fence: bytes = null
|
|
gvk_frame_fence: bytes = null # the presented frame still on the GPU (one frame in flight)
|
|
gvk_tmp_buf: pointer = null # the per-call scratch ring (gvk_tmp)
|
|
gvk_tmp_off: int = 0
|
|
gvk_seen: words = null # gvk_draw's vertex buffers already bound, reused
|
|
gvk_frame_pending: bool = false
|
|
gvk_frame_pending_cb: pointer = null
|
|
gvk_frame_pending_no: int = -1 # which frame it is (gvk_frame_no when it was submitted)
|
|
gvk_dpools: []long = null # a descriptor pool per frame slot (frame_no & 1)
|
|
gvk_ring_end: int = 0 # the end of this frame's half of the ring
|
|
@max(4096) gvk_retired_frame: []int = null # the last frame that read each retired buffer
|
|
gvk_labels: bool = false # R3D_VK_LABELS: each profiled pass is a debug label (Metal System Trace)
|
|
gvk_inflight: int = -1
|
|
gvk_nopool: bool = false
|
|
gvk_bc_said: int = 0 # attachments refused for being compressed, said so far
|
|
gvk_map_slot: []pointer = null # gvk_mem_new's mapped-pointer slot, made once
|
|
gvk_lay_sig: words = null # gvk_layout_id's scratch: one layout as numbers
|
|
gvk_lay_seen: words = null
|
|
gvk_lay_flat: []int = null # every layout known, end to end; gvk_lay_off / _len find each
|
|
gvk_lay_off: []int = null
|
|
gvk_lay_len: []int = null
|
|
@max(4096) gvk_tex_spare: []int = null # ids of freed textures, handed out again by gvk_tex_new
|
|
@max(4096) gvk_buf_spare: []int = null # the same for buffers (gvk_buf_delete)
|
|
gvk_has_bc: bool = false # textureCompressionBC: .dds textures are uploaded compressed
|
|
# R3D_VK_PROF: Vulkan objects made and destroyed, reported every 120 frames
|
|
gvk_mk_img: int = 0
|
|
gvk_mk_view: int = 0
|
|
gvk_mk_buf: int = 0
|
|
gvk_mk_mem: int = 0
|
|
gvk_mk_smp: int = 0
|
|
gvk_mk_set: int = 0
|
|
gvk_mk_cmd: int = 0
|
|
gvk_mk_dpool: int = 0
|
|
gvk_mk_x_img: int = 0
|
|
gvk_mk_x_view: int = 0
|
|
gvk_mk_x_buf: int = 0
|
|
gvk_mk_x_mem: int = 0
|
|
gvk_label_depth: int = 0 # -1 until asked: 1 leaves the presented frame in flight
|
|
gvk_has_hqr: bool = false
|
|
gvk_ts_period: float = 0.0 # float bits: nanoseconds per timestamp tick
|
|
gvk_qpool: long = 0
|
|
gvk_q_active: int = -1
|
|
gvk_prog_var: []GpuVariant = null
|
|
gvk_prog_vs: []long = null
|
|
gvk_prog_fs: []long = null
|
|
gvk_prog_dsl: []long = null
|
|
gvk_prog_layout: []long = null
|
|
gvk_spv_dir: string = ""
|
|
gvk_spv_len: int = 0
|
|
gvk_prog_mesh: []int = null
|
|
gvk_cp_pipe: []long = null
|
|
gvk_cp_layout: []long = null
|
|
gvk_cp_dsl: []long = null
|
|
gvk_cp_nbuf: []int = null
|
|
gvk_cp_ntex: []int = null
|
|
gvk_pipe_keys: []string = null
|
|
gvk_pipe: []long = null
|
|
gvk_zero_vbuf: int = 0
|
|
gvk_skip_said: words = null # per program: its skipped draws have been reported
|
|
gvk_ublk_v: []bytes = null # per program: the vertex stage's block as last set
|
|
gvk_ublk_f: []bytes = null
|
|
gvk_prog_tex: []words = null # per program: the texture bound to each manifest sampler
|
|
gvk_prog_unit: []words = null # per program: the unit + 1 each sampler was pointed at with u_i
|
|
gvk_prog_dirty: []int = null # per program: its blocks or textures changed since its last set
|
|
gvk_set_last: []long = null # per program: the descriptor set its last draw used
|
|
gvk_set_frame: []int = null # per program: the frame that set belongs to
|
|
gvk_set_tex: []words = null # per program: the textures that set was filled with
|
|
gvk_ring_buf: int = 0 # a gvk_buf handle
|
|
gvk_ring_off: int = 0
|
|
gvk_ring_align: int = 256
|
|
gvk_dpool: long = 0
|
|
gvk_white: int = 0 # a 1x1 white texture for a sampler nothing was bound to
|
|
gvk_msaa_max: int = 0 # samples the scene may use (gvk_frame_init reads the device's limits)
|
|
gvk_kpool: long = 0
|
|
gvk_sc_prog: []int = null # per cached set: its program
|
|
gvk_sc_koff: []int = null # per cached set: where its key starts in gvk_sc_keys
|
|
gvk_sc_set: []long = null
|
|
gvk_sc_next: []int = null # the program's next cached set, -1 at the end
|
|
gvk_sc_keys: []long = null # per texture of a key: handle * 65536 + generation, sampler
|
|
gvk_sc_head: words = null # per program (< 4096): its most recently made set, -1 if none
|
|
@max(130) gvk_sc_tmp: []long = null # this draw's key while it is looked up
|
|
gvk_set_offs: bytes = null # this draw's dynamic offsets, in binding order
|
|
gvk_set_ndyn: int = 0
|
|
@max(4096) gvk_ub_frame: []int = null # per program: the frame its blocks were last copied into the ring
|
|
@max(4096) gvk_ub_offv: []int = null
|
|
@max(4096) gvk_ub_offf: []int = null
|
|
gvk_sc_made: int = 0 # sets made since start (R3D_VK_PROF)
|
|
gvk_default_smp: long = 0 # linear, clamped: for a texture slot nothing was bound to
|
|
gvk_cb: pointer = null
|
|
gvk_in_pass: bool = false
|
|
gvk_fb_cur: int = 0
|
|
gvk_fb_read: int = 0
|
|
gvk_fb_draw: int = 0
|
|
gvk_pass_w: int = 0
|
|
gvk_pass_h: int = 0
|
|
gvk_pass_ncolor: int = 0
|
|
gvk_pass_cfmt: int = 0
|
|
gvk_pass_dfmt: int = 0
|
|
gvk_pass_samples: int = 1 # the attachments' sample count, which every pipeline in the pass must match
|
|
gvk_pass_col: words = null # the pass's colour attachments: texture, layer + 1
|
|
gvk_pass_dep: words = null # its depth attachment: texture, layer + 1
|
|
gvk_clear_bits: int = 0 # GL_COLOR_BUFFER_BIT / GL_DEPTH_BUFFER_BIT waiting for the pass
|
|
gvk_clear_rgba: floats = null # float bits
|
|
gvk_vp: words = null # x, y, w, h
|
|
gvk_sc: words = null # scissor on, x, y (OpenGL rows), w, h
|
|
gvk_screen_color: int = 0
|
|
gvk_screen_depth: int = 0
|
|
gvk_screen_w: int = 0
|
|
gvk_screen_h: int = 0
|
|
gvk_layer_views: []int = null # generation * 4096 + layer, beside gvk_layer_view_tex
|
|
gvk_layer_view: []long = null
|
|
gvk_layer_view_tex: []int = null # the texture each cached view is of, so a release drops them
|
|
gvk_fb_ncolor: words = null # per framebuffer: colour slots drawn (draw buffers; 0 = none)
|
|
gvk_hdr_want: bool = false # r3d_hdr: the setting
|
|
gvk_hdr_on: bool = false # the swapchain is HDR10 now
|
|
gvk_has_colorspace: bool = false # the instance took VK_EXT_swapchain_colorspace
|
|
gvk_has_hdr_meta: bool = false # the device took VK_EXT_hdr_metadata
|
|
r3d_hdr_peak: float = 0.0 # 0 until r3d_hdr_calibrate: 1000
|
|
r3d_hdr_paper: float = 0.0 # 200
|
|
r3d_hdr_black: float = 0.0 # 0
|
|
gvk_fb_counter: int = 0
|
|
gvk_prog_counter: int = 0
|
|
gvk_wireframe: int = 0
|
|
gvk_state: GvkState = null
|
|
gvk_ind_buf: int = 0
|
|
gvk_ind_off: int = 0
|
|
gvk_ind_n: int = 0
|
|
gvk_ind_cbuf: int = 0
|
|
gvk_ind_coff: int = 0
|
|
gvk_mesh_x: int = 0
|
|
gvk_mesh_y: int = 0
|
|
gvk_mesh_z: int = 0
|
|
gvk_surface: long = 0
|
|
gvk_swap: long = 0
|
|
gvk_swap_n: int = 0
|
|
gvk_swap_images: bytes = null
|
|
gvk_swap_fmt: int = 0
|
|
gvk_swap_w: int = 0
|
|
gvk_swap_h: int = 0
|
|
gvk_vsync: bool = true
|
|
gvk_acq_fence: bytes = null
|
|
gvk_swap_stale: bool = false
|
|
gvk_size_buf: words = null
|
|
gvk_prof_state: int = -1
|
|
gvk_us_pipe: long = 0
|
|
gvk_us_set: long = 0
|
|
gvk_us_draw: long = 0
|
|
gvk_n_draws: int = 0
|
|
gvk_n_asked: int = 0 # draws that reached gvk_draw_now: every one the renderer asked for
|
|
gvk_n_flush: int = 0
|
|
gvk_prof_frames: int = 0
|
|
gvk_n_pipe_new: int = 0 # pipelines made this profile window
|
|
gvk_pc_prog: []int = null
|
|
gvk_pc_layout: []int = null
|
|
gvk_pc_state: []int = null
|
|
gvk_pc_bias: []int = null
|
|
gvk_pc_pass: []int = null
|
|
gvk_pc_pipe: []long = null
|
|
gvk_pc_last: words = null
|
|
gvk_tex_image: []long = null
|
|
gvk_tex_view: []long = null
|
|
gvk_tex_mem: []long = null
|
|
gvk_tex_levels: []int = null
|
|
gvk_tex_layers: []int = null
|
|
gvk_tex_vkfmt: []int = null
|
|
gvk_tex_dims_w: []int = null
|
|
gvk_tex_dims_h: []int = null
|
|
gvk_tex_glfmt: []int = null # the format the renderer asked for (gpu.ludic's vocabulary)
|
|
gvk_tex_array: []int = null # 1 for an array image
|
|
gvk_tex_gen: []int = null # bumped whenever the image behind a handle is replaced
|
|
gvk_tex_smp_sig: []int = null # the sampling parameters the cached sampler was made for
|
|
gvk_tex_smp: []long = null
|
|
gvk_tex_samples: []int = null # 1, or the sample count of a multisampled renderbuffer
|
|
gvk_storage_samples: int = 1 # what the next gvk_tex_storage makes: gpu_rb_storage sets it around its call
|
|
gvk_unpack_swap: bool = false # GL_UNPACK_SWAP_BYTES: 16-bit PNG samples arrive big-endian
|
|
gvk_st_buf: long = 0
|
|
gvk_st_mem: long = 0
|
|
gvk_smp_keys: []int = null # 7 numbers per sampler: filters, wraps, compare, anisotropy, bias
|
|
gvk_smp: []long = null
|
|
gvk_buf: []long = null
|
|
gvk_buf_mem: []long = null
|
|
gvk_buf_size: []int = null
|
|
gvk_buf_map: []pointer = null # host-visible buffers stay mapped for their whole life
|
|
gvk_buf_used: []int = null # the frame (gvk_frame_no) a draw last bound the buffer in
|
|
gvk_bsp_buf: []long = null # per handle, a second buffer a re-filled one swaps with (gvk_buf_reserve)
|
|
gvk_bsp_mem: []long = null
|
|
gvk_bsp_size: []int = null
|
|
gvk_bsp_map: []pointer = null
|
|
gvk_bsp_used: []int = null
|
|
gvk_frame_no: int = 1
|
|
@max(4096) gvk_retired_buf: []long = null
|
|
@max(4096) gvk_retired_mem: []long = null
|
|
@max(16384) gvk_buf_gpu: []int = null
|
|
grass_prog: int = 0
|
|
grass_mesh: Mesh = null
|
|
grass_on: bool = true
|
|
grass_kind: GrassKind = null # the kind the blades are (grass_kind.ludic); its wind, sheen and shape
|
|
grass_cell: int = 4 # the kind's hash cell in metres (1, 2 or 4)
|
|
grass_q_s0: float = 0.0 # the settings' tier: no closer spacing than this (grass_quality)
|
|
grass_q_r: float = 0.0 # ... and no blades past this (0: the kind's own radius)
|
|
grass_s0: float = 0.0 # float bits: blade spacing at the camera (m)
|
|
grass_d0: float = 0.0 # the distance at which the spacing has doubled (m)
|
|
grass_radius: float = 0.0 # no blades past this (m)
|
|
grass_draws: int = 0
|
|
grass_dbg: int = 0
|
|
grass_merge: bool = false
|
|
grass_rec: words = null # VkDrawIndexedIndirectCommand records, 5 words each
|
|
grass_tv: floats = null # per record: corner x, corner z, indices per cell, 0 (float bits)
|
|
grass_chunk_tv: floats = null
|
|
grass_n: int = 0
|
|
grass_cmds: int = 0
|
|
grass_band_start: words = null # per band: its first record
|
|
grass_band_cells: words = null # ... and its cells per tile side
|
|
grass_band_n: int = 0
|
|
gg_on: bool = false # the blades are culled on the GPU (grass_gpu.ludic)
|
|
gg_reset: int = 0
|
|
gg_cull: int = 0
|
|
gg_prog: int = 0
|
|
gg_tiles_buf: []int = null
|
|
gg_tv: floats = null
|
|
gg_out: int = 0
|
|
gg_cmds: int = 0
|
|
gg_mesh: []Mesh = null
|
|
gg_n: int = 0
|
|
gg_max: int = 0
|
|
gg_rb: words = null # the per-frame dispatch arguments, made once (grass_gpu.ludic)
|
|
gg_cb: words = null
|
|
gg_bufs: words = null
|
|
gg_texs: words = null
|
|
gg_pr: words = null
|
|
grass_band_mesh: []Mesh = null # per band: the blade it draws (rows fall with distance)
|
|
grass_mesh3: Mesh = null # three rows: the middle distance
|
|
grass_mesh2: Mesh = null # two rows, one quad: far enough that the arch is under a pixel
|
|
grass_mesh_on: bool = false
|
|
grass_mesh_prog: int = 0
|
|
r3d_draw_cb: fn() = null
|
|
r3d_casters_cb: fn(floats) = null
|
|
r3d_fill_cb: fn(Stream, int, int, int) = null
|
|
ov_prog: int = 0
|
|
ov_mesh: Mesh = null
|
|
ov_vbo: int = 0
|
|
ov_buf: pointer = null
|
|
ov_n: int = 0
|
|
ov_tex: int = 0
|
|
ov_mode: int = 2 # what the next quads read: 0 the image texture, 1 the font, 2 a flat colour
|
|
ov_voff: float = 0.0 # float bits: 4 x ov_mode, added to v (overlay.frag)
|
|
ov_white: int = 0
|
|
ov_font: int = 0
|
|
ov_font_adv: floats = null # float bits, em units, one per glyph in the atlas
|
|
ov_font_n: int = 0 # glyphs in the atlas
|
|
ov_font_map: words = null
|
|
ov_font_hi_cp: words = null # code points >= OV_MAP_N, ascending
|
|
ov_font_hi_g: words = null
|
|
ov_font_hi_n: int = 0
|
|
ov_font_space: int = 0 # the glyph for ' ', and for what has none: '?'
|
|
ov_font_qmark: int = 0
|
|
ov_font_cols: int = 16
|
|
ov_font_rows: int = 6
|
|
ov_font_cell: int = 128 # px per cell in the atlas
|
|
ov_font_em: int = 100 # px per em in the atlas
|
|
ov_pad_x: float = 0.0 # float bits, em
|
|
ov_base_y: float = 0.0
|
|
ov_ready: bool = false
|
|
ov_open: bool = false
|
|
ov_dbg: bool = false
|
|
ov_ranges: words = null
|
|
ov_nr: int = 0
|
|
ov_range_start: int = 0
|
|
ov_clip_x: int = 0 # the current clip rectangle in screen pixels (top-left origin)
|
|
ov_clip_y: int = 0
|
|
ov_clip_w: int = 0
|
|
ov_clip_h: int = 0
|
|
ov_prog_sdr: int = 0
|
|
ov_prog_hdr: int = 0
|
|
ov_hdr_scale: float = 0.0 # float bits; 0 until ov_begin sets 1
|
|
ov_u8_len: int = 1
|
|
post_hdr: Target = null
|
|
post_ms_fbo: int = 0 # 4x multisampled scene target, resolved into post_hdr
|
|
post_ms_samples: int = 1 # temporal AA carries the edges; R3D_MSAA=n to compare
|
|
post_bloom: []Target = null
|
|
post_p_down: int = 0
|
|
post_p_up: int = 0
|
|
post_p_tone: int = 0
|
|
post_fs: Mesh = null
|
|
post_exposure: float = 0.0
|
|
post_bloom_strength: int = 0
|
|
post_vignette: float = 0.0
|
|
post_saturation: float = 0.0
|
|
post_contrast: float = 0.0
|
|
post_w: int = 0
|
|
post_h: int = 0
|
|
post_key: float = 0.0 # target mean luminance after exposure (float bits)
|
|
post_lum: words = null
|
|
post_mips: int = 0
|
|
post_adapt: float = 0.0 # smoothed exposure (float bits)
|
|
post_exposure_max: float = 20.0 # 20: the ceiling auto-exposure may reach (night lowers it)
|
|
post_wb_r: float = 1.02 # 1.02
|
|
post_wb_g: float = 1.0 # 1.0
|
|
post_wb_b: float = 0.97 # 0.97
|
|
post_lift_r: float = 0.004 # 0.004
|
|
post_lift_g: float = 0.004 # 0.004
|
|
post_lift_b: float = 0.012 # 0.012
|
|
post_gain_r: float = 0.99 # 0.99
|
|
post_gain_g: float = 0.995 # 0.995
|
|
post_gain_b: float = 1.0 # 1.0
|
|
post_ao: Target = null
|
|
post_ao_blur: Target = null
|
|
post_p_ao: int = 0
|
|
post_p_ao_blur: int = 0
|
|
post_ao_radius: float = 0.0
|
|
post_ao_intensity: float = 0.0
|
|
post_ao_strength: float = 0.0
|
|
post_gi_strength: float = 0.4 # 0.4
|
|
post_no_gi: bool = false
|
|
post_ldr: Target = null
|
|
post_depth_copy: Target = null
|
|
post_vol: Target = null
|
|
post_p_vol: int = 0
|
|
post_vol_density: float = 0.002 # 0.002
|
|
post_vol_falloff: float = 0.005 # 0.005
|
|
post_vol_mist: float = 0.0 # the day sets these two
|
|
post_prev: Target = null # last frame's scene colour, for the SSGI bounce only
|
|
post_scene: Target = null # this frame's scene colour before the water, for refraction
|
|
post_frame: int = 0
|
|
post_color_w: int = 0 # its size: the display's when DLSS upscaled it
|
|
post_color_h: int = 0
|
|
post_color: int = 0 # the HDR colour the rest of post reads # the resolved depth, copied so passes can read it while drawing into the frame
|
|
post_p_sharp: int = 0
|
|
post_p_dof: int = 0
|
|
post_dof: Target = null
|
|
post_p_tone_hdr: int = 0 # the tonemap's HDR10 variant, made the first time HDR is on
|
|
post_ldr_hdr: bool = false # post_ldr was made for HDR10 output (10-bit)
|
|
post_sharpen: float = 0.0
|
|
post_grain: int = 0
|
|
post_adapt_t: []Target = null
|
|
post_adapt_i: int = 0
|
|
post_p_adapt: int = 0
|
|
post_adapt_reset: bool = true
|
|
prof_on: bool = false
|
|
prof_names: []pointer = null
|
|
prof_ids: words = null # PROF_SLOTS * PROF_RING query objects
|
|
prof_ns: []long = null # accumulated nanoseconds per slot
|
|
prof_hits: []long = null # samples accumulated per slot
|
|
prof_n: int = 0 # slots in use
|
|
prof_frame: int = 0
|
|
prof_active: int = -1 # slot whose query is currently open
|
|
prof_scratch: words = null
|
|
prof_gen: []int = null
|
|
prof_gen_cur: int = 0
|
|
prof_ft: []long = null # real frame times, microseconds
|
|
prof_last_us: long = 0
|
|
prof_chunk_us: []long = null
|
|
prof_chunk_kind: []int = null
|
|
prof_chunk_band: []int = null
|
|
prof_chunk_n: []int = null
|
|
prof_gen_us_cur: long = 0
|
|
prof_gen_us: []long = null # generation microseconds per frame
|
|
prof_layer_us_cur: long = 0 # rebuilding and uploading instance buffers
|
|
prof_bake_us_cur: long = 0 # the height-field shadow rebake
|
|
prof_layer_us: []long = null
|
|
prof_bake_us: []long = null
|
|
prof_dt: []long = null # frame time, aligned with the arrays above
|
|
prof_up_cur: long = 0 # instance bytes uploaded this frame
|
|
prof_up: []long = null
|
|
prof_pre_swap: long = 0
|
|
prof_cpu_us: []long = null
|
|
prof_sum_dt: long = 0 # sums over the frames past the first eight, for the mean split
|
|
prof_sum_cpu: long = 0
|
|
prof_sum_game: long = 0
|
|
prof_sum_n: int = 0
|
|
prof_mark_last: long = 0
|
|
prof_mark_best: long = 0
|
|
prof_mark_name: pointer = null
|
|
prof_mark_us: []long = null
|
|
prof_mark_who: []pointer = null
|
|
prof_mk_names: []pointer = null
|
|
prof_mk_us: []long = null
|
|
prof_mk_n: int = 0
|
|
prof_game_us_cur: long = 0
|
|
prof_game_us: []long = null
|
|
r3d_root: string = "packages/ludic.render3d" # where shaders/ lives
|
|
r3d_assets: string = "assets/polyhaven" # where the CC0 assets live
|
|
r3d_root_found: bool = false
|
|
r3d_prog_log: int = -1
|
|
q_scratch: floats = floats(16)
|
|
q_sy: floats = null # views of q_scratch's second, third and fourth
|
|
q_sz: floats = null
|
|
q_st: floats = null
|
|
r3d_sky_prog: int = 0
|
|
r3d_fog_wall: float = 0.0 # r3d_fog_wall: > 0, nothing past it is seen or drawn
|
|
r3d_fog_density: float = 0.0
|
|
r3d_fog_falloff: float = 0.0
|
|
r3d_fog_inscatter: float = 0.02 # 0.02, what the shader used to hard-code
|
|
r3d_fog_desat: float = 1.35 # 1.35
|
|
r3d_sky_relight: float = 0.0
|
|
r3d_time: float = 0.0
|
|
r3d_ready: bool = false
|
|
r3d_plate: bool = false
|
|
r3d_small: bool = false # set before r3d_open: a small UI window (a launcher) - the ring, the memory blocks and the descriptor pools sized for it
|
|
r3d_sky_path: string = null
|
|
r3d_debug: bool = false
|
|
r3d_debug_shadow: bool = false
|
|
r3d_clip_y: float = -2147483600.0 # -2^31: no clipping
|
|
r3d_prepass_env: int = -1
|
|
r3d_test_frame: int = 0
|
|
r3d_test_resize: int = 0
|
|
r3d_no_shadow: bool = false
|
|
r3d_no_trees: bool = false
|
|
r3d_no_refl: bool = false
|
|
r3d_cam_log: int = -1
|
|
sc_prog: int = 0
|
|
sc_prog_fol: int = 0
|
|
sc_prog_wind: int = 0
|
|
sc_prog_blade: int = 0
|
|
sc_prog_flower: int = 0
|
|
sc_prog_card: int = 0
|
|
sc_prog_card_shadow: int = 0
|
|
sc_prog_card_cheap: int = 0
|
|
sc_blade_base: floats = null
|
|
sc_blade_tip: floats = null
|
|
sc_blade_tint: floats = null
|
|
sc_prog_shadow: int = 0
|
|
sc_prog_shadow_wind: int = 0
|
|
sc_prog_shadow_fol: int = 0 # foliage meshes: alpha-tested casters
|
|
sc_prog_fol_depth: int = 0
|
|
sc_prog_fol_eq: int = 0
|
|
sc_prepass: bool = false # the main pass is drawing over what the prepass laid down
|
|
sc_imp_prog: int = 0
|
|
sc_imp_prog_shadow: int = 0
|
|
sc_bake_prog: int = 0
|
|
sc_bake_card_prog: int = 0
|
|
sc_bake_flower_prog: int = 0
|
|
sc_card: Mesh = null
|
|
sc_ident_buf: int = 0
|
|
sc_layers: []Layer = null
|
|
sc_debug_dump: bool = false
|
|
sc_printed: bool = false
|
|
sc_dump_n: int = 0
|
|
sc_view_gen: int = 1
|
|
sc_view_pos: floats = null
|
|
sc_view_fwd: floats = null
|
|
sc_cull_prog: int = 0
|
|
sc_cull_tried: bool = false
|
|
sc_ind_base: int = -1 # >= 0: layer_draw_model / layer_draw_depth draw records from here
|
|
sc_ind_n: int = 1 # records each of those draws covers: one per level of a material
|
|
sc_ind_stride: int = 4 # records between one material's first and the next's (3 for the shadow LOD)
|
|
sc_freeze: bool = false # a secondary pass (reflection) reuses the partition
|
|
sc_dbg_level: int = -1
|
|
sc_dbg_lod: bool = false
|
|
sc_dbg_tint: floats = null
|
|
sc_cast_all: int = -1
|
|
sc_cast_gen: int = -1
|
|
sc_cast_dy: float = 0.0
|
|
sc_cast_k: float = 0.0
|
|
sc_skip_blade: bool = false
|
|
sc_skip_grass: bool = false
|
|
grass_force: bool = false # R3D_BLADES: the blades on whatever the game set
|
|
grass_env_off: bool = false # R3D_NOBLADES: the blades off whatever the game set
|
|
sc_skip_card: bool = false
|
|
cb_state: int = 12345
|
|
shadow_res: int = 2048
|
|
shadow_refused: int = 0 # the last size the graphics card had no memory for (0: none)
|
|
sh_tex: int = 0
|
|
sh_fbo: int = 0
|
|
sh_vp: floats = null # the cascades' view-projections, 16 floats each
|
|
sh_vp_v: [][]float = null # a view of each
|
|
sh_split: floats = null # view-space far distance of each cascade
|
|
sh_range: floats = null # 4 light-frustum depth extents (metres)
|
|
sh_texel: floats = null # 4 shadow texel sizes (metres)
|
|
sh_tmp_proj: floats = null
|
|
sh_tmp_vp: floats = null
|
|
sh_tmp_inv: floats = null
|
|
sh_tmp_view: floats = null
|
|
sh_corner: floats = null
|
|
sh_cascade: int = 0 # the cascade being rendered (for casters that skip far ones)
|
|
sh_printed2: bool = false
|
|
sh_printed3: bool = false
|
|
sh_force: int = -1 # R3D_FORCE=<c> pins every pixel to cascade c (debug)
|
|
sh_printed: bool = false
|
|
sky_tex: int = 0
|
|
sky_w: int = 0
|
|
sky_h: int = 0
|
|
sky_irradiance: int = 0
|
|
sky_prefilter: int = 0 # GL_TEXTURE_2D_ARRAY
|
|
sky_brdf: int = 0
|
|
sun_dir: floats = null # toward the sun (float bits)
|
|
sun_color: floats = null # radiance (float bits)
|
|
sky_fullscreen: Mesh = null
|
|
sky_yaw: float = 0.0 # radians: the HDRI is turned by this about y
|
|
sky_rot_s: float = 0.0
|
|
sky_rot_c: float = 0.0
|
|
sun_hdri: floats = null # the sun direction as found in the file
|
|
sky_baked: bool = false # the IBL set exists, baked at sky_baked_yaw
|
|
sky_baked_yaw: float = 0.0
|
|
sky_p_irr: int = 0
|
|
sky_p_pre: int = 0
|
|
sky_p_brdf: int = 0
|
|
sky_prefilter_w: int = 512
|
|
sky_bake_dir: string = "" # where the sky's IBL bakes are (sky_baked_in, bake_load.ludic); "" = none
|
|
sky_bake_key: string = ""
|
|
sky_bake_version: int = 0
|
|
sky_bake_said: bool = false # a missing bake said once
|
|
STREAM_MAX_CHUNKS: int = 4096
|
|
stream_all: []Stream = null
|
|
stream_cap_read: bool = false
|
|
stream_no_evict: bool = false # R3D_NOEVICT: the old behaviour, for comparison
|
|
stream_walk_no: int = 0 # counts ring walks; a chunk's age is measured in these
|
|
stream_evictions: int = 0
|
|
stream_us_gen: long = 0 # generating new chunks (stream_fill)
|
|
stream_us_gather: long = 0 # copying cached chunks into the layer buffer
|
|
stream_us_walk: long = 0 # the ring walk itself
|
|
stream_walks: int = 0 # streams that walked their whole ring this frame
|
|
stream_debug_n: int = 0
|
|
stream_scratch: floats = null
|
|
gvk_pipe_bufs: words = null # a pipeline's vertex buffers, while it is made
|
|
gsl_up: floats = floats(3)
|
|
sh_fit_cview: floats = floats(3) # shadow_fit's scratch
|
|
sh_fit_corners: floats = floats(24)
|
|
sh_fit_center: floats = floats(3)
|
|
sh_fit_eye: floats = floats(3)
|
|
sh_fit_up: floats = floats(3)
|
|
sh_fit_out: floats = floats(16)
|
|
water_eye: floats = floats(3) # water_reflection_pass's scratch
|
|
water_mirror: floats = floats(16)
|
|
water_mv: floats = floats(16)
|
|
sc_lod_counts: words = words(64) # layer_partition_lods' scratch (SC_LOD_ROOM)
|
|
sc_lod_start: words = words(64)
|
|
sc_lod_fill: words = words(64)
|
|
sc_gpu_rec: words = words(29 * 5) # layer_gpu_prepare's (SC_RECS * 5) and layer_gpu_cull's
|
|
sc_gpu_zeros: words = words(5)
|
|
sc_gpu_pr: words = words(36)
|
|
sc_gpu_bufs: words = words(4) # the camera's up for DLSS's constants
|
|
ov_nine_buf: floats = floats(16) # ov_nine's corners and uvs
|
|
gvk_ac: pointer = null # the VkAllocationCallbacks every create and destroy is given (R3D_ALLOC_VK=1)
|
|
gvk_prime_b: words = null # buffers made since the frame began, read once so MoltenVK makes their
|
|
@max(16384) gvk_prime_h: []long = null # Metal buffers now (gvk_prime), and their handles
|
|
gvk_prime_n: int = 0
|
|
gvk_prime_dst: long = 0 # the 64 bytes those reads land in
|
|
gvk_prime_mem: long = 0
|
|
stream_loose: Chunk = null # the record for a chunk no stream's cache can keep this walk
|
|
stream_deadline: long = 0
|
|
gsl_on: bool = false # slInit succeeded: the interposer is the loader, the plugins are in
|
|
gsl_dlss_ok: bool = false # what this adapter can run, from slIsFeatureSupported
|
|
gsl_rr_ok: bool = false
|
|
gsl_fg_ok: bool = false
|
|
gsl_reflex_ok: bool = false
|
|
gsl_pcl_ok: bool = false
|
|
gsl_feats: bytes = null # kept alive: Preferences points at it
|
|
gsl_logdir: bytes = null # and at this
|
|
gsl_vp: bytes = null # sl::ViewportHandle 0, the one view
|
|
gsl_tok_buf: bytes = null
|
|
gsl_idx_buf: bytes = null
|
|
gsl_token: pointer = null # this frame's sl::FrameToken, owned by Streamline
|
|
gsl_frame_n: int = 0
|
|
gsl_said: bool = false # one failure message, not one a frame
|
|
gsl_fresh: bool = false # a token was taken since the last frame started (a present took it)
|
|
gsl_reflex_mode: int = 0 # 0 off, 1 low latency, 2 low latency + boost
|
|
gsl_reflex_applied: int = -1
|
|
gsl_f_sleep: pointer = null
|
|
gsl_f_marker: pointer = null
|
|
gsl_dlss_mode: int = 0 # 0 off, 1 DLAA, 2 quality, 3 balanced, 4 performance
|
|
gsl_opts: bytes = null
|
|
gsl_opt_mode: int = -1
|
|
gsl_opt_w: int = 0
|
|
gsl_opt_h: int = 0
|
|
gsl_rw: int = 0 # the render size DLSS asked for
|
|
gsl_rh: int = 0
|
|
gsl_set_mode: int = -1
|
|
gsl_set_w: int = 0
|
|
gsl_set_h: int = 0
|
|
gsl_mv: Target = null
|
|
gsl_out: Target = null
|
|
gsl_consts: bytes = null
|
|
gsl_tags: bytes = null
|
|
gsl_res: bytes = null
|
|
gsl_inputs: bytes = null
|
|
gsl_prev_vp: floats = null
|
|
gsl_reset: bool = true
|
|
gsl_jitter_x: float = 0.0 # float bits, NDC offsets the projection carries this frame
|
|
gsl_jitter_y: float = 0.0
|
|
gsl_jpx: float = 0.0 # float bits, the same in pixels
|
|
gsl_jpy: float = 0.0
|
|
gsl_eval_ok: bool = true # the last evaluate worked: only then is the next frame jittered
|
|
TERRAIN_HALF: int = 4096 # world half-size in metres (8 km square)
|
|
cd_mesh: Mesh = null
|
|
cd_range: floats = null # float bits: how far each level is drawn
|
|
cd_min: []floats = null # per level: min height of each patch (float bits)
|
|
cd_max: []floats = null
|
|
cd_draws: int = 0
|
|
cd_far_draws: int = 0
|
|
cd_near_draws: int = 0
|
|
ter_force_far: bool = false
|
|
ter_no_split: bool = false
|
|
ter_force_near: bool = false
|
|
ter_skip: bool = false
|
|
ter_height_tex: int = 0
|
|
ter_normal_tex: int = 0 # the baked surface normal, x and z in RG16F (y rebuilt when read)
|
|
ter_heights: floats = null # CPU copy, float bits, TERRAIN_RES^2
|
|
ter_reflect: bool = false # drawing the reflection: the mid mesh is plenty
|
|
ter_prog: int = 0
|
|
ter_prog_far: int = 0
|
|
ter_prog_near: int = 0 # the detailed tier alone (NEAR_ONLY)
|
|
ter_sun_prog: int = 0 # tersun.frag: sun visibility into a screen buffer
|
|
ter_sun_inline: bool = false # the ground's shader reads the cascades itself (Vulkan); no sun pass
|
|
ter_sun_tgt: Target = null # that buffer, at the frame's size
|
|
ter_sun_refl: Target = null # and at the reflection's, which is smaller
|
|
ter_sun_dumped: bool = false
|
|
ter_sun_checked: bool = false
|
|
ter_sun_done: bool = false # the caller already ran the pass (so it can time it)
|
|
ter_sun_pass: bool = false # selection is drawing the visibility pass
|
|
ter_sun_tex: int = 0
|
|
ter_prog_cur: int = 0 # the program currently bound during selection
|
|
ter_smooth: bool = false # generate the analytic test ground instead of a survey
|
|
ter_far_split: float = 0.0 # metres: beyond this the terrain takes its cheap far path (R3D_TFAR)
|
|
ter_far_band: float = 0.0 # half-width of the near/far blend (R3D_TBAND)
|
|
ter_snow_line: float = 0.0
|
|
ter_tex: words = null # 11 material textures (see terrain_bind)
|
|
ter_ox: float = 0.0 # world x/z of the terrain centre (float bits)
|
|
ter_oz: float = 0.0
|
|
ter_dem_tex: int = 0 # a real height map (16-bit), or 0 for the procedural valley
|
|
ter_dem_min: float = 0.0
|
|
ter_dem_max: float = 0.0
|
|
ter_dem_base: float = 0.0
|
|
ter_ortho_tex: int = 0 # a photograph of the same window, draped with distance
|
|
ter_carpet: int = 0 # the distant-grass carpet (carpet_bake), 0 = none
|
|
ter_shadow_tex: int = 0 # height-field sun shadow: R32F, the lowest lit height
|
|
stream_capture_c: Chunk = null # the bake's capture chunk (stream_baked.ludic)
|
|
sb_rec: floats = floats(8) # one decoded baked record, reused (stream_baked.ludic)
|
|
tb_tiles: string = "" # the map's baked tiles and shadow (terrain_baked_boot.ludic)
|
|
tb_shadow: string = ""
|
|
tb_key: string = ""
|
|
tb_version: int = 0
|
|
tb_shadow_ok: bool = false # the shadow came from its bake this map
|
|
gltf_pure: int = 0 # a 1x1 white a factor multiplies exactly (gltf_factors)
|
|
gd_file: pointer = null # the map's ground densities (ground_density.ludic)
|
|
gd_base: int = 0
|
|
gd_n: int = 0
|
|
gd_layers: int = 0
|
|
gd_ch: words = null
|
|
gd_off: words = null
|
|
gd_pool: []byte = null
|
|
gd_key: words = null
|
|
gd_ref: words = null
|
|
gd_slot_of: words = null
|
|
gd_hand: int = 0
|
|
gd_trample_cb: fn(float, float) -> float = null
|
|
gb_layer: int = -1 # the densities' layer the blades grow by; -1: the rules (grass_density.ludic)
|
|
gb_buf: int = 0 # its window round the camera, on the GPU
|
|
gb_win: words = null # ... and the window's bytes, four texels a word, made once
|
|
gb_tx: int = -1000000 # the window's first texel in the map, x and z (-1000000: not filled)
|
|
gb_tz: int = 0
|
|
tt_dir: string = "" # terrain_tiles_to: where a map's tiles are written ("" keeps the whole copies)
|
|
tt_key: string = ""
|
|
tt_file: pointer = null # the tiles' file, open for reading (terrain_tiles.ludic)
|
|
tt_n: int = 0 # tiles a side
|
|
tt_oside: int = 0 # photograph texels a tile a side
|
|
tt_hoff: int = 0 # where the heights and the photograph start in the file
|
|
tt_ooff: int = 0
|
|
tt_noff: int = 0
|
|
tt_h: floats = null # TT_SLOTS tiles of heights
|
|
tt_o: words = null # ... and of photograph, 0xRRGGBB
|
|
tt_nm: words = null # ... and of normals, RG16F in a word
|
|
tt_tab: floats = null # per tile: its heights' minimum and step (terrain_ltt2_*.ludic)
|
|
tt_scratch: []byte = null # one tile's bytes as read
|
|
tt_cnoff: int = 0 # the coarse normals and photograph in the file
|
|
tt_cooff: int = 0
|
|
tt_baked: bool = false # the terrain came from a bake: nothing is generated or cut
|
|
tt_coarse: floats = null # the heights at TT_COARSE a side, for terrain_height_near
|
|
tt_slot_of: words = null # per tile: its slot, or -1
|
|
tt_tile_in: words = null # per slot: its tile, or -1
|
|
tt_ref: words = null # per slot: asked for since the clock's hand last passed
|
|
tt_hand: int = 0
|
|
tt_reads: int = 0 # tiles read from the file, over the run and this frame
|
|
tt_frame_reads: int = 0
|
|
tt_warned: bool = false
|
|
tp_on: bool = false # the GPU pages the fine tiles round the camera (terrain_pages.ludic)
|
|
tp_page_tex: int = 0 # R32F tt_n a side: slot + 1 of each resident tile, 0 = the coarse level
|
|
tp_h_tex: int = 0 # the pool: heights, normals and photograph, a layer a slot
|
|
tp_n_tex: int = 0
|
|
tp_o_tex: int = 0
|
|
tp_dummy_page: int = 0 # bound while paging is off: an array sampler needs an array
|
|
tp_dummy_h: int = 0
|
|
tp_dummy_n: int = 0
|
|
tp_dummy_o: int = 0
|
|
tp_slots: int = 0
|
|
tp_reach: float = 0.0 # metres the pool was sized for
|
|
tp_page: floats = null # the page table's CPU mirror, uploaded whole when it changes
|
|
tp_tile_of: words = null # per slot: its tile, or -1
|
|
tp_free: words = null # the free slots, a stack
|
|
tp_nfree: int = 0
|
|
tp_dirty: bool = false
|
|
tp_cam_t: int = -1 # the camera's tile when residency last ran
|
|
tp_short: bool = false # a wanted tile was left for the next frame
|
|
tp_cand: words = null # this frame's loads, nearest first: their tiles, distances, slots
|
|
tp_cand_d: floats = null
|
|
tp_cand_s: words = null
|
|
tp_zero: words = null # the one layer a 2-D texture has, for gpu_layers_copy
|
|
tp_st_buf: long = 0 # the staging buffer the loads are written into, two halves
|
|
tp_st_mem: long = 0
|
|
tp_st_ptr: pointer = null
|
|
tp_st_bytes: int = 0
|
|
tp_loads: int = 0 # tiles loaded over the run, and this frame
|
|
tp_frame_loads: int = 0
|
|
tp_bytes: int = 0 # the pool's and the page table's GPU bytes
|
|
ter_shadow_prog_aux: int = 0 # the bake of the aux target (TS_AUX)
|
|
ter_shadow_aux: int = 0 # beside it, RG16F: the occluder distance and the cloud mask
|
|
ter_shadow_yaw: float = 1000000000.0 # the sky yaw it was baked for
|
|
ter_shadow_gen: int = -1 # the daylight generation it was baked for
|
|
ter_shadow_prog: int = 0
|
|
ter_lake_level: float = 0.0 # a lake carved into the height map (float bits; ex = 0 → none)
|
|
ter_lake_cx: float = 0.0
|
|
ter_lake_cz: float = 0.0
|
|
ter_lake_ex: float = 0.0
|
|
ter_lake_ez: float = 0.0
|
|
ter_lake_carve: bool = true
|
|
ter_sea_level: float = 0.0
|
|
ter_sea_set: bool = false
|
|
ter_isle_cx: float = 0.0
|
|
ter_isle_cz: float = 0.0
|
|
ter_isle_r: float = 0.0
|
|
ter_isle_fall: float = 0.0
|
|
ter_isle_mode: int = 0
|
|
ter_ortho_px: pointer = null # the photograph on the CPU (RGB8, TERRAIN_RES^2) for placement rules
|
|
ter_ortho_w: int = 0
|
|
ter_ortho_c: int = 3
|
|
ter_h_scale: float = 0.0
|
|
ter_o_scale: float = 0.0
|
|
ter_bw: floats = floats(8)
|
|
ter_wire: bool = false
|
|
ter_printed: bool = false
|
|
ter_scr: floats = floats(16)
|
|
tex_w: int = 0 # the last decoded image
|
|
tex_h: int = 0
|
|
tex_channels: int = 0
|
|
tex_depth: int = 0 # bits per sample (8 or 16)
|
|
tex_file_len: int = 0
|
|
tex_anisotropy: fixed = 16.0
|
|
tex_size_ws: []int = new []int
|
|
tex_size_hs: []int = new []int
|
|
hdr_max_lum: float = 0.0 # float bits of the brightest texel (sun finding)
|
|
hdr_max_x: int = 0
|
|
hdr_max_y: int = 0
|
|
hdr_sun_r: float = 0.0 # irradiance (float bits) of everything above the IBL clip: the sun
|
|
hdr_sun_g: float = 0.0
|
|
hdr_sun_b: float = 0.0
|
|
hdr_clip: float = 0.0 # float bits; texels above this (per channel) feed the sun, not the IBL
|
|
tex_dump_alpha: bool = false
|
|
water_mesh: Mesh = null
|
|
water_prog: int = 0
|
|
water_level: float = 0.0
|
|
water_cx: float = 0.0
|
|
water_cz: float = 0.0
|
|
water_ex: float = 0.0
|
|
water_ez: float = 0.0
|
|
water_on: bool = false
|
|
water_refl: Target = null # the world mirrored in the surface, half resolution
|
|
water_refl_div: int = 2 # R3D_REFLDIV overrides: 2 = half res, 4 = quarter
|
|
water_saved: floats = floats(16 * 4 + 3) # the real camera's matrices, restored after the pass
|
|
water_saved_vp: floats = null # views of its second and third matrices
|
|
water_saved_ivp: floats = null
|
|
water_dumped: bool = false
|
|
wb_n: int = 0
|
|
wb_level: floats = null
|
|
wb_cx: floats = null
|
|
wb_cz: floats = null
|
|
wb_ex: floats = null
|
|
wb_ez: floats = null
|
|
wb_reflect: words = null
|
|
wb_primary: int = -1 # the body the reflection pass mirrors, or -1
|
|
wb_cells: floats = null # x0, z0, x1, z1 of each rectangle with water showing
|
|
wb_ncells: int = -1 # -1: not built for the current mirrored body
|
|
wb_blocks: words = null # x0, z0, x1, z1, first cell, cells past the last - of each block
|
|
wb_nblocks: int = 0
|
|
wb_refl_always: int = -1
|
|
wb_dbg: int = -1
|
|
wb_build_us: long = 0 # how long the last water_cells_build took (R3D_REFL_DBG prints it)
|
|
grass_blade_tex: int = 0
|
|
grass_blade_cols: int = 8
|
|
grass_push_x: float = 0.0
|
|
grass_push_z: float = 0.0
|
|
grass_push_r: float = 0.0
|
|
post_auto: bool = true
|
|
post_contact: float = 1.25 # 1.25: how hard a thing is darkened where it meets the ground
|
|
post_vol_steps: float = 24.0 # 24
|
|
post_vol_far: float = 800.0 # 800 m
|
|
post_vol_g: float = 0.6 # 0.6: air throws light forward
|
|
post_vol_mist_h: float = 40.0 # 40 m
|
|
post_fxaa: float = 1.0
|
|
post_dof_focus: float = 10.0 # 10 m
|
|
post_dof_aperture: float = 0.0 # 0 = no lens, and no pass
|
|
post_dof_max: float = 12.0 # 12 px
|
|
r3d_global_defs: string = ""
|
|
r3d_fog_scale: float = 1.0 # float bits: a setting's multiplier over the density the day sets
|
|
r3d_fog_base: float = 0.0 # the height fog is measured from (float bits); 0 = y = 0
|
|
r3d_ground_alb_r: float = 0.3
|
|
r3d_ground_alb_g: float = 0.34
|
|
r3d_ground_alb_b: float = 0.14
|
|
r3d_ground_hi_r: float = 0.289
|
|
r3d_ground_hi_g: float = 0.28
|
|
r3d_ground_hi_b: float = 0.26
|
|
r3d_ground_hi_y: float = 480.0 # 480
|
|
r3d_ground_hi_w: float = 150.0 # 150
|
|
r3d_dem_path: string = null
|
|
r3d_dem_min: float = 0.0
|
|
r3d_dem_max: float = 0.0
|
|
r3d_dem_base: float = 0.0
|
|
r3d_dem_ox: float = 0.0
|
|
r3d_dem_oz: float = 0.0
|
|
r3d_ortho_path: string = null
|
|
r3d_debug_max: bool = false
|
|
r3d_cloud_shadow: float = 0.5 # 0.5
|
|
sc_a2c: bool = true
|
|
sc_bake_flower: bool = false
|
|
sc_dbg_blade: int = 0
|
|
sc_skip_flower: bool = false
|
|
sh_enabled: bool = true
|
|
sh_skip_terrain: bool = false
|
|
sh_probe_x: float = 0.0
|
|
sh_probe_y: float = 0.0
|
|
sh_probe_z: float = 0.0
|
|
sky_sun_boost: float = 2.3 # 2.3: the photograph's thin cloud dims its sun; a crisper day wants more
|
|
sky_start_yaw: float = 0.0
|
|
STREAM_BUDGET_US: int = 2500 # microseconds of generation per frame; a setting may move it
|
|
stream_budget_left: int = 0
|
|
ter_wet: float = 0.0
|
|
ter_dem_blur: float = 0.0 # gaussian texels applied to the survey (0 for lidar; ~3 for 30 m data)
|
|
wt_wade_x: float = 0.0
|
|
wt_wade_z: float = 0.0
|
|
wt_wade_s: float = 0.0
|
|
}
|
|
function r3d_dev(render3d_st: mut Render3dState) -> bool {
|
|
if render3d_st.r3d_dev_v < 0 { if Os.has_env("R3D_DEV") and Os.env("R3D_DEV") != "0" { render3d_st.r3d_dev_v = 1 } else { render3d_st.r3d_dev_v = 0 } }
|
|
return render3d_st.r3d_dev_v == 1
|
|
}
|
|
function r3d_env_has(render3d_st: mut Render3dState, name: string) -> bool {
|
|
if is_windowed() and not r3d_dev(render3d_st) { return false }
|
|
return Os.has_env(name)
|
|
}
|
|
function r3d_env(render3d_st: mut Render3dState, name: string) -> string {
|
|
if is_windowed() and not r3d_dev(render3d_st) { return "" }
|
|
return Os.env(name)
|
|
}
|