Compare commits

...

6 Commits

Author SHA1 Message Date
733cdd2760 lot's of work on polishing the engine 2026-03-20 18:49:19 +02:00
4697c016e1 Merge branch 'main' of git.ktj.st:katajisto/trueno 2026-03-11 13:00:36 +02:00
89c0e36bee wip work 2026-03-11 13:00:25 +02:00
1bfe79fc6b work on editor 2026-03-04 19:30:50 +02:00
8668157060 small improvements 2026-03-04 16:33:17 +02:00
629af83d9b trile editing fixes 2026-03-02 20:48:50 +02:00
47 changed files with 10334 additions and 6844 deletions

View File

@ -6,8 +6,12 @@ Iprof :: #import "Iprof"(IMPORT_MODE = .METAPROGRAM);
Trueno_Build_Options :: struct {
wasm_build : bool;
release_build : bool;
tacoma_enabled : bool;
iprof_enabled : bool;
tacoma_enabled : bool;
iprof_enabled : bool;
demo_build : bool;
test_engine : bool;
test_game : bool;
short_tests : bool;
}
build_options_from_args :: (args: []string) -> Trueno_Build_Options {
@ -23,6 +27,17 @@ build_options_from_args :: (args: []string) -> Trueno_Build_Options {
opts.release_build = true;
case "iprof";
opts.iprof_enabled = true;
case "demo";
opts.demo_build = true;
case "test";
opts.test_game = true;
opts.test_engine = true;
case "test_game";
opts.test_game = true;
case "test_engine";
opts.test_engine = true;
case "test_short";
opts.short_tests = true;
}
}
@ -108,7 +123,7 @@ native_build :: (opts: Build_Options, trueno_opts: Trueno_Build_Options) {
// }
compiler_begin_intercept(w);
add_trueno_opts_to_compiler_strings(trueno_opts, w);
add_build_file("src/platform_specific/main_native.jai", w);
add_shaders_to_workspace(w);
@ -185,6 +200,8 @@ wasm_build :: (opts: Build_Options, trueno_opts: Trueno_Build_Options) {
}
exit(1);
}
file_delete("dist/main.o");
}
#run {

View File

@ -24,149 +24,4 @@ VK_KHR_deferred_host_operations
VK_KHR_acceleration_structure
VK_KHR_ray_query
BLAS Compaction: 0.7MB -> 0.2MB (0.4MB saved, 66.0% smaller)
_______________
Vulkan Version:
- available: 1.4.309
- requesting: 1.3.0
______________________
Used Instance Layers :
VK_LAYER_KHRONOS_validation
Used Instance Extensions :
____________________
Devices : 1
0: AMD Radeon RX 6950 XT
- Compatible
Compatible physical devices found : 1
Using Device:
- Device Name : AMD Radeon RX 6950 XT
- Vendor : AMD
- Driver Version : 2.0.341
- API Version : 1.4.308
- Device Type : Discrete GPU
________________________
Used Device Extensions :
VK_KHR_deferred_host_operations
VK_KHR_acceleration_structure
VK_KHR_ray_query
BLAS Compaction: 0.7MB -> 0.2MB (0.4MB saved, 66.0% smaller)
_______________
Vulkan Version:
- available: 1.4.309
- requesting: 1.3.0
______________________
Used Instance Layers :
VK_LAYER_KHRONOS_validation
Used Instance Extensions :
____________________
Devices : 1
0: AMD Radeon RX 6950 XT
- Compatible
Compatible physical devices found : 1
Using Device:
- Device Name : AMD Radeon RX 6950 XT
- Vendor : AMD
- Driver Version : 2.0.341
- API Version : 1.4.308
- Device Type : Discrete GPU
________________________
Used Device Extensions :
VK_KHR_deferred_host_operations
VK_KHR_acceleration_structure
VK_KHR_ray_query
BLAS Compaction: 0.7MB -> 0.2MB (0.4MB saved, 66.0% smaller)
_______________
Vulkan Version:
- available: 1.4.309
- requesting: 1.3.0
______________________
Used Instance Layers :
VK_LAYER_KHRONOS_validation
Used Instance Extensions :
____________________
Devices : 1
0: AMD Radeon RX 6950 XT
- Compatible
Compatible physical devices found : 1
Using Device:
- Device Name : AMD Radeon RX 6950 XT
- Vendor : AMD
- Driver Version : 2.0.341
- API Version : 1.4.308
- Device Type : Discrete GPU
________________________
Used Device Extensions :
VK_KHR_deferred_host_operations
VK_KHR_acceleration_structure
VK_KHR_ray_query
BLAS Compaction: 0.7MB -> 0.2MB (0.4MB saved, 66.0% smaller)
_______________
Vulkan Version:
- available: 1.4.309
- requesting: 1.3.0
______________________
Used Instance Layers :
VK_LAYER_KHRONOS_validation
Used Instance Extensions :
____________________
Devices : 1
0: AMD Radeon RX 6950 XT
- Compatible
Compatible physical devices found : 1
Using Device:
- Device Name : AMD Radeon RX 6950 XT
- Vendor : AMD
- Driver Version : 2.0.341
- API Version : 1.4.308
- Device Type : Discrete GPU
________________________
Used Device Extensions :
VK_KHR_deferred_host_operations
VK_KHR_acceleration_structure
VK_KHR_ray_query
BLAS Compaction: 0.7MB -> 0.2MB (0.4MB saved, 66.0% smaller)
_______________
Vulkan Version:
- available: 1.4.309
- requesting: 1.3.0
______________________
Used Instance Layers :
VK_LAYER_KHRONOS_validation
Used Instance Extensions :
____________________
Devices : 1
0: AMD Radeon RX 6950 XT
- Compatible
Compatible physical devices found : 1
Using Device:
- Device Name : AMD Radeon RX 6950 XT
- Vendor : AMD
- Driver Version : 2.0.341
- API Version : 1.4.308
- Device Type : Discrete GPU
________________________
Used Device Extensions :
VK_KHR_deferred_host_operations
VK_KHR_acceleration_structure
VK_KHR_ray_query
BLAS Compaction: 0.7MB -> 0.2MB (0.4MB saved, 66.0% smaller)
_______________
Vulkan Version:
- available: 1.4.309
- requesting: 1.3.0
______________________
Used Instance Layers :
VK_LAYER_KHRONOS_validation
Used Instance Extensions :
__________________
BLAS Compaction: 1.9MB -> 0.6MB (1.2MB saved, 66.1% smaller)

View File

@ -31,10 +31,12 @@ Fetch_Request :: struct {
}
Asset_Manager :: struct {
fetch_queue : [..]Fetch_Request;
is_fetching : bool;
current_fetch : Fetch_Request;
loadedPacks : [..]Loaded_Pack;
fetch_queue : [..]Fetch_Request;
is_fetching : bool;
current_fetch : Fetch_Request;
loadedPacks : [..]Loaded_Pack;
pending_hot_reload : bool;
hot_reload_unpause_pending : bool;
}
g_asset_manager : Asset_Manager;
@ -65,12 +67,11 @@ fetch_callback :: (res: *sfetch_response_t) #c_call {
req := g_asset_manager.current_fetch;
g_asset_manager.is_fetching = false;
if req.type == {
case .PACK;
if res.failed {
print("Failed to load pack '%'\n", req.pack_name);
log_error("Failed to load pack '%'", req.pack_name);
return;
}
mem := NewArray(res.data.size.(s64), u8, false);
@ -79,13 +80,13 @@ fetch_callback :: (res: *sfetch_response_t) #c_call {
pack.nameHash = hash.get_hash(req.pack_name);
pack.name = req.pack_name;
success := init_from_memory(*pack.content, mem, sprint("%", req.pack_name));
if !success { print("Failed to load pack!!\n"); return; }
if !success { log_error("Failed to load pack!!"); return; }
add_resources_from_pack(*pack);
array_add(*g_asset_manager.loadedPacks, pack);
case .WORLD;
if res.failed {
print("Failed to load world '%'\n", req.world_name);
log_error("Failed to load world '%'", req.world_name);
return;
}
data: []u8;
@ -95,9 +96,9 @@ fetch_callback :: (res: *sfetch_response_t) #c_call {
if ok {
set_loaded_world(world);
rdm_loader_enqueue_world(*get_current_world().world);
print("Loaded world: %\n", world.name);
log_info("Loaded world: %", world.name);
} else {
print("Failed to parse world '%'\n", req.world_name);
log_error("Failed to parse world '%'", req.world_name);
}
case .RDM_ATLAS;
@ -105,17 +106,17 @@ fetch_callback :: (res: *sfetch_response_t) #c_call {
if !curworld.valid || curworld.world.name != req.world_name then return;
if res.failed {
print("RDM: failed to load atlas for chunk %\n", req.chunk_key);
log_error("RDM: failed to load atlas for chunk %", req.chunk_key);
return;
}
header_size := cast(s64) size_of(RDM_File_Header);
if res.data.size < cast(u64) header_size {
print("RDM: atlas too small for chunk %\n", req.chunk_key);
log_error("RDM: atlas too small for chunk %", req.chunk_key);
return;
}
header := cast(*RDM_File_Header) res.data.ptr;
if header.magic != RDM_FILE_MAGIC {
print("RDM: bad atlas magic for chunk %\n", req.chunk_key);
log_error("RDM: bad atlas magic for chunk %", req.chunk_key);
return;
}
atlas_pixel_bytes := cast(u64) header.width * cast(u64) header.height * 4 * size_of(float);
@ -143,19 +144,19 @@ fetch_callback :: (res: *sfetch_response_t) #c_call {
world_ok := curworld.valid && curworld.world.name == req.world_name;
if res.failed || !world_ok {
if res.failed then print("RDM: failed to load lookup for chunk %\n", req.chunk_key);
if res.failed then log_error("RDM: failed to load lookup for chunk %", req.chunk_key);
if req.rdm_pending_atlas.id != 0 then sg_destroy_image(req.rdm_pending_atlas);
return;
}
header_size := cast(s64) size_of(RDM_File_Header);
if res.data.size < cast(u64) header_size {
print("RDM: lookup too small for chunk %\n", req.chunk_key);
log_error("RDM: lookup too small for chunk %", req.chunk_key);
sg_destroy_image(req.rdm_pending_atlas);
return;
}
header := cast(*RDM_File_Header) res.data.ptr;
if header.magic != RDM_FILE_MAGIC {
print("RDM: bad lookup magic for chunk %\n", req.chunk_key);
log_error("RDM: bad lookup magic for chunk %", req.chunk_key);
sg_destroy_image(req.rdm_pending_atlas);
return;
}
@ -175,7 +176,7 @@ fetch_callback :: (res: *sfetch_response_t) #c_call {
chunk.rdm_atlas = req.rdm_pending_atlas;
chunk.rdm_lookup = sg_make_image(*lookup_desc);
chunk.rdm_valid = true;
print("RDM: loaded chunk %\n", req.chunk_key);
log_debug("RDM: loaded chunk %", req.chunk_key);
} else {
sg_destroy_image(req.rdm_pending_atlas);
}
@ -225,7 +226,7 @@ add_resources_from_pack :: (pack: *Loaded_Pack) {
s := create_string_from_memory(v.data);
success, sheet := Jaison.json_parse_string(s, Aseprite_Sheet,, temp);
if !success {
print("Failed to parse animation sheet JSON for sheet(%)\n", name);
log_error("Failed to parse animation sheet JSON for sheet(%)", name);
continue;
}
queuedSheet := table_find_pointer(*sheets_to_init, name);
@ -243,9 +244,9 @@ add_resources_from_pack :: (pack: *Loaded_Pack) {
case "ttf";
// Load into a font. Add to free list.
case;
print("There was file(%) in pack(%), that did not match any known fileformat...\n", v.name, pack);
log_warn("File(%) in pack(%) has unknown format", v.name, pack.name);
}
print("% -> %\n", v.name, extension);
log_debug("% -> %", v.name, extension);
}
// Properly initialize animations from the pack now that we have the images
@ -268,7 +269,7 @@ add_resources_from_pack :: (pack: *Loaded_Pack) {
});
}
table_add(*pack.animations, anim.name, anim);
print("Added anim(%)\n", anim.name);
log_debug("Added anim(%)", anim.name);
}
}
@ -276,14 +277,6 @@ add_resources_from_pack :: (pack: *Loaded_Pack) {
// load_color_lut_images(*pack.content, pack.name);
}
free_resources_from_pack :: (pack: *Loaded_Pack) {
for pack.textures sg_destroy_image(it);
for *pack.audio array_free(it.data);
table_reset(*pack.textures);
table_reset(*pack.audio);
table_reset(*pack.animations);
}
find_pack_by_name :: (name: string) -> (bool, Loaded_Pack) {
nameHash := get_hash(name);
for g_asset_manager.loadedPacks {
@ -291,12 +284,20 @@ find_pack_by_name :: (name: string) -> (bool, Loaded_Pack) {
return true, it;
}
}
print("[WARNING] Was unable to find pack: %\n", name);
log_warn("Unable to find pack: %", name);
return false, .{};
}
#scope_export
free_resources_from_pack :: (pack: *Loaded_Pack) {
for pack.textures sg_destroy_image(it);
for *pack.audio array_free(it.data);
table_reset(*pack.textures);
table_reset(*pack.audio);
table_reset(*pack.animations);
}
mandatory_loads_done :: () -> bool {
if g_asset_manager.is_fetching && g_asset_manager.current_fetch.should_block_engine then return false;
for g_asset_manager.fetch_queue {
@ -314,6 +315,17 @@ show_loading_screen :: () -> bool {
}
asset_manager_tick :: () {
#if !FLAG_RELEASE_BUILD && OS != .WASM {
if g_asset_manager.pending_hot_reload && !g_asset_manager.is_fetching && g_asset_manager.fetch_queue.count == 0 {
g_asset_manager.pending_hot_reload = false;
hot_reload_all_packs();
}
if g_asset_manager.hot_reload_unpause_pending && !show_loading_screen() {
g_mixer.paused = false;
g_asset_manager.hot_reload_unpause_pending = false;
}
}
if !g_asset_manager.is_fetching && g_asset_manager.fetch_queue.count > 0 {
req := g_asset_manager.fetch_queue[0];
// Ordered remove from front to preserve queue priority.
@ -373,7 +385,7 @@ get_texture_from_pack :: (pack: string, path: string) -> (sg_image) {
ok, img := table_find(*pack.textures, path);
if !ok {
print("[WARNING] Failed to find texture(%) from pack(%)\n", path, pack.name);
log_warn("Failed to find texture(%) from pack(%)", path, pack.name);
return invalid_img;
}
@ -390,7 +402,7 @@ get_audio_from_pack :: (pack: string, path: string) -> *Audio_Data {
found, pack := find_pack_by_name(pack);
if !found then return null;
audio := table_find_pointer(*pack.audio, path);
if !audio then print("Failed to find audio(%)\n", path);
if !audio then log_error("Failed to find audio(%)", path);
return audio;
}
@ -399,20 +411,20 @@ add_font_from_pack :: (pack: string, path: string) {
if !pack_ok then return;
ok, entry := table_find(*pack.content.lookup, path);
if !ok {
print("Failed to find font % from pack...\n", path);
log_error("Failed to find font % from pack", path);
return;
}
state.font_default.fons_font = fonsAddFontMem(state.fons, "sans", entry.data.data, xx entry.data.count, 0);
}
load_string_from_pack :: (pack: string, path: string) -> string {
print("Warning: you are circumventing the asset management system....\n");
log_warn("You are circumventing the asset management system");
pack_ok, pack := find_pack_by_name(pack);
if !pack_ok return "";
ok, entry := table_find(*pack.content.lookup, path);
if !ok {
print("Failed to load string from pack: %\n", path);
log_error("Failed to load string from pack: %", path);
return "";
}

View File

@ -37,15 +37,14 @@ load_wav_from_memory :: (data: []u8) -> Audio_Data {
dataString.data = data.data;
dataString.count = data.count;
format, samples, success := Wav.get_wav_header(dataString);
if !success print("Failed to load wav file!\n");
if !success log_error("Failed to load wav file!");
audio_samples : []s16;
audio_samples.data = cast(*s16)samples.data;
audio_samples.count = samples.count / 2;
for sample, i: audio_samples {
if i % 2 == 0 {
array_add(*audio.data, cast(float)sample / 32768.0);
}
for sample: audio_samples {
array_add(*audio.data, cast(float)sample / 32768.0);
}
audio.channels = format.nChannels;
audio.channels = format.nChannels;
audio.sample_rate = format.nSamplesPerSec;
return audio;
}

View File

@ -1,4 +1,5 @@
Audio_Data :: struct {
channels: s16;
data: [..]float;
channels : s16;
sample_rate : s32;
data : [..]float;
}

View File

@ -18,7 +18,7 @@ Mixer_Play_Task :: struct {
bus : Mixer_Bus;
mode : Play_Mode;
unique : bool = true;
curSample : s64 = 0;
curSample : s64 = 0; // output frames consumed
startTime : float64 = 0;
delay : float64 = 0;
@ -98,38 +98,52 @@ mixer_get_samples :: (buffer: *float, frame_count: s32, channel_count: s32) {
vol := bus_vol * g_mixer.config.masterVolume;
source_data := task.audio.data;
source_channels := task.audio.channels;
source_data := task.audio.data;
source_channels := cast(s64) task.audio.channels;
src_rate := cast(s64) task.audio.sample_rate;
out_rate := cast(s64) saudio_sample_rate();
num_src_frames := source_data.count / source_channels;
task_finished := false;
for f : 0..frame_count-1 {
if task.curSample >= source_data.count {
src_pos := cast(float64)(task.curSample + f) * cast(float64)src_rate / cast(float64)out_rate;
src_frame0 := cast(s64) src_pos;
src_frame1 := src_frame0 + 1;
t := cast(float)(src_pos - cast(float64)src_frame0);
if src_frame0 >= num_src_frames {
if task.mode == .ONESHOT {
task_finished = true;
break;
} else {
task.curSample = 0;
src_frame0 = src_frame0 % num_src_frames;
src_frame1 = src_frame1 % num_src_frames;
}
} else if src_frame1 >= num_src_frames {
// At the very last source frame: clamp for ONESHOT, wrap for REPEAT.
src_frame1 = ifx task.mode == .ONESHOT then src_frame0 else 0;
}
for ch : 0..channel_count-1 {
out_index := (f * channel_count) + ch;
offset := ifx source_channels == 1 then 0 else ch;
sample : float = 0;
if task.curSample + f + offset < source_data.count {
sample = source_data[task.curSample + f + offset];
}
src_ch := ifx source_channels == 1 then 0 else ch;
buffer[out_index] += sample * vol;
s0 := source_data[src_frame0 * source_channels + src_ch];
s1 := source_data[src_frame1 * source_channels + src_ch];
buffer[out_index] += (s0 + (s1 - s0) * t) * vol;
}
}
task.curSample += frame_count;
// Keep curSample bounded for REPEAT tracks so it never overflows.
if task.mode == .REPEAT && out_rate > 0 && src_rate > 0 {
loop_period := num_src_frames * out_rate / src_rate;
if loop_period > 0 then task.curSample = task.curSample % loop_period;
}
if task_finished {
array_unordered_remove_by_index(*g_mixer.tasks, i);
}

View File

@ -6,14 +6,16 @@ Console_State :: enum {
OPEN_FULL;
}
MAX_REPORT_ROWS :: 100;
MAX_REPORT_ROWS :: 5000;
console_state : Console_State = .CLOSED;
console_report : [..]string;
console_h : float = 0.0;
console_move_speed : float = 400.0;
console_h : float = 0.0;
console_move_speed : float = 400.0;
console_scroll_offset : int = 0; // lines scrolled up from the most recent
console_at_bottom : bool = true; // auto-follow new lines unless user has scrolled
get_console_h_target_from_state :: (state: Console_State) -> float {
if state == {
@ -79,7 +81,7 @@ verify_argument_count :: (range_start: s64, range_end: s64, count: s64) -> bool
}
tick_console :: () {
if input_button_states[Key_Code.F1] & .START {
if input_button_states[get_action_combo(Editor_Action.TOGGLE_CONSOLE).key] & .START {
if console_state != .CLOSED {
if input_button_states[Key_Code.SHIFT] & .DOWN {
if console_state == .OPEN_FULL {
@ -113,12 +115,21 @@ tick_console :: () {
}
}
while console_report.count > MAX_REPORT_ROWS {
array_ordered_remove_by_index(*console_report, 0);
}
if console_state != .CLOSED {
console_open_ignore_input = true;
line_h := ui_h(5, 4);
max_visible := cast(int)((console_h - line_h) / line_h);
max_scroll := max(0, console_report.count - max_visible);
scroll_delta := 0;
if input_button_states[Key_Code.PAGE_UP] & .START scroll_delta = max_visible;
if input_button_states[Key_Code.PAGE_DOWN] & .START scroll_delta = -max_visible;
if scroll_delta != 0 {
console_scroll_offset = clamp(console_scroll_offset + scroll_delta, 0, max_scroll);
console_at_bottom = (console_scroll_offset == 0);
}
} else {
console_open_ignore_input = false;
}
@ -126,6 +137,11 @@ tick_console :: () {
console_add_output_line :: (s: string) {
array_add(*console_report, s);
while console_report.count > MAX_REPORT_ROWS {
array_ordered_remove_by_index(*console_report, 0);
if console_scroll_offset > 0 then console_scroll_offset -= 1;
}
if console_at_bottom then console_scroll_offset = 0;
}
draw_console :: (theme: *GR.Overall_Theme) {
@ -157,9 +173,21 @@ draw_console :: (theme: *GR.Overall_Theme) {
if !found then array_add(*console_report, "Unknown command.");
}
for < console_report {
max_visible := cast(int)((console_h - r.h) / r.h);
max_scroll := max(0, console_report.count - max_visible);
console_scroll_offset = clamp(console_scroll_offset, 0, max_scroll);
start_idx := console_report.count - 1 - console_scroll_offset;
for i: 0..max_visible-1 {
idx := start_idx - i;
if idx < 0 break;
r.y -= r.h;
GR.label(r, it, *t_label_left(theme));
GR.label(r, console_report[idx], *t_label_left(theme));
}
if console_scroll_offset > 0 {
r.y -= r.h;
GR.label(r, tprint("[ ↑ % more ]", console_scroll_offset), *t_label_left(theme));
}
if !state.active then GR.activate(state);

View File

@ -27,6 +27,8 @@ in_editor_view : bool = false;
init_editor :: () {
#if OS != .WASM {init_profiler();}
init_console();
init_keybinds();
init_settings_menu();
}
// Used when the console is open, so typing doesn't cause all sorts of stuff.
@ -44,16 +46,11 @@ draw_editor_ui :: (theme: *GR.Overall_Theme) {
GR.label(r, tprint("Trueno v%.%", V_MAJOR, V_MINOR), *t_label_left(theme));
r.x = 100*vw - r.w;
if GR.button(r, "Level studio", *t_button_selectable(theme, current_editor_view == .Level_Editor))
then current_editor_view = .Level_Editor;
if keybind_button(r, "Level studio", .STUDIO_LEVEL, *t_button_selectable(theme, current_editor_view == .Level_Editor)) then current_editor_view = .Level_Editor;
r.x -= r.w;
if GR.button(r, "Trile studio", *t_button_selectable(theme, current_editor_view == .Trile_Editor))
then current_editor_view = .Trile_Editor;
if keybind_button(r, "Trile studio", .STUDIO_TRILE, *t_button_selectable(theme, current_editor_view == .Trile_Editor)) then current_editor_view = .Trile_Editor;
r.x -= r.w;
if GR.button(r, "Material studio", *t_button_selectable(theme, current_editor_view == .Material_Editor))
then current_editor_view = .Material_Editor;
if keybind_button(r, "Material studio", .STUDIO_MATERIAL, *t_button_selectable(theme, current_editor_view == .Material_Editor)) then current_editor_view = .Material_Editor;
if current_editor_view == {
@ -65,7 +62,6 @@ draw_editor_ui :: (theme: *GR.Overall_Theme) {
}
draw_profiler();
}
draw_console(theme);
draw_texture_debugger(theme);
draw_postprocess_popup(theme);
draw_lighting_popup(theme);
@ -89,9 +85,17 @@ draw_editor :: () {
}
tick_editor_ui :: () {
if input_button_states[Key_Code.F3] & .START {
if is_action_start(Editor_Action.TOGGLE_EDITOR) {
in_editor_view = !in_editor_view;
g_mixer.paused = in_editor_view;
if !in_editor_view then bypass_postprocess = false;
}
#if !FLAG_RELEASE_BUILD && OS != .WASM {
if is_action_start(Editor_Action.HOT_RELOAD) {
g_asset_manager.pending_hot_reload = true;
log_info("Hot-reload: queued, waiting for in-flight loads to finish...");
}
}
#if OS != .WASM {
@ -106,4 +110,5 @@ tick_editor_ui :: () {
}
tick_console();
tick_settings_menu();
}

View File

@ -1,4 +1,4 @@
#if HAS_IPROF == false {
#if FLAG_IPROF_ENABLED == false {
init_profiler :: () {}

View File

@ -20,6 +20,36 @@ cameraCenter : Vector2;
trile_preview_disabled : bool = false;
Level_Editor_Tool_Mode :: enum {
POINT;
BRUSH;
AREA;
LINE;
}
current_tool_mode : Level_Editor_Tool_Mode = .POINT;
brush_radius : int = 2;
brush_height : int = 0;
area_active : bool;
area_delete : bool;
area_start_x : int;
area_start_y : int;
area_start_z : int;
line_active : bool;
line_delete : bool;
line_start_x : int;
line_start_y : int;
line_start_z : int;
current_orientation_face : u8 = 0;
current_orientation_twist : u8 = 0;
get_current_orientation :: () -> u8 {
return current_orientation_face * 4 + current_orientation_twist;
}
#scope_export
toggle_preview :: () {
@ -124,12 +154,12 @@ tick_level_editor_camera :: () {
cameraCenter += cameraSpeed * zoomCameraMovementMultiplier * (xx delta_time) * left2d;
}
if input_button_states[Key_Code.ARROW_UP] & .START {
if is_action_start(Editor_Action.LEVEL_HEIGHT_UP) {
lastInputTime = get_time();
editY = min(editY + 1, 100);
}
if input_button_states[Key_Code.ARROW_DOWN] & .START {
if is_action_start(Editor_Action.LEVEL_HEIGHT_DOWN) {
lastInputTime = get_time();
editY = max(editY - 1, 0);
}
@ -248,7 +278,70 @@ editMode : Edit_Mode;
draw_tools_tab :: (theme: *GR.Overall_Theme, total_r: GR.Rect) {
r := total_r;
r.h = ui_h(3,0);
r.h = ui_h(4, 0);
if keybind_button(r, "Save world", .SAVE, *theme.button_theme) then sworld();
r.y += r.h * 2;
// Tool mode buttons
if keybind_button(r, "Point", .LEVEL_TOOL_POINT, *t_button_selectable(theme, current_tool_mode == .POINT)) then current_tool_mode = .POINT;
r.y += r.h;
if keybind_button(r, "Brush", .LEVEL_TOOL_BRUSH, *t_button_selectable(theme, current_tool_mode == .BRUSH)) then current_tool_mode = .BRUSH;
r.y += r.h;
if keybind_button(r, "Area", .LEVEL_TOOL_AREA, *t_button_selectable(theme, current_tool_mode == .AREA)) { current_tool_mode = .AREA; area_active = false; }
r.y += r.h;
if keybind_button(r, "Line", .LEVEL_TOOL_LINE, *t_button_selectable(theme, current_tool_mode == .LINE)) { current_tool_mode = .LINE; line_active = false; }
r.y += r.h;
// Brush radius/height (only for brush mode)
if current_tool_mode == .BRUSH {
r.h = ui_h(3, 2);
GR.label(r, "Brush Radius", *t_label_left(theme));
r.y += r.h;
r.h = ui_h(4, 0);
GR.slider(r, *brush_radius, 1, 8, 1, *theme.slider_theme);
r.y += r.h;
r.h = ui_h(3, 2);
GR.label(r, "Brush Height (±Y layers)", *t_label_left(theme));
r.y += r.h;
r.h = ui_h(4, 0);
GR.slider(r, *brush_height, 0, 8, 1, *theme.slider_theme);
r.y += r.h * 2;
} else {
r.y += r.h;
}
// Status hints for multi-click tools
r.h = ui_h(3, 2);
if current_tool_mode == .AREA {
if area_active {
GR.label(r, "Click second corner to fill", *t_label_left(theme));
} else {
GR.label(r, "Click first corner to start", *t_label_left(theme));
}
r.y += r.h;
} else if current_tool_mode == .LINE {
if line_active {
GR.label(r, "Click endpoint to draw line", *t_label_left(theme));
} else {
GR.label(r, "Click start of line", *t_label_left(theme));
}
r.y += r.h;
}
// Orientation controls
r.y += r.h;
r.h = ui_h(3, 2);
GR.label(r, "-- Orientation --", *t_label_left(theme));
r.y += r.h;
twist_angle := current_orientation_twist * 90;
GR.label(r, tprint("Face: % Twist: %°", current_orientation_face, twist_angle), *t_label_left(theme));
r.y += r.h;
GR.label(r, tprint("%/%: twist %: face",
key_combo_string(get_action_combo(Editor_Action.LEVEL_TWIST_CCW)),
key_combo_string(get_action_combo(Editor_Action.LEVEL_TWIST_CW)),
key_combo_string(get_action_combo(Editor_Action.LEVEL_CYCLE_FACE))), *t_label_left(theme));
r.y += r.h;
}
handle_tool_click :: (x: int, y: int, z: int, delete: bool = false) {
@ -256,10 +349,53 @@ handle_tool_click :: (x: int, y: int, z: int, delete: bool = false) {
if delete {
remove_trile(cast(s32)x, cast(s32)y, cast(s32)z);
} else {
if editor_current_trile != null then add_trile(editor_current_trile.name, cast(s32)x, cast(s32)y, cast(s32)z);
if editor_current_trile != null then add_trile(editor_current_trile.name, cast(s32)x, cast(s32)y, cast(s32)z, get_current_orientation());
}
}
apply_brush :: (cx: int, cy: int, cz: int, delete: bool) {
for dy: -brush_height..brush_height {
for dx: -brush_radius..brush_radius {
for dz: -brush_radius..brush_radius {
dist := sqrt(cast(float)(dx*dx + dz*dz));
if dist <= cast(float)brush_radius {
handle_tool_click(cx + dx, cy + dy, cz + dz, delete);
}
}
}
}
}
apply_area :: (x2: int, y2: int, z2: int, delete: bool) {
for x: min(area_start_x, x2)..max(area_start_x, x2) {
for y: min(area_start_y, y2)..max(area_start_y, y2) {
for z: min(area_start_z, z2)..max(area_start_z, z2) {
handle_tool_click(x, y, z, delete);
}
}
}
}
apply_line :: (x2: int, y2: int, z2: int, delete: bool) {
x1 := line_start_x; y1 := line_start_y; z1 := line_start_z;
dx := abs(x2 - x1); dy := abs(y2 - y1); dz := abs(z2 - z1);
sx := ifx x1 < x2 then 1 else -1;
sy := ifx y1 < y2 then 1 else -1;
sz := ifx z1 < z2 then 1 else -1;
// 3D Bresenham: drive along the longest axis
dm := max(dx, max(dy, dz));
x := x1; y := y1; z := z1;
ex := dm / 2; ey := dm / 2; ez := dm / 2;
count := 0;
while count <= dm && count < 2000 {
handle_tool_click(x, y, z, delete);
ex -= dx; if ex < 0 { x += sx; ex += dm; }
ey -= dy; if ey < 0 { y += sy; ey += dm; }
ez -= dz; if ez < 0 { z += sz; ez += dm; }
count += 1;
}
}
add_trile :: (name: string, x: s32, y: s32, z: s32, orientation: u8 = 0) {
curworld := get_current_world();
@ -316,9 +452,29 @@ remove_trile :: (x: s32, y: s32, z: s32) {
tick_level_editor :: () {
#if FLAG_TACOMA_ENABLED { rdm_bake_tick(); }
tick_level_editor_camera();
if is_action_start(Editor_Action.SAVE) then sworld();
if is_action_start(Editor_Action.LEVEL_TOOL_POINT) then current_tool_mode = .POINT;
if is_action_start(Editor_Action.LEVEL_TOOL_BRUSH) then current_tool_mode = .BRUSH;
if is_action_start(Editor_Action.LEVEL_TOOL_AREA) { current_tool_mode = .AREA; area_active = false; }
if is_action_start(Editor_Action.LEVEL_TOOL_LINE) { current_tool_mode = .LINE; line_active = false; }
if is_action_start(Editor_Action.LEVEL_TWIST_CCW) {
lastInputTime = get_time();
current_orientation_twist = (current_orientation_twist + 1) % 4;
}
if is_action_start(Editor_Action.LEVEL_TWIST_CW) {
lastInputTime = get_time();
current_orientation_twist = (current_orientation_twist + 3) % 4;
}
if is_action_start(Editor_Action.LEVEL_CYCLE_FACE) {
lastInputTime = get_time();
current_orientation_face = (current_orientation_face + 1) % 6;
}
ray := get_mouse_ray(*get_level_editor_camera());
hit, point := ray_plane_collision_point(ray, xx editY, 20);
show_trile_preview = false;
if hit {
show_trile_preview = true;
@ -326,20 +482,168 @@ tick_level_editor :: () {
trile_preview_y = editY;
trile_preview_z = xx floor(point.y);
if get_mouse_state(Key_Code.MOUSE_BUTTON_LEFT) & .START {
handle_tool_click(xx floor(point.x), xx editY, xx floor(point.y));
}
if get_mouse_state(Key_Code.MOUSE_BUTTON_RIGHT) & .START {
handle_tool_click(xx floor(point.x), xx editY, xx floor(point.y), true);
px := trile_preview_x;
py := trile_preview_y;
pz := trile_preview_z;
if current_tool_mode == .POINT {
if get_mouse_state(Key_Code.MOUSE_BUTTON_LEFT) & .START {
handle_tool_click(px, py, pz);
}
if get_mouse_state(Key_Code.MOUSE_BUTTON_RIGHT) & .START {
handle_tool_click(px, py, pz, true);
}
} else if current_tool_mode == .BRUSH {
if get_mouse_state(Key_Code.MOUSE_BUTTON_LEFT) & .DOWN {
apply_brush(px, py, pz, false);
}
if get_mouse_state(Key_Code.MOUSE_BUTTON_RIGHT) & .DOWN {
apply_brush(px, py, pz, true);
}
} else if current_tool_mode == .AREA {
if get_mouse_state(Key_Code.MOUSE_BUTTON_LEFT) & .START {
if !area_active {
area_active = true;
area_delete = false;
area_start_x = px;
area_start_y = py;
area_start_z = pz;
} else if !area_delete {
apply_area(px, py, pz, false);
area_active = false;
} else {
area_active = false; // cancel delete selection
}
}
if get_mouse_state(Key_Code.MOUSE_BUTTON_RIGHT) & .START {
if !area_active {
area_active = true;
area_delete = true;
area_start_x = px;
area_start_y = py;
area_start_z = pz;
} else if area_delete {
apply_area(px, py, pz, true);
area_active = false;
} else {
area_active = false; // cancel add selection
}
}
} else if current_tool_mode == .LINE {
if get_mouse_state(Key_Code.MOUSE_BUTTON_LEFT) & .START {
if !line_active {
line_active = true;
line_delete = false;
line_start_x = px;
line_start_y = py;
line_start_z = pz;
} else if !line_delete {
apply_line(px, py, pz, false);
line_active = false;
} else {
line_active = false; // cancel delete selection
}
}
if get_mouse_state(Key_Code.MOUSE_BUTTON_RIGHT) & .START {
if !line_active {
line_active = true;
line_delete = true;
line_start_x = px;
line_start_y = py;
line_start_z = pz;
} else if line_delete {
apply_line(px, py, pz, true);
line_active = false;
} else {
line_active = false; // cancel add selection
}
}
}
}
}
create_level_editor_preview_tasks :: () {
curworld := get_current_world();
if !curworld.valid then return;
if !editor_current_trile then return;
positions: [..]Vector4;
positions.allocator = temp;
ori := cast(float) get_current_orientation();
px := trile_preview_x; py := trile_preview_y; pz := trile_preview_z;
if current_tool_mode == .POINT {
array_add(*positions, .{cast(float)px, cast(float)py, cast(float)pz, ori});
} else if current_tool_mode == .BRUSH {
for dy: -brush_height..brush_height {
for dx: -brush_radius..brush_radius {
for dz: -brush_radius..brush_radius {
dist := sqrt(cast(float)(dx*dx + dz*dz));
if dist <= cast(float)brush_radius {
array_add(*positions, .{cast(float)(px+dx), cast(float)(py+dy), cast(float)(pz+dz), ori});
}
}
}
}
} else if current_tool_mode == .AREA {
if area_active {
for x: min(area_start_x, px)..max(area_start_x, px) {
for y: min(area_start_y, py)..max(area_start_y, py) {
for z: min(area_start_z, pz)..max(area_start_z, pz) {
array_add(*positions, .{cast(float)x, cast(float)y, cast(float)z, ori});
}
}
}
} else {
array_add(*positions, .{cast(float)px, cast(float)py, cast(float)pz, ori});
}
} else if current_tool_mode == .LINE {
if line_active {
x1 := line_start_x; y1 := line_start_y; z1 := line_start_z;
x2 := px; y2 := py; z2 := pz;
dx := abs(x2-x1); dy := abs(y2-y1); dz := abs(z2-z1);
sx := ifx x1 < x2 then 1 else -1;
sy := ifx y1 < y2 then 1 else -1;
sz := ifx z1 < z2 then 1 else -1;
dm := max(dx, max(dy, dz));
x := x1; y := y1; z := z1;
ex := dm/2; ey := dm/2; ez := dm/2;
count := 0;
while count <= dm && count < 2000 {
array_add(*positions, .{cast(float)x, cast(float)y, cast(float)z, ori});
ex -= dx; if ex < 0 { x += sx; ex += dm; }
ey -= dy; if ey < 0 { y += sy; ey += dm; }
ez -= dz; if ez < 0 { z += sz; ez += dm; }
count += 1;
}
} else {
array_add(*positions, .{cast(float)px, cast(float)py, cast(float)pz, ori});
}
}
if positions.count == 0 then return;
is_delete := (current_tool_mode == .AREA && area_active && area_delete)
|| (current_tool_mode == .LINE && line_active && line_delete);
task: Rendering_Task_Trile;
task.trile = editor_current_trile.name;
task.positions = positions;
task.worldConf = *curworld.world.conf;
task.preview_mode = ifx is_delete then cast(s32)2 else cast(s32)1;
add_rendering_task(task);
}
draw_level_editor :: () {
curworld := get_current_world();
if !curworld.valid then return;
create_set_cam_rendering_task(get_level_editor_camera(), curworld.world.conf.planeHeight);
create_world_rendering_tasks(*curworld.world);
cam := get_level_editor_camera();
create_set_cam_rendering_task(cam, effective_plane_height(*curworld.world.conf));
create_world_rendering_tasks(*curworld.world, cam);
if show_trile_preview && !trile_preview_disabled {
create_level_editor_preview_tasks();
}
}
draw_level_editor_ui :: (theme: *GR.Overall_Theme) {
@ -350,17 +654,11 @@ draw_level_editor_ui :: (theme: *GR.Overall_Theme) {
tab_r.h = ui_h(3,0);
tab_r.w = ui_w(20, 20) / 3;
if GR.button(tab_r, "Tools", *t_button_tab(theme, current_tab == .TOOLS)) {
current_tab = .TOOLS;
}
if keybind_button(tab_r, "Tools", .LEVEL_TAB_TOOLS, *t_button_tab(theme, current_tab == .TOOLS)) then current_tab = .TOOLS;
tab_r.x += tab_r.w;
if GR.button(tab_r, "Info", *t_button_tab(theme, current_tab == .INFO)) {
current_tab = .INFO;
}
if keybind_button(tab_r, "Info", .LEVEL_TAB_INFO, *t_button_tab(theme, current_tab == .INFO)) then current_tab = .INFO;
tab_r.x += tab_r.w;
if GR.button(tab_r, "Tacoma", *t_button_tab(theme, current_tab == .TACOMA)) {
current_tab = .TACOMA;
}
if keybind_button(tab_r, "Tacoma", .LEVEL_TAB_TACOMA, *t_button_tab(theme, current_tab == .TACOMA)) then current_tab = .TACOMA;
r.y += tab_r.h;
curworld := get_current_world();

View File

@ -74,6 +74,59 @@ get_trile_roughness_set :: (trile_name: string) -> u8 {
return mask;
}
// Predicted pixel dimensions of a single RDM entry at a given roughness level.
// roughness 0 → 512×768, roughness 1 → 256×384, ..., roughness 7 → 4×6.
rdm_entry_predicted_size :: (roughness: s32) -> (w: s32, h: s32) {
size : s32 = cast(s32)(1 << (8 - roughness));
return 2 * size, 3 * size;
}
// Simulate shelf-pack of jobs into a canvas of given width; return total height used.
rdm_simulate_pack_height :: (jobs: []RDM_Bake_Job, canvas_w: s32) -> s32 {
cx : s32 = 0;
cy : s32 = 0;
rh : s32 = 0;
for job: jobs {
w, h := rdm_entry_predicted_size(job.roughness);
if cx + w > canvas_w { cy += rh; cx = 0; rh = 0; }
cx += w;
if h > rh rh = h;
}
cy += rh;
return cy;
}
// Simulate shelf-packing for a chunk's sorted job list and return minimum
// power-of-2 atlas dimensions, capped at RDM_ATLAS_SIZE.
rdm_calc_chunk_atlas_size :: (jobs: []RDM_Bake_Job) -> (s32, s32) {
if jobs.count == 0 return 16, 16;
// Estimate canvas width from sqrt(total pixel area).
total_area : s64 = 0;
for job: jobs {
w, h := rdm_entry_predicted_size(job.roughness);
total_area += cast(s64) w * cast(s64) h;
}
target_w : s32 = 16;
sqrt_area := cast(s32) sqrt(cast(float) total_area) + 1;
while target_w < sqrt_area target_w *= 2;
// Widen until the packed height fits within the width (roughly square).
while target_w < RDM_ATLAS_SIZE {
if rdm_simulate_pack_height(jobs, target_w) <= target_w break;
target_w *= 2;
}
// Round height up to next power of 2.
final_height := rdm_simulate_pack_height(jobs, target_w);
target_h : s32 = 16;
while target_h < final_height target_h *= 2;
if target_w > RDM_ATLAS_SIZE target_w = RDM_ATLAS_SIZE;
if target_h > RDM_ATLAS_SIZE target_h = RDM_ATLAS_SIZE;
return target_w, target_h;
}
// Build the Tacoma scene from the world, and emit bake jobs for selected chunks.
// If chunk_keys is null, all chunks are queued.
rdm_bake_start :: (world: World, quality: s32, include_water: bool, chunk_keys: []Chunk_Key = .[]) {
@ -205,15 +258,38 @@ rdm_bake_start :: (world: World, quality: s32, include_water: bool, chunk_keys:
}
}
// Pre-allocate per-chunk atlas CPU buffers.
atlas_bytes := cast(s64) RDM_ATLAS_SIZE * cast(s64) RDM_ATLAS_SIZE * 4 * size_of(float);
for job: rdm_bake.jobs {
chunk_key := world_to_chunk_coord(cast(s32) job.world_pos.x, cast(s32) job.world_pos.y, cast(s32) job.world_pos.z);
if !table_contains(*rdm_chunk_bakes, chunk_key) {
// Pre-allocate per-chunk atlas CPU buffers with optimal (minimum) sizes.
{
// Collect unique chunk keys.
unique_chunk_keys : [..]Chunk_Key;
unique_chunk_keys.allocator = temp;
for job: rdm_bake.jobs {
ck := world_to_chunk_coord(cast(s32) job.world_pos.x, cast(s32) job.world_pos.y, cast(s32) job.world_pos.z);
already := false;
for unique_chunk_keys { if it == ck { already = true; break; } }
if !already array_add(*unique_chunk_keys, ck);
}
for chunk_key: unique_chunk_keys {
// Collect this chunk's jobs (already sorted by roughness ascending).
this_jobs : [..]RDM_Bake_Job;
this_jobs.allocator = temp;
for job: rdm_bake.jobs {
ck := world_to_chunk_coord(cast(s32) job.world_pos.x, cast(s32) job.world_pos.y, cast(s32) job.world_pos.z);
if ck == chunk_key array_add(*this_jobs, job);
}
atlas_w, atlas_h := rdm_calc_chunk_atlas_size(this_jobs);
log_info("RDM atlas for chunk %: %x% (%.1f MB, was % MB)",
chunk_key, atlas_w, atlas_h,
cast(float)(cast(s64) atlas_w * atlas_h * 4 * size_of(float)) / (1024.0 * 1024.0),
RDM_ATLAS_SIZE * RDM_ATLAS_SIZE * 4 * size_of(float) / (1024 * 1024));
atlas_bytes := cast(s64) atlas_w * cast(s64) atlas_h * 4 * size_of(float);
bake : RDM_Chunk_Bake;
bake.width = RDM_ATLAS_SIZE;
bake.height = RDM_ATLAS_SIZE;
bake.data = cast(*float) alloc(atlas_bytes);
bake.width = atlas_w;
bake.height = atlas_h;
bake.data = cast(*float) alloc(atlas_bytes);
memset(bake.data, 0, atlas_bytes);
table_set(*rdm_chunk_bakes, chunk_key, bake);
}
@ -284,7 +360,7 @@ rdm_bake_tick :: () {
entry.h = h;
array_add(*bake.entries, entry);
} else {
print("Warning: RDM atlas overflow for chunk %, skipping (pos=%, roughness=%)\n", chunk_key, job.world_pos, job.roughness);
log_warn("RDM atlas overflow for chunk %, skipping (pos=%, roughness=%)", chunk_key, job.world_pos, job.roughness);
}
bake.cursor_x += w;
@ -385,7 +461,7 @@ rdm_bake_finish :: () {
chunk_count += 1;
}
print("RDM bake complete: % chunks, % total entries\n", chunk_count, total_entries);
log_info("RDM bake complete: % chunks, % total entries", chunk_count, total_entries);
// Save baked RDM data to disk.
rdm_save_all_chunks_to_disk();
@ -465,12 +541,12 @@ tacoma_start :: (world: World, include_water: bool) {
blases : Tacoma.Trile_Set = .{trile_list.data, cast(s32)trile_list.count};
for world_triles {
print("World trile %\n", it);
log_debug("World trile %", it);
}
tlas : Tacoma.World = .{world_triles.data, cast(s32)world_triles.count};
ctx = Tacoma.tacoma_init("./modules/Tacoma/");
print("CTX: %\n\n", ctx);
log_debug("CTX: %", ctx);
Tacoma.tacoma_load_scene(ctx, sky, blases, tlas, cast(s32) include_water);
}
@ -590,7 +666,7 @@ rdm_save_all_chunks_to_disk :: () {
lookup_path := rdm_chunk_filename(world_name, chunk_key, "rdm_lookup");
rdm_save_image_to_file(lookup_path, lookup_data.data, RDM_LOOKUP_SIZE, RDM_LOOKUP_SIZE);
print("Saved RDM data for chunk % to disk\n", chunk_key);
log_info("Saved RDM data for chunk % to disk", chunk_key);
}
}
}

View File

@ -138,9 +138,24 @@ handle_tool_click :: () {
current_color : Vector3 = .{1.0, 0.0, 0.0};
reset_trile :: () {
newt : Trile;
set_trile("test", newt);
editor_current_trile = get_trile("test");
for x: 0..15 {
for y: 0..15 {
for z: 0..15 {
editor_current_trile.trixels[x][y][z].empty = false;
}
}
}
} @Command
trile_copy :: (from: string) {
src := get_trile(from);
for x: 0..15 {
for y: 0..15 {
for z: 0..15 {
editor_current_trile.trixels[x][y][z] = src.trixels[x][y][z];
}
}
}
} @Command
tick_trile_editor :: () {
@ -239,35 +254,24 @@ trile_palette_scroll : float = 0.0;
draw_tool_tab :: (theme: *GR.Overall_Theme, area: GR.Rect) {
r := area;
r.h = ui_h(4, 0);
if GR.button(r, "Paint (P)", *t_button_selectable(theme, current_tool == .PAINT)) {
current_tool = .PAINT;
}
if keybind_button(r, "Paint", .TRIXEL_TOOL_PAINT, *t_button_selectable(theme, current_tool == .PAINT)) then current_tool = .PAINT;
r.y += r.h;
if GR.button(r, "Add (+)", *t_button_selectable(theme, current_tool == .ADD)) {
current_tool = .ADD;
}
if keybind_button(r, "Add", .TRIXEL_TOOL_ADD, *t_button_selectable(theme, current_tool == .ADD)) then current_tool = .ADD;
r.y += r.h;
if GR.button(r, "Remove (-)", *t_button_selectable(theme, current_tool == .REMOVE)) {
current_tool = .REMOVE;
}
if keybind_button(r, "Remove", .TRIXEL_TOOL_REMOVE, *t_button_selectable(theme, current_tool == .REMOVE)) then current_tool = .REMOVE;
r.y += r.h * 3;
if GR.button(r, "Point (c-P)", *t_button_selectable(theme, current_mode == .POINT)) {
current_mode = .POINT;
}
if keybind_button(r, "Point", .TRIXEL_MODE_POINT, *t_button_selectable(theme, current_mode == .POINT)) then current_mode = .POINT;
r.y += r.h;
if GR.button(r, "Area (c-A)", *t_button_selectable(theme, current_mode == .AREA)) {
current_mode = .AREA;
}
if keybind_button(r, "Area", .TRIXEL_MODE_AREA, *t_button_selectable(theme, current_mode == .AREA)) then current_mode = .AREA;
r.y += r.h;
if GR.button(r, "Brush (c-B)", *t_button_selectable(theme, current_mode == .BRUSH)) {
current_mode = .BRUSH;
}
if keybind_button(r, "Brush", .TRIXEL_MODE_BRUSH, *t_button_selectable(theme, current_mode == .BRUSH)) then current_mode = .BRUSH;
r.y += r.h;
GR.slider(r, *brush_radius, 0, 12, 1, *theme.slider_theme);
r.y += r.h * 2;
if GR.button(r, "Save and gen", *theme.button_theme) {
if keybind_button(r, "Save and gen", .SAVE, *theme.button_theme) {
set_trile_gfx(editor_current_trile.name, generate_trile_gfx_matias(editor_current_trile));
striles();
};
}
@ -311,38 +315,17 @@ draw_trile_editor :: () {
}
trile_editor_shortcuts :: () {
if console_open_ignore_input then return;
if input_button_states[Key_Code.CTRL] & .DOWN {
if input_button_states[#char "A"] & .START {
current_mode = .AREA;
}
if input_button_states[#char "P"] & .START {
current_mode = .POINT;
}
if input_button_states[#char "B"] & .START {
current_mode = .BRUSH;
}
} else {
if input_button_states[#char "T"] & .START {
current_tab = .TOOLSET;
}
if input_button_states[#char "M"] & .START {
current_tab = .MATERIAL;
}
if input_button_states[#char "I"] & .START {
current_tab = .METADATA;
}
if input_button_states[#char "P"] & .START {
current_tool = .PAINT;
}
// Hack: These will only work on nordic keyboards as expected...
if input_button_states[#char "-"] & .START {
current_tool = .ADD;
}
if input_button_states[#char "/"] & .START {
current_tool = .REMOVE;
}
// Tool/mode buttons are only rendered in the Toolset tab — handle shortcuts here so they work from any tab.
if is_action_start(Editor_Action.TRIXEL_TOOL_PAINT) then current_tool = .PAINT;
if is_action_start(Editor_Action.TRIXEL_TOOL_ADD) then current_tool = .ADD;
if is_action_start(Editor_Action.TRIXEL_TOOL_REMOVE) then current_tool = .REMOVE;
if is_action_start(Editor_Action.TRIXEL_MODE_POINT) then current_mode = .POINT;
if is_action_start(Editor_Action.TRIXEL_MODE_AREA) then current_mode = .AREA;
if is_action_start(Editor_Action.TRIXEL_MODE_BRUSH) then current_mode = .BRUSH;
// Save is in the Toolset tab only.
if is_action_start(Editor_Action.SAVE) {
set_trile_gfx(editor_current_trile.name, generate_trile_gfx_matias(editor_current_trile));
striles();
}
}
@ -354,17 +337,11 @@ draw_trile_editor_ui :: (theme: *GR.Overall_Theme) {
tab_r.h = ui_h(3,0);
tab_r.w = ui_w(20, 20) / 3;
if GR.button(tab_r, "Tool (T)", *t_button_tab(theme, current_tab == .TOOLSET)) {
current_tab = .TOOLSET;
}
if keybind_button(tab_r, "Tools", .TRIXEL_TAB_TOOLS, *t_button_tab(theme, current_tab == .TOOLSET)) then current_tab = .TOOLSET;
tab_r.x += tab_r.w;
if GR.button(tab_r, "Material (M)", *t_button_tab(theme, current_tab == .MATERIAL)) {
current_tab = .MATERIAL;
}
if keybind_button(tab_r, "Material", .TRIXEL_TAB_MATERIAL, *t_button_tab(theme, current_tab == .MATERIAL)) then current_tab = .MATERIAL;
tab_r.x += tab_r.w;
if GR.button(tab_r, "Meta (I)", *t_button_tab(theme, current_tab == .METADATA)) {
current_tab = .METADATA;
}
if keybind_button(tab_r, "Meta", .TRIXEL_TAB_INFO, *t_button_tab(theme, current_tab == .METADATA)) then current_tab = .METADATA;
r.y += tab_r.h;
@ -390,19 +367,11 @@ draw_trile_editor_ui :: (theme: *GR.Overall_Theme) {
r2 : GR.Rect;
r2.x = bar_x; r2.y = bar_y; r2.w = btn_w; r2.h = btn_h;
if GR.button(r2, "Lit", *t_button_selectable(theme, trixel_view_mode == 0)) {
trixel_view_mode = 0;
}
if keybind_button(r2, "Lit", .TRIXEL_VIEW_LIT, *t_button_selectable(theme, trixel_view_mode == 0)) then trixel_view_mode = 0;
r2.x += btn_w;
if GR.button(r2, "Normals", *t_button_selectable(theme, trixel_view_mode == 1)) {
trixel_view_mode = 1;
}
if keybind_button(r2, "Normals", .TRIXEL_VIEW_NORMALS, *t_button_selectable(theme, trixel_view_mode == 1)) then trixel_view_mode = 1;
r2.x += btn_w;
if GR.button(r2, "Albedo", *t_button_selectable(theme, trixel_view_mode == 2)) {
trixel_view_mode = 2;
}
if keybind_button(r2, "Albedo", .TRIXEL_VIEW_ALBEDO, *t_button_selectable(theme, trixel_view_mode == 2)) then trixel_view_mode = 2;
r2.x += btn_w;
if GR.button(r2, "Mixed", *t_button_selectable(theme, trixel_view_mode == 3)) {
trixel_view_mode = 3;
}
if keybind_button(r2, "Mixed", .TRIXEL_VIEW_MIXED, *t_button_selectable(theme, trixel_view_mode == 3)) then trixel_view_mode = 3;
}

View File

@ -1 +1 @@
#load "keybinds.jai";

182
src/input/keybinds.jai Normal file
View File

@ -0,0 +1,182 @@
Editor_Action :: enum {
TOGGLE_CONSOLE;
TOGGLE_EDITOR;
TOGGLE_SETTINGS;
HOT_RELOAD;
// Level editor
LEVEL_HEIGHT_UP;
LEVEL_HEIGHT_DOWN;
LEVEL_TWIST_CW;
LEVEL_TWIST_CCW;
LEVEL_CYCLE_FACE;
// Trile editor — tools
TRIXEL_TOOL_PAINT;
TRIXEL_TOOL_ADD;
TRIXEL_TOOL_REMOVE;
// Trile editor — modes
TRIXEL_MODE_POINT;
TRIXEL_MODE_AREA;
TRIXEL_MODE_BRUSH;
// Trile editor — tabs
TRIXEL_TAB_TOOLS;
TRIXEL_TAB_MATERIAL;
TRIXEL_TAB_INFO;
// Level editor — tool modes
LEVEL_TOOL_POINT;
LEVEL_TOOL_BRUSH;
LEVEL_TOOL_AREA;
LEVEL_TOOL_LINE;
// Level editor — tabs
LEVEL_TAB_TOOLS;
LEVEL_TAB_INFO;
LEVEL_TAB_TACOMA;
// Shared
SAVE;
// Top-level studio tabs
STUDIO_TRILE;
STUDIO_LEVEL;
STUDIO_MATERIAL;
// Trile editor — view modes
TRIXEL_VIEW_LIT;
TRIXEL_VIEW_NORMALS;
TRIXEL_VIEW_ALBEDO;
TRIXEL_VIEW_MIXED;
}
#scope_file;
EDITOR_ACTION_COUNT :: #run enum_highest_value(Editor_Action) + 1;
game_keybind_enum_type : Type;
Key_Combo :: struct {
key : Key_Code;
ctrl : bool;
shift : bool;
}
// 5000 different actions ought to be enough for anything right?
keys : [5000]Key_Combo;
check_action :: (action: $T, status: Key_Current_State) -> bool {
offset := 0;
if T != Editor_Action {
offset = EDITOR_ACTION_COUNT;
}
if console_open_ignore_input then return false;
combo := keys[cast(s32)action + offset];
ctrl_down := cast(bool)(input_button_states[Key_Code.CTRL] & .DOWN);
shift_down := cast(bool)(input_button_states[Key_Code.SHIFT] & .DOWN);
if combo.ctrl != ctrl_down then return false;
if combo.shift != shift_down then return false;
return cast(bool)(input_button_states[combo.key] & status);
}
#scope_export;
set_binding :: (action: $T, combo: Key_Combo) {
offset := 0;
if T != Editor_Action {
offset = EDITOR_ACTION_COUNT;
}
keys[cast(s32)action + offset] = combo;
}
is_action_down :: (action: $T) -> bool {
return check_action(action, .DOWN);
}
is_action_start :: (action: $T) -> bool {
return check_action(action, .START);
}
init_keybinds :: () {
set_default_bindings();
}
get_action_combo :: (action: $T) -> Key_Combo {
offset := 0;
#if T != Editor_Action {
offset = EDITOR_ACTION_COUNT;
}
return keys[cast(s32)action + offset];
}
keybind_button :: (r: GR.Rect, label: string, action: Editor_Action, theme: *GR.Button_Theme, loc := #caller_location) -> bool {
combo := get_action_combo(action);
full_label := tprint("% [%]", label, key_combo_string(combo));
clicked := GR.button(r, full_label, theme, loc = loc);
return clicked || is_action_start(action);
}
key_combo_string :: (combo: Key_Combo) -> string {
k := key_code_to_string(combo.key);
if combo.ctrl && combo.shift return tprint("C+S+%", k);
if combo.ctrl return tprint("C+%", k);
if combo.shift return tprint("S+%", k);
return k;
}
key_code_to_string :: (key: Key_Code) -> string {
if key == .ARROW_UP return "↑";
if key == .ARROW_DOWN return "↓";
if key == .ARROW_LEFT return "←";
if key == .ARROW_RIGHT return "→";
if key == .F1 return "F1"; if key == .F2 return "F2";
if key == .F3 return "F3"; if key == .F4 return "F4";
if key == .F5 return "F5"; if key == .F6 return "F6";
if key == .F7 return "F7"; if key == .F8 return "F8";
if key == .F9 return "F9"; if key == .F10 return "F10";
if key == .F11 return "F11"; if key == .F12 return "F12";
v := cast(s64) key;
if v >= 32 && v < 127 {
buf := cast(*u8) talloc(2);
buf[0] = cast(u8) v;
buf[1] = 0;
return string.{ count = 1, data = buf };
}
return "?";
}
#scope_file
set_default_bindings :: () {
set :: (a: Editor_Action, k: Key_Code, ctrl := false, shift := false) #expand {
set_binding(a, .{ k, ctrl, shift });
}
set(.TOGGLE_CONSOLE, .F1);
set(.TOGGLE_EDITOR, .F3);
set(.TOGGLE_SETTINGS, .ESCAPE);
set(.HOT_RELOAD, .F5);
set(.LEVEL_HEIGHT_UP, .ARROW_UP);
set(.LEVEL_HEIGHT_DOWN, .ARROW_DOWN);
set(.LEVEL_TWIST_CW, cast(Key_Code) #char "E");
set(.LEVEL_TWIST_CCW, cast(Key_Code) #char "Q");
set(.LEVEL_CYCLE_FACE, cast(Key_Code) #char "R");
set(.TRIXEL_TOOL_PAINT, cast(Key_Code) #char "P");
set(.TRIXEL_TOOL_ADD, cast(Key_Code) #char "-");
set(.TRIXEL_TOOL_REMOVE, cast(Key_Code) #char "/");
set(.TRIXEL_MODE_POINT, cast(Key_Code) #char "P", ctrl = true);
set(.TRIXEL_MODE_AREA, cast(Key_Code) #char "A", ctrl = true);
set(.TRIXEL_MODE_BRUSH, cast(Key_Code) #char "B", ctrl = true);
set(.TRIXEL_TAB_TOOLS, cast(Key_Code) #char "T");
set(.TRIXEL_TAB_MATERIAL, cast(Key_Code) #char "M");
set(.TRIXEL_TAB_INFO, cast(Key_Code) #char "I");
set(.LEVEL_TOOL_POINT, cast(Key_Code) #char "1");
set(.LEVEL_TOOL_BRUSH, cast(Key_Code) #char "2");
set(.LEVEL_TOOL_AREA, cast(Key_Code) #char "3");
set(.LEVEL_TOOL_LINE, cast(Key_Code) #char "4");
set(.LEVEL_TAB_TOOLS, cast(Key_Code) #char "T");
set(.LEVEL_TAB_INFO, cast(Key_Code) #char "I");
set(.LEVEL_TAB_TACOMA, cast(Key_Code) #char "X");
set(.SAVE, cast(Key_Code) #char "S", ctrl = true);
set(.STUDIO_TRILE, cast(Key_Code) #char "1", ctrl = true);
set(.STUDIO_LEVEL, cast(Key_Code) #char "2", ctrl = true);
set(.STUDIO_MATERIAL, cast(Key_Code) #char "3", ctrl = true);
set(.TRIXEL_VIEW_LIT, cast(Key_Code) #char "5");
set(.TRIXEL_VIEW_NORMALS, cast(Key_Code) #char "6");
set(.TRIXEL_VIEW_ALBEDO, cast(Key_Code) #char "7");
set(.TRIXEL_VIEW_MIXED, cast(Key_Code) #char "8");
}

14
src/loading_screen.jai Normal file
View File

@ -0,0 +1,14 @@
Loading_Screen_Config :: struct {
background_color : Vector4 = .{ 0.05, 0.05, 0.05, 1.0 };
bar_bg_color : Vector4 = .{ 0.15, 0.15, 0.15, 1.0 };
bar_fill_color : Vector4 = .{ 0.3, 0.7, 1.0, 1.0 };
}
loading_screen_config : Loading_Screen_Config;
set_loading_screen_config :: (config: Loading_Screen_Config) {
loading_screen_config = config;
}
draw_loading_screen :: () {
}

61
src/logging.jai Normal file
View File

@ -0,0 +1,61 @@
Log_Level :: enum {
DEBUG;
INFO;
WARN;
ERROR;
}
log_min_level : Log_Level = .INFO;
#scope_file
_emit :: (level: Log_Level, message: string) {
if level < log_min_level return;
prefix := ifx level == .DEBUG then "[DEBUG] "
else ifx level == .WARN then "[WARN] "
else ifx level == .ERROR then "[ERROR] "
else "[INFO] ";
// Always allocate on the heap regardless of context.allocator (e.g. mesh pool).
old_alloc := context.allocator;
context.allocator = default_context.allocator;
line := copy_string(tprint("%1%2", prefix, message));
context.allocator = old_alloc;
print("%\n", line);
console_add_output_line(line);
}
#scope_export
logger :: (level: Log_Level, fmt: string, args: ..Any) {
if level < log_min_level return;
_emit(level, tprint(fmt, ..args));
}
// Hook for Jai's context.logger — catches log() calls from Basic and libraries.
_logger_proc :: (message: string, data: *void, info: Log_Info) {
level : Log_Level;
if info.common_flags & .ERROR then level = .ERROR;
else if info.common_flags & .WARNING then level = .WARN;
else if (info.common_flags & .VERBOSE_ONLY) || (info.common_flags & .VERY_VERBOSE_ONLY) then level = .DEBUG;
else level = .INFO;
_emit(level, message);
}
log_debug :: (fmt: string, args: ..Any) { logger(.DEBUG, fmt, ..args); }
log_info :: (fmt: string, args: ..Any) { logger(.INFO, fmt, ..args); }
log_warn :: (fmt: string, args: ..Any) { logger(.WARN, fmt, ..args); }
log_error :: (fmt: string, args: ..Any) { logger(.ERROR, fmt, ..args); }
set_log_level :: (level_str: string) -> string {
if level_str == {
case "DEBUG"; log_min_level = .DEBUG;
case "INFO"; log_min_level = .INFO;
case "WARN"; log_min_level = .WARN;
case "ERROR"; log_min_level = .ERROR;
case; return tprint("Unknown log level '%'. Use DEBUG, INFO, WARN or ERROR.", level_str);
}
return tprint("Log level set to %.", level_str);
} @Command

View File

@ -15,7 +15,11 @@ String :: #import "String";
Jaison :: #import "Jaison";
stbi :: #import "stb_image";
#if FLAG_TEST_ENGINE { #load "tests/index.jai"; }
#load "logging.jai";
#load "pseudophysics/core.jai";
#load "pack_hotreload.jai";
#load "trile.jai";
#load "rendering/rendering.jai";
#load "input/hotkeys.jai";
@ -30,6 +34,8 @@ stbi :: #import "stb_image";
#load "utils.jai";
#load "audio/audio.jai";
#load "assets/asset_manager.jai";
#load "settings_menu.jai";
#load "ui/demo.jai";
#load "../game/game.jai";
@ -39,7 +45,7 @@ delta\ _time : float64;
latest_frametime : float64; // latest frame generation duration
V_MAJOR :: 0;
V_MINOR :: 6;
V_MINOR :: 7;
state: struct {
pass_action_clear : sg_pass_action;
@ -113,16 +119,12 @@ init :: () {
}
init_after_mandatory :: () {
}
init_after_core :: () {
init_plane_textures();
init_brdf_lut();
add_font_from_pack("boot", "DroidSerif-Regular.ttf");
ui_init_font_fields(*state.font_default);
init_ui();
ltriles();
tt := get_trile_table_ptr();
@ -163,13 +165,7 @@ frame :: () {
if !mandatory_loads_done() then return;
if !init_after_mandatory_done {
init_after_mandatory();
init_after_mandatory_done = true;
}
if show_loading_screen() {
print("Should show loading screen....\n");
return;
}
@ -190,10 +186,10 @@ frame :: () {
if !in_editor_view then delta_time_accumulator += delta_time;
if !in_editor_view {
while delta_time_accumulator > (1.0/60.0) {
game_tick(1.0/60.0);
delta_time_accumulator -= (1.0/60.0);
if !in_editor_view && !settings_menu_blocks_game() {
while delta_time_accumulator > (1.0/480.0) {
game_tick(1.0/480.0);
delta_time_accumulator -= (1.0/480.0);
}
}
fonsClearState(state.fons);

84
src/pack_hotreload.jai Normal file
View File

@ -0,0 +1,84 @@
#if !FLAG_RELEASE_BUILD && OS != .WASM {
#import "String";
Pack_Writer :: #import "Simple_Package";
File_Util :: #import "File_Utilities";
File_IO :: #import "File";
_hotreload_visitor :: (info: *File_Util.File_Visit_Info, packs: *Table(string, Pack_Writer.Create_Package)) {
{
ok, left, right := split_from_right(info.short_name, #char ".");
if right == "aseprite" return;
}
if contains(info.full_name, "/worlds/") return;
_, _, pack_path := split_from_left(info.full_name, "/resources/");
_, pack_name, file_name := split_from_left(pack_path, "/");
if !table_contains(packs, pack_name) {
package: Pack_Writer.Create_Package;
Pack_Writer.init(*package);
table_set(packs, pack_name, package);
}
pack_ptr := table_find_pointer(packs, pack_name);
file_content, ok := File_IO.read_entire_file(info.full_name);
if !ok {
log_warn("Hot-reload: failed to read '%'", info.full_name);
return;
}
data: []u8;
data.data = file_content.data;
data.count = file_content.count;
Pack_Writer.add(pack_ptr, file_name, data);
}
recreate_packs_on_disk :: () {
packs: Table(string, Pack_Writer.Create_Package);
File_Util.visit_files("./resources", true, *packs, _hotreload_visitor);
File_Util.visit_files("./game/resources", true, *packs, _hotreload_visitor);
for pack, key: packs {
Pack_Writer.write(*pack, tprint("./packs/%.pack", key));
log_info("Hot-reload: wrote pack '%'", key);
}
}
hot_reload_all_packs :: () {
pack_names: [..]string;
pack_names.allocator = temp;
for pack: g_asset_manager.loadedPacks {
array_add(*pack_names, sprint("%", pack.name));
}
array_reset(*g_asset_manager.fetch_queue);
g_mixer.paused = true;
g_asset_manager.hot_reload_unpause_pending = true;
// Clear tasks while holding the lock so the audio thread can't be
// mid-sample when we free the audio data below.
mixer_lock(*g_mixer);
array_reset(*g_mixer.tasks);
mixer_unlock(*g_mixer);
for *pack: g_asset_manager.loadedPacks {
free_resources_from_pack(pack);
}
array_reset(*g_asset_manager.loadedPacks);
// Force init_after_core to re-run once the new packs are loaded,
// so that all pack-dependent state (textures, post-process, game_init, etc.)
// is refreshed with the new content.
init_after_core_done = false;
log_info("Hot-reload: recreating packs on disk...");
recreate_packs_on_disk();
for name: pack_names {
load_pack(name, true, false);
}
log_info("Hot-reload: queued % pack(s) for reload", pack_names.count);
}
} // #if !RELEASE_BUILD && OS != .WASM

View File

@ -5,14 +5,6 @@ main :: () {
sapp_init();
}
log_warn :: (format_string: string, args: .. Any, loc := #caller_location, flags := Log_Flags.NONE, user_flags : u32 = 0, section : *Log_Section = null) {
log(format_string, ..args, loc = loc, flags = flags | .WARNING, user_flags = user_flags, section = section);
} @PrintLike
log_content :: (format_string: string, args: .. Any, loc := #caller_location, flags := Log_Flags.NONE, user_flags : u32 = 0, section : *Log_Section = null) {
log(format_string, ..args, loc = loc, flags = flags | .CONTENT, user_flags = user_flags, section = section);
} @PrintLike
logger :: (message: string, data: *void, info: Log_Info) {
print("% % %\n", message, data, info);
_logger_proc(message, data, info);
}

View File

@ -40,15 +40,14 @@ Ray_Collision :: struct {
normal : Vector3;
}
// At which 2D XZ point does a ray hit the ground plane at a height of
// plane_height. Used for the level editor and maybe later the trile editor as well.
// At which 2D XZ point does a ray hit the horizontal plane at plane_height.
// Works whether the camera is above or below the plane.
ray_plane_collision_point :: (ray: Ray, plane_height: float, acceptable_radius: float = -1) -> (bool, Vector2) {
dist_to_plane := ray.origin.y - plane_height;
if ray.direction.y >= 0 then return false, .{0,0};
multi := dist_to_plane / abs(ray.direction.y);
ray_to_plane := ray.direction * multi;
planePoint := ray_to_plane + ray.origin;
if acceptable_radius > 0 && abs(length(Vector2.{planePoint.x, planePoint.z} - Vector2.{ray.origin.x, ray.origin.z})) > acceptable_radius {
if abs(ray.direction.y) < 0.0001 then return false, .{0,0}; // parallel to plane
multi := (plane_height - ray.origin.y) / ray.direction.y;
if multi < 0 then return false, .{0,0}; // plane is behind the camera
planePoint := ray.origin + ray.direction * multi;
if acceptable_radius > 0 && length(Vector2.{planePoint.x, planePoint.z} - Vector2.{ray.origin.x, ray.origin.z}) > acceptable_radius {
return false, .{};
}
return true, .{planePoint.x, planePoint.z};

View File

@ -4,7 +4,7 @@ g_animations: Table(string, Animation);
get_animation_from_string :: (animation: string) -> *Animation {
ok, pack, anim := split_from_left(animation, ".");
if !ok {
print("Malformed animation query: %\n", animation);
log_warn("Malformed animation query: %", animation);
return null;
}
return get_animation_from_pack(pack, anim);
@ -37,7 +37,7 @@ animation_player_tick :: (player: *Animation_Player) {
animation_draw :: (player: *Animation_Player, position: Vector3, flipX: bool = false, flipY: bool = false) {
animation_player_tick(player);
if player.current_animation == null then print("Trying to draw a null animation!!\n");
if player.current_animation == null then log_warn("Trying to draw a null animation!!");
create_billboard_rendering_task(position, player.current_animation, player.current_frame, flipX, flipY);
}

View File

@ -47,12 +47,14 @@ Render_Command_Add_Trile_Positions :: struct {
}
Render_Command_Draw_Trile_Positions :: struct {
#as using c : Render_Command;
c.type = .DRAW_TRILE_POSITIONS;
trile : string;
chunk_key : Chunk_Key;
amount : s32;
conf : *World_Config;
#as using c : Render_Command;
c.type = .DRAW_TRILE_POSITIONS;
trile : string;
chunk_key : Chunk_Key;
amount : s32;
conf : *World_Config;
preview_mode : s32 = 0; // 0=normal, 1=add preview (blue), 2=delete preview (red)
offset_index : s32 = 0; // index into trile_offsets, assigned at task-conversion time
}
Render_Command_Update_Trixels :: struct {

View File

@ -3,9 +3,10 @@ camera: Camera;
trixel_count : s32 = 0;
trixel_view_mode : s32 = 0;
bypass_postprocess : bool = false;
bypass_shadows : bool = false;
bypass_reflections : bool = false;
trile_offsets : [..]s32;
current_trile_offset_index : s32 = 0;
current_world_config : *World_Config = null;
in_shadowmap_pass : bool = false;
@ -20,7 +21,7 @@ backend_handle_command :: (cmd: *Render_Command) {
backend_add_trile_positions(add_command.positions);
case .DRAW_TRILE_POSITIONS;
draw_command := cast(*Render_Command_Draw_Trile_Positions)cmd;
backend_draw_trile_positions(draw_command.trile, draw_command.amount, draw_command.conf, draw_command.chunk_key);
backend_draw_trile_positions(draw_command.trile, draw_command.amount, draw_command.conf, draw_command.chunk_key, draw_command.preview_mode, draw_command.offset_index);
case .DRAW_SKY;
sky_command := cast(*Render_Command_Sky)cmd;
backend_draw_sky(sky_command.worldConfig);
@ -115,15 +116,16 @@ backend_add_trile_positions :: (positions : []Vector4) {
array_add(*trile_offsets, offset);
}
backend_draw_trile_positions :: (trile : string, amount : s32, worldConf: *World_Config, chunk_key: Chunk_Key) {
backend_draw_trile_positions :: (trile : string, amount : s32, worldConf: *World_Config, chunk_key: Chunk_Key, preview_mode: s32 = 0, offset_index: s32 = 0) {
if in_gbuffer_pass {
backend_draw_trile_positions_gbuffer(trile, amount, worldConf);
backend_draw_trile_positions_gbuffer(trile, amount, worldConf, offset_index);
} else {
backend_draw_trile_positions_main(trile, amount, worldConf, chunk_key);
backend_draw_trile_positions_main(trile, amount, worldConf, chunk_key, preview_mode, offset_index);
}
}
backend_draw_trile_positions_gbuffer :: (trile : string, amount : s32, worldConf: *World_Config) {
backend_draw_trile_positions_gbuffer :: (trile : string, amount : s32, worldConf: *World_Config, offset_index: s32) {
if offset_index >= trile_offsets.count then return;
mvp := create_viewproj(*camera);
view := create_lookat(*camera);
vs_params : Gbuffer_Vs_Params;
@ -133,8 +135,7 @@ backend_draw_trile_positions_gbuffer :: (trile : string, amount : s32, worldConf
world_conf : Trile_World_Config;
world_config_to_shader_type(worldConf, *world_conf);
offset := trile_offsets[current_trile_offset_index];
current_trile_offset_index += 1;
offset := trile_offsets[offset_index];
trilegfx := get_trile_gfx(trile);
bindings : sg_bindings;
@ -151,14 +152,34 @@ backend_draw_trile_positions_gbuffer :: (trile : string, amount : s32, worldConf
sg_draw(0, cast(s32) trilegfx.vertex_count, amount);
}
backend_draw_trile_positions_main :: (trile : string, amount : s32, worldConf: *World_Config, chunk_key: Chunk_Key) {
backend_draw_trile_positions_main :: (trile : string, amount : s32, worldConf: *World_Config, chunk_key: Chunk_Key, preview_mode: s32 = 0, offset_index: s32 = 0) {
start_frame_profiling_group("Draw trile positions");
mvp : Matrix4;
if !in_shadowmap_pass {
mvp = create_viewproj(*camera);
} else {
mvp = shadow_mvp;
if offset_index >= trile_offsets.count {
end_frame_profiling_group("Draw trile positions");
return;
}
trilegfx := get_trile_gfx(trile);
offset := trile_offsets[offset_index];
if in_shadowmap_pass {
vs_params : Trile_Shadow_Vs_Params;
vs_params.mvp = shadow_mvp.floats;
bindings : sg_bindings;
bindings.vertex_buffers[0] = trilegfx.vertex_buffer;
bindings.vertex_buffers[1] = trilegfx.normal_buffer;
bindings.vertex_buffers[2] = trilegfx.centre_buffer;
bindings.vertex_buffers[3] = gPipelines.trile.bind.vertex_buffers[3];
bindings.vertex_buffer_offsets[3] = offset;
sg_apply_pipeline(gPipelines.trile_shadow.pipeline);
sg_apply_bindings(*bindings);
sg_apply_uniforms(UB_trile_shadow_vs_params, *(sg_range.{ ptr = *vs_params, size = size_of(type_of(vs_params)) }));
sg_draw(0, cast(s32) trilegfx.vertex_count, amount);
end_frame_profiling_group("Draw trile positions");
return;
}
mvp := create_viewproj(*camera);
vs_params : Trile_Vs_Params;
vs_params.mvp = mvp.floats;
vs_params.mvp_shadow = shadow_mvp.floats;
@ -166,11 +187,8 @@ backend_draw_trile_positions_main :: (trile : string, amount : s32, worldConf: *
sg_apply_pipeline(gPipelines.trile.pipeline);
world_conf : Trile_World_Config;
world_config_to_shader_type(worldConf, *world_conf);
world_conf.planeHeight = effective_plane_height(worldConf);
offset := trile_offsets[current_trile_offset_index];
current_trile_offset_index += 1;
trilegfx := get_trile_gfx(trile);
bindings : sg_bindings;
bindings.vertex_buffers[0] = trilegfx.vertex_buffer;
bindings.vertex_buffers[1] = trilegfx.normal_buffer;
@ -181,14 +199,7 @@ backend_draw_trile_positions_main :: (trile : string, amount : s32, worldConf: *
bindings.images[0] = trilegfx.trixel_colors;
bindings.images[1] = g_ssaobuf;
bindings.samplers[2] = g_shadowmap_sampler;
if !in_shadowmap_pass {
bindings.images[2] = g_shadowmap;
} else {
// Just put something in this slot instead of the shadowmap
// so we don't have a circular shadowmap drawing situation.
// The texture is not used in shadowmap pass.
bindings.images[2] = g_rendertex_depth;
}
bindings.images[2] = g_shadowmap;
// Bind RDM textures for this chunk. Fall back to a 1x1 black image when
// no baked data is available so sokol doesn't drop the draw call.
@ -219,8 +230,9 @@ backend_draw_trile_positions_main :: (trile : string, amount : s32, worldConf: *
fs_params.rdm_diff_scale = lc.rdm_diff_scale;
fs_params.rdm_spec_scale = lc.rdm_spec_scale;
fs_params.ambient_color = lc.ambient_color.component;
fs_params.is_preview = preview_mode;
fs_params.rdm_tint = lc.rdm_tint.component;
sg_apply_bindings(*bindings);
sg_apply_uniforms(UB_trile_fs_params, *(sg_range.{ ptr = *fs_params, size = size_of(type_of(fs_params)) }));
sg_apply_uniforms(UB_trile_vs_params, *(sg_range.{ ptr = *vs_params, size = size_of(type_of(vs_params))}));
@ -261,7 +273,7 @@ backend_draw_ground :: (wc: *World_Config) {
world_config_to_shader_type(wc, *world_conf);
vs_params.mvp = mvp.floats;
vs_params.planeHeight = wc.planeHeight;
vs_params.planeHeight = effective_plane_height(wc);
sg_apply_pipeline(gPipelines.plane.pipeline);
gPipelines.plane.bind.samplers[1] = g_shadowmap_sampler;
gPipelines.plane.bind.images[1] = g_shadowmap;
@ -341,7 +353,7 @@ backend_draw_ground_gbuf :: (wc: *World_Config) {
vs_params.mvp = mvp.floats;
vs_params.view_matrix = view.floats;
vs_params.isGround = 1;
vs_params.planeHeight = wc.planeHeight;
vs_params.planeHeight = effective_plane_height(wc);
sg_apply_pipeline(gPipelines.gbuffer.pipeline);
bindings : sg_bindings;
@ -369,25 +381,27 @@ backend_process_command_buckets :: () {
shadow_mvp = create_shadow_viewproj(*camera, current_world_config);
in_shadowmap_pass = true;
sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, attachments = g_shadowmap_attachments}));
for render_command_buckets.shadow {
backend_handle_command(it);
if !bypass_shadows {
for render_command_buckets.shadow {
backend_handle_command(it);
}
}
sg_end_pass();
in_shadowmap_pass = false;
}
current_trile_offset_index = 0; // This is not optimal, but it is nice and simple.
end_frame_profiling_group("Shadow pass");
start_frame_profiling_group("Reflection pass");
// 3. Reflection pass
sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, attachments = gPipelines.plane.attachments}));
in_reflection_pass = true;
for render_command_buckets.reflection {
backend_handle_command(it);
}
in_reflection_pass = false;
if !bypass_reflections {
in_reflection_pass = true;
for render_command_buckets.reflection {
backend_handle_command(it);
}
in_reflection_pass = false;
}
sg_end_pass();
current_trile_offset_index = 0; // This is not optimal, but it is nice and simple.
end_frame_profiling_group("Reflection pass");
// 4. G-Buffer pass
@ -399,7 +413,6 @@ backend_process_command_buckets :: () {
}
sg_end_pass();
in_gbuffer_pass = false;
current_trile_offset_index = 0; // This is not optimal, but it is nice and simple.
end_frame_profiling_group("G-Buffer pass");
start_frame_profiling_group("SSAO pass");
@ -439,7 +452,6 @@ backend_process_command_buckets :: () {
backend_handle_command(it);
}
sg_end_pass();
current_trile_offset_index = 0; // This is not optimal, but it is nice and simple.
end_frame_profiling_group("Main pass");
start_frame_profiling_group("Postprocess pass");
@ -461,6 +473,7 @@ backend_process_command_buckets :: () {
post_process_config_uniform : Post_Process_Config;
if bypass_postprocess {
neutral : Post_Process;
neutral.tonemap = current_post_process.tonemap;
fill_uniform_with_engine_data(*post_process_config_uniform, *neutral);
} else {
fill_uniform_with_engine_data(*post_process_config_uniform, *current_post_process);

View File

@ -18,45 +18,103 @@ Gathered_Positions :: struct {
positions: [..]Vector4;
}
create_world_rendering_tasks :: (world: *World) {
extract_frustum_planes :: (mvp: Matrix4) -> [6]Vector4 {
planes : [6]Vector4;
m := mvp;
planes[0] = .{m._14+m._11, m._24+m._21, m._34+m._31, m._44+m._41}; // left
planes[1] = .{m._14-m._11, m._24-m._21, m._34-m._31, m._44-m._41}; // right
planes[2] = .{m._14+m._12, m._24+m._22, m._34+m._32, m._44+m._42}; // bottom
planes[3] = .{m._14-m._12, m._24-m._22, m._34-m._32, m._44-m._42}; // top
planes[4] = .{m._14+m._13, m._24+m._23, m._34+m._33, m._44+m._43}; // near
planes[5] = .{m._14-m._13, m._24-m._23, m._34-m._33, m._44-m._43}; // far
return planes;
}
aabb_in_frustum :: (planes: [6]Vector4, bmin: Vector3, bmax: Vector3) -> bool {
for plane: planes {
px := ifx plane.x >= 0 then bmax.x else bmin.x;
py := ifx plane.y >= 0 then bmax.y else bmin.y;
pz := ifx plane.z >= 0 then bmax.z else bmin.z;
if plane.x*px + plane.y*py + plane.z*pz + plane.w < 0 return false;
}
return true;
}
create_world_rendering_tasks :: (world: *World, camera: Camera) {
create_sky_rendering_task(*world.conf);
create_set_light_rendering_task(*world.conf);
// Gather all trile positions from chunks, grouped by trile type.
gathered: [..]Gathered_Positions;
cam_mvp := create_viewproj(*camera);
shadow_mvp := create_shadow_viewproj(*camera, *world.conf);
cam_planes := extract_frustum_planes(cam_mvp);
shadow_planes := extract_frustum_planes(shadow_mvp);
// Gather positions for camera-visible instances (all passes) and
// shadow-only instances (chunks visible from sun but not camera).
gathered : [..]Gathered_Positions;
gathered.allocator = temp;
shad_gathered : [..]Gathered_Positions;
shad_gathered.allocator = temp;
find_or_create :: (list: *[..]Gathered_Positions, name: string, chunk_key: Chunk_Key) -> *Gathered_Positions {
for *g: list.* {
if g.name == name && g.chunk_key == chunk_key return g;
}
array_add(list, .{name = name, chunk_key = chunk_key});
g := *list.*[list.count - 1];
g.positions.allocator = temp;
return g;
}
for chunk: world.chunks {
bmin := Vector3.{chunk.coord.x * 32.0, chunk.coord.y * 32.0, chunk.coord.z * 32.0};
bmax := bmin + .{32, 32, 32};
in_cam := aabb_in_frustum(cam_planes, bmin, bmax);
in_shad := aabb_in_frustum(shadow_planes, bmin, bmax);
if !in_cam && !in_shad continue;
for group: chunk.groups {
// Find or create the gathered entry for this (chunk, trile_type) pair.
target: *Gathered_Positions = null;
for *g: gathered {
if g.name == group.trile_name && g.chunk_key == chunk.coord {
target = g;
break;
}
}
if !target {
array_add(*gathered, .{name = group.trile_name, chunk_key = chunk.coord});
target = *gathered[gathered.count - 1];
target.positions.allocator = temp;
}
for inst: group.instances {
wx, wy, wz := chunk_local_to_world(chunk.coord, inst.x, inst.y, inst.z);
array_add(*target.positions, Vector4.{cast(float) wx, cast(float) wy, cast(float) wz, cast(float) inst.orientation});
imin := Vector3.{cast(float)wx, cast(float)wy, cast(float)wz};
imax := imin + .{1, 1, 1};
inst_cam := in_cam && aabb_in_frustum(cam_planes, imin, imax);
inst_shad := in_shad && aabb_in_frustum(shadow_planes, imin, imax);
if !inst_cam && !inst_shad continue;
pos := Vector4.{cast(float)wx, cast(float)wy, cast(float)wz, cast(float)inst.orientation};
if inst_cam {
target := find_or_create(*gathered, group.trile_name, chunk.coord);
array_add(*target.positions, pos);
} else {
target := find_or_create(*shad_gathered, group.trile_name, chunk.coord);
array_add(*target.positions, pos);
}
}
}
}
for g: gathered {
if g.positions.count < 1 then continue;
triletask := Rendering_Task_Trile.{};
triletask.trile = g.name;
if g.positions.count < 1 continue;
triletask : Rendering_Task_Trile;
triletask.trile = g.name;
triletask.chunk_key = g.chunk_key;
triletask.positions = g.positions;
triletask.worldConf = *world.conf;
add_rendering_task(triletask);
}
for g: shad_gathered {
if g.positions.count < 1 continue;
triletask : Rendering_Task_Trile;
triletask.trile = g.name;
triletask.chunk_key = g.chunk_key;
triletask.positions = g.positions;
triletask.worldConf = *world.conf;
triletask.shadow_only = true;
add_rendering_task(triletask);
}
create_ground_rendering_task(world);
}

View File

@ -419,7 +419,7 @@ generate_trile_gfx_matias :: (trileptr : *Trile) -> Trile_GFX {
trile_normal_buffer_info := sg_buffer_desc.{ data = .{ ptr = triangleNorms.data, size = xx (triangleNorms.count * 4) } };
trile_normal_buffer := sg_make_buffer(*trile_normal_buffer_info);
print("Successfully generated mesh for trile with % triangles.\n", triangleVecs.count / 3 / 3);
log_debug("Successfully generated mesh for trile with % triangles.", triangleVecs.count / 3 / 3);
centres : [..]float;
@ -492,7 +492,7 @@ generate_trile_gfx_matias :: (trileptr : *Trile) -> Trile_GFX {
img := sg_make_image(*texdesc);
state := sg_query_image_state(img);
print("IMG: %\n", state);
log_debug("IMG: %", state);
context.allocator = old_alloc;
vecsCopy := array_copy(triangleVecs);

View File

@ -56,6 +56,9 @@ gPipelines : struct {
// Renders sets of triles
trile : Pipeline_Binding;
// Depth-only shadow pass for triles (no lighting/RDM)
trile_shadow : Pipeline_Binding;
// Renders the ground plane. (just water)
plane : Pipeline_Binding;
@ -80,7 +83,7 @@ create_final_image :: () {
if g_rendertex.id != INVALID_ID then sg_destroy_image(g_rendertex);
if g_rendertex_depth.id != INVALID_ID then sg_destroy_image(g_rendertex);
if g_rendertex_depth.id != INVALID_ID then sg_destroy_image(g_rendertex_depth);
img_desc := sg_image_desc.{
width = w,
@ -140,6 +143,7 @@ create_pipelines :: () {
create_arbtri_pipeline();
create_trixel_pipeline();
create_trile_pipeline();
create_trile_shadow_pipeline();
create_sky_pipeline();
create_plane_pipeline();
create_postprocess_pipeline();
@ -408,6 +412,28 @@ create_trile_pipeline :: () {
}));
}
create_trile_shadow_pipeline :: () {
pipeline: sg_pipeline_desc;
shader_desc := trile_shadow_shader_desc(sg_query_backend());
pipeline.shader = sg_make_shader(*shader_desc);
pipeline.layout.buffers[0].stride = 4*3;
pipeline.layout.buffers[1].stride = 4*3;
pipeline.layout.buffers[3].step_func = .PER_INSTANCE;
// Explicit locations matching layout(location=N) in the shader.
pipeline.layout.attrs[0] = .{ format = .FLOAT3, buffer_index = 0 }; // position
pipeline.layout.attrs[1] = .{ format = .FLOAT3, buffer_index = 1 }; // normal (slot match)
pipeline.layout.attrs[2] = .{ format = .FLOAT3, buffer_index = 2 }; // centre (slot match)
pipeline.layout.attrs[3] = .{ format = .FLOAT4, buffer_index = 3 }; // instance
pipeline.depth = .{
write_enabled = true,
compare = .LESS_EQUAL,
pixel_format = .DEPTH,
};
pipeline.color_count = 1;
pipeline.colors[0].pixel_format = .RGBA32F;
gPipelines.trile_shadow.pipeline = sg_make_pipeline(*pipeline);
}
create_sky_pipeline :: () {
pipeline: sg_pipeline_desc;
shader_desc := sky_shader_desc(sg_query_backend());

View File

@ -56,6 +56,8 @@ Rendering_Task_Trile :: struct {
chunk_key : Chunk_Key;
positions : []Vector4;
worldConf : *World_Config;
preview_mode : s32 = 0; // 0=normal, 1=add preview (blue), 2=delete preview (red)
shadow_only : bool = false; // only submit to shadow bucket (frustum-culled from camera)
}
Rendering_Task_Trixels :: struct {
@ -84,6 +86,7 @@ add_rendering_task :: (task: $T) {
rendering_tasklist : [..]*Rendering_Task;
tasks_to_commands :: () {
trile_add_counter: s32 = 0;
for rendering_tasklist {
if it.type == {
case .SET_LIGHT;
@ -109,14 +112,23 @@ tasks_to_commands :: () {
addPositionsCmd.positions = trileTask.positions;
array_add(*render_command_buckets.setup, addPositionsCmd);
drawPositionsCmd := New(Render_Command_Draw_Trile_Positions,, temp);
drawPositionsCmd.trile = trileTask.trile;
drawPositionsCmd.chunk_key = trileTask.chunk_key;
drawPositionsCmd.amount = cast(s32)trileTask.positions.count;
drawPositionsCmd.conf = trileTask.worldConf;
array_add(*render_command_buckets.reflection, drawPositionsCmd);
array_add(*render_command_buckets.main, drawPositionsCmd);
array_add(*render_command_buckets.gbuffer, drawPositionsCmd);
array_add(*render_command_buckets.shadow, drawPositionsCmd);
drawPositionsCmd.trile = trileTask.trile;
drawPositionsCmd.chunk_key = trileTask.chunk_key;
drawPositionsCmd.amount = cast(s32)trileTask.positions.count;
drawPositionsCmd.conf = trileTask.worldConf;
drawPositionsCmd.preview_mode = trileTask.preview_mode;
drawPositionsCmd.offset_index = trile_add_counter;
trile_add_counter += 1;
if trileTask.shadow_only {
array_add(*render_command_buckets.shadow, drawPositionsCmd);
} else if trileTask.preview_mode != 0 {
array_add(*render_command_buckets.main, drawPositionsCmd);
} else {
array_add(*render_command_buckets.reflection, drawPositionsCmd);
array_add(*render_command_buckets.main, drawPositionsCmd);
array_add(*render_command_buckets.gbuffer, drawPositionsCmd);
array_add(*render_command_buckets.shadow, drawPositionsCmd);
}
case .SKY;
command := New(Render_Command_Sky,, temp);
command.worldConfig = (cast(*Rendering_Task_Sky)it).worldConfig;

189
src/settings_menu.jai Normal file
View File

@ -0,0 +1,189 @@
#scope_file
TRANSITION_SPEED :: 3.0;
Settings_Page :: enum {
MAIN;
AUDIO;
}
Settings_State :: struct {
open : bool = false;
transition : float = 0.0;
page : Settings_Page = .MAIN;
cursor : s32 = 0;
title_font : *Font;
item_font : *Font;
}
g_settings : Settings_State;
MAIN_ITEMS :: string.["Audio"];
AUDIO_LABELS :: string.["Master Volume", "Music Volume", "Sound Effects"];
audio_get :: (i: s32) -> float {
if i == 0 return g_mixer.config.masterVolume;
if i == 1 return g_mixer.config.musicVolume;
if i == 2 return g_mixer.config.soundEffectVolume;
return 0.0;
}
audio_set :: (i: s32, v: float) {
if i == 0 then g_mixer.config.masterVolume = clamp(v, 0.0, 1.0);
if i == 1 then g_mixer.config.musicVolume = clamp(v, 0.0, 1.0);
if i == 2 then g_mixer.config.soundEffectVolume = clamp(v, 0.0, 1.0);
}
page_count :: () -> s32 {
if g_settings.page == .MAIN return MAIN_ITEMS.count;
if g_settings.page == .AUDIO return AUDIO_LABELS.count;
return 0;
}
#scope_export
settings_menu_blocks_game :: () -> bool {
return g_settings.open;
}
init_settings_menu :: () {
g_settings.title_font = get_font_at_size(60);
g_settings.item_font = get_font_at_size(30);
}
tick_settings_menu :: () {
if in_editor_view then return;
if is_action_start(Editor_Action.TOGGLE_SETTINGS) {
if !g_settings.open {
g_settings.open = true;
g_settings.page = .MAIN;
g_settings.cursor = 0;
} else if g_settings.page != .MAIN {
g_settings.page = .MAIN;
g_settings.cursor = 0;
} else {
g_settings.open = false;
}
}
dt := cast(float) delta_time;
if g_settings.open {
g_settings.transition = min(g_settings.transition + TRANSITION_SPEED * dt, 1.0);
} else {
g_settings.transition = max(g_settings.transition - TRANSITION_SPEED * dt, 0.0);
}
if !g_settings.open then return;
if console_open_ignore_input then return;
count := page_count();
up := cast(bool)(input_button_states[Key_Code.ARROW_UP] & .START);
down := cast(bool)(input_button_states[Key_Code.ARROW_DOWN] & .START);
left := cast(bool)(input_button_states[Key_Code.ARROW_LEFT] & .START);
right := cast(bool)(input_button_states[Key_Code.ARROW_RIGHT]& .START);
enter := cast(bool)(input_button_states[Key_Code.ENTER] & .START);
if up then g_settings.cursor = (g_settings.cursor - 1 + count) % count;
if down then g_settings.cursor = (g_settings.cursor + 1) % count;
if g_settings.page == .MAIN && enter {
if g_settings.cursor == 0 {
g_settings.page = .AUDIO;
g_settings.cursor = 0;
}
}
if g_settings.page == .AUDIO {
delta : float = 0.0;
if left then delta = -0.1;
if right then delta = 0.1;
if delta != 0.0 then audio_set(g_settings.cursor, audio_get(g_settings.cursor) + delta);
}
}
draw_settings_menu :: (theme: *GR.Overall_Theme) {
t := g_settings.transition;
if t < 0.001 then return;
fw := vw * 100.0;
fh := vh * 100.0;
half_h := fh * 0.5;
bar_h := t * half_h;
bg := Vector4.{0.04, 0.04, 0.06, 1.0};
set_shader_for_color();
// Top eyelid sliding down
immediate_quad(.{0, 0}, .{fw, 0}, .{fw, bar_h}, .{0, bar_h}, bg);
immediate_flush();
// Bottom eyelid sliding up
bottom_y := fh - bar_h;
immediate_quad(.{0, bottom_y}, .{fw, bottom_y}, .{fw, fh}, .{0, fh}, bg);
immediate_flush();
// Content fades in during the last quarter of the transition
content_alpha := clamp((t - 0.75) / 0.25, 0.0, 1.0);
if content_alpha < 0.01 then return;
white := Vector4.{1.0, 1.0, 1.0, content_alpha};
dim := Vector4.{0.45, 0.45, 0.45, content_alpha};
selected := Vector4.{1.0, 0.95, 0.65, content_alpha};
// Game title
prepare_text(g_settings.title_font, "BEACHBALL");
title_x := (fw - cast(float) gPreppedTextWidth) * 0.5;
draw_prepared_text(g_settings.title_font, xx title_x, xx (fh * 0.22), white);
item_h := cast(float)(g_settings.item_font.character_height) * 1.7;
if g_settings.page == .MAIN {
total_h := MAIN_ITEMS.count * item_h;
start_y := half_h - total_h * 0.5;
for i: 0..MAIN_ITEMS.count-1 {
col := ifx cast(s32)i == g_settings.cursor then selected else dim;
prepare_text(g_settings.item_font, MAIN_ITEMS[i]);
x := (fw - cast(float) gPreppedTextWidth) * 0.5;
draw_prepared_text(g_settings.item_font, xx x, xx (start_y + cast(float)i * item_h), col);
}
hint_str := "↑↓ navigate Enter select";
prepare_text(g_settings.item_font, hint_str);
hint_x := (fw - cast(float) gPreppedTextWidth) * 0.5;
draw_prepared_text(g_settings.item_font, xx hint_x, xx (fh * 0.82), dim);
} else if g_settings.page == .AUDIO {
total_h := AUDIO_LABELS.count * item_h;
start_y := half_h - total_h * 0.5;
for i: 0..AUDIO_LABELS.count-1 {
col := ifx cast(s32)i == g_settings.cursor then selected else dim;
pct := cast(s32)(audio_get(cast(s32)i) * 100.0 + 0.5);
bar := make_volume_bar(pct, cast(s32)i == g_settings.cursor);
label := tprint("% %", AUDIO_LABELS[i], bar);
prepare_text(g_settings.item_font, label);
x := (fw - cast(float) gPreppedTextWidth) * 0.5;
draw_prepared_text(g_settings.item_font, xx x, xx (start_y + cast(float)i * item_h), col);
}
hint_str := "↑↓ navigate ← → adjust Esc back";
prepare_text(g_settings.item_font, hint_str);
hint_x := (fw - cast(float) gPreppedTextWidth) * 0.5;
draw_prepared_text(g_settings.item_font, xx hint_x, xx (fh * 0.82), dim);
}
}
#scope_file
make_volume_bar :: (pct: s32, active: bool) -> string {
STEPS :: 10;
filled := (pct + 5) / STEPS;
builder : String_Builder;
append(*builder, "[ ");
for i: 0..STEPS-1 {
if i < filled then append(*builder, "■");
else append(*builder, "·");
}
append(*builder, tprint(" %", pct));
append(*builder, " ]");
return builder_to_string(*builder,, allocator = temp);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,907 @@
/*
#version:1# (machine generated, don't edit!)
Generated by sokol-shdc (https://github.com/floooh/sokol-tools)
Cmdline:
sokol-shdc -i shader_trile_shadow.glsl -o ./jai/shader_trile_shadow.jai -l glsl430:glsl300es:metal_macos -f sokol_jai
Overview:
=========
Shader program: 'trile_shadow':
Get shader desc: trile_shadow_shader_desc(sg_query_backend())
Vertex Shader: vs_trile_shadow
Fragment Shader: fs_trile_shadow
Attributes:
ATTR_trile_shadow_position => 0
ATTR_trile_shadow_normal => 1
ATTR_trile_shadow_centre => 2
ATTR_trile_shadow_instance => 3
Bindings:
Uniform block 'trile_shadow_vs_params':
Jai struct: Trile_Shadow_Vs_Params
Bind slot: UB_trile_shadow_vs_params => 0
*/
ATTR_trile_shadow_position :: 0;
ATTR_trile_shadow_normal :: 1;
ATTR_trile_shadow_centre :: 2;
ATTR_trile_shadow_instance :: 3;
UB_trile_shadow_vs_params :: 0;
Trile_Shadow_Vs_Params :: struct {
mvp: [16]float;
};
/*
#version 430
uniform vec4 trile_shadow_vs_params[4];
layout(location = 3) in vec4 instance;
layout(location = 0) in vec4 position;
layout(location = 1) in vec4 normal;
layout(location = 2) in vec4 centre;
mat3 rot_x(float a)
{
float _28 = cos(a);
float _31 = sin(a);
return mat3(vec3(1.0, 0.0, 0.0), vec3(0.0, _28, -_31), vec3(0.0, _31, _28));
}
mat3 rot_z(float a)
{
float _47 = cos(a);
float _50 = sin(a);
return mat3(vec3(_47, -_50, 0.0), vec3(_50, _47, 0.0), vec3(0.0, 0.0, 1.0));
}
mat3 rot_y(float a)
{
float _64 = cos(a);
float _67 = sin(a);
return mat3(vec3(_64, 0.0, _67), vec3(0.0, 1.0, 0.0), vec3(-_67, 0.0, _64));
}
mat3 get_orientation_matrix(int ori)
{
int _82 = ori / 4;
mat3 base;
if (_82 == 0)
{
base = mat3(vec3(1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, 0.0, 1.0));
}
else
{
if (_82 == 1)
{
float param = 3.1415927410125732421875;
base = rot_x(param);
}
else
{
if (_82 == 2)
{
float param_1 = -1.57079637050628662109375;
base = rot_z(param_1);
}
else
{
if (_82 == 3)
{
float param_2 = 1.57079637050628662109375;
base = rot_z(param_2);
}
else
{
if (_82 == 4)
{
float param_3 = 1.57079637050628662109375;
base = rot_x(param_3);
}
else
{
float param_4 = -1.57079637050628662109375;
base = rot_x(param_4);
}
}
}
}
}
float param_5 = float(ori % 4) * 1.57079637050628662109375;
return base * rot_y(param_5);
}
void main()
{
int param = int(round(instance.w));
gl_Position = mat4(trile_shadow_vs_params[0], trile_shadow_vs_params[1], trile_shadow_vs_params[2], trile_shadow_vs_params[3]) * vec4(((get_orientation_matrix(param) * (position.xyz - vec3(0.5))) + vec3(0.5)) + instance.xyz, 1.0);
}
*/
vs_trile_shadow_source_glsl430 := u8.[
0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x34,0x33,0x30,0x0a,0x0a,0x75,0x6e,
0x69,0x66,0x6f,0x72,0x6d,0x20,0x76,0x65,0x63,0x34,0x20,0x74,0x72,0x69,0x6c,0x65,
0x5f,0x73,0x68,0x61,0x64,0x6f,0x77,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,
0x73,0x5b,0x34,0x5d,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,
0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x33,0x29,0x20,0x69,0x6e,0x20,0x76,0x65,
0x63,0x34,0x20,0x69,0x6e,0x73,0x74,0x61,0x6e,0x63,0x65,0x3b,0x0a,0x6c,0x61,0x79,
0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,
0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x34,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,
0x6f,0x6e,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,
0x69,0x6f,0x6e,0x20,0x3d,0x20,0x31,0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x34,
0x20,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,
0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x32,0x29,0x20,0x69,0x6e,
0x20,0x76,0x65,0x63,0x34,0x20,0x63,0x65,0x6e,0x74,0x72,0x65,0x3b,0x0a,0x0a,0x6d,
0x61,0x74,0x33,0x20,0x72,0x6f,0x74,0x5f,0x78,0x28,0x66,0x6c,0x6f,0x61,0x74,0x20,
0x61,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,
0x32,0x38,0x20,0x3d,0x20,0x63,0x6f,0x73,0x28,0x61,0x29,0x3b,0x0a,0x20,0x20,0x20,
0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x33,0x31,0x20,0x3d,0x20,0x73,0x69,0x6e,
0x28,0x61,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,
0x6d,0x61,0x74,0x33,0x28,0x76,0x65,0x63,0x33,0x28,0x31,0x2e,0x30,0x2c,0x20,0x30,
0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x29,0x2c,0x20,0x76,0x65,0x63,0x33,0x28,0x30,
0x2e,0x30,0x2c,0x20,0x5f,0x32,0x38,0x2c,0x20,0x2d,0x5f,0x33,0x31,0x29,0x2c,0x20,
0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x30,0x2c,0x20,0x5f,0x33,0x31,0x2c,0x20,0x5f,
0x32,0x38,0x29,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x6d,0x61,0x74,0x33,0x20,0x72,0x6f,
0x74,0x5f,0x7a,0x28,0x66,0x6c,0x6f,0x61,0x74,0x20,0x61,0x29,0x0a,0x7b,0x0a,0x20,
0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x34,0x37,0x20,0x3d,0x20,0x63,
0x6f,0x73,0x28,0x61,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,
0x20,0x5f,0x35,0x30,0x20,0x3d,0x20,0x73,0x69,0x6e,0x28,0x61,0x29,0x3b,0x0a,0x20,
0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6d,0x61,0x74,0x33,0x28,0x76,
0x65,0x63,0x33,0x28,0x5f,0x34,0x37,0x2c,0x20,0x2d,0x5f,0x35,0x30,0x2c,0x20,0x30,
0x2e,0x30,0x29,0x2c,0x20,0x76,0x65,0x63,0x33,0x28,0x5f,0x35,0x30,0x2c,0x20,0x5f,
0x34,0x37,0x2c,0x20,0x30,0x2e,0x30,0x29,0x2c,0x20,0x76,0x65,0x63,0x33,0x28,0x30,
0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30,0x29,0x29,0x3b,0x0a,
0x7d,0x0a,0x0a,0x6d,0x61,0x74,0x33,0x20,0x72,0x6f,0x74,0x5f,0x79,0x28,0x66,0x6c,
0x6f,0x61,0x74,0x20,0x61,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,
0x61,0x74,0x20,0x5f,0x36,0x34,0x20,0x3d,0x20,0x63,0x6f,0x73,0x28,0x61,0x29,0x3b,
0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x36,0x37,0x20,0x3d,
0x20,0x73,0x69,0x6e,0x28,0x61,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,
0x75,0x72,0x6e,0x20,0x6d,0x61,0x74,0x33,0x28,0x76,0x65,0x63,0x33,0x28,0x5f,0x36,
0x34,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x5f,0x36,0x37,0x29,0x2c,0x20,0x76,0x65,
0x63,0x33,0x28,0x30,0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,
0x29,0x2c,0x20,0x76,0x65,0x63,0x33,0x28,0x2d,0x5f,0x36,0x37,0x2c,0x20,0x30,0x2e,
0x30,0x2c,0x20,0x5f,0x36,0x34,0x29,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x6d,0x61,0x74,
0x33,0x20,0x67,0x65,0x74,0x5f,0x6f,0x72,0x69,0x65,0x6e,0x74,0x61,0x74,0x69,0x6f,
0x6e,0x5f,0x6d,0x61,0x74,0x72,0x69,0x78,0x28,0x69,0x6e,0x74,0x20,0x6f,0x72,0x69,
0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x69,0x6e,0x74,0x20,0x5f,0x38,0x32,0x20,
0x3d,0x20,0x6f,0x72,0x69,0x20,0x2f,0x20,0x34,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6d,
0x61,0x74,0x33,0x20,0x62,0x61,0x73,0x65,0x3b,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,
0x20,0x28,0x5f,0x38,0x32,0x20,0x3d,0x3d,0x20,0x30,0x29,0x0a,0x20,0x20,0x20,0x20,
0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x61,0x73,0x65,0x20,0x3d,
0x20,0x6d,0x61,0x74,0x33,0x28,0x76,0x65,0x63,0x33,0x28,0x31,0x2e,0x30,0x2c,0x20,
0x30,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x29,0x2c,0x20,0x76,0x65,0x63,0x33,0x28,
0x30,0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x29,0x2c,0x20,
0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x31,
0x2e,0x30,0x29,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,
0x65,0x6c,0x73,0x65,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x5f,0x38,0x32,0x20,0x3d,0x3d,0x20,0x31,0x29,
0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x70,0x61,0x72,
0x61,0x6d,0x20,0x3d,0x20,0x33,0x2e,0x31,0x34,0x31,0x35,0x39,0x32,0x37,0x34,0x31,
0x30,0x31,0x32,0x35,0x37,0x33,0x32,0x34,0x32,0x31,0x38,0x37,0x35,0x3b,0x0a,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x61,0x73,0x65,0x20,
0x3d,0x20,0x72,0x6f,0x74,0x5f,0x78,0x28,0x70,0x61,0x72,0x61,0x6d,0x29,0x3b,0x0a,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x65,0x6c,0x73,0x65,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7b,
0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,
0x28,0x5f,0x38,0x32,0x20,0x3d,0x3d,0x20,0x32,0x29,0x0a,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x70,
0x61,0x72,0x61,0x6d,0x5f,0x31,0x20,0x3d,0x20,0x2d,0x31,0x2e,0x35,0x37,0x30,0x37,
0x39,0x36,0x33,0x37,0x30,0x35,0x30,0x36,0x32,0x38,0x36,0x36,0x32,0x31,0x30,0x39,
0x33,0x37,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x62,0x61,0x73,0x65,0x20,0x3d,0x20,0x72,0x6f,0x74,0x5f,
0x7a,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x0a,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x5f,0x38,0x32,
0x20,0x3d,0x3d,0x20,0x33,0x29,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,
0x61,0x74,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x32,0x20,0x3d,0x20,0x31,0x2e,0x35,
0x37,0x30,0x37,0x39,0x36,0x33,0x37,0x30,0x35,0x30,0x36,0x32,0x38,0x36,0x36,0x32,
0x31,0x30,0x39,0x33,0x37,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x61,0x73,0x65,
0x20,0x3d,0x20,0x72,0x6f,0x74,0x5f,0x7a,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x32,
0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x69,0x66,0x20,0x28,0x5f,0x38,0x32,0x20,0x3d,0x3d,0x20,0x34,0x29,0x0a,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,
0x74,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x33,0x20,0x3d,0x20,0x31,0x2e,0x35,0x37,
0x30,0x37,0x39,0x36,0x33,0x37,0x30,0x35,0x30,0x36,0x32,0x38,0x36,0x36,0x32,0x31,
0x30,0x39,0x33,0x37,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x62,
0x61,0x73,0x65,0x20,0x3d,0x20,0x72,0x6f,0x74,0x5f,0x78,0x28,0x70,0x61,0x72,0x61,
0x6d,0x5f,0x33,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x65,0x6c,0x73,0x65,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x34,
0x20,0x3d,0x20,0x2d,0x31,0x2e,0x35,0x37,0x30,0x37,0x39,0x36,0x33,0x37,0x30,0x35,
0x30,0x36,0x32,0x38,0x36,0x36,0x32,0x31,0x30,0x39,0x33,0x37,0x35,0x3b,0x0a,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x61,0x73,0x65,0x20,0x3d,0x20,0x72,0x6f,
0x74,0x5f,0x78,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x34,0x29,0x3b,0x0a,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,
0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x70,0x61,
0x72,0x61,0x6d,0x5f,0x35,0x20,0x3d,0x20,0x66,0x6c,0x6f,0x61,0x74,0x28,0x6f,0x72,
0x69,0x20,0x25,0x20,0x34,0x29,0x20,0x2a,0x20,0x31,0x2e,0x35,0x37,0x30,0x37,0x39,
0x36,0x33,0x37,0x30,0x35,0x30,0x36,0x32,0x38,0x36,0x36,0x32,0x31,0x30,0x39,0x33,
0x37,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x62,
0x61,0x73,0x65,0x20,0x2a,0x20,0x72,0x6f,0x74,0x5f,0x79,0x28,0x70,0x61,0x72,0x61,
0x6d,0x5f,0x35,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,
0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x69,0x6e,0x74,0x20,0x70,
0x61,0x72,0x61,0x6d,0x20,0x3d,0x20,0x69,0x6e,0x74,0x28,0x72,0x6f,0x75,0x6e,0x64,
0x28,0x69,0x6e,0x73,0x74,0x61,0x6e,0x63,0x65,0x2e,0x77,0x29,0x29,0x3b,0x0a,0x20,
0x20,0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,
0x20,0x6d,0x61,0x74,0x34,0x28,0x74,0x72,0x69,0x6c,0x65,0x5f,0x73,0x68,0x61,0x64,
0x6f,0x77,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d,0x2c,
0x20,0x74,0x72,0x69,0x6c,0x65,0x5f,0x73,0x68,0x61,0x64,0x6f,0x77,0x5f,0x76,0x73,
0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x31,0x5d,0x2c,0x20,0x74,0x72,0x69,0x6c,
0x65,0x5f,0x73,0x68,0x61,0x64,0x6f,0x77,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,
0x6d,0x73,0x5b,0x32,0x5d,0x2c,0x20,0x74,0x72,0x69,0x6c,0x65,0x5f,0x73,0x68,0x61,
0x64,0x6f,0x77,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x33,0x5d,
0x29,0x20,0x2a,0x20,0x76,0x65,0x63,0x34,0x28,0x28,0x28,0x67,0x65,0x74,0x5f,0x6f,
0x72,0x69,0x65,0x6e,0x74,0x61,0x74,0x69,0x6f,0x6e,0x5f,0x6d,0x61,0x74,0x72,0x69,
0x78,0x28,0x70,0x61,0x72,0x61,0x6d,0x29,0x20,0x2a,0x20,0x28,0x70,0x6f,0x73,0x69,
0x74,0x69,0x6f,0x6e,0x2e,0x78,0x79,0x7a,0x20,0x2d,0x20,0x76,0x65,0x63,0x33,0x28,
0x30,0x2e,0x35,0x29,0x29,0x29,0x20,0x2b,0x20,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,
0x35,0x29,0x29,0x20,0x2b,0x20,0x69,0x6e,0x73,0x74,0x61,0x6e,0x63,0x65,0x2e,0x78,
0x79,0x7a,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#version 430
layout(location = 0) out vec4 frag_color;
void main()
{
frag_color = vec4(0.0);
}
*/
fs_trile_shadow_source_glsl430 := u8.[
0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x34,0x33,0x30,0x0a,0x0a,0x6c,0x61,
0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,
0x30,0x29,0x20,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x34,0x20,0x66,0x72,0x61,0x67,
0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,
0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,
0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x76,0x65,0x63,0x34,0x28,0x30,0x2e,0x30,
0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#version 300 es
uniform vec4 trile_shadow_vs_params[4];
layout(location = 3) in vec4 instance;
layout(location = 0) in vec4 position;
layout(location = 1) in vec4 normal;
layout(location = 2) in vec4 centre;
mat3 rot_x(float a)
{
float _28 = cos(a);
float _31 = sin(a);
return mat3(vec3(1.0, 0.0, 0.0), vec3(0.0, _28, -_31), vec3(0.0, _31, _28));
}
mat3 rot_z(float a)
{
float _47 = cos(a);
float _50 = sin(a);
return mat3(vec3(_47, -_50, 0.0), vec3(_50, _47, 0.0), vec3(0.0, 0.0, 1.0));
}
mat3 rot_y(float a)
{
float _64 = cos(a);
float _67 = sin(a);
return mat3(vec3(_64, 0.0, _67), vec3(0.0, 1.0, 0.0), vec3(-_67, 0.0, _64));
}
mat3 get_orientation_matrix(int ori)
{
int _82 = ori / 4;
mat3 base;
if (_82 == 0)
{
base = mat3(vec3(1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, 0.0, 1.0));
}
else
{
if (_82 == 1)
{
float param = 3.1415927410125732421875;
base = rot_x(param);
}
else
{
if (_82 == 2)
{
float param_1 = -1.57079637050628662109375;
base = rot_z(param_1);
}
else
{
if (_82 == 3)
{
float param_2 = 1.57079637050628662109375;
base = rot_z(param_2);
}
else
{
if (_82 == 4)
{
float param_3 = 1.57079637050628662109375;
base = rot_x(param_3);
}
else
{
float param_4 = -1.57079637050628662109375;
base = rot_x(param_4);
}
}
}
}
}
float param_5 = float(ori % 4) * 1.57079637050628662109375;
return base * rot_y(param_5);
}
void main()
{
int param = int(round(instance.w));
gl_Position = mat4(trile_shadow_vs_params[0], trile_shadow_vs_params[1], trile_shadow_vs_params[2], trile_shadow_vs_params[3]) * vec4(((get_orientation_matrix(param) * (position.xyz - vec3(0.5))) + vec3(0.5)) + instance.xyz, 1.0);
}
*/
vs_trile_shadow_source_glsl300es := u8.[
0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x33,0x30,0x30,0x20,0x65,0x73,0x0a,
0x0a,0x75,0x6e,0x69,0x66,0x6f,0x72,0x6d,0x20,0x76,0x65,0x63,0x34,0x20,0x74,0x72,
0x69,0x6c,0x65,0x5f,0x73,0x68,0x61,0x64,0x6f,0x77,0x5f,0x76,0x73,0x5f,0x70,0x61,
0x72,0x61,0x6d,0x73,0x5b,0x34,0x5d,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,
0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x33,0x29,0x20,0x69,0x6e,
0x20,0x76,0x65,0x63,0x34,0x20,0x69,0x6e,0x73,0x74,0x61,0x6e,0x63,0x65,0x3b,0x0a,
0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,
0x3d,0x20,0x30,0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x34,0x20,0x70,0x6f,0x73,
0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,
0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x31,0x29,0x20,0x69,0x6e,0x20,0x76,
0x65,0x63,0x34,0x20,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x3b,0x0a,0x6c,0x61,0x79,0x6f,
0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x32,0x29,
0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x34,0x20,0x63,0x65,0x6e,0x74,0x72,0x65,0x3b,
0x0a,0x0a,0x6d,0x61,0x74,0x33,0x20,0x72,0x6f,0x74,0x5f,0x78,0x28,0x66,0x6c,0x6f,
0x61,0x74,0x20,0x61,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,
0x74,0x20,0x5f,0x32,0x38,0x20,0x3d,0x20,0x63,0x6f,0x73,0x28,0x61,0x29,0x3b,0x0a,
0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x33,0x31,0x20,0x3d,0x20,
0x73,0x69,0x6e,0x28,0x61,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,
0x72,0x6e,0x20,0x6d,0x61,0x74,0x33,0x28,0x76,0x65,0x63,0x33,0x28,0x31,0x2e,0x30,
0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x29,0x2c,0x20,0x76,0x65,0x63,
0x33,0x28,0x30,0x2e,0x30,0x2c,0x20,0x5f,0x32,0x38,0x2c,0x20,0x2d,0x5f,0x33,0x31,
0x29,0x2c,0x20,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x30,0x2c,0x20,0x5f,0x33,0x31,
0x2c,0x20,0x5f,0x32,0x38,0x29,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x6d,0x61,0x74,0x33,
0x20,0x72,0x6f,0x74,0x5f,0x7a,0x28,0x66,0x6c,0x6f,0x61,0x74,0x20,0x61,0x29,0x0a,
0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x34,0x37,0x20,
0x3d,0x20,0x63,0x6f,0x73,0x28,0x61,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,
0x6f,0x61,0x74,0x20,0x5f,0x35,0x30,0x20,0x3d,0x20,0x73,0x69,0x6e,0x28,0x61,0x29,
0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6d,0x61,0x74,
0x33,0x28,0x76,0x65,0x63,0x33,0x28,0x5f,0x34,0x37,0x2c,0x20,0x2d,0x5f,0x35,0x30,
0x2c,0x20,0x30,0x2e,0x30,0x29,0x2c,0x20,0x76,0x65,0x63,0x33,0x28,0x5f,0x35,0x30,
0x2c,0x20,0x5f,0x34,0x37,0x2c,0x20,0x30,0x2e,0x30,0x29,0x2c,0x20,0x76,0x65,0x63,
0x33,0x28,0x30,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30,0x29,
0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x6d,0x61,0x74,0x33,0x20,0x72,0x6f,0x74,0x5f,0x79,
0x28,0x66,0x6c,0x6f,0x61,0x74,0x20,0x61,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,
0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x36,0x34,0x20,0x3d,0x20,0x63,0x6f,0x73,0x28,
0x61,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x36,
0x37,0x20,0x3d,0x20,0x73,0x69,0x6e,0x28,0x61,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,
0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6d,0x61,0x74,0x33,0x28,0x76,0x65,0x63,0x33,
0x28,0x5f,0x36,0x34,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x5f,0x36,0x37,0x29,0x2c,
0x20,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30,0x2c,0x20,
0x30,0x2e,0x30,0x29,0x2c,0x20,0x76,0x65,0x63,0x33,0x28,0x2d,0x5f,0x36,0x37,0x2c,
0x20,0x30,0x2e,0x30,0x2c,0x20,0x5f,0x36,0x34,0x29,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,
0x6d,0x61,0x74,0x33,0x20,0x67,0x65,0x74,0x5f,0x6f,0x72,0x69,0x65,0x6e,0x74,0x61,
0x74,0x69,0x6f,0x6e,0x5f,0x6d,0x61,0x74,0x72,0x69,0x78,0x28,0x69,0x6e,0x74,0x20,
0x6f,0x72,0x69,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x69,0x6e,0x74,0x20,0x5f,
0x38,0x32,0x20,0x3d,0x20,0x6f,0x72,0x69,0x20,0x2f,0x20,0x34,0x3b,0x0a,0x20,0x20,
0x20,0x20,0x6d,0x61,0x74,0x33,0x20,0x62,0x61,0x73,0x65,0x3b,0x0a,0x20,0x20,0x20,
0x20,0x69,0x66,0x20,0x28,0x5f,0x38,0x32,0x20,0x3d,0x3d,0x20,0x30,0x29,0x0a,0x20,
0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x61,0x73,
0x65,0x20,0x3d,0x20,0x6d,0x61,0x74,0x33,0x28,0x76,0x65,0x63,0x33,0x28,0x31,0x2e,
0x30,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x29,0x2c,0x20,0x76,0x65,
0x63,0x33,0x28,0x30,0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,
0x29,0x2c,0x20,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,
0x2c,0x20,0x31,0x2e,0x30,0x29,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,
0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x5f,0x38,0x32,0x20,0x3d,0x3d,
0x20,0x31,0x29,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,
0x70,0x61,0x72,0x61,0x6d,0x20,0x3d,0x20,0x33,0x2e,0x31,0x34,0x31,0x35,0x39,0x32,
0x37,0x34,0x31,0x30,0x31,0x32,0x35,0x37,0x33,0x32,0x34,0x32,0x31,0x38,0x37,0x35,
0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x61,
0x73,0x65,0x20,0x3d,0x20,0x72,0x6f,0x74,0x5f,0x78,0x28,0x70,0x61,0x72,0x61,0x6d,
0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x69,0x66,0x20,0x28,0x5f,0x38,0x32,0x20,0x3d,0x3d,0x20,0x32,0x29,0x0a,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,
0x74,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x20,0x3d,0x20,0x2d,0x31,0x2e,0x35,
0x37,0x30,0x37,0x39,0x36,0x33,0x37,0x30,0x35,0x30,0x36,0x32,0x38,0x36,0x36,0x32,
0x31,0x30,0x39,0x33,0x37,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x61,0x73,0x65,0x20,0x3d,0x20,0x72,
0x6f,0x74,0x5f,0x7a,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x29,0x3b,0x0a,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x0a,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,
0x5f,0x38,0x32,0x20,0x3d,0x3d,0x20,0x33,0x29,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x66,0x6c,0x6f,0x61,0x74,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x32,0x20,0x3d,0x20,
0x31,0x2e,0x35,0x37,0x30,0x37,0x39,0x36,0x33,0x37,0x30,0x35,0x30,0x36,0x32,0x38,
0x36,0x36,0x32,0x31,0x30,0x39,0x33,0x37,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x62,
0x61,0x73,0x65,0x20,0x3d,0x20,0x72,0x6f,0x74,0x5f,0x7a,0x28,0x70,0x61,0x72,0x61,
0x6d,0x5f,0x32,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x0a,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x5f,0x38,0x32,0x20,0x3d,0x3d,0x20,0x34,0x29,
0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,
0x6c,0x6f,0x61,0x74,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x33,0x20,0x3d,0x20,0x31,
0x2e,0x35,0x37,0x30,0x37,0x39,0x36,0x33,0x37,0x30,0x35,0x30,0x36,0x32,0x38,0x36,
0x36,0x32,0x31,0x30,0x39,0x33,0x37,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x62,0x61,0x73,0x65,0x20,0x3d,0x20,0x72,0x6f,0x74,0x5f,0x78,0x28,0x70,
0x61,0x72,0x61,0x6d,0x5f,0x33,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x70,0x61,0x72,0x61,
0x6d,0x5f,0x34,0x20,0x3d,0x20,0x2d,0x31,0x2e,0x35,0x37,0x30,0x37,0x39,0x36,0x33,
0x37,0x30,0x35,0x30,0x36,0x32,0x38,0x36,0x36,0x32,0x31,0x30,0x39,0x33,0x37,0x35,
0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x61,0x73,0x65,0x20,0x3d,
0x20,0x72,0x6f,0x74,0x5f,0x78,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x34,0x29,0x3b,
0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,
0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,
0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x35,0x20,0x3d,0x20,0x66,0x6c,0x6f,0x61,0x74,
0x28,0x6f,0x72,0x69,0x20,0x25,0x20,0x34,0x29,0x20,0x2a,0x20,0x31,0x2e,0x35,0x37,
0x30,0x37,0x39,0x36,0x33,0x37,0x30,0x35,0x30,0x36,0x32,0x38,0x36,0x36,0x32,0x31,
0x30,0x39,0x33,0x37,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,
0x6e,0x20,0x62,0x61,0x73,0x65,0x20,0x2a,0x20,0x72,0x6f,0x74,0x5f,0x79,0x28,0x70,
0x61,0x72,0x61,0x6d,0x5f,0x35,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x76,0x6f,0x69,0x64,
0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x69,0x6e,
0x74,0x20,0x70,0x61,0x72,0x61,0x6d,0x20,0x3d,0x20,0x69,0x6e,0x74,0x28,0x72,0x6f,
0x75,0x6e,0x64,0x28,0x69,0x6e,0x73,0x74,0x61,0x6e,0x63,0x65,0x2e,0x77,0x29,0x29,
0x3b,0x0a,0x20,0x20,0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,
0x6e,0x20,0x3d,0x20,0x6d,0x61,0x74,0x34,0x28,0x74,0x72,0x69,0x6c,0x65,0x5f,0x73,
0x68,0x61,0x64,0x6f,0x77,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,
0x30,0x5d,0x2c,0x20,0x74,0x72,0x69,0x6c,0x65,0x5f,0x73,0x68,0x61,0x64,0x6f,0x77,
0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x31,0x5d,0x2c,0x20,0x74,
0x72,0x69,0x6c,0x65,0x5f,0x73,0x68,0x61,0x64,0x6f,0x77,0x5f,0x76,0x73,0x5f,0x70,
0x61,0x72,0x61,0x6d,0x73,0x5b,0x32,0x5d,0x2c,0x20,0x74,0x72,0x69,0x6c,0x65,0x5f,
0x73,0x68,0x61,0x64,0x6f,0x77,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,
0x5b,0x33,0x5d,0x29,0x20,0x2a,0x20,0x76,0x65,0x63,0x34,0x28,0x28,0x28,0x67,0x65,
0x74,0x5f,0x6f,0x72,0x69,0x65,0x6e,0x74,0x61,0x74,0x69,0x6f,0x6e,0x5f,0x6d,0x61,
0x74,0x72,0x69,0x78,0x28,0x70,0x61,0x72,0x61,0x6d,0x29,0x20,0x2a,0x20,0x28,0x70,
0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2e,0x78,0x79,0x7a,0x20,0x2d,0x20,0x76,0x65,
0x63,0x33,0x28,0x30,0x2e,0x35,0x29,0x29,0x29,0x20,0x2b,0x20,0x76,0x65,0x63,0x33,
0x28,0x30,0x2e,0x35,0x29,0x29,0x20,0x2b,0x20,0x69,0x6e,0x73,0x74,0x61,0x6e,0x63,
0x65,0x2e,0x78,0x79,0x7a,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,
0x00,
];
/*
#version 300 es
precision mediump float;
precision highp int;
layout(location = 0) out highp vec4 frag_color;
void main()
{
frag_color = vec4(0.0);
}
*/
fs_trile_shadow_source_glsl300es := u8.[
0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x33,0x30,0x30,0x20,0x65,0x73,0x0a,
0x70,0x72,0x65,0x63,0x69,0x73,0x69,0x6f,0x6e,0x20,0x6d,0x65,0x64,0x69,0x75,0x6d,
0x70,0x20,0x66,0x6c,0x6f,0x61,0x74,0x3b,0x0a,0x70,0x72,0x65,0x63,0x69,0x73,0x69,
0x6f,0x6e,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x69,0x6e,0x74,0x3b,0x0a,0x0a,0x6c,
0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,
0x20,0x30,0x29,0x20,0x6f,0x75,0x74,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x76,0x65,
0x63,0x34,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x0a,
0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,
0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x76,
0x65,0x63,0x34,0x28,0x30,0x2e,0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct trile_shadow_vs_params
{
float4x4 mvp;
};
struct main0_out
{
float4 gl_Position [[position]];
};
struct main0_in
{
float4 position [[attribute(0)]];
float4 instance [[attribute(3)]];
};
static inline __attribute__((always_inline))
float3x3 rot_x(thread const float& a)
{
float _28 = cos(a);
float _31 = sin(a);
return float3x3(float3(1.0, 0.0, 0.0), float3(0.0, _28, -_31), float3(0.0, _31, _28));
}
static inline __attribute__((always_inline))
float3x3 rot_z(thread const float& a)
{
float _47 = cos(a);
float _50 = sin(a);
return float3x3(float3(_47, -_50, 0.0), float3(_50, _47, 0.0), float3(0.0, 0.0, 1.0));
}
static inline __attribute__((always_inline))
float3x3 rot_y(thread const float& a)
{
float _64 = cos(a);
float _67 = sin(a);
return float3x3(float3(_64, 0.0, _67), float3(0.0, 1.0, 0.0), float3(-_67, 0.0, _64));
}
static inline __attribute__((always_inline))
float3x3 get_orientation_matrix(thread const int& ori)
{
int _82 = ori / 4;
float3x3 base;
if (_82 == 0)
{
base = float3x3(float3(1.0, 0.0, 0.0), float3(0.0, 1.0, 0.0), float3(0.0, 0.0, 1.0));
}
else
{
if (_82 == 1)
{
float param = 3.1415927410125732421875;
base = rot_x(param);
}
else
{
if (_82 == 2)
{
float param_1 = -1.57079637050628662109375;
base = rot_z(param_1);
}
else
{
if (_82 == 3)
{
float param_2 = 1.57079637050628662109375;
base = rot_z(param_2);
}
else
{
if (_82 == 4)
{
float param_3 = 1.57079637050628662109375;
base = rot_x(param_3);
}
else
{
float param_4 = -1.57079637050628662109375;
base = rot_x(param_4);
}
}
}
}
}
float param_5 = float(ori % 4) * 1.57079637050628662109375;
return base * rot_y(param_5);
}
vertex main0_out main0(main0_in in [[stage_in]], constant trile_shadow_vs_params& _193 [[buffer(0)]])
{
main0_out out = {};
int param = int(round(in.instance.w));
out.gl_Position = _193.mvp * float4(((get_orientation_matrix(param) * (in.position.xyz - float3(0.5))) + float3(0.5)) + in.instance.xyz, 1.0);
return out;
}
*/
vs_trile_shadow_source_metal_macos := u8.[
0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x63,0x6c,0x61,0x6e,0x67,0x20,0x64,0x69,
0x61,0x67,0x6e,0x6f,0x73,0x74,0x69,0x63,0x20,0x69,0x67,0x6e,0x6f,0x72,0x65,0x64,
0x20,0x22,0x2d,0x57,0x6d,0x69,0x73,0x73,0x69,0x6e,0x67,0x2d,0x70,0x72,0x6f,0x74,
0x6f,0x74,0x79,0x70,0x65,0x73,0x22,0x0a,0x0a,0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,
0x65,0x20,0x3c,0x6d,0x65,0x74,0x61,0x6c,0x5f,0x73,0x74,0x64,0x6c,0x69,0x62,0x3e,
0x0a,0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x20,0x3c,0x73,0x69,0x6d,0x64,0x2f,
0x73,0x69,0x6d,0x64,0x2e,0x68,0x3e,0x0a,0x0a,0x75,0x73,0x69,0x6e,0x67,0x20,0x6e,
0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x20,0x6d,0x65,0x74,0x61,0x6c,0x3b,0x0a,
0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x74,0x72,0x69,0x6c,0x65,0x5f,0x73,0x68,
0x61,0x64,0x6f,0x77,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x0a,0x7b,
0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x78,0x34,0x20,0x6d,0x76,
0x70,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,
0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,
0x6f,0x61,0x74,0x34,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,
0x20,0x5b,0x5b,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5d,0x5d,0x3b,0x0a,0x7d,
0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,
0x69,0x6e,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,
0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x5b,0x5b,0x61,0x74,0x74,0x72,0x69,
0x62,0x75,0x74,0x65,0x28,0x30,0x29,0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,
0x6c,0x6f,0x61,0x74,0x34,0x20,0x69,0x6e,0x73,0x74,0x61,0x6e,0x63,0x65,0x20,0x5b,
0x5b,0x61,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x28,0x33,0x29,0x5d,0x5d,0x3b,
0x0a,0x7d,0x3b,0x0a,0x0a,0x73,0x74,0x61,0x74,0x69,0x63,0x20,0x69,0x6e,0x6c,0x69,
0x6e,0x65,0x20,0x5f,0x5f,0x61,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x5f,0x5f,
0x28,0x28,0x61,0x6c,0x77,0x61,0x79,0x73,0x5f,0x69,0x6e,0x6c,0x69,0x6e,0x65,0x29,
0x29,0x0a,0x66,0x6c,0x6f,0x61,0x74,0x33,0x78,0x33,0x20,0x72,0x6f,0x74,0x5f,0x78,
0x28,0x74,0x68,0x72,0x65,0x61,0x64,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x66,0x6c,
0x6f,0x61,0x74,0x26,0x20,0x61,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,
0x6f,0x61,0x74,0x20,0x5f,0x32,0x38,0x20,0x3d,0x20,0x63,0x6f,0x73,0x28,0x61,0x29,
0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x33,0x31,0x20,
0x3d,0x20,0x73,0x69,0x6e,0x28,0x61,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,
0x74,0x75,0x72,0x6e,0x20,0x66,0x6c,0x6f,0x61,0x74,0x33,0x78,0x33,0x28,0x66,0x6c,
0x6f,0x61,0x74,0x33,0x28,0x31,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x30,
0x2e,0x30,0x29,0x2c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x33,0x28,0x30,0x2e,0x30,0x2c,
0x20,0x5f,0x32,0x38,0x2c,0x20,0x2d,0x5f,0x33,0x31,0x29,0x2c,0x20,0x66,0x6c,0x6f,
0x61,0x74,0x33,0x28,0x30,0x2e,0x30,0x2c,0x20,0x5f,0x33,0x31,0x2c,0x20,0x5f,0x32,
0x38,0x29,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x73,0x74,0x61,0x74,0x69,0x63,0x20,0x69,
0x6e,0x6c,0x69,0x6e,0x65,0x20,0x5f,0x5f,0x61,0x74,0x74,0x72,0x69,0x62,0x75,0x74,
0x65,0x5f,0x5f,0x28,0x28,0x61,0x6c,0x77,0x61,0x79,0x73,0x5f,0x69,0x6e,0x6c,0x69,
0x6e,0x65,0x29,0x29,0x0a,0x66,0x6c,0x6f,0x61,0x74,0x33,0x78,0x33,0x20,0x72,0x6f,
0x74,0x5f,0x7a,0x28,0x74,0x68,0x72,0x65,0x61,0x64,0x20,0x63,0x6f,0x6e,0x73,0x74,
0x20,0x66,0x6c,0x6f,0x61,0x74,0x26,0x20,0x61,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,
0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x34,0x37,0x20,0x3d,0x20,0x63,0x6f,0x73,
0x28,0x61,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,
0x35,0x30,0x20,0x3d,0x20,0x73,0x69,0x6e,0x28,0x61,0x29,0x3b,0x0a,0x20,0x20,0x20,
0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x66,0x6c,0x6f,0x61,0x74,0x33,0x78,0x33,
0x28,0x66,0x6c,0x6f,0x61,0x74,0x33,0x28,0x5f,0x34,0x37,0x2c,0x20,0x2d,0x5f,0x35,
0x30,0x2c,0x20,0x30,0x2e,0x30,0x29,0x2c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x33,0x28,
0x5f,0x35,0x30,0x2c,0x20,0x5f,0x34,0x37,0x2c,0x20,0x30,0x2e,0x30,0x29,0x2c,0x20,
0x66,0x6c,0x6f,0x61,0x74,0x33,0x28,0x30,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x2c,
0x20,0x31,0x2e,0x30,0x29,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x73,0x74,0x61,0x74,0x69,
0x63,0x20,0x69,0x6e,0x6c,0x69,0x6e,0x65,0x20,0x5f,0x5f,0x61,0x74,0x74,0x72,0x69,
0x62,0x75,0x74,0x65,0x5f,0x5f,0x28,0x28,0x61,0x6c,0x77,0x61,0x79,0x73,0x5f,0x69,
0x6e,0x6c,0x69,0x6e,0x65,0x29,0x29,0x0a,0x66,0x6c,0x6f,0x61,0x74,0x33,0x78,0x33,
0x20,0x72,0x6f,0x74,0x5f,0x79,0x28,0x74,0x68,0x72,0x65,0x61,0x64,0x20,0x63,0x6f,
0x6e,0x73,0x74,0x20,0x66,0x6c,0x6f,0x61,0x74,0x26,0x20,0x61,0x29,0x0a,0x7b,0x0a,
0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x36,0x34,0x20,0x3d,0x20,
0x63,0x6f,0x73,0x28,0x61,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,
0x74,0x20,0x5f,0x36,0x37,0x20,0x3d,0x20,0x73,0x69,0x6e,0x28,0x61,0x29,0x3b,0x0a,
0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x66,0x6c,0x6f,0x61,0x74,
0x33,0x78,0x33,0x28,0x66,0x6c,0x6f,0x61,0x74,0x33,0x28,0x5f,0x36,0x34,0x2c,0x20,
0x30,0x2e,0x30,0x2c,0x20,0x5f,0x36,0x37,0x29,0x2c,0x20,0x66,0x6c,0x6f,0x61,0x74,
0x33,0x28,0x30,0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x29,
0x2c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x33,0x28,0x2d,0x5f,0x36,0x37,0x2c,0x20,0x30,
0x2e,0x30,0x2c,0x20,0x5f,0x36,0x34,0x29,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x73,0x74,
0x61,0x74,0x69,0x63,0x20,0x69,0x6e,0x6c,0x69,0x6e,0x65,0x20,0x5f,0x5f,0x61,0x74,
0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x5f,0x5f,0x28,0x28,0x61,0x6c,0x77,0x61,0x79,
0x73,0x5f,0x69,0x6e,0x6c,0x69,0x6e,0x65,0x29,0x29,0x0a,0x66,0x6c,0x6f,0x61,0x74,
0x33,0x78,0x33,0x20,0x67,0x65,0x74,0x5f,0x6f,0x72,0x69,0x65,0x6e,0x74,0x61,0x74,
0x69,0x6f,0x6e,0x5f,0x6d,0x61,0x74,0x72,0x69,0x78,0x28,0x74,0x68,0x72,0x65,0x61,
0x64,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x69,0x6e,0x74,0x26,0x20,0x6f,0x72,0x69,
0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x69,0x6e,0x74,0x20,0x5f,0x38,0x32,0x20,
0x3d,0x20,0x6f,0x72,0x69,0x20,0x2f,0x20,0x34,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,
0x6c,0x6f,0x61,0x74,0x33,0x78,0x33,0x20,0x62,0x61,0x73,0x65,0x3b,0x0a,0x20,0x20,
0x20,0x20,0x69,0x66,0x20,0x28,0x5f,0x38,0x32,0x20,0x3d,0x3d,0x20,0x30,0x29,0x0a,
0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x61,
0x73,0x65,0x20,0x3d,0x20,0x66,0x6c,0x6f,0x61,0x74,0x33,0x78,0x33,0x28,0x66,0x6c,
0x6f,0x61,0x74,0x33,0x28,0x31,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x30,
0x2e,0x30,0x29,0x2c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x33,0x28,0x30,0x2e,0x30,0x2c,
0x20,0x31,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x29,0x2c,0x20,0x66,0x6c,0x6f,0x61,
0x74,0x33,0x28,0x30,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30,
0x29,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x65,0x6c,
0x73,0x65,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x69,0x66,0x20,0x28,0x5f,0x38,0x32,0x20,0x3d,0x3d,0x20,0x31,0x29,0x0a,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x70,0x61,0x72,0x61,0x6d,
0x20,0x3d,0x20,0x33,0x2e,0x31,0x34,0x31,0x35,0x39,0x32,0x37,0x34,0x31,0x30,0x31,
0x32,0x35,0x37,0x33,0x32,0x34,0x32,0x31,0x38,0x37,0x35,0x3b,0x0a,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x61,0x73,0x65,0x20,0x3d,0x20,
0x72,0x6f,0x74,0x5f,0x78,0x28,0x70,0x61,0x72,0x61,0x6d,0x29,0x3b,0x0a,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x65,0x6c,0x73,0x65,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x5f,
0x38,0x32,0x20,0x3d,0x3d,0x20,0x32,0x29,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x70,0x61,0x72,
0x61,0x6d,0x5f,0x31,0x20,0x3d,0x20,0x2d,0x31,0x2e,0x35,0x37,0x30,0x37,0x39,0x36,
0x33,0x37,0x30,0x35,0x30,0x36,0x32,0x38,0x36,0x36,0x32,0x31,0x30,0x39,0x33,0x37,
0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x62,0x61,0x73,0x65,0x20,0x3d,0x20,0x72,0x6f,0x74,0x5f,0x7a,0x28,
0x70,0x61,0x72,0x61,0x6d,0x5f,0x31,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x5f,0x38,0x32,0x20,0x3d,
0x3d,0x20,0x33,0x29,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,
0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x32,0x20,0x3d,0x20,0x31,0x2e,0x35,0x37,0x30,
0x37,0x39,0x36,0x33,0x37,0x30,0x35,0x30,0x36,0x32,0x38,0x36,0x36,0x32,0x31,0x30,
0x39,0x33,0x37,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x61,0x73,0x65,0x20,0x3d,
0x20,0x72,0x6f,0x74,0x5f,0x7a,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x32,0x29,0x3b,
0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,
0x20,0x28,0x5f,0x38,0x32,0x20,0x3d,0x3d,0x20,0x34,0x29,0x0a,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,
0x70,0x61,0x72,0x61,0x6d,0x5f,0x33,0x20,0x3d,0x20,0x31,0x2e,0x35,0x37,0x30,0x37,
0x39,0x36,0x33,0x37,0x30,0x35,0x30,0x36,0x32,0x38,0x36,0x36,0x32,0x31,0x30,0x39,
0x33,0x37,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x61,0x73,
0x65,0x20,0x3d,0x20,0x72,0x6f,0x74,0x5f,0x78,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,
0x33,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x65,0x6c,
0x73,0x65,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x70,0x61,0x72,0x61,0x6d,0x5f,0x34,0x20,0x3d,
0x20,0x2d,0x31,0x2e,0x35,0x37,0x30,0x37,0x39,0x36,0x33,0x37,0x30,0x35,0x30,0x36,
0x32,0x38,0x36,0x36,0x32,0x31,0x30,0x39,0x33,0x37,0x35,0x3b,0x0a,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x62,0x61,0x73,0x65,0x20,0x3d,0x20,0x72,0x6f,0x74,0x5f,
0x78,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,0x34,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,
0x7d,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x70,0x61,0x72,0x61,
0x6d,0x5f,0x35,0x20,0x3d,0x20,0x66,0x6c,0x6f,0x61,0x74,0x28,0x6f,0x72,0x69,0x20,
0x25,0x20,0x34,0x29,0x20,0x2a,0x20,0x31,0x2e,0x35,0x37,0x30,0x37,0x39,0x36,0x33,
0x37,0x30,0x35,0x30,0x36,0x32,0x38,0x36,0x36,0x32,0x31,0x30,0x39,0x33,0x37,0x35,
0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x62,0x61,0x73,
0x65,0x20,0x2a,0x20,0x72,0x6f,0x74,0x5f,0x79,0x28,0x70,0x61,0x72,0x61,0x6d,0x5f,
0x35,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x76,0x65,0x72,0x74,0x65,0x78,0x20,0x6d,0x61,
0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x28,0x6d,0x61,
0x69,0x6e,0x30,0x5f,0x69,0x6e,0x20,0x69,0x6e,0x20,0x5b,0x5b,0x73,0x74,0x61,0x67,
0x65,0x5f,0x69,0x6e,0x5d,0x5d,0x2c,0x20,0x63,0x6f,0x6e,0x73,0x74,0x61,0x6e,0x74,
0x20,0x74,0x72,0x69,0x6c,0x65,0x5f,0x73,0x68,0x61,0x64,0x6f,0x77,0x5f,0x76,0x73,
0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x26,0x20,0x5f,0x31,0x39,0x33,0x20,0x5b,0x5b,
0x62,0x75,0x66,0x66,0x65,0x72,0x28,0x30,0x29,0x5d,0x5d,0x29,0x0a,0x7b,0x0a,0x20,
0x20,0x20,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,0x6f,0x75,0x74,
0x20,0x3d,0x20,0x7b,0x7d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x69,0x6e,0x74,0x20,0x70,
0x61,0x72,0x61,0x6d,0x20,0x3d,0x20,0x69,0x6e,0x74,0x28,0x72,0x6f,0x75,0x6e,0x64,
0x28,0x69,0x6e,0x2e,0x69,0x6e,0x73,0x74,0x61,0x6e,0x63,0x65,0x2e,0x77,0x29,0x29,
0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,0x67,0x6c,0x5f,0x50,0x6f,0x73,
0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x5f,0x31,0x39,0x33,0x2e,0x6d,0x76,0x70,
0x20,0x2a,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x28,0x28,0x28,0x67,0x65,0x74,0x5f,
0x6f,0x72,0x69,0x65,0x6e,0x74,0x61,0x74,0x69,0x6f,0x6e,0x5f,0x6d,0x61,0x74,0x72,
0x69,0x78,0x28,0x70,0x61,0x72,0x61,0x6d,0x29,0x20,0x2a,0x20,0x28,0x69,0x6e,0x2e,
0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2e,0x78,0x79,0x7a,0x20,0x2d,0x20,0x66,
0x6c,0x6f,0x61,0x74,0x33,0x28,0x30,0x2e,0x35,0x29,0x29,0x29,0x20,0x2b,0x20,0x66,
0x6c,0x6f,0x61,0x74,0x33,0x28,0x30,0x2e,0x35,0x29,0x29,0x20,0x2b,0x20,0x69,0x6e,
0x2e,0x69,0x6e,0x73,0x74,0x61,0x6e,0x63,0x65,0x2e,0x78,0x79,0x7a,0x2c,0x20,0x31,
0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,
0x6f,0x75,0x74,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct main0_out
{
float4 frag_color [[color(0)]];
};
fragment main0_out main0()
{
main0_out out = {};
out.frag_color = float4(0.0);
return out;
}
*/
fs_trile_shadow_source_metal_macos := u8.[
0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x20,0x3c,0x6d,0x65,0x74,0x61,0x6c,0x5f,
0x73,0x74,0x64,0x6c,0x69,0x62,0x3e,0x0a,0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,
0x20,0x3c,0x73,0x69,0x6d,0x64,0x2f,0x73,0x69,0x6d,0x64,0x2e,0x68,0x3e,0x0a,0x0a,
0x75,0x73,0x69,0x6e,0x67,0x20,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x20,
0x6d,0x65,0x74,0x61,0x6c,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,
0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,
0x6c,0x6f,0x61,0x74,0x34,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,
0x20,0x5b,0x5b,0x63,0x6f,0x6c,0x6f,0x72,0x28,0x30,0x29,0x5d,0x5d,0x3b,0x0a,0x7d,
0x3b,0x0a,0x0a,0x66,0x72,0x61,0x67,0x6d,0x65,0x6e,0x74,0x20,0x6d,0x61,0x69,0x6e,
0x30,0x5f,0x6f,0x75,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x28,0x29,0x0a,0x7b,0x0a,
0x20,0x20,0x20,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,0x6f,0x75,
0x74,0x20,0x3d,0x20,0x7b,0x7d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,
0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x66,0x6c,0x6f,
0x61,0x74,0x34,0x28,0x30,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,
0x74,0x75,0x72,0x6e,0x20,0x6f,0x75,0x74,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
trile_shadow_shader_desc :: (backend: sg_backend) -> sg_shader_desc {
desc: sg_shader_desc;
desc.label = "trile_shadow_shader";
if backend == {
case .GLCORE;
desc.vertex_func.source = xx *vs_trile_shadow_source_glsl430;
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_trile_shadow_source_glsl430;
desc.fragment_func.entry = "main";
desc.attrs[0].base_type = .FLOAT;
desc.attrs[0].glsl_name = "position";
desc.attrs[1].base_type = .FLOAT;
desc.attrs[1].glsl_name = "normal";
desc.attrs[2].base_type = .FLOAT;
desc.attrs[2].glsl_name = "centre";
desc.attrs[3].base_type = .FLOAT;
desc.attrs[3].glsl_name = "instance";
desc.uniform_blocks[0].stage = .VERTEX;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 64;
desc.uniform_blocks[0].glsl_uniforms[0].type = .FLOAT4;
desc.uniform_blocks[0].glsl_uniforms[0].array_count = 4;
desc.uniform_blocks[0].glsl_uniforms[0].glsl_name = "trile_shadow_vs_params";
case .GLES3;
desc.vertex_func.source = xx *vs_trile_shadow_source_glsl300es;
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_trile_shadow_source_glsl300es;
desc.fragment_func.entry = "main";
desc.attrs[0].base_type = .FLOAT;
desc.attrs[0].glsl_name = "position";
desc.attrs[1].base_type = .FLOAT;
desc.attrs[1].glsl_name = "normal";
desc.attrs[2].base_type = .FLOAT;
desc.attrs[2].glsl_name = "centre";
desc.attrs[3].base_type = .FLOAT;
desc.attrs[3].glsl_name = "instance";
desc.uniform_blocks[0].stage = .VERTEX;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 64;
desc.uniform_blocks[0].glsl_uniforms[0].type = .FLOAT4;
desc.uniform_blocks[0].glsl_uniforms[0].array_count = 4;
desc.uniform_blocks[0].glsl_uniforms[0].glsl_name = "trile_shadow_vs_params";
case .METAL_MACOS;
desc.vertex_func.source = xx *vs_trile_shadow_source_metal_macos;
desc.vertex_func.entry = "main0";
desc.fragment_func.source = xx *fs_trile_shadow_source_metal_macos;
desc.fragment_func.entry = "main0";
desc.attrs[0].base_type = .FLOAT;
desc.attrs[1].base_type = .FLOAT;
desc.attrs[2].base_type = .FLOAT;
desc.attrs[3].base_type = .FLOAT;
desc.uniform_blocks[0].stage = .VERTEX;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 64;
desc.uniform_blocks[0].msl_buffer_n = 0;
}
return desc;
}

File diff suppressed because it is too large Load Diff

View File

@ -14,6 +14,24 @@ in vec4 instance;
out vec3 view_space_pos;
out vec3 view_space_normal;
mat3 gbuf_rot_x(float a) { float c=cos(a),s=sin(a); return mat3(1,0,0, 0,c,-s, 0,s,c); }
mat3 gbuf_rot_z(float a) { float c=cos(a),s=sin(a); return mat3(c,-s,0, s,c,0, 0,0,1); }
mat3 gbuf_rot_y(float a) { float c=cos(a),s=sin(a); return mat3(c,0,s, 0,1,0, -s,0,c); }
mat3 gbuf_get_orientation_matrix(int ori) {
int face = ori / 4;
int twist = ori % 4;
float PI = 3.1415927;
mat3 base;
if (face == 0) base = mat3(1.0);
else if (face == 1) base = gbuf_rot_x(PI);
else if (face == 2) base = gbuf_rot_z(-PI*0.5);
else if (face == 3) base = gbuf_rot_z( PI*0.5);
else if (face == 4) base = gbuf_rot_x( PI*0.5);
else base = gbuf_rot_x(-PI*0.5);
return base * gbuf_rot_y(float(twist) * PI * 0.5);
}
void main() {
if (isGround == 1) {
vec4 world_pos = vec4(position.x * 100.0, planeHeight, position.z * 100.0, 1.0);
@ -22,12 +40,15 @@ void main() {
view_space_pos = view_pos_4.xyz;
view_space_normal = mat3(view_matrix) * normal.xyz;
} else {
vec4 world_pos = vec4(position.xyz + instance.xyz, 1.0);
vec4 view_pos_4 = view_matrix * world_pos;
gl_Position = mvp * world_pos;
view_space_pos = view_pos_4.xyz;
view_space_normal = mat3(view_matrix) * normal.xyz;
int ori = int(round(instance.w));
mat3 rot = gbuf_get_orientation_matrix(ori);
vec3 local = position.xyz - 0.5;
vec3 rotated = rot * local + 0.5;
vec4 world_pos = vec4(rotated + instance.xyz, 1.0);
vec4 view_pos_4 = view_matrix * world_pos;
gl_Position = mvp * world_pos;
view_space_pos = view_pos_4.xyz;
view_space_normal = mat3(view_matrix) * (rot * normal.xyz);
}
}
@end

View File

@ -41,7 +41,7 @@ layout(binding=1) uniform plane_world_config {
float skyIntensity;
int hasClouds;
float planeHeight;
int planeType;
int animatePlaneHeight;
vec3 waterColor;
vec3 deepColor;
float time;

View File

@ -32,7 +32,7 @@ layout(binding=1) uniform sky_world_config {
int hasClouds;
float planeHeight;
int planeType;
int animatePlaneHeight;
vec3 waterColor;
vec3 deepColor;

View File

@ -16,18 +16,43 @@ out vec3 to_center;
out vec3 vpos; // The actual position;
out vec3 ipos; // Trile space position;
out vec4 fnormal;
out vec3 orig_normal; // Unrotated object-space normal, used for trixel lookup
out vec3 trileCenter;
out vec3 cv;
mat3 rot_x(float a) { float c=cos(a),s=sin(a); return mat3(1,0,0, 0,c,-s, 0,s,c); }
mat3 rot_z(float a) { float c=cos(a),s=sin(a); return mat3(c,-s,0, s,c,0, 0,0,1); }
mat3 rot_y(float a) { float c=cos(a),s=sin(a); return mat3(c,0,s, 0,1,0, -s,0,c); }
mat3 get_orientation_matrix(int ori) {
int face = ori / 4;
int twist = ori % 4;
float PI = 3.1415927;
mat3 base;
if (face == 0) base = mat3(1.0);
else if (face == 1) base = rot_x(PI);
else if (face == 2) base = rot_z(-PI*0.5);
else if (face == 3) base = rot_z( PI*0.5);
else if (face == 4) base = rot_x( PI*0.5);
else base = rot_x(-PI*0.5);
return base * rot_y(float(twist) * PI * 0.5);
}
void main() {
gl_Position = mvp * vec4(position.xyz + instance.xyz, 1.0);
fnormal = normal;
to_center = centre.xyz - position.xyz;
vpos = position.xyz + instance.xyz;
ipos = position.xyz;
cam = camera;
cv = normalize(camera - vpos);
trileCenter = vpos - ipos + vec3(0.5);
int ori = int(round(instance.w));
mat3 rot = get_orientation_matrix(ori);
vec3 local = position.xyz - 0.5;
vec3 rotated = rot * local + 0.5;
gl_Position = mvp * vec4(rotated + instance.xyz, 1.0);
fnormal = vec4(rot * normal.xyz, 0.0);
orig_normal = normal.xyz; // unrotated, for trixel lookup
to_center = centre.xyz - position.xyz; // unrotated, for trixel lookup
vpos = rotated + instance.xyz;
ipos = position.xyz;
cam = camera;
cv = normalize(camera - vpos);
trileCenter = instance.xyz + vec3(0.5);
}
@end
@ -47,7 +72,7 @@ layout(binding=1) uniform trile_world_config {
int hasClouds;
float planeHeight;
int planeType;
int animatePlaneHeight;
vec3 waterColor;
vec3 deepColor;
@ -59,6 +84,7 @@ in vec3 to_center;
in vec3 vpos;
in vec3 ipos;
in vec4 fnormal;
in vec3 orig_normal;
in vec3 trileCenter;
in vec3 cv;
out vec4 frag_color;
@ -74,6 +100,7 @@ layout(binding=3) uniform trile_fs_params {
float rdm_diff_scale;
float rdm_spec_scale;
vec3 ambient_color;
int is_preview;
vec3 rdm_tint;
};
@ -447,7 +474,7 @@ void main() {
}
// Trixel material sampling
vec3 pos_after_adjust = ipos - fnormal.xyz * 0.02;
vec3 pos_after_adjust = ipos - orig_normal * 0.02;
int count = 0;
vec4 trixel_material;
while (count < 5) {
@ -534,6 +561,9 @@ void main() {
vec3 kDiff = 1.0 - Frough;
kDiff *= 1.0 - metallic;
light += (kDiff * indirectDiff / PI * albedo) * ssao_sample * rdm_diff_scale;
if (rdm_diff_scale < 0.001) {
light += ambient_color * ambient_intensity * albedo * ssao_sample;
}
} else {
// Fallback: ambient + sky reflection when no RDM data (or RDM disabled).
light += ambient_color * ambient_intensity * albedo * ssao_sample;
@ -543,6 +573,11 @@ void main() {
}
frag_color = vec4(mix(deepColor, light + emissive, smoothstep(0.0, planeHeight, vpos.y)), 1.0);
if (is_preview == 1) {
frag_color.rgb = mix(frag_color.rgb, vec3(0.3, 0.7, 1.0), 0.5);
} else if (is_preview == 2) {
frag_color.rgb = mix(frag_color.rgb, vec3(1.0, 0.3, 0.2), 0.5);
}
}
@end

View File

@ -0,0 +1,46 @@
@vs vs_trile_shadow
layout(location=0) in vec4 position;
layout(location=1) in vec4 normal; // same slot as shader_trile; not used
layout(location=2) in vec4 centre; // same slot as shader_trile; not used
layout(location=3) in vec4 instance; // xyz=world_pos, w=orientation
layout(binding=0) uniform trile_shadow_vs_params {
mat4 mvp;
};
mat3 rot_x(float a) { float c=cos(a),s=sin(a); return mat3(1,0,0, 0,c,-s, 0,s,c); }
mat3 rot_z(float a) { float c=cos(a),s=sin(a); return mat3(c,-s,0, s,c,0, 0,0,1); }
mat3 rot_y(float a) { float c=cos(a),s=sin(a); return mat3(c,0,s, 0,1,0, -s,0,c); }
mat3 get_orientation_matrix(int ori) {
int face = ori / 4;
int twist = ori % 4;
float PI = 3.1415927;
mat3 base;
if (face == 0) base = mat3(1.0);
else if (face == 1) base = rot_x(PI);
else if (face == 2) base = rot_z(-PI*0.5);
else if (face == 3) base = rot_z( PI*0.5);
else if (face == 4) base = rot_x( PI*0.5);
else base = rot_x(-PI*0.5);
return base * rot_y(float(twist) * PI * 0.5);
}
void main() {
int ori = int(round(instance.w));
mat3 rot = get_orientation_matrix(ori);
vec3 local = position.xyz - 0.5;
vec3 rotated = rot * local + 0.5;
gl_Position = mvp * vec4(rotated + instance.xyz, 1.0);
}
@end
@fs fs_trile_shadow
out vec4 frag_color;
void main() {
frag_color = vec4(0.0);
}
@end
@program trile_shadow vs_trile_shadow fs_trile_shadow

View File

@ -47,7 +47,7 @@ layout(binding=1) uniform trixel_world_config {
int hasClouds;
float planeHeight;
int planeType;
int animatePlaneHeight;
vec3 waterColor;
vec3 deepColor;

4
src/tests/index.jai Normal file
View File

@ -0,0 +1,4 @@
#run {
// print("1st test!!!\n");
// main();
}

View File

@ -50,21 +50,36 @@ set_trile_gfx :: (name: string, gfx: Trile_GFX, skip_preexist_check: bool = fals
sg_destroy_buffer(old_gfx.centre_buffer);
sg_destroy_image(old_gfx.trixel_colors);
array_reset(*old_gfx.vertices);
print("Destroyed old GFX buffers for trile: %\n", name);
log_debug("Destroyed old GFX buffers for trile: %", name);
}
}
table_set(*trile_gfx_table, name, gfx);
}
set_trile :: (name: string, trile: Trile) {
print("Setting trile with name: %\n",name);
log_debug("Setting trile with name: %", name);
// Destroy and remove any cached GFX so it gets regenerated from new data.
gfx_exists, old_gfx := table_find(*trile_gfx_table, name);
if gfx_exists {
sg_destroy_buffer(old_gfx.vertex_buffer);
sg_destroy_buffer(old_gfx.normal_buffer);
sg_destroy_buffer(old_gfx.centre_buffer);
sg_destroy_image(old_gfx.trixel_colors);
array_reset(*old_gfx.vertices);
table_remove(*trile_gfx_table, name);
}
saved_editor_name: string;
if editor_current_trile then saved_editor_name = editor_current_trile.name;
table_set(*trile_table, name, trile);
if saved_editor_name.count > 0 {
editor_current_trile = table_find_pointer(*trile_table, saved_editor_name);
}
}
get_trile :: (name: string) -> (*Trile, success: bool) {
trileptr := table_find_pointer(*trile_table, name);
if !trileptr {
print("Failed to get trile with name: %\n", name);
log_error("Failed to get trile with name: %", name);
return null, false;
}
return trileptr, true;
@ -100,7 +115,7 @@ ltriles :: () {
success, triles := Jaison.json_parse_string(s, [..]TrileSerialize,, temp);
for triles {
set_trile(sprint("%",it.name), trile_from_serialize_form(it));
print("Loaded %\n", it.name);
log_debug("Loaded %", it.name);
}
} @Command

View File

@ -5,7 +5,7 @@
autoedit_scrolls : Table(u64, float);
loc_to_key :: (line: s32) -> string {
print("Creating key: %\n", line);
log_debug("Creating key: %", line);
return tprint("%", line);
}

59
src/ui/demo.jai Normal file
View File

@ -0,0 +1,59 @@
#if FLAG_DEMO_BUILD {
demo_saved_ssao : float = -1.0;
demo_saved_tonemap : float = -1.0;
demo_saved_rdm_diff : float = -1.0;
demo_saved_rdm_spec : float = -1.0;
demo_toggle_float :: (val: *float, saved: *float, default: float) {
if val.* > 0 {
saved.* = val.*;
val.* = 0.0;
} else {
val.* = ifx saved.* > 0 then saved.* else default;
}
}
draw_demo_ui :: (theme: *GR.Overall_Theme) {
r := GR.get_rect(ui_w(86,0), ui_h(1,0), ui_w(13,0), ui_h(3,0));
rdm_diff_on := current_lighting_config.rdm_diff_scale > 0;
if GR.button(r, ifx rdm_diff_on then "RDM Diffuse: ON" else "RDM Diffuse: OFF") {
demo_toggle_float(*current_lighting_config.rdm_diff_scale, *demo_saved_rdm_diff, 1.0);
}
r.y += r.h * 1.3;
rdm_spec_on := current_lighting_config.rdm_spec_scale > 0;
if GR.button(r, ifx rdm_spec_on then "RDM Specular: ON" else "RDM Specular: OFF") {
demo_toggle_float(*current_lighting_config.rdm_spec_scale, *demo_saved_rdm_spec, 1.0);
}
r.y += r.h * 1.3;
if GR.button(r, ifx !bypass_shadows then "Shadows: ON" else "Shadows: OFF") {
bypass_shadows = !bypass_shadows;
}
r.y += r.h * 1.3;
if GR.button(r, ifx !bypass_reflections then "Reflections: ON" else "Reflections: OFF") {
bypass_reflections = !bypass_reflections;
}
r.y += r.h * 1.3;
ssao_on := current_post_process.ssao > 0;
if GR.button(r, ifx ssao_on then "SSAO: ON" else "SSAO: OFF") {
demo_toggle_float(*current_post_process.ssao, *demo_saved_ssao, 1.0);
}
r.y += r.h * 1.3;
tonemap_on := current_post_process.tonemap > 0;
if GR.button(r, ifx tonemap_on then "Tonemapping: ON" else "Tonemapping: OFF") {
demo_toggle_float(*current_post_process.tonemap, *demo_saved_tonemap, 1.0);
}
r.y += r.h * 1.3;
if GR.button(r, ifx !bypass_postprocess then "Post FX: ON" else "Post FX: OFF") {
bypass_postprocess = !bypass_postprocess;
}
}
} // #if FLAG_DEMO_BUILD

View File

@ -183,6 +183,8 @@ prepare_text :: (font: *Ui_Type_Indicator.Font, text: string, effects: Ui_Type_I
return 0;
}
// print("Font: %\n", font);
fonsPushState(state.fons);
defer fonsPopState(state.fons);
fonsSetFont(state.fons, state.font_default.fons_font);
fonsSetSize(state.fons, xx font.character_height);
w := fonsTextBounds(state.fons, 0.0, 0.0, text.data, text.data + text.count, null);
@ -210,6 +212,10 @@ prepare_text :: (font: *Ui_Type_Indicator.Font, text: string, effects: Ui_Type_I
}
draw_prepared_text :: (font: *Ui_Type_Indicator.Font, x: s64, y: s64, text_color: Vector4, effects: Ui_Type_Indicator.Font_Effects = 0) {
if gPreppedText.count < 1 then return;
fonsPushState(state.fons);
defer fonsPopState(state.fons);
fonsSetFont(state.fons, state.font_default.fons_font);
fonsSetSize(state.fons, xx font.character_height);
color := sfons_rgba(xx (255.0 * text_color.x), xx (255.0 * text_color.y), xx (255.0 * text_color.z), xx (255.0 * text_color.w));
fonsSetColor(state.fons, color);
result := cast(*u8) temporary_alloc(gPreppedText.count + 1); // Add 1 for the zero.
@ -217,10 +223,9 @@ draw_prepared_text :: (font: *Ui_Type_Indicator.Font, x: s64, y: s64, text_color
result[gPreppedText.count] = 0;
sgl_layer(layer);
fonsDrawText(state.fons, xx x, xx y, result, null);
fonsPushState(state.fons);
arb_tri_command_add(.{
type = .DRAW_TEXT,
layer = layer
layer = layer
});
layer += 1;
}
@ -420,6 +425,9 @@ render_ui :: () {
GR.set_default_theme(my_theme);
draw_editor_ui(*my_theme);
if !in_editor_view then game_ui(*my_theme);
#if FLAG_DEMO_BUILD { if !in_editor_view then draw_demo_ui(*my_theme); }
draw_settings_menu(*my_theme);
draw_console(*my_theme);
}
ui_pass :: () {

View File

@ -180,7 +180,7 @@ World_Config_Binary :: struct {
sky_intensity: float;
has_clouds: s32;
plane_height: float;
plane_type: s32;
animate_plane_height: s32;
water_color: [3]float;
deep_color: [3]float;
}
@ -198,7 +198,7 @@ world_config_to_binary :: (conf: *World_Config) -> World_Config_Binary {
b.sky_intensity = conf.skyIntensity;
b.has_clouds = conf.hasClouds;
b.plane_height = conf.planeHeight;
b.plane_type = conf.planeType;
b.animate_plane_height = conf.animatePlaneHeight;
b.water_color = conf.waterColor.component;
b.deep_color = conf.deepColor.component;
return b;
@ -217,7 +217,7 @@ world_config_from_binary :: (b: *World_Config_Binary) -> World_Config {
conf.skyIntensity = b.sky_intensity;
conf.hasClouds = b.has_clouds;
conf.planeHeight = b.plane_height;
conf.planeType = b.plane_type;
conf.animatePlaneHeight = b.animate_plane_height;
conf.waterColor.component = b.water_color;
conf.deepColor.component = b.deep_color;
return conf;
@ -252,7 +252,7 @@ read_string :: (data: []u8, cursor: *s64, len: s64) -> string {
sworld :: () {
if !current_world.valid {
print("Cannot save: no world loaded\n");
log_error("Cannot save: no world loaded");
return;
}
#if OS != .WASM {
@ -262,7 +262,7 @@ sworld :: () {
file.make_directory_if_it_does_not_exist(dir, recursive = true);
data := save_world(*current_world.world);
file.write_entire_file(tprint("%/index.world", dir), data);
print("Saved world '%' (% bytes)\n", name, data.count);
log_info("Saved world '%' (% bytes)", name, data.count);
}
} @Command
@ -350,20 +350,20 @@ load_world_from_data :: (data: []u8) -> (World, bool) {
cursor: s64 = 0;
if data.count < size_of(u32) + size_of(u16) {
print("World file too small\n");
log_error("World file too small");
return world, false;
}
// Header
magic := read_value(data, *cursor, u32);
if magic != WORLD_MAGIC {
print("Invalid world file magic\n");
log_error("Invalid world file magic");
return world, false;
}
version := read_value(data, *cursor, u16);
if version != WORLD_VERSION {
print("Unsupported world version: %\n", version);
log_error("Unsupported world version: %", version);
return world, false;
}
@ -435,7 +435,7 @@ World_Config :: struct {
hasClouds : s32 = 1; @Slider,0,1,1
planeHeight : float = 0.0; @Slider,0,3,0.1
planeType : s32 = 1; @Slider,0,1,1
animatePlaneHeight : s32 = 1; @Slider,0,1,1
waterColor : Vector3 = .{1.0, 1.0, 1.0}; @Color // @ToDo: sensible default values.
deepColor : Vector3 = .{1.0, 1.0, 1.0}; @Color // @ToDo: sensible default values.
@ -460,6 +460,13 @@ world_config_to_shader_type :: (wc: *World_Config, data: *$T) {
#insert #run,stallable generate_copy_code();
}
effective_plane_height :: (wc: *World_Config) -> float {
if wc.animatePlaneHeight {
return wc.planeHeight * (1.0 + sin(cast(float)get_time() * 0.5) * 0.1);
}
return wc.planeHeight;
}
draw_world_picker :: (r_in: GR.Rect, theme: *GR.Overall_Theme) {
r := r_in;
r.h = ui_h(4,4);