# 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 ac_actors: []Actor = null ac_next_id: int = 0 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_lp0: floats = null ac_lpx: floats = null ac_lpy: floats = null ac_lpz: floats = null 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 = null 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_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_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 = null 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_glcheck: int = -1 gpu_rb_samples: int = 0 gpu_drawbufs: words = null gpu_glcheck_seen: []string = 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_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 gvk_fr_blk: []int = null # free ranges: block, offset, length (0 = an unused slot) gvk_fr_off: []int = null 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_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 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 # 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 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 gvk_ub_frame: []int = null # per program: the frame its blocks were last copied into the ring gvk_ub_offv: []int = null 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_layout_keys: []string = null 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: []string = null 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_frame_no: int = 1 gvk_retired_buf: []long = null gvk_retired_mem: []long = null gvk_buf_gpu: []int = null grass_prog: int = 0 grass_mesh: Mesh = null grass_on: bool = true grass_wind: float = 0.0 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_noise_src: string = null r3d_lighting_src: string = null r3d_wind_src: string = null r3d_prog_log: int = -1 q_scratch: floats = null 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_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_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= 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 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 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_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: RG32F (lowest lit height, occluder distance) 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 = null ter_wire: bool = false ter_printed: bool = false ter_scr: floats = null 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_ids: []int = new []int 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 = null # 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) }