Compare commits

..

6 Commits

Author SHA1 Message Date
dd947e5738 start on foliage 2026-10-05 19:58:18 +03:00
0bd7102b35 keep moving rendering to new format 2026-10-03 22:59:28 +03:00
b415b81584 add trile AO 2026-10-03 00:01:24 +03:00
ff7787a4e0 port more rendering to the new system 2026-10-02 23:41:45 +03:00
9ebeea8772 move UI code to new renderer 2026-10-02 21:29:02 +03:00
897fbeea4b cleanup 2026-10-02 20:07:49 +03:00
148 changed files with 24827 additions and 152769 deletions

View File

@ -1,8 +1,4 @@
#!/bin/bash
set -e
cd src/shaders/
./compile_shaders.sh
cd ..
cd ..
jai -x64 first.jai
./first

View File

@ -124,8 +124,7 @@ beachgame/
│ │ ├── helpers.jai create_world_rendering_tasks(), uniform helpers
│ │ ├── arbtri.jai Immediate-mode triangle batch renderer (UI)
│ │ ├── post_processing.jai Post-process config, LUT management
│ │ ├── sky.jai Sky rendering helpers
│ │ └── ssao.jai SSAO kernel/noise generation
│ │ └── sky.jai Sky rendering helpers
│ │
│ ├── editor/
│ │ ├── editor.jai Editor root: three views, F3 toggle
@ -249,10 +248,8 @@ Sokol GFX draw calls
| Setup | GPU position/uniform buffers | Uploads trile instance stream data |
| Shadow | 1000×1000 depth texture | Orthographic sun directional light; PCF soft edges (Gaussian-weighted sampling) |
| Reflection | Half-res RGBA32F texture | Planar water reflection: camera Y-flipped around water plane; handles dynamic objects that RDMs cannot |
| G-Buffer | Position + Normal RGBA16F | Used by SSAO and deferred effects |
| SSAO | Single-channel AO texture | Random sample kernel, 64 samples |
| SSAO Blur | Blurred AO texture | Separable blur |
| Main | RGBA32F HDR target | Forward render: sun direct + RDM indirect (specular + diffuse) + SSAO |
| G-Buffer | Position + Normal RGBA16F | Used by SH irradiance and deferred effects |
| Main | RGBA32F HDR target | Forward render: albedo-first trile shading with trixel AO and sky fog; RDM triles keep PBR |
| Post chain | Bloom → DoF ping-pong | Between postprocess_a / postprocess_b |
| Final | Swapchain | Tonemap, LUT grade, vignette, grain |
@ -371,12 +368,31 @@ handles dynamic objects (players, ball) that do not appear in the static RDMs, a
sharp mirror-like reflections correct for large flat surfaces. Post-processing can add ripple
distortion to the reflection texture.
#### SSAO
#### Trixel AO
Screen-space ambient occlusion darkens cavities and contact areas. A geometry pass outputs
world-space position and normal (RGBA16F G-buffer), then the SSAO pass samples 64 random
offsets to estimate local occlusion. The result is blurred with a separable filter and applied to
the ambient/diffuse contribution.
Ambient occlusion is worked out per pixel in the trile shaders, voxel style, from the trile's
16³ trixel grid: each corner of a trixel face is darkened by the trixels in front of it, and the
four corners are blended across the face. It darkens all of a face's lighting, squared for crisp
edges and scaled by `trixel_ao_strength` in the lighting config.
To carry across trile boundaries, every instance knows which of its 26 surrounding cells hold an
opaque trile (`Chunk_Trile_Group.neighbours`, computed alongside `is_buried`). Those cells count
as solid throughout. The mask is in the trile's own unrotated frame and is packed together with
the orientation into the instance's `w` (`trile_instance_w`), so every shader that reads the
orientation decodes it first.
#### Trile shading
Opaque triles are shaded albedo-first, after Fez: a sunlit face shows its colour, a shaded face
that colour times `shadow_tint`, slightly more saturated. Top, x sides, z sides and bottom each
get a fixed brightness (`face_shade_*`). Trixel colours are converted from sRGB to linear before
lighting. Specular only appears on smooth materials: roughness 0..7 is read as gloss
`1 - roughness/7`, so roughness 7 never shines. Fog takes the sky colour in the view direction,
climbs to `fog_max` between `fog_start` and `fog_end`, then to fully fogged by the LOD cull
distance so nothing pops. All of it lives in `Lighting_Config`, saved to
`game_core/lighting.json` next to `postprocess.json`; `lighting_debug` shows colour × face shade
(1), AO (2) or light only (3). Post adds `tonemap = 2`, a hue-preserving soft clip, and applies
LUTs after gamma encoding.
#### Pre-bake pipeline

View File

@ -1,4 +1,5 @@
#load "./src/meta/meta.jai";
#load "./src/renderer_sokol/shaders/build.jai";
Iprof :: #import "Iprof"(IMPORT_MODE = .METAPROGRAM);
#import "File_Utilities";
@ -8,11 +9,11 @@ Trueno_Build_Options :: struct {
release_build : bool;
tacoma_enabled : bool;
iprof_enabled : bool;
demo_build : bool;
test_engine : bool;
test_game : bool;
test_exe_engine : bool;
test_exe_game : bool;
renderer : string = "sokol";
}
// Engine tests build against test_game/ so they work without the game/ directory;
@ -26,6 +27,10 @@ build_options_from_args :: (args: []string) -> Trueno_Build_Options {
opts : Trueno_Build_Options;
for arg : args {
if begins_with(arg, "renderer=") {
opts.renderer = slice(arg, 9, arg.count - 9);
continue;
}
if arg == {
case "wasm";
opts.wasm_build = true;
@ -35,8 +40,6 @@ 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;
@ -77,20 +80,17 @@ add_asset_buffer_sizes_to_compiler_strings :: (trueno_opts: Trueno_Build_Options
pack_dir := ifx use_test_game then "./test_packs" else "./packs";
game_resources_dir := ifx use_test_game then "./test_game/resources" else "./game/resources";
sizes: [6]s64;
sizes: [4]s64;
sizes[0] = max_asset_file_size(pack_dir, ".pack", 1 * 1024 * 1024);
sizes[1] = max(
max_asset_file_size(game_resources_dir, "world.json", 64 * 1024),
max_asset_file_size(game_resources_dir, "index.world", 64 * 1024)
);
sizes[2] = max_asset_file_size(game_resources_dir, "chunks.bin", 1 * 1024 * 1024);
sizes[3] = max_asset_file_size(game_resources_dir, ".shgrid", 1 * 1024 * 1024);
sizes[4] = max_asset_file_size(game_resources_dir, "rdm_atlas.rdm", 16 * 1024 * 1024);
sizes[5] = max_asset_file_size(game_resources_dir, "rdm_manifest.json", 256 * 1024);
sizes[3] = max_asset_file_size(game_resources_dir, "probes.bin", 4 * 1024 * 1024);
names :: string.["MAX_PACK_SIZE", "MAX_WORLD_SIZE", "MAX_CHUNKS_SIZE",
"MAX_SHGRID_SIZE", "MAX_RDM_ATLAS_SIZE", "MAX_RDM_MANIFEST_SIZE"];
for i: 0..5 {
names :: string.["MAX_PACK_SIZE", "MAX_WORLD_SIZE", "MAX_CHUNKS_SIZE", "MAX_PROBES_SIZE"];
for i: 0..3 {
add_build_string(tprint("% :: %;\n", names[i], sizes[i]), w);
}
}
@ -103,22 +103,13 @@ add_trueno_opts_to_compiler_strings :: (trueno_opts : Trueno_Build_Options, w: W
trueno_opts_info := type_info(Trueno_Build_Options);
for trueno_opts_info.members {
if it.type.type != .BOOL continue;
optPtr := (cast(*bool)(*trueno_opts)) + it.offset_in_bytes;
name := tprint("%", it.name);
to_upper_in_place(name);
add_build_string(tprint("FLAG_% :: %;\n", name, bool_to_string(optPtr.*)), w);
}
}
compile_shaders :: () {
process_result, output, error := run_command("bash", ifx OS == .MACOS then "./compile_shaders_mac.sh" else "./compile_shaders.sh", working_directory=tprint("%/src/shaders", #filepath));
if process_result.exit_code != 0 {
log_error("Shader compilation failed.");
if output {
log_error(output,, logger = runtime_support_default_logger);
}
exit(1);
}
add_build_string(tprint("RENDERER :: \"%\";\n", trueno_opts.renderer), w);
}
wasm_copy_assets :: () {
@ -155,7 +146,8 @@ native_build :: (opts: Build_Options, trueno_opts: Trueno_Build_Options) {
opts.cpu_target = root_opts.cpu_target;
opts.os_target = root_opts.os_target;
opts.backend = ifx (trueno_opts.release_build || OS == .MACOS) then .LLVM else .X64;
// opts.backend = ifx (trueno_opts.release_build || OS == .MACOS) then .LLVM else .X64;
opts.backend = .LLVM; // rad debugger doesn't currently work with the x64 backend.
opts.output_executable_name = root_opts.output_executable_name;
set_build_options(opts, w);
@ -178,7 +170,6 @@ native_build :: (opts: Build_Options, trueno_opts: Trueno_Build_Options) {
add_trueno_opts_to_compiler_strings(trueno_opts, w);
add_asset_buffer_sizes_to_compiler_strings(trueno_opts, w);
add_build_file("src/platform_specific/main_native.jai", w);
add_shaders_to_workspace(w);
metaprogramming_loop(trueno_opts, *w, iprof_plugin);
@ -230,13 +221,12 @@ wasm_build :: (opts: Build_Options, trueno_opts: Trueno_Build_Options) {
add_trueno_opts_to_compiler_strings(trueno_opts, w);
add_asset_buffer_sizes_to_compiler_strings(trueno_opts, w);
add_build_file("src/platform_specific/main_web.jai", w);
add_shaders_to_workspace(w);
metaprogramming_loop(trueno_opts, *w);
args := string.[
"emcc",
"src/platform_specific/main.c", "dist/main.o", "modules/sokol-jai/sokol/gfx/sokol_gfx_wasm_gl_release.a", "modules/sokol-jai/sokol/log/sokol_log_wasm_gl_release.a", "modules/sokol-jai/sokol/audio/sokol_audio_wasm_gl_release.a", "modules/sokol-jai/sokol/time/sokol_time_wasm_gl_release.a", "modules/sokol-jai/sokol/app/sokol_app_wasm_gl_release.a", "modules/sokol-jai/sokol/glue/sokol_glue_wasm_gl_release.a", "modules/sokol-jai/sokol/fetch/sokol_fetch_wasm_gl_release.a", "modules/sokol-jai/sokol/gl/sokol_gl_wasm_gl_release.a", "modules/sokol-jai/sokol/fontstash/sokol_fontstash_wasm_gl_release.a",
"src/platform_specific/main.c", "dist/main.o", "modules/sokol-jai/sokol/gfx/sokol_gfx_wasm_gl_release.a", "modules/sokol-jai/sokol/log/sokol_log_wasm_gl_release.a", "modules/sokol-jai/sokol/audio/sokol_audio_wasm_gl_release.a", "modules/sokol-jai/sokol/time/sokol_time_wasm_gl_release.a", "modules/sokol-jai/sokol/app/sokol_app_wasm_gl_release.a", "modules/sokol-jai/sokol/glue/sokol_glue_wasm_gl_release.a", "modules/sokol-jai/sokol/fetch/sokol_fetch_wasm_gl_release.a", "modules/Fontstash/wasm/fontstash.a",
"modules/sokol-jai/sokol/stbi/stb_image.a",
"modules/sokol-jai/sokol/stbv/stb_vorbis.a",
"-o", "dist/index.html",
@ -262,10 +252,11 @@ wasm_build :: (opts: Build_Options, trueno_opts: Trueno_Build_Options) {
#run {
opt := get_build_options();
trueno_opts := build_options_from_args(opt.compile_time_command_line);
compile_shaders();
use_test_game := uses_test_game(trueno_opts);
create_pack(use_test_game, ifx use_test_game then "./test_packs" else "./packs");
if trueno_opts.renderer == "sokol" && !compile_sokol_shaders() exit(1);
if trueno_opts.wasm_build {
wasm_build(opt, trueno_opts);
} else {

BIN
first.rdi Executable file

Binary file not shown.

Binary file not shown.

View File

@ -24,7 +24,7 @@ VK_KHR_deferred_host_operations
VK_KHR_acceleration_structure
VK_KHR_ray_query
BLAS Compaction: 0.7MB -> 0.2MB (0.5MB saved, 65.9% smaller)
BLAS Compaction: 0.4MB -> 0.2MB (0.3MB saved, 65.7% smaller)
_______________
Vulkan Version:
- available: 1.4.309
@ -51,7 +51,7 @@ VK_KHR_deferred_host_operations
VK_KHR_acceleration_structure
VK_KHR_ray_query
BLAS Compaction: 0.8MB -> 0.3MB (0.5MB saved, 66.0% smaller)
BLAS Compaction: 0.4MB -> 0.2MB (0.3MB saved, 65.7% smaller)
_______________
Vulkan Version:
- available: 1.4.309
@ -78,85 +78,4 @@ VK_KHR_deferred_host_operations
VK_KHR_acceleration_structure
VK_KHR_ray_query
BLAS Compaction: 0.8MB -> 0.3MB (0.5MB 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.8MB -> 0.3MB (0.5MB 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.8MB -> 0.3MB (0.5MB saved, 65.9% 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.8MB -> 0.3MB (0.5MB saved, 65.9% smaller)
BLAS Compaction: 0.4MB -> 0.2MB (0.3MB saved, 65.7% smaller)

13
modules/Fontstash/build.sh Executable file
View File

@ -0,0 +1,13 @@
#!/bin/bash
# Builds fontstash (with stb_truetype) as a plain static library, without the
# sokol glue the sokol-jai version comes with. Run on each platform:
# ./build.sh linux | macos | wasm
set -e
cd "$(dirname "$0")"
case "$1" in
linux) cc -c -O2 -fPIC source/fontstash.c -o fontstash.o && mkdir -p linux && ar rcs linux/fontstash.a fontstash.o ;;
macos) cc -c -O2 -arch arm64 -arch x86_64 source/fontstash.c -o fontstash.o && mkdir -p macos && ar rcs macos/fontstash.a fontstash.o ;;
wasm) emcc -c -O2 -sMEMORY64 source/fontstash.c -o fontstash.o && mkdir -p wasm && emar rcs wasm/fontstash.a fontstash.o ;;
*) echo "usage: $0 linux|macos|wasm"; exit 1 ;;
esac
rm fontstash.o

Binary file not shown.

View File

@ -0,0 +1,43 @@
// Fontstash with stb_truetype, as a plain C library: no rendering backend,
// glyphs reach the caller through FONSparams' render callbacks. Only the parts
// the engine uses are bound. Libraries are built with build.sh.
FONScontext :: struct {}
FONS_ZERO_TOPLEFT :: 1;
FONSparams :: struct {
width, height : s32;
flags : u8;
userPtr : *void;
renderCreate : (uptr: *void, width: s32, height: s32) -> s32 #c_call;
renderResize : (uptr: *void, width: s32, height: s32) -> s32 #c_call;
renderUpdate : (uptr: *void, rect: *s32, data: *u8) #c_call;
renderDraw : (uptr: *void, verts: *float, tcoords: *float, colors: *u32, nverts: s32) #c_call;
renderDelete : (uptr: *void) #c_call;
}
fonsCreateInternal :: (params: *FONSparams) -> *FONScontext #foreign fontstash;
fonsResetAtlas :: (s: *FONScontext, width: s32, height: s32) -> s32 #foreign fontstash;
fonsAddFontMem :: (s: *FONScontext, name: *u8, data: *u8, ndata: s32, free_data: s32) -> s32 #foreign fontstash;
fonsClearState :: (s: *FONScontext) #foreign fontstash;
fonsSetSize :: (s: *FONScontext, size: float) #foreign fontstash;
fonsSetColor :: (s: *FONScontext, color: u32) #foreign fontstash;
fonsSetFont :: (s: *FONScontext, font: s32) #foreign fontstash;
fonsDrawText :: (s: *FONScontext, x: float, y: float, str: *u8, end: *u8) -> float #foreign fontstash;
fonsTextBounds :: (s: *FONScontext, x: float, y: float, str: *u8, end: *u8, bounds: *float) -> float #foreign fontstash;
fonsVertMetrics :: (s: *FONScontext, ascender: *float, descender: *float, line_height: *float) #foreign fontstash;
fonsGetTextureData :: (s: *FONScontext, width: *s32, height: *s32) -> *u8 #foreign fontstash;
#scope_file
#if OS == .LINUX {
fontstash :: #library,no_dll "linux/fontstash";
#library,system,link_always "libm";
} else #if OS == .MACOS {
fontstash :: #library,no_dll "macos/fontstash";
} else #if OS == .WASM {
fontstash :: #library,no_dll "wasm/fontstash";
} else {
#assert false "Fontstash has no library for this OS; see build.sh.";
}

View File

@ -0,0 +1,4 @@
#include <stdio.h>
#include <stdlib.h>
#define FONTSTASH_IMPLEMENTATION
#include "fontstash.h"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

View File

@ -15,14 +15,19 @@ Sky_Config :: struct {
skyDesaturation : float = 0.0;
}
Trixel_Data :: struct {
empty : bool = false;
color : Vector3 = .{1.0, 0.0, 0.0};
material : float = 1.0;
// emission is the light it gives off, already scaled. Glass is seen as a solid
// surface but lets the sun through, tinted by its colour.
Swatch :: struct {
color : Vector3;
emission : Vector3;
glass : s32;
}
SWATCH_COUNT :: 256;
PROBE_FLOATS :: 13; // R, G, B × (c0, y, z, x), then the fraction of rays that hit a back face
Trile_Data :: struct {
trixels : [16][16][16]Trixel_Data;
trixels : [16][16][16]u8; // swatch ids, 0 = empty
vertices : *float;
vertexCount : s32;
}
@ -47,7 +52,7 @@ Tacoma_Context :: struct {}
tacoma_init :: (base_path: *u8) -> *Tacoma_Context #foreign libtacoma;
tacoma_destroy :: (ctx: *Tacoma_Context) #foreign libtacoma;
tacoma_load_scene :: (ctx: *Tacoma_Context, sky: Sky_Config, ts: Trile_Set, world: World, include_water: s32) #foreign libtacoma;
tacoma_load_scene :: (ctx: *Tacoma_Context, sky: Sky_Config, swatches: *Swatch, ts: Trile_Set, world: World, include_water: s32) #foreign libtacoma;
tacoma_render_rdm :: (ctx: *Tacoma_Context, world_trile_index: s32, roughness: s32, quality: s32, size: s32) -> *float #foreign libtacoma;
tacoma_render_reference :: (ctx: *Tacoma_Context, width: s32, height: s32, eye: Vector3, target: Vector3, roughness: float, quality: s32) -> *float #foreign libtacoma;
tacoma_render_sh_chunk :: (ctx: *Tacoma_Context, origin_x: float, origin_y: float, origin_z: float, probe_n: s32, probe_spacing: float, quality: s32) -> *float #foreign libtacoma;

View File

@ -1,4 +1,4 @@
master_volume 0
master_volume 0.205032
music_volume 1
sfx_volume 1
fullscreen 0
fullscreen 1

View File

@ -6,8 +6,7 @@ Pool :: #import "Pool";
#load "loaders.jai";
// MAX_PACK_SIZE, MAX_WORLD_SIZE, MAX_CHUNKS_SIZE, MAX_SHGRID_SIZE,
// MAX_RDM_ATLAS_SIZE, MAX_RDM_MANIFEST_SIZE are injected as build strings
// MAX_PACK_SIZE, MAX_WORLD_SIZE and MAX_CHUNKS_SIZE are injected as build strings
// by first.jai after scanning the actual asset files at compile time.
MAX_FETCH_SLOTS :: 16;
@ -25,9 +24,7 @@ Fetch_Type :: enum {
PACK;
WORLD;
WORLD_CHUNKS;
RDM_ATLAS;
RDM_MANIFEST;
SHGRID;
WORLD_PROBES;
}
Fetch_Request :: struct {
@ -38,9 +35,8 @@ Fetch_Request :: struct {
// PACK
pack_name : string;
// WORLD / RDM / SH
// WORLD
world_name : string;
chunk_key : Chunk_Key;
// WORLD_CHUNKS: JSON carried forward from the WORLD fetch
world_json_data : []u8;
@ -66,17 +62,12 @@ g_asset_manager : Asset_Manager;
#scope_file
#load "rdm_loader.jai";
#load "sh_loader.jai";
fetch_type_buffer_size :: (type: Fetch_Type) -> s64 {
if #complete type == {
case .PACK; return MAX_PACK_SIZE;
case .WORLD; return MAX_WORLD_SIZE;
case .WORLD_CHUNKS; return MAX_CHUNKS_SIZE;
case .RDM_ATLAS; return MAX_RDM_ATLAS_SIZE;
case .RDM_MANIFEST; return MAX_RDM_MANIFEST_SIZE;
case .SHGRID; return MAX_SHGRID_SIZE;
case .WORLD_PROBES; return MAX_PROBES_SIZE;
}
}
@ -136,14 +127,8 @@ handle_fetch_failed :: (req: *Fetch_Request) {
free(req.world_json_data.data);
log_error("Failed to load chunks.bin for world '%'", req.world_name);
case .RDM_ATLAS;
log_info("RDM: no global atlas for world '%' (ok if none baked yet)", req.world_name);
case .RDM_MANIFEST;
log_info("RDM: no manifest for world '%' (ok if none baked yet)", req.world_name);
case .SHGRID;
sh_loader_handle_failed(req);
case .WORLD_PROBES;
log_info("No baked probes for world '%'", req.world_name);
}
}
@ -189,60 +174,22 @@ process_completed_fetch :: (req: *Fetch_Request, data: []u8) {
world, ok := load_world_from_json(json_str, data);
if ok {
set_loaded_world(world);
rdm_loader_enqueue_world(*get_current_world().world);
shgrid_loader_enqueue_world(*get_current_world().world);
log_info("Loaded world: %", req.world_name);
probes_req: Fetch_Request;
probes_req.type = .WORLD_PROBES;
probes_req.priority = .BACKGROUND;
probes_req.world_name = req.world_name;
probes_req.path = sprint("%/worlds/%/probes.bin", GAME_RESOURCES_DIR, req.world_name);
array_add(*g_asset_manager.queue, probes_req);
} else {
log_error("Failed to parse world '%'", req.world_name);
}
case .RDM_ATLAS;
case .WORLD_PROBES;
// Another world may have been loaded while these were on the way.
curworld := get_current_world();
if !curworld.valid || curworld.world.name != req.world_name then return;
header_size := cast(s64) size_of(RDM_File_Header);
if data.count < header_size {
log_error("RDM: global atlas too small (world %)", req.world_name);
return;
}
header := cast(*RDM_File_Header) data.data;
if header.magic != RDM_FILE_MAGIC {
log_error("RDM: bad atlas magic (world %)", req.world_name);
return;
}
atlas_pixel_bytes := cast(u64) header.width * cast(u64) header.height * 4 * size_of(u16);
atlas_imgdata: sg_image_data;
atlas_imgdata.subimage[0][0] = .{ data.data + header_size, atlas_pixel_bytes };
atlas_desc: sg_image_desc = .{
render_target = false,
width = header.width,
height = header.height,
pixel_format = sg_pixel_format.RGBA16F,
sample_count = 1,
data = atlas_imgdata,
};
if g_rdm_atlas.id != 0 then sg_destroy_image(g_rdm_atlas);
g_rdm_atlas = sg_make_image(*atlas_desc);
log_debug("RDM: loaded global atlas (%x%)", header.width, header.height);
case .RDM_MANIFEST;
curworld := get_current_world();
if !curworld.valid || curworld.world.name != req.world_name then return;
json_str : string;
json_str.data = data.data;
json_str.count = data.count;
ok, entries := Jaison.json_parse_string(json_str, [..]Rdm_Atlas_Entry,, temp);
if !ok {
log_error("RDM: failed to parse manifest for world '%'", req.world_name);
return;
}
array_reset_keeping_memory(*curworld.world.rdm_lookup);
for e: entries array_add(*curworld.world.rdm_lookup, e);
log_debug("RDM: loaded manifest (% entries)", entries.count);
case .SHGRID;
sh_loader_handle_completed(req, data);
if !curworld.valid || curworld.world.name != req.world_name return;
if !load_probes(data) log_error("Broken probes.bin for world '%'", req.world_name);
}
}
@ -252,7 +199,7 @@ Loaded_Pack :: struct {
nameHash : u32 = 0;
data_buffer : []u8;
content : Load_Package;
textures : Table(string, sg_image);
textures : Table(string, Texture);
animations : Table(string, Animation);
audio : Table(string, Audio_Data);
pool : Pool.Pool;
@ -263,7 +210,7 @@ add_resources_from_pack :: (pack: *Loaded_Pack) {
Queued_Sheet_File :: struct {
name : string;
image : sg_image;
image : Texture;
sheet_w : s32;
sheet_h : s32;
sheet : Aseprite_Sheet;
@ -300,9 +247,6 @@ add_resources_from_pack :: (pack: *Loaded_Pack) {
} else {
queuedSheet.sheet = sheet;
}
case "colorgrade.png";
img, x, y := create_texture_from_memory(v.data);
add_image_to_lut_list(img, v.name);
case "wav";
audio := load_wav_from_memory(v.data);
table_set(*pack.audio, name, audio);
@ -323,12 +267,17 @@ add_resources_from_pack :: (pack: *Loaded_Pack) {
}
log_info("Loaded % particle definitions from pack", g_emitter_defs.count);
}
} else if name == "foliage" {
load_foliage_defs_from_json(create_string_from_memory(v.data));
}
case "hex";
pal : Loaded_Palette;
pal.name = sprint("%", name);
pal.entries = load_hex_palette_from_memory(v.data);
array_add(*g_palettes, pal);
// Pack hot reload brings the same palettes in again.
replaced := false;
for *g_palettes if it.name == pal.name { it.* = pal; replaced = true; }
if !replaced array_add(*g_palettes, pal);
log_info("Loaded % colors from hex palette(%)", pal.entries.count, v.name);
case "ttf";
case;
@ -421,7 +370,7 @@ dispatch_slots :: () {
#scope_export
free_resources_from_pack :: (pack: *Loaded_Pack) {
for pack.textures sg_destroy_image(it);
for pack.textures texture_destroy(it);
table_reset(*pack.textures);
table_reset(*pack.audio);
table_reset(*pack.animations);
@ -499,9 +448,9 @@ load_pack :: (name: string, priority: Load_Priority = .LOADING_SCREEN) {
#scope_file
#scope_export
get_texture_from_pack :: (pack: string, path: string) -> (sg_image) {
get_texture_from_pack :: (pack: string, path: string) -> (Texture) {
found, pack := find_pack_by_name(pack);
invalid_img : sg_image;
invalid_img : Texture;
if !found {
return invalid_img;
@ -539,7 +488,16 @@ add_font_from_pack :: (pack: string, path: string) {
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);
state.font_default.face = font_face_add("sans", entry.data);
}
// For files that may legitimately be absent from a pack.
get_raw_file_from_pack :: (pack: string, path: string) -> ([]u8, found: bool) {
pack_ok, loaded := find_pack_by_name(pack);
if !pack_ok return .[], false;
ok, entry := table_find(*loaded.content.lookup, path);
if !ok return .[], false;
return entry.data, true;
}
load_string_from_pack :: (pack: string, path: string) -> string {

View File

@ -1,26 +1,9 @@
create_texture_from_memory :: (data: []u8) -> (sg_image, s32, s32) {
create_texture_from_memory :: (data: []u8) -> (Texture, s32, s32) {
x, y, channels : s32;
image := stbi.stbi_load_from_memory(data.data, xx data.count, *x, *y, *channels, 4);
subimg : [6][16]sg_range;
subimg[0][0] = .{
ptr = image,
size = xx (x * y * 4)
};
img := sg_alloc_image();
sg_init_image(img, *(sg_image_desc.{
width = x,
height = y,
pixel_format = sg_pixel_format.RGBA8,
data = .{
subimage = subimg
}
}));
texture := texture_create(x, y, .{x * y * 4, image});
stbi.stbi_image_free(image);
return img, x, y;
return texture, x, y;
}
create_string_from_memory :: (data: []u8) -> string {

View File

@ -1,58 +0,0 @@
// RDM streaming helpers.
// The unified fetch queue lives in asset_manager.jai; these functions
// enqueue and cancel the world-level global RDM atlas + manifest.
#scope_export
rdm_loader_enqueue_world :: (world: *World) {
already_atlas := false;
already_manifest := false;
for g_asset_manager.slots {
if !it.occupied continue;
if it.req.world_name != world.name continue;
if it.req.type == .RDM_ATLAS then already_atlas = true;
if it.req.type == .RDM_MANIFEST then already_manifest = true;
}
for g_asset_manager.queue {
if it.world_name != world.name continue;
if it.type == .RDM_ATLAS then already_atlas = true;
if it.type == .RDM_MANIFEST then already_manifest = true;
}
if !already_atlas {
req : Fetch_Request;
req.type = .RDM_ATLAS;
req.priority = .LOADING_SCREEN;
req.world_name = world.name;
req.path = rdm_global_atlas_filename(world.name);
array_add(*g_asset_manager.queue, req);
}
if !already_manifest {
req : Fetch_Request;
req.type = .RDM_MANIFEST;
req.priority = .LOADING_SCREEN;
req.world_name = world.name;
req.path = rdm_global_manifest_filename(world.name);
array_add(*g_asset_manager.queue, req);
}
}
// Drain all pending RDM work.
rdm_loader_cancel_all :: () {
new_count := 0;
for i: 0..g_asset_manager.queue.count - 1 {
item := g_asset_manager.queue[i];
if item.type != .RDM_ATLAS && item.type != .RDM_MANIFEST {
g_asset_manager.queue[new_count] = item;
new_count += 1;
}
}
g_asset_manager.queue.count = new_count;
for *slot: g_asset_manager.slots {
if !slot.occupied then continue;
if slot.req.type != .RDM_ATLAS && slot.req.type != .RDM_MANIFEST then continue;
slot.req.world_name = "";
}
}

View File

@ -1,119 +0,0 @@
// SH probe grid streaming helpers.
// The unified fetch queue lives in asset_manager.jai; these functions
// add entries to that queue and handle completed/failed fetches.
#scope_export
shgrid_loader_enqueue_world :: (world: *World) {
for *chunk: world.chunks {
if chunk.sh_valid then continue;
already := false;
for g_asset_manager.slots {
if !it.occupied then continue;
if it.req.type == .SHGRID &&
it.req.world_name == world.name && it.req.chunk_key == chunk.coord {
already = true;
break;
}
}
if already then continue;
for g_asset_manager.queue {
if it.type == .SHGRID &&
it.world_name == world.name && it.chunk_key == chunk.coord {
already = true;
break;
}
}
if already then continue;
req : Fetch_Request;
req.type = .SHGRID;
req.priority = .LOADING_SCREEN;
req.world_name = world.name;
req.chunk_key = chunk.coord;
req.path = shgrid_filename(world.name, chunk.coord);
array_add(*g_asset_manager.queue, req);
}
}
sh_loader_handle_failed :: (req: *Fetch_Request) {
log_error("SH: failed to load probe grid for chunk %", req.chunk_key);
}
sh_loader_handle_completed :: (req: *Fetch_Request, data: []u8) {
curworld := get_current_world();
if !curworld.valid || curworld.world.name != req.world_name then return;
header_size := cast(s64) size_of(SH_Grid_File_Header);
if data.count < header_size {
log_error("SH: probe grid too small for chunk %", req.chunk_key);
return;
}
sh_header := cast(*SH_Grid_File_Header) data.data;
if sh_header.magic != SH_FILE_MAGIC {
log_error("SH: bad magic for chunk %", req.chunk_key);
return;
}
n := sh_header.probe_n;
if n != SH_PROBE_N {
log_error("SH: probe_n mismatch for chunk % (file=%, expected=%) — re-bake required", req.chunk_key, n, SH_PROBE_N);
return;
}
total_values := cast(s64) n * n * n * 12;
bytes_per_val := ifx sh_header.version >= 2 then size_of(u16) else size_of(float);
if data.count < header_size + total_values * bytes_per_val {
log_error("SH: probe grid data too short for chunk %", req.chunk_key);
return;
}
// Pack flat [n^3 * 12] coefficients → 3-RGBA16F-texels-per-probe 2D texture layout.
// Texture dims: (n*3) x (n*n). Probe (px,py,pz) at row (pz*n+py), col (px*3+k).
// Coefficient layout in 3 texels (12 slots):
// t0: R.c0-3 t1: G.c0-3 t2: B.c0-3
tex_w := n * 3;
n_tex := cast(s64) tex_w * n * n;
packed := NewArray(n_tex * 4, u16);
if sh_header.version >= 2 {
src := cast(*u16) (data.data + header_size);
for pz: 0..n-1 for py: 0..n-1 for px: 0..n-1 {
probe_idx := px + py * n + pz * n * n;
s := src + probe_idx * 12;
for k: 0..2 {
tex_idx := (pz * n + py) * tex_w + (px * 3 + k);
d := packed.data + tex_idx * 4;
for ch: 0..3 d[ch] = (s + k * 4 + ch).*;
}
}
} else {
src := cast(*float) (data.data + header_size);
for pz: 0..n-1 for py: 0..n-1 for px: 0..n-1 {
probe_idx := px + py * n + pz * n * n;
s := src + probe_idx * 12;
for k: 0..2 {
tex_idx := (pz * n + py) * tex_w + (px * 3 + k);
d := packed.data + tex_idx * 4;
for ch: 0..3 d[ch] = f32_to_f16((s + k * 4 + ch).*);
}
}
}
sh_imgdata : sg_image_data;
sh_imgdata.subimage[0][0] = .{ packed.data, cast(u64)(n_tex * 4 * size_of(u16)) };
sh_desc : sg_image_desc = .{
width = tex_w,
height = n * n,
pixel_format = sg_pixel_format.RGBA16F,
sample_count = 1,
data = sh_imgdata,
};
chunk := table_find_pointer(*curworld.world.chunks, req.chunk_key);
if chunk != null {
if chunk.sh_probe_grid.id != 0 then sg_destroy_image(chunk.sh_probe_grid);
chunk.sh_probe_grid = sg_make_image(*sh_desc);
chunk.sh_valid = true;
log_debug("SH: loaded probe grid for chunk %", req.chunk_key);
}
free(packed.data);
}

View File

@ -6,10 +6,11 @@
#load "trile_editor.jai";
#load "level_editor.jai";
#load "particle_editor.jai";
#load "material_studio.jai";
#load "foliage_studio.jai";
}
#if FLAG_TACOMA_ENABLED { #load "tacoma.jai"; }
#load "console.jai";
#load "textureDebugger.jai";
#scope_file
@ -18,6 +19,8 @@ Editor_View :: enum {
Trile_Editor;
Level_Editor;
Particle_Editor;
Material_Editor;
Foliage_Editor;
};
current_editor_view : Editor_View = .Trile_Editor;
@ -62,6 +65,10 @@ draw_editor_ui :: (theme: *GR.Overall_Theme) {
if keybind_button(r, "Trile studio", .STUDIO_TRILE, *t_button_selectable(theme, current_editor_view == .Trile_Editor)) { clear_particles(); current_editor_view = .Trile_Editor; }
r.x -= r.w;
if keybind_button(r, "Particle studio", .STUDIO_MATERIAL, *t_button_selectable(theme, current_editor_view == .Particle_Editor)) { clear_particles(); current_editor_view = .Particle_Editor; }
r.x -= r.w;
if keybind_button(r, "Material studio", .STUDIO_SWATCHES, *t_button_selectable(theme, current_editor_view == .Material_Editor)) { clear_particles(); current_editor_view = .Material_Editor; }
r.x -= r.w;
if keybind_button(r, "Foliage studio", .STUDIO_FOLIAGE, *t_button_selectable(theme, current_editor_view == .Foliage_Editor)) { clear_particles(); current_editor_view = .Foliage_Editor; }
if current_editor_view == {
case .Trile_Editor;
@ -70,23 +77,21 @@ draw_editor_ui :: (theme: *GR.Overall_Theme) {
draw_level_editor_ui(theme);
case .Particle_Editor;
draw_particle_editor_ui(theme);
case .Material_Editor;
draw_material_studio_ui(theme);
case .Foliage_Editor;
draw_foliage_studio_ui(theme);
}
}
draw_profiler();
}
draw_texture_debugger(theme);
draw_postprocess_popup(theme);
draw_lighting_popup(theme);
GR.draw_popups();
immediate_flush();
}
draw_editor :: () {
#if OS != .WASM {
disable_dof_post_process = false;
if !in_editor_view then return;
disable_dof_post_process = true;
if current_editor_view == {
case .Trile_Editor;

View File

@ -0,0 +1,155 @@
#scope_file
fs_selected_index : s32 = -1;
fs_scroll : float = 0;
fs_name_input_start : string = "";
fs_anim_input_start : string = "";
fs_label :: (r: *GR.Rect, text: string, theme: *GR.Overall_Theme) {
GR.label(r.*, text, *t_label_left(theme));
r.y += r.h;
}
fs_float :: (r: *GR.Rect, label: string, value: *float, lo: float, hi: float, step: float, theme: *GR.Overall_Theme, loc := #caller_location) {
GR.label(r.*, label, *t_label_left(theme));
r.y += r.h;
GR.slider(r.*, value, lo, hi, step, *theme.slider_theme, loc = loc);
r.y += r.h;
}
fs_select_def :: (idx: s32) {
fs_selected_index = idx;
if idx >= 0 && idx < cast(s32) g_foliage_defs.count {
fs_name_input_start = g_foliage_defs[idx].name;
fs_anim_input_start = g_foliage_defs[idx].animation_name;
}
}
#scope_export
draw_foliage_studio_ui :: (theme: *GR.Overall_Theme) {
panel_w := ui_w(20, 20);
row_h := ui_h(3, 0);
list_r := GR.get_rect(ui_w(80, 20), ui_h(5,0), panel_w, ui_h(95, 0));
ui_add_mouse_occluder(list_r);
draw_bg_rectangle(list_r, theme);
r := list_r;
r.h = row_h;
half_w := r.w / 2;
orig_w := r.w;
r.w = half_w;
if GR.button(r, "New", *theme.button_theme) {
def : Foliage_Def;
def.name = sprint("foliage_%", g_foliage_defs.count);
array_add(*g_foliage_defs, def);
fs_select_def(cast(s32)(g_foliage_defs.count - 1));
}
r.x += half_w;
if GR.button(r, "Duplicate", *theme.button_theme) {
if fs_selected_index >= 0 && fs_selected_index < cast(s32) g_foliage_defs.count {
def := g_foliage_defs[fs_selected_index];
def.name = sprint("%_copy", def.name);
def.animation_name = copy_string(def.animation_name);
array_add(*g_foliage_defs, def);
fs_select_def(cast(s32)(g_foliage_defs.count - 1));
}
}
r.x -= half_w;
r.w = orig_w;
r.y += r.h;
for def, idx : g_foliage_defs {
if r.y > list_r.y + list_r.h - row_h * 3 then break;
selected := (cast(s32)idx == fs_selected_index);
if GR.button(r, def.name, *t_button_selectable(theme, selected), cast(s32)idx) {
fs_select_def(cast(s32)idx);
}
r.y += r.h;
}
r.y = list_r.y + list_r.h - row_h * 2;
r.w = half_w;
if keybind_button(r, "Save", .SAVE, *theme.button_theme) {
save_foliage_defs();
}
r.x += half_w;
if GR.button(r, "Delete", *theme.button_theme) {
if fs_selected_index >= 0 && fs_selected_index < cast(s32) g_foliage_defs.count {
array_ordered_remove_by_index(*g_foliage_defs, fs_selected_index);
if fs_selected_index >= cast(s32) g_foliage_defs.count then fs_selected_index -= 1;
fs_select_def(fs_selected_index);
}
}
r.w = orig_w;
if fs_selected_index < 0 || fs_selected_index >= cast(s32) g_foliage_defs.count then return;
def := *g_foliage_defs[fs_selected_index];
edit_r := GR.get_rect(0, ui_h(5,0), panel_w, ui_h(95, 0));
ui_add_mouse_occluder(edit_r);
draw_bg_rectangle(edit_r, theme);
region, inside := GR.begin_scrollable_region(edit_r, *theme.scrollable_region_theme);
er := inside;
er.y -= fs_scroll;
er.h = row_h;
fs_label(*er, "Name", theme);
a, new_name, _ := GR.text_input(er, fs_name_input_start, *theme.text_input_theme, 0);
if a & .ENTERED {
def.name = copy_string(new_name);
fs_name_input_start = def.name;
}
er.y += er.h;
fs_label(*er, "Animation (pack.anim)", theme);
a2, new_anim, _ := GR.text_input(er, fs_anim_input_start, *theme.text_input_theme, 1);
if a2 & .ENTERED {
def.animation_name = copy_string(new_anim);
fs_anim_input_start = def.animation_name;
}
er.y += er.h;
anim := get_animation_from_string(def.animation_name);
if anim != null {
fs_label(*er, tprint("Animation: % frames", anim.frames.count), theme);
} else {
fs_label(*er, tprint("Animation: not found ('%')", def.animation_name), theme);
}
orig_w2 := er.w;
er.w = orig_w2 / 2;
fs_label(*er, "Type", theme);
if GR.button(er, "Grass", *t_button_selectable(theme, def.type == .GRASS), 100) then def.type = .GRASS;
er.x += er.w;
if GR.button(er, "Tree", *t_button_selectable(theme, def.type == .TREE), 101) then def.type = .TREE;
er.x -= er.w;
er.y += er.h;
fs_label(*er, "Frames", theme);
if GR.button(er, "Variant", *t_button_selectable(theme, def.frame_mode == .VARIANT), 102) then def.frame_mode = .VARIANT;
er.x += er.w;
if GR.button(er, "Loop", *t_button_selectable(theme, def.frame_mode == .LOOP), 103) then def.frame_mode = .LOOP;
er.x -= er.w;
er.y += er.h;
er.w = orig_w2;
if def.type == .GRASS {
fs_float(*er, tprint("Density: %", def.density), *def.density, 0, 1, 0.05, theme);
fs_float(*er, tprint("Jitter: %", def.jitter), *def.jitter, 0, 0.5, 0.05, theme);
}
fs_float(*er, tprint("Scale Min: %", def.scale_min), *def.scale_min, 0.1, 4, 0.05, theme);
fs_float(*er, tprint("Scale Max: %", def.scale_max), *def.scale_max, 0.1, 4, 0.05, theme);
if def.scale_max < def.scale_min then def.scale_max = def.scale_min;
fs_float(*er, tprint("Sway Intensity: %", def.sway_intensity), *def.sway_intensity, 0, 1, 0.05, theme);
fs_float(*er, tprint("Sway Speed: %", def.sway_speed), *def.sway_speed, 0, 5, 0.1, theme);
GR.end_scrollable_region(region, er.x + er.w, er.y, *fs_scroll);
}

View File

@ -36,14 +36,7 @@ draw_line :: (p0: Vector2, p1: Vector2, p2: Vector2, p3: Vector2, color: Vector4
}
text_width :: (text: string) -> float {
if text.count < 1 {
return 0;
}
fonsSetFont(state.fons, state.font_default.fons_font);
fonsSetSize(state.fons, xx iprof_font.character_height);
w := fonsTextBounds(state.fons, 0.0, 0.0, text.data, text.data + text.count, null);
return cast(float) w;
return text_measure(state.font_default.face, xx iprof_font.character_height, text);
}
draw_rectangle_prof :: (x0: float, y0: float, x1: float, y1: float, color: Vector4) {

View File

@ -56,7 +56,6 @@ inspector_x : s32;
inspector_y : s32;
inspector_z : s32;
inspector_emitter_def : s32 = -1;
inspector_rdm_roughness : int = 0;
inspector_note_deactivate : bool;
inspector_note_activate_next : bool;
@ -131,11 +130,7 @@ get_level_editor_camera :: () -> Camera {
camera.position = camera.target;
camera.position += cameraDir * cameraDist;
if is_in_reflection_pass {
camera.position.y *= -1;
camera.target.y *= -1;
}
return camera;
}
@ -258,37 +253,24 @@ draw_tacoma_tab :: (theme: *GR.Overall_Theme, total_r: GR.Rect) {
r.h = ui_h(3,0);
if GR.button(r, "Render with Tacoma", *theme.button_theme) {
cam := get_level_editor_camera();
gen_reference(tacomaResolution, tacomaResolution, cam.position, cam.target, tacomaSamples, true, curworld.world);
if curworld.valid gen_reference(tacomaResolution, tacomaResolution, cam.position, cam.target, tacomaSamples, *curworld.world);
}
r.y += r.h;
if GR.button(r, "Bake all chunk RDMs", *theme.button_theme) {
if curworld.valid then rdm_bake_all_chunks(curworld.world, tacomaSamples, true);
if GR.button(r, "Bake probes", *t_button_selectable(theme, !probe_bake.active)) {
if curworld.valid && !probe_bake.active bake_probes(tacomaSamples);
}
r.y += r.h;
if GR.button(r, "Bake all chunk SH grids", *t_button_selectable(theme, !sh_bake.active)) {
if curworld.valid && !sh_bake.active sh_bake_start(tacomaSamples);
}
r.y += r.h;
if rdm_bake.active {
total := cast(s32) rdm_bake.jobs.count;
done := rdm_bake.current_job;
pct := ifx total > 0 then done * 100 / total else 0;
GR.label(r, tprint("Baking RDMs: %/% (\%%)", done, total, pct), *t_label_left(theme));
if probe_bake.active {
total := probe_bake.keys.count;
done := probe_bake.results.count;
GR.label(r, tprint("Baking probes: %/% chunks", done, total), *t_label_left(theme));
r.y += r.h;
}
if sh_bake.active {
total := cast(s32) sh_bake.chunk_keys.count;
done := sh_bake.current_chunk;
pct := ifx total > 0 then done * 100 / total else 0;
GR.label(r, tprint("Baking SH grids: %/% (\%%)", done, total, pct), *t_label_left(theme));
r.y += r.h;
}
if current_screenshot.valid {
aspect := cast(float)current_screenshot.width / cast(float)current_screenshot.height;
if tacoma_preview.texture.id {
aspect := cast(float) tacoma_preview.width / cast(float) tacoma_preview.height;
r.h = r.w / aspect;
uiTex := New(Ui_Texture,, temp);
uiTex.tex = current_screenshot.image;
uiTex.tex = tacoma_preview.texture;
set_shader_for_images(uiTex);
immediate_quad(.{r.x, r.y}, .{r.x + r.w, r.y}, .{r.x + r.w, r.y + r.h}, .{r.x, r.y + r.h});
set_shader_for_color();
@ -304,13 +286,9 @@ draw_tacoma_tab :: (theme: *GR.Overall_Theme, total_r: GR.Rect) {
r.y += r.h;
GR.slider(r, *tacomaResolution, 10, 5000, 10, *theme.slider_theme);
r.y += r.h;
GR.label(r, tprint("Sky Scale (bake): %", formatFloat(bake_sky_scale, trailing_width=2)), *t_label_left(theme));
GR.label(r, "Emissive light (bake)", *t_label_left(theme));
r.y += r.h;
GR.slider(r, *bake_sky_scale, 0.0, 5.0, 0.05, *theme.slider_theme);
r.y += r.h;
GR.label(r, tprint("Sky Desaturation (bake): %", formatFloat(bake_sky_desaturation, trailing_width=2)), *t_label_left(theme));
r.y += r.h;
GR.slider(r, *bake_sky_desaturation, 0.0, 1.0, 0.05, *theme.slider_theme);
GR.slider(r, *bake_emissive_light, 0.0, 50.0, 0.5, *theme.slider_theme);
r.y += r.h;
GR.end_scrollable_region(region, r.x + r.w, r.y, *tacoma_tab_scroll);
@ -487,7 +465,6 @@ add_trile :: (name: string, x: s32, y: s32, z: s32, orientation: u8 = 0) {
for *group: chunk.groups {
if group.trile_name == name {
array_add(*group.instances, inst);
recompute_group_bounds(group);
added = true;
break;
}
@ -496,10 +473,9 @@ add_trile :: (name: string, x: s32, y: s32, z: s32, orientation: u8 = 0) {
group: Chunk_Trile_Group;
group.trile_name = sprint("%", name);
array_add(*group.instances, inst);
recompute_group_bounds(*group);
array_add(*chunk.groups, group);
}
invalidate_buried_around(*curworld.world, x, y, z);
upload_chunk(chunk);
trile, ok := get_trile(name);
if !ok || trile.skip_collision then return;
chunk_set_occupancy_mask_at(chunk, lx, ly, lz, occupancy_state_for(trile, orientation));
@ -519,17 +495,13 @@ remove_trile :: (x: s32, y: s32, z: s32) {
for inst, idx: group.instances {
if inst.x == lx && inst.y == ly && inst.z == lz {
array_unordered_remove_by_index(*group.instances, idx);
if group.is_buried.count > idx {
array_unordered_remove_by_index(*group.is_buried, idx);
}
recompute_group_bounds(group);
removed = true;
break;
}
}
if removed break;
}
if removed invalidate_buried_around(*curworld.world, x, y, z);
if removed upload_chunk(chunk);
chunk_set_occupancy_mask_at(chunk, lx, ly, lz, .FREE);
} @Command
@ -661,7 +633,7 @@ editor_edit_y :: () -> float {
}
tick_level_editor :: () {
#if FLAG_TACOMA_ENABLED { rdm_bake_tick(); sh_bake_tick(); }
#if FLAG_TACOMA_ENABLED { probe_bake_tick(); }
tick_level_editor_camera();
tick_particles(cast(float)delta_time);
@ -790,7 +762,7 @@ tick_level_editor :: () {
}
}
create_level_editor_preview_tasks :: () {
draw_level_editor_preview :: (view: View_Id) {
curworld := get_current_world();
if !curworld.valid then return;
@ -802,20 +774,8 @@ create_level_editor_preview_tasks :: () {
if current_tool_mode == .INSPECTOR {
name, orientation, found := get_trile_at(*curworld.world, xx px, xx py, xx pz);
cursor_trile := ifx found then name else (ifx editor_current_trile then editor_current_trile.name else "");
if cursor_trile != "" {
ck := world_to_chunk_coord(xx px, xx py, xx pz);
lx, ly, lz := world_to_local(xx px, xx py, xx pz);
positions: [..]Trile_Instance;
positions.allocator = temp;
array_add(*positions, Trile_Instance.{lx, ly, lz, xx orientation});
task: Rendering_Task_Trile;
task.trile = cursor_trile;
task.positions = positions;
task.worldConf = *curworld.world.conf;
task.preview_mode = 1;
task.chunk_key = ck;
add_rendering_task(task);
}
mesh, ok := get_trile_mesh(cursor_trile);
if ok draw_trile(view, mesh, .{xx px, xx py, xx pz}, orientation, .ADD_PREVIEW);
return;
}
@ -880,37 +840,10 @@ create_level_editor_preview_tasks :: () {
is_delete := (current_tool_mode == .AREA && area_active && area_delete)
|| (current_tool_mode == .LINE && line_active && line_delete);
chunk_groups: [..] struct { key: Chunk_Key; instances: [..]Trile_Instance; };
chunk_groups.allocator = temp;
for pos : positions {
wx := cast(s32) pos.x; wy := cast(s32) pos.y; wz := cast(s32) pos.z;
ck := world_to_chunk_coord(wx, wy, wz);
lx, ly, lz := world_to_local(wx, wy, wz);
found := false;
for *grp : chunk_groups {
if grp.key == ck {
array_add(*grp.instances, Trile_Instance.{lx, ly, lz, ori_u8});
found = true;
break;
}
}
if !found {
instances: [..]Trile_Instance;
instances.allocator = temp;
array_add(*instances, Trile_Instance.{lx, ly, lz, ori_u8});
array_add(*chunk_groups, .{ck, instances});
}
}
for grp : chunk_groups {
task: Rendering_Task_Trile;
task.trile = editor_current_trile.name;
task.positions = grp.instances;
task.worldConf = *curworld.world.conf;
task.chunk_key = grp.key;
task.preview_mode = ifx is_delete then cast(s32)2 else cast(s32)1;
add_rendering_task(task);
}
mesh, ok := get_trile_mesh(editor_current_trile.name);
if !ok then return;
tint := ifx is_delete then Trile_Tint.DELETE_PREVIEW else .ADD_PREVIEW;
for positions draw_trile(view, mesh, it.xyz, ori_u8, tint);
}
get_trile_at :: (world: *World, wx: s32, wy: s32, wz: s32) -> (name: string, orientation: u8, found: bool) {
@ -958,36 +891,6 @@ draw_inspector_panel :: (r: *GR.Rect, theme: *GR.Overall_Theme) {
if has_trile {
GR.label(r.*, tprint("Trile: % orient: %", trile_name, orientation), *t_label_left(theme));
r.y += r.h;
r.h = ui_h(3, 2);
GR.label(r.*, "-- RDM --", *t_label_left(theme));
r.y += r.h;
r.h = ui_h(4, 0);
rdm_on := is_rdm_instance_enabled(world, inspector_x, inspector_y, inspector_z);
label := ifx rdm_on then "RDM: ON (sharp specular)" else "RDM: OFF (sky reflection)";
if GR.button(r.*, label, *theme.button_theme, 300) {
set_rdm_instance_enabled(world, inspector_x, inspector_y, inspector_z, !rdm_on);
}
r.y += r.h;
if rdm_on {
cur_size := get_rdm_instance_size(world, inspector_x, inspector_y, inspector_z);
tile_w := 2 * cur_size;
tile_h := 3 * cur_size;
size_label := tprint("Size: % (% x % px)", cur_size, tile_w, tile_h);
GR.label(r.*, size_label, *t_label_left(theme));
r.y += r.h;
r2 := r.*;
r2.w = r.w / 2;
if GR.button(r2, "- size", *theme.button_theme, 304) {
set_rdm_instance_size(world, inspector_x, inspector_y, inspector_z, rdm_cycle_size(cur_size, -1));
}
r2.x += r2.w;
if GR.button(r2, "+ size", *theme.button_theme, 305) {
set_rdm_instance_size(world, inspector_x, inspector_y, inspector_z, rdm_cycle_size(cur_size, +1));
}
r.y += r.h;
}
} else {
GR.label(r.*, "Trile: (empty)", *t_label_left(theme));
r.y += r.h;
@ -1081,60 +984,6 @@ draw_inspector_panel :: (r: *GR.Rect, theme: *GR.Overall_Theme) {
r.y += r.h;
}
r.h = ui_h(3, 2);
r.y += r.h * 0.5;
GR.label(r.*, "-- RDM --", *t_label_left(theme));
r.y += r.h;
rdm_flagged := is_rdm_instance_enabled(world, inspector_x, inspector_y, inspector_z);
if rdm_flagged {
GR.label(r.*, "RDM: flagged", *t_label_left(theme));
r.y += r.h;
rect, has_rect := rdm_get_atlas_rect(world, inspector_x, inspector_y, inspector_z);
if has_rect {
GR.label(r.*, tprint("Rect: %.2,%.2 %.2x%.2", rect.x, rect.y, rect.z, rect.w), *t_label_left(theme));
r.y += r.h;
r.y += r.h * 0.5;
tex_size := r.w * 0.9;
tex_r : GR.Rect;
tex_r.x = r.x + (r.w - tex_size) * 0.5;
tex_r.y = r.y;
tex_r.w = tex_size;
tex_r.h = tex_size * 1.5;
fy0 := 1.0 - rect.y;
fy1 := 1.0 - (rect.y + rect.w);
uv0 := Vector2.{rect.x, fy0};
uv1 := Vector2.{rect.x + rect.z, fy0};
uv2 := Vector2.{rect.x + rect.z, fy1};
uv3 := Vector2.{rect.x, fy1};
uiTex := New(Ui_Texture,, temp);
uiTex.tex = g_rdm_atlas;
if uiTex.tex.id != INVALID_ID {
set_shader_for_images(uiTex);
immediate_quad(
.{tex_r.x, tex_r.y},
.{tex_r.x + tex_r.w, tex_r.y},
.{tex_r.x + tex_r.w, tex_r.y + tex_r.h},
.{tex_r.x, tex_r.y + tex_r.h},
.{1,1,1,1},
uv0, uv1, uv2, uv3
);
set_shader_for_color();
immediate_flush();
}
r.y += tex_r.h + r.h * 0.5;
} else {
GR.label(r.*, "RDM: not yet baked", *t_label_left(theme));
r.y += r.h;
}
} else {
GR.label(r.*, "RDM: not flagged", *t_label_left(theme));
r.y += r.h;
}
}
draw_entity_tool_panel :: (r: *GR.Rect, theme: *GR.Overall_Theme) {
@ -1245,7 +1094,7 @@ entity_autoedit :: (rect: GR.Rect, e: *Entity, theme: *GR.Overall_Theme) {
#insert #run,stallable gen_entity_dispatch("autoedit(rect, cast(*%)e, theme, 400)");
}
add_editor_billboards :: () {
draw_editor_billboards :: (view: View_Id) {
if !editor_billboards_visible then return;
curworld := get_current_world();
if !curworld.valid then return;
@ -1255,45 +1104,32 @@ add_editor_billboards :: () {
for e: curworld.world.entities {
marker := entity_marker_animation(e);
if marker == null then continue;
task : Rendering_Task_Billboard;
task.position = e.position + ENTITY_PIVOT;
task.animation = marker;
task.frame = 0;
add_rendering_task(task);
draw_animation_frame(view, marker, 0, e.position + ENTITY_PIVOT);
}
anim := get_animation_from_string("game_core.ball");
if anim == null then return;
for inst: curworld.world.emitter_instances {
task : Rendering_Task_Billboard;
task.position = inst.position;
task.animation = anim;
task.frame = 0;
add_rendering_task(task);
draw_animation_frame(view, anim, 0, inst.position);
}
for note: curworld.world.notes {
task : Rendering_Task_Billboard;
task.position = .{cast(float)note.position.x + 0.5, cast(float)note.position.y + 0.5, cast(float)note.position.z + 0.5};
task.animation = anim;
task.frame = 0;
add_rendering_task(task);
draw_animation_frame(view, anim, 0, .{cast(float)note.position.x + 0.5, cast(float)note.position.y + 0.5, cast(float)note.position.z + 0.5});
}
}
draw_level_editor :: () {
curworld := get_current_world();
if !curworld.valid then return;
cam := get_level_editor_camera();
ph := effective_plane_height(*curworld.world.conf);
create_set_cam_rendering_task(cam, ph);
create_world_rendering_tasks(*curworld.world, cam, ph);
add_entity_render_tasks(*curworld.world);
camera := get_level_editor_camera();
view := add_view(.{camera = camera, environment = world_environment(*curworld.world), cut = true, focus = camera.target});
draw_entities(view, *curworld.world);
draw_live_particles(view);
if show_trile_preview && !trile_preview_disabled {
create_level_editor_preview_tasks();
draw_level_editor_preview(view);
}
add_editor_billboards();
draw_editor_billboards(view);
debug_grid(floor(cameraCenter.x), editor_edit_y(), floor(cameraCenter.y), 20, .{0.3, 0.3, 0.35, 0.7});
}

View File

@ -0,0 +1,126 @@
#scope_file
ms_selected : u8;
ms_scroll : float;
ms_name_input : string;
#scope_export
draw_material_studio_ui :: (theme: *GR.Overall_Theme) {
panel := GR.get_rect(0, ui_h(5,0), ui_w(20, 20), ui_h(95, 0));
ui_add_mouse_occluder(panel);
draw_bg_rectangle(panel, theme);
row_h := ui_h(4, 0);
r := panel;
r.h = row_h;
if GR.button(r, "New material", *theme.button_theme) {
id, ok := swatch_add("new", u8.[255, 255, 255]);
if ok {
ms_selected = id;
ms_name_input = copy_string(g_swatches[id].name);
}
}
r.y += row_h;
// .hex palettes in a pack, one RRGGBB per line.
for g_palettes {
if GR.button(r, tprint("Import % (% colours)", it.name, it.entries.count), *theme.button_theme, it_index) {
log_info("Imported % new materials from %", swatch_import_palette(it), it.name);
}
r.y += row_h;
}
grid := r;
grid.h = ui_h(25, 0);
previous := ms_selected;
region, inside := GR.begin_scrollable_region(grid, *theme.scrollable_region_theme);
end_y := draw_swatch_grid(inside, *ms_scroll, *ms_selected, theme);
GR.end_scrollable_region(region, inside.x + inside.w, end_y, *ms_scroll);
if ms_selected != previous ms_name_input = copy_string(g_swatches[ms_selected].name);
r.y += grid.h + row_h * 0.5;
if ms_selected == 0 || !g_swatches[ms_selected].used return;
swatch := *g_swatches[ms_selected];
GR.label(r, tprint("Material %", ms_selected), *t_label_left(theme));
r.y += row_h;
a, new_text := GR.text_input(r, ms_name_input, *theme.text_input_theme, 128);
if a & .ENTERED {
ms_name_input = copy_string(new_text);
swatch.name = copy_string(new_text);
}
r.y += row_h;
r.h = ui_h(3, 2);
GR.label(r, "Reflectivity", *t_label_left(theme));
r.y += r.h;
GR.slider(r, *swatch.reflectivity, 0, 255, 1, *theme.slider_theme);
r.y += r.h;
GR.label(r, "Gloss", *t_label_left(theme));
r.y += r.h;
GR.slider(r, *swatch.gloss, 0, 255, 1, *theme.slider_theme);
r.y += r.h;
GR.label(r, "Emittance", *t_label_left(theme));
r.y += r.h;
GR.slider(r, *swatch.emittance, 0, 127, 1, *theme.slider_theme);
r.y += r.h;
if GR.base_checkbox(r, "Glass (lets sunlight through)", swatch.glass, *theme.checkbox_theme) swatch.glass = !swatch.glass;
r.y += r.h * 2;
// The colour gets its own panel on the right, so the picker has room.
color_panel := GR.get_rect(100*vw - panel.w, panel.y, panel.w, ui_h(45, 0));
ui_add_mouse_occluder(color_panel);
draw_bg_rectangle(color_panel, theme);
picker := color_panel;
picker.h = ui_h(40, 0);
color := swatch_color(ms_selected);
GR.color_picker(picker, *color, *theme.color_picker_theme);
for 0..2 swatch.color[it] = cast(u8) clamp(color.component[it] * 255 + 0.5, 0, 255);
picker.y += picker.h;
picker.h = row_h;
GR.label(picker, tprint("#%", hex_color(swatch.color)), *t_label_left(theme));
used_panel := GR.get_rect(color_panel.x, color_panel.y + color_panel.h, color_panel.w, ui_h(45, 0));
ui_add_mouse_occluder(used_panel);
draw_bg_rectangle(used_panel, theme);
line := used_panel;
line.h = row_h;
GR.label(line, "Used by", *t_label_left(theme));
line.y += row_h;
for trile: get_trile_table_ptr() {
count := trile_swatch_counts(*trile)[ms_selected];
if count == 0 continue;
GR.label(line, tprint("% (%)", trile.name, count), *t_label_left(theme));
line.y += row_h;
}
swatch_changed(ms_selected);
r.h = row_h;
if GR.button(r, "Save", *theme.button_theme) {
striles();
for trile: get_trile_table_ptr() update_trile_thumbnail(trile.name);
}
r.y += row_h;
if swatch_in_use(ms_selected) {
GR.label(r, "In use, can't delete", *t_label_left(theme));
} else if GR.button(r, "Delete", *theme.button_theme) {
swatch.* = .{};
swatch_changed(ms_selected);
ms_selected = 0;
}
}
#scope_file
hex_color :: (c: [3]u8) -> string {
digits :: "0123456789abcdef";
out := talloc_string(6);
for 0..2 {
out[it * 2] = digits[c[it] >> 4];
out[it * 2 + 1] = digits[c[it] & 0xf];
}
return out;
}

View File

@ -151,6 +151,7 @@ draw_particle_editor_ui :: (theme: *GR.Overall_Theme) {
pe_vec4(*er, "Color Start", *def.color_start, 0, 1, theme);
pe_vec4(*er, "Color End", *def.color_end, 0, 1, theme);
pe_float(*er, tprint("Gravity: %", def.gravity), *def.gravity, -20, 20, 0.1, theme);
pe_float(*er, tprint("Glow: %", def.glow), *def.glow, 0, 1, 0.05, theme);
pe_label(*er, tprint("Blend Mode: %", def.blend_mode), theme);
orig_w2 := er.w;
@ -184,7 +185,8 @@ draw_particle_editor_ui :: (theme: *GR.Overall_Theme) {
}
draw_particle_editor :: () {
create_set_cam_rendering_task(pe_cam, 0.0);
view := add_view(.{camera = pe_cam, environment = New(Environment,, temp), draw_world = false});
draw_live_particles(view);
if pe_selected_index >= 0 && pe_selected_index < cast(s32)g_emitter_defs.count {
def := *g_emitter_defs[pe_selected_index];

View File

@ -59,7 +59,7 @@ draw_trile_picker :: (r_in: GR.Rect, theme: *GR.Overall_Theme) {
btn_theme.frame_color_down = .{0, 0, 0, 0};
btn_theme.frame_color_flash = .{0, 0, 0, 0};
atlas_valid := g_thumbnail_atlas.tex.id != INVALID_ID;
atlas_valid := g_thumbnail_atlas.tex.id != 0;
region, inside := GR.begin_scrollable_region(r, *theme.scrollable_region_theme);

View File

@ -1,48 +0,0 @@
// RDM disk format helpers shared by the baking tool (tacoma) and the
// sfetch-based streaming loader (rdm_loader.jai).
RDM_File_Header :: struct {
magic: u32;
width: s32;
height: s32;
}
RDM_FILE_MAGIC :: u32.[0x4D445254][0]; // "TRDM" as little-endian u32
rdm_global_atlas_filename :: (world_name: string) -> string {
return sprint("%/worlds/%/rdm_atlas.rdm", GAME_RESOURCES_DIR, world_name);
}
rdm_global_manifest_filename :: (world_name: string) -> string {
return sprint("%/worlds/%/rdm_manifest.json", GAME_RESOURCES_DIR, world_name);
}
// SH probe grid (1 probe per trile per axis = 32x32x32 per 32x32x32 chunk)
SH_FILE_MAGIC :: u32.[0x44475348][0]; // "SHGD" as little-endian u32
SH_PROBE_N :: 32; // probes per axis (1 per trile in a 32-trile chunk)
SH_TEX_W :: SH_PROBE_N * 3; // 96 — 3 RGBA texels per probe along X
SH_Grid_File_Header :: struct {
magic: u32;
version: u16;
probe_n: s32;
}
shgrid_filename :: (world_name: string, chunk_key: Chunk_Key) -> string {
return sprint("%/worlds/%/%_%_%.shgrid", GAME_RESOURCES_DIR, world_name, chunk_key.x, chunk_key.y, chunk_key.z);
}
f32_to_f16 :: (f: float) -> u16 {
b := (cast(*u32) *f).*;
sign := (b >> 31) & 0x1;
exp := cast(s32)((b >> 23) & 0xFF) - 127;
mant := b & 0x7FFFFF;
if exp >= 16 return cast(u16)((sign << 15) | 0x7C00); // clamp to inf
if exp >= -14 return cast(u16)((sign << 15) | (cast(u32)(exp + 15) << 10) | (mant >> 13));
if exp >= -24 {
shift := cast(u32)(-exp - 1);
return cast(u16)((sign << 15) | ((mant | 0x800000) >> shift));
}
return cast(u16)(sign << 15); // underflow → ±0
}

View File

@ -1,35 +0,0 @@
test_f32_to_f16 :: () {
s := begin_suite("f32_to_f16");
check(*s, "0.0 → 0x0000", f32_to_f16(0.0) == 0x0000);
check(*s, "-0.0 → 0x8000", f32_to_f16(-0.0) == 0x8000);
check(*s, "1.0 → 0x3C00", f32_to_f16(1.0) == 0x3C00);
check(*s, "-1.0 → 0xBC00", f32_to_f16(-1.0) == 0xBC00);
check(*s, "0.5 → 0x3800", f32_to_f16(0.5) == 0x3800);
check(*s, "2.0 → 0x4000", f32_to_f16(2.0) == 0x4000);
check(*s, "1.5 → 0x3E00", f32_to_f16(1.5) == 0x3E00);
// Max normal f16 = 65504
check(*s, "65504.0 → 0x7BFF", f32_to_f16(65504.0) == 0x7BFF);
// Min normal f16 = 2^-14
check(*s, "2^-14 → 0x0400", f32_to_f16(cast(float)(1.0 / 16384.0)) == 0x0400);
// Overflow clamps to infinity
check(*s, "65536.0 → 0x7C00 (inf)", f32_to_f16(65536.0) == 0x7C00);
check(*s, "1e10 → 0x7C00 (inf)", f32_to_f16(1.0e10) == 0x7C00);
check(*s, "-65536.0 → 0xFC00 (-inf)", f32_to_f16(-65536.0) == 0xFC00);
// Denormals: 2^-15 is the largest f16 denormal base
check(*s, "2^-15 → 0x0200", f32_to_f16(cast(float)(1.0 / 32768.0)) == 0x0200);
// Smallest representable f16 denormal = 2^-24
check(*s, "2^-24 → 0x0001", f32_to_f16(cast(float)(1.0 / 16777216.0)) == 0x0001);
// Underflow to zero
check(*s, "2^-25 → 0x0000", f32_to_f16(cast(float)(1.0 / 33554432.0)) == 0x0000);
check(*s, "-2^-25 → 0x8000", f32_to_f16(cast(float)(-1.0 / 33554432.0)) == 0x8000);
end_suite(s);
}
#run test_f32_to_f16();

View File

@ -5,346 +5,86 @@
Tacoma :: #import "Tacoma";
Tacoma_Screenshot :: struct {
image : sg_image;
width : s32;
height : s32;
valid : bool = false;
}
current_screenshot : Tacoma_Screenshot;
// Single global atlas entry: stored on the World once baked.
RDM_Atlas_Entry_Bake :: struct {
world_pos: Vector3;
x, y: s32; // top-left in atlas pixels
w, h: s32; // pixel size of this RDM (= 2*size, 3*size)
}
RDM_ATLAS_MAX_SIZE :: 16384; // GPU 2D texture ceiling.
ctx : *Tacoma.Tacoma_Context;
RDM_Bake_Job :: struct {
world_trile_index: s32;
world_pos: Vector3;
size: s32; // per-instance RDM side in px (tile = 2*size x 3*size).
tacoma_preview : struct {
texture : Texture;
width : s32;
height : s32;
}
RDM_Global_Bake :: struct {
data : *float; // CPU atlas buffer (RGBA32F during bake)
width : s32;
height : s32;
cursor_x : s32;
cursor_y : s32;
row_height : s32;
entries : [..]RDM_Atlas_Entry_Bake;
// Light given off by a fully emissive swatch, relative to full sun on a white face.
bake_emissive_light : float = 10.0;
// Probes where more of the rays than this hit the back of a face are inside geometry.
PROBE_INSIDE_BACKFACES :: 0.25;
Probe_Bake :: struct {
active : bool;
quality : s32;
world_name : string;
keys : [..]Chunk_Key;
results : [..]*float; // from Tacoma, one per baked key
}
RDM_Bake_State :: struct {
active : bool = false;
quality : s32 = 100;
jobs : [..]RDM_Bake_Job;
current_job : s32 = 0;
atlas : RDM_Global_Bake;
}
probe_bake : Probe_Bake;
rdm_bake : RDM_Bake_State;
bake_probes :: (quality: s32 = 100) {
if probe_bake.active return;
curworld := get_current_world();
if !curworld.valid { log_warn("bake_probes: no world loaded"); return; }
SH_Bake_State :: struct {
active : bool;
quality : s32;
include_water : bool;
chunk_keys : [..]Chunk_Key;
current_chunk : s32;
}
for _, key: curworld.world.chunks array_add(*probe_bake.keys, key);
if !probe_bake.keys.count return;
sh_bake : SH_Bake_State;
tacoma_init_scene(*curworld.world);
probe_bake.active = true;
probe_bake.quality = quality;
probe_bake.world_name = copy_string(curworld.world.name);
} @Command
rdm_job_quality :: (job: RDM_Bake_Job) -> s32 {
return rdm_bake.quality;
}
rdm_sort_jobs_by_height_desc :: (jobs: *[..]RDM_Bake_Job) {
n := jobs.count;
for i: 1..n-1 {
key := jobs.data[i];
j := i - 1;
while j >= 0 && jobs.data[j].size < key.size {
jobs.data[j + 1] = jobs.data[j];
j -= 1;
}
jobs.data[j + 1] = key;
// Bakes one chunk per call.
probe_bake_tick :: () {
if !probe_bake.active return;
curworld := get_current_world();
if !curworld.valid || curworld.world.name != probe_bake.world_name {
log_warn("Probe bake cancelled: the world changed");
probe_bake_end();
return;
}
}
// Simulate shelf pack of the current jobs array into a square atlas of `atlas_size`.
// Returns true if all fit. Assumes jobs are already sorted by tile height descending.
rdm_simulate_shelf_pack :: (jobs: []RDM_Bake_Job, atlas_size: s32) -> bool {
cursor_x : s32 = 0;
cursor_y : s32 = 0;
row_h : s32 = 0;
for job: jobs {
w := 2 * job.size;
h := 3 * job.size;
if w > atlas_size || h > atlas_size return false;
if cursor_x + w > atlas_size {
cursor_y += row_h;
cursor_x = 0;
row_h = 0;
}
if cursor_y + h > atlas_size return false;
cursor_x += w;
if h > row_h then row_h = h;
}
return true;
}
// Choose min pow2 square atlas fitting all jobs (variable tile sizes). Caps at RDM_ATLAS_MAX_SIZE.
rdm_calc_global_atlas_size :: (jobs: []RDM_Bake_Job) -> (s32, s32) {
if jobs.count == 0 return 16, 16;
target : s32 = 16;
while target < RDM_ATLAS_MAX_SIZE {
if rdm_simulate_shelf_pack(jobs, target) return target, target;
target *= 2;
}
if !rdm_simulate_shelf_pack(jobs, RDM_ATLAS_MAX_SIZE) {
log_warn("RDM atlas cap reached (%); some instances may not fit.", RDM_ATLAS_MAX_SIZE);
}
return RDM_ATLAS_MAX_SIZE, RDM_ATLAS_MAX_SIZE;
}
// Build the Tacoma scene from the world and emit one bake job per RDM-flagged instance.
// chunk_keys is accepted for API compatibility but ignored — bakes always cover every flagged
// instance because the global atlas + manifest is rewritten as a whole.
rdm_bake_start :: (world: World, quality: s32, include_water: bool, chunk_keys: []Chunk_Key = .[]) {
if rdm_bake.active then return;
trile_list : [..]Tacoma.Trile_Data;
trile_list.allocator = temp;
world_triles : [..]Tacoma.World_Trile;
world_triles.allocator = temp;
trile_name_to_index: Table(string, s32);
trile_name_to_index.allocator = temp;
for chunk: world.chunks {
for group: chunk.groups {
success, idx := table_find(*trile_name_to_index, group.trile_name);
if !success {
trile, trile_ok := get_trile(group.trile_name);
if !trile_ok continue;
ttrile : Tacoma.Trile_Data;
for x: 0..15 {
for y: 0..15 {
for z: 0..15 {
ttrile.trixels[x][y][z] = .{
trile.trixels[x][y][z].empty,
trile.trixels[x][y][z].material.color,
material_encode_to_float(trile.trixels[x][y][z].material)
};
}
}
}
gfx := get_trile_gfx(group.trile_name);
ttrile.vertices = gfx.vertices.data;
ttrile.vertexCount = cast(s32) (gfx.vertices.count / 3);
idx = cast(s32) trile_list.count;
array_add(*trile_list, ttrile);
table_set(*trile_name_to_index, group.trile_name, idx);
}
for inst: group.instances {
world_trile_idx := cast(s32) world_triles.count;
wx, wy, wz := chunk_local_to_world(chunk.coord, inst.x, inst.y, inst.z);
wpos := Vector3.{cast(float) wx, cast(float) wy, cast(float) wz};
array_add(*world_triles, Tacoma.World_Trile.{idx, wpos, cast(s32) inst.orientation});
inst_size := get_rdm_instance_size(*world, wx, wy, wz);
if inst_size > 0 {
array_add(*rdm_bake.jobs, .{
world_trile_index = world_trile_idx,
world_pos = wpos,
size = inst_size,
});
}
}
}
}
sky : Tacoma.Sky_Config = world_to_sky_config(world);
blases : Tacoma.Trile_Set = .{trile_list.data, cast(s32) trile_list.count};
tlas : Tacoma.World = .{world_triles.data, cast(s32) world_triles.count};
ctx = Tacoma.tacoma_init("./modules/Tacoma/");
Tacoma.tacoma_load_scene(ctx, sky, blases, tlas, cast(s32) include_water);
// Sort jobs tallest-first for a tighter shelf pack.
rdm_sort_jobs_by_height_desc(*rdm_bake.jobs);
// Allocate global CPU atlas large enough for all jobs.
aw, ah := rdm_calc_global_atlas_size(rdm_bake.jobs);
atlas_bytes := cast(s64) aw * cast(s64) ah * 4 * size_of(float);
rdm_bake.atlas.width = aw;
rdm_bake.atlas.height = ah;
rdm_bake.atlas.data = cast(*float) alloc(atlas_bytes);
memset(rdm_bake.atlas.data, 0, atlas_bytes);
log_info("RDM global atlas: %x% (% MB) for % jobs",
aw, ah, cast(float)atlas_bytes / (1024.0 * 1024.0), rdm_bake.jobs.count);
rdm_bake.active = true;
rdm_bake.quality = quality;
if rdm_bake.jobs.count == 0 {
rdm_bake_finish();
}
}
// Queue all RDM-flagged instances. (chunk_keys parameter is ignored — see rdm_bake_start.)
rdm_bake_all_chunks :: (world: World, quality: s32, include_water: bool) {
rdm_bake_start(world, quality, include_water);
}
rdm_bake_chunks :: (chunk_keys: []Chunk_Key, world: World, quality: s32, include_water: bool) {
rdm_bake_start(world, quality, include_water, chunk_keys);
}
// Process at most one RDM per frame.
rdm_bake_tick :: () {
if !rdm_bake.active then return;
if rdm_bake.current_job >= cast(s32) rdm_bake.jobs.count {
rdm_bake_finish();
if probe_bake.results.count == probe_bake.keys.count {
probe_bake_finish();
return;
}
job := rdm_bake.jobs[rdm_bake.current_job];
key := probe_bake.keys[probe_bake.results.count];
x, y, z := chunk_local_to_world(key, 0, 0, 0);
data := Tacoma.tacoma_render_sh_chunk(ctx, xx x, xx y, xx z, CHUNK_SIZE, 1.0, probe_bake.quality);
array_add(*probe_bake.results, data);
log_info("Baked probes for chunk % (%/%)", key, probe_bake.results.count, probe_bake.keys.count);
}
size : s32 = job.size;
w := 2 * size;
h := 3 * size;
ptr := Tacoma.tacoma_render_rdm(ctx, job.world_trile_index, 0, rdm_job_quality(job), size);
gen_reference :: (w: s32, h: s32, eye: Vector3, target: Vector3, quality: s32, world: *World) {
tacoma_init_scene(world);
data := Tacoma.tacoma_render_reference(ctx, w, h, eye, target, 0.01, quality);
tacoma_stop();
bake := *rdm_bake.atlas;
if bake.cursor_x + w > bake.width {
bake.cursor_y += bake.row_height;
bake.cursor_x = 0;
bake.row_height = 0;
pixels := NewArray(w * h * 4, u8,, temp);
for i: 0..w * h - 1 {
for c: 0..2 pixels[i * 4 + c] = xx (clamp(data[i * 4 + c], 0, 1) * 255 + 0.5);
pixels[i * 4 + 3] = 255;
}
Tacoma.tacoma_free_result(data);
ax := bake.cursor_x;
ay := bake.cursor_y;
if ay + h <= bake.height {
src := cast(*u8) ptr;
row_bytes := cast(s64) w * 4 * size_of(float);
for row: 0..h-1 {
dst_offset := (cast(s64)(ay + row) * cast(s64) bake.width + cast(s64) ax) * 4 * size_of(float);
src_offset := cast(s64) row * row_bytes;
memcpy(cast(*u8) bake.data + dst_offset, src + src_offset, row_bytes);
}
entry : RDM_Atlas_Entry_Bake;
entry.world_pos = job.world_pos;
entry.x = ax;
entry.y = ay;
entry.w = w;
entry.h = h;
array_add(*bake.entries, entry);
} else {
log_warn("RDM global atlas overflow, skipping (pos=%)", job.world_pos);
}
bake.cursor_x += w;
if h > bake.row_height then bake.row_height = h;
tacoma_handle_result(ptr, w, h);
rdm_bake.current_job += 1;
if tacoma_preview.texture.id texture_destroy(tacoma_preview.texture);
tacoma_preview.texture = texture_create(w, h, pixels);
tacoma_preview.width = w;
tacoma_preview.height = h;
}
rdm_bake_finish :: () {
if ctx != null then tacoma_stop();
#scope_file
curworld := get_current_world();
bake := *rdm_bake.atlas;
if bake.entries.count > 0 {
// a) Pack atlas into RGBA16F half-floats and upload to g_rdm_atlas.
upload_global_atlas_image(bake);
// b) Populate world.rdm_lookup with normalized UV rects.
if curworld.valid {
array_reset_keeping_memory(*curworld.world.rdm_lookup);
atlas_w := cast(float) bake.width;
atlas_h := cast(float) bake.height;
for entry: bake.entries {
e : Rdm_Atlas_Entry;
e.x = cast(s32) entry.world_pos.x;
e.y = cast(s32) entry.world_pos.y;
e.z = cast(s32) entry.world_pos.z;
e.atlas_rect = .{
cast(float) entry.x / atlas_w,
cast(float) entry.y / atlas_h,
cast(float) entry.w / atlas_w,
cast(float) entry.h / atlas_h,
};
array_add(*curworld.world.rdm_lookup, e);
}
}
// c) Save atlas + manifest to disk.
rdm_save_global_atlas_to_disk(bake);
if curworld.valid then rdm_save_global_manifest_to_disk(curworld.world.name, curworld.world.rdm_lookup);
}
log_info("RDM bake complete: % entries", bake.entries.count);
if bake.data != null then free(bake.data);
array_free(bake.entries);
array_free(rdm_bake.jobs);
rdm_bake = .{};
}
// Convert RGBA32F CPU atlas to RGBA16F and upload to g_rdm_atlas.
upload_global_atlas_image :: (bake: *RDM_Global_Bake) {
pixel_count := cast(s64) bake.width * cast(s64) bake.height * 4;
halves := cast(*u16) alloc(pixel_count * size_of(u16));
defer free(halves);
for i: 0..pixel_count - 1 halves[i] = f32_to_f16(bake.data[i]);
imgdata : sg_image_data;
imgdata.subimage[0][0] = .{halves, cast(u64)(pixel_count * size_of(u16))};
desc : sg_image_desc = .{
render_target = false,
width = bake.width,
height = bake.height,
pixel_format = sg_pixel_format.RGBA16F,
sample_count = 1,
data = imgdata,
};
if g_rdm_atlas.id != 0 then sg_destroy_image(g_rdm_atlas);
g_rdm_atlas = sg_make_image(*desc);
}
bake_sky_scale : float = 1.0;
bake_sky_desaturation : float = 1.0;
world_to_sky_config :: (world: World) -> Tacoma.Sky_Config {
sky : Tacoma.Sky_Config;
sky.skyBase = world.conf.skyBase;
sky.skyTop = world.conf.skyTop;
sky.sunDisk = world.conf.sunDisk;
sky.horizonHalo = world.conf.horizonHalo;
sky.sunHalo = world.conf.sunHalo;
sky.sunLightColor = world.conf.sunLightColor;
sky.sunPosition = world.conf.sunPosition;
sky.sunIntensity = world.conf.sunIntensity;
sky.skyIntensity = world.conf.skyIntensity * bake_sky_scale;
sky.skyDesaturation = bake_sky_desaturation;
return sky;
}
// Build trile BLASes + world TLAS from a world, then initialize ctx.
tacoma_init_scene :: (world: World, include_water: bool) {
tacoma_init_scene :: (world: *World) {
trile_list : [..]Tacoma.Trile_Data; trile_list.allocator = temp;
world_triles : [..]Tacoma.World_Trile; world_triles.allocator = temp;
trile_name_to_index : Table(string, s32); trile_name_to_index.allocator = temp;
@ -355,230 +95,136 @@ tacoma_init_scene :: (world: World, include_water: bool) {
if !success {
trile, trile_ok := get_trile(group.trile_name);
if !trile_ok continue;
vertices, indices := mesh_trile(trile);
positions := NewArray(indices.count * 3, float,, temp);
for indices for c: 0..2 positions[it_index * 3 + c] = vertices[it].position.component[c];
ttrile : Tacoma.Trile_Data;
for x: 0..15 for y: 0..15 for z: 0..15 {
ttrile.trixels[x][y][z] = .{
trile.trixels[x][y][z].empty,
trile.trixels[x][y][z].material.color,
material_encode_to_float(trile.trixels[x][y][z].material)
};
}
gfx := get_trile_gfx(group.trile_name);
ttrile.vertices = gfx.vertices.data;
ttrile.vertexCount = cast(s32)(gfx.vertices.count / 3);
ttrile.trixels = trile.trixels;
ttrile.vertices = positions.data;
ttrile.vertexCount = xx indices.count;
idx = cast(s32) trile_list.count;
array_add(*trile_list, ttrile);
table_set(*trile_name_to_index, group.trile_name, idx);
}
for inst: group.instances {
wx, wy, wz := chunk_local_to_world(chunk.coord, inst.x, inst.y, inst.z);
array_add(*world_triles, Tacoma.World_Trile.{idx,
Vector3.{cast(float) wx, cast(float) wy, cast(float) wz},
cast(s32) inst.orientation});
array_add(*world_triles, Tacoma.World_Trile.{idx, .{xx wx, xx wy, xx wz}, xx inst.orientation});
}
}
}
sky : Tacoma.Sky_Config = world_to_sky_config(world);
blases : Tacoma.Trile_Set = .{trile_list.data, cast(s32) trile_list.count};
tlas : Tacoma.World = .{world_triles.data, cast(s32) world_triles.count};
swatches : [Tacoma.SWATCH_COUNT]Tacoma.Swatch;
for g_swatches {
if !it.used continue;
color := swatch_color(xx it_index);
emission := color * (min(cast(int) it.emittance, 127) / 127.0) * bake_emissive_light;
swatches[it_index] = .{color, emission, xx it.glass};
}
env := world_environment(world);
sky : Tacoma.Sky_Config;
sky.skyBase = env.sky_base;
sky.skyTop = env.sky_top;
sky.sunDisk = env.sun_disk;
sky.horizonHalo = env.horizon_halo;
sky.sunHalo = env.sun_halo;
sky.sunLightColor = env.sun_color;
sky.sunPosition = env.sun_direction;
sky.sunIntensity = 1;
sky.skyIntensity = ifx env.sky then env.sky_intensity else 0;
blases : Tacoma.Trile_Set = .{trile_list.data, xx trile_list.count};
tlas : Tacoma.World = .{world_triles.data, xx world_triles.count};
ctx = Tacoma.tacoma_init("./modules/Tacoma/");
Tacoma.tacoma_load_scene(ctx, sky, blases, tlas, cast(s32) include_water);
Tacoma.tacoma_load_scene(ctx, sky, swatches.data, blases, tlas, xx env.water);
}
tacoma_stop :: () {
Tacoma.tacoma_destroy(ctx);
ctx = null;
}
tacoma_handle_result :: (ptr: *float, w: s32, h: s32) {
data := cast(*float) talloc(w*h*4*size_of(float));
memcpy(data, ptr, w*h*4*4);
for 0..(w*h) {
color : Vector3;
color.x = data[it * 4 + 0];
color.y = data[it * 4 + 1];
color.z = data[it * 4 + 2];
data[it * 4 + 0] = color.x;
data[it * 4 + 1] = color.y;
data[it * 4 + 2] = color.z;
}
imgdata : sg_image_data;
imgdata.subimage[0][0] = .{data, cast(u64) (w*h*4*4)};
texdesc : sg_image_desc = .{
render_target = false,
width = w,
height = h,
pixel_format = sg_pixel_format.RGBA32F,
sample_count = 1,
data = imgdata
};
if current_screenshot.valid {
sg_destroy_image(current_screenshot.image);
}
current_screenshot = .{
sg_make_image(*texdesc),
w,
h,
true
};
Tacoma.tacoma_free_result(ptr);
}
gen_reference :: (w: s32, h: s32, eye: Vector3, target: Vector3, quality: s32, include_water: bool, world: World) {
tacoma_init_scene(world, include_water);
ptr := Tacoma.tacoma_render_reference(ctx, w, h, eye, target, 0.01, quality);
tacoma_handle_result(ptr, w, h);
probe_bake_finish :: () {
tacoma_stop();
chunks := probes_from_bake(probe_bake.keys, probe_bake.results);
for chunks world_set_chunk_probes(it.key, it.probes);
file :: #import "File";
path := tprint("%/worlds/%/probes.bin", GAME_RESOURCES_DIR, probe_bake.world_name);
if file.write_entire_file(path, save_probes(chunks)) log_info("Probe bake complete, saved %", path);
else log_error("Probe bake complete, but writing % failed", path);
for chunks array_free(it.probes);
probe_bake_end();
}
sh_bake_start :: (quality: s32 = 50, include_water: bool = false) {
if sh_bake.active then return;
curworld := get_current_world();
if !curworld.valid { log_warn("sh_bake_start: no world loaded"); return; }
probe_bake_end :: () {
if ctx tacoma_stop();
for probe_bake.results Tacoma.tacoma_free_result(it);
array_free(probe_bake.results);
array_free(probe_bake.keys);
free(probe_bake.world_name);
probe_bake = .{};
}
world := *curworld.world;
for _, key: world.chunks array_add(*sh_bake.chunk_keys, key);
// Marks probes inside geometry, and evens out bake noise by averaging each probe
// with its face neighbours, across chunk borders. Probes inside geometry take no part.
probes_from_bake :: (keys: []Chunk_Key, results: []*float) -> []Probe_Chunk {
N :: CHUNK_SIZE;
baked : Table(Chunk_Key, *float, chunk_key_hash, chunk_key_compare);
baked.allocator = temp;
for keys table_set(*baked, it, results[it_index]);
if sh_bake.chunk_keys.count == 0 then return;
tacoma_init_scene(world.*, include_water);
sh_bake.active = true;
sh_bake.quality = quality;
sh_bake.include_water = include_water;
sh_bake.current_chunk = 0;
} @Command
sh_bake_tick :: () {
if !sh_bake.active then return;
if sh_bake.current_chunk >= cast(s32) sh_bake.chunk_keys.count {
sh_bake_finish();
return;
Baked :: type_of(baked);
baked_probe :: (baked: *Baked, x: s32, y: s32, z: s32) -> *float {
found, data := table_find(baked, world_to_chunk_coord(x, y, z));
if !found return null;
lx, ly, lz := world_to_local(x, y, z);
p := data + (cast(s64) lx + cast(s64) ly * N + cast(s64) lz * N * N) * Tacoma.PROBE_FLOATS;
if p[12] > PROBE_INSIDE_BACKFACES return null;
return p;
}
curworld := get_current_world();
if !curworld.valid { sh_bake_finish(); return; }
NEIGHBOURS :: s32.[1, 0, 0, -1, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 1, 0, 0, -1];
n :: SH_PROBE_N;
tex_w :: SH_TEX_W;
chunk_key := sh_bake.chunk_keys[sh_bake.current_chunk];
chunk := table_find_pointer(*curworld.world.chunks, chunk_key);
sh_bake.current_chunk += 1;
if chunk == null then return;
ox, oy, oz := chunk_local_to_world(chunk_key, 0, 0, 0);
SH_PAD :: 2.0;
SH_SPACING :: (32.0 + 2.0 * SH_PAD) / n;
ptr := Tacoma.tacoma_render_sh_chunk(ctx,
cast(float) ox - SH_PAD, cast(float) oy - SH_PAD, cast(float) oz - SH_PAD,
n, SH_SPACING, sh_bake.quality);
tex_halfs :: tex_w * n * n * 4;
packed : *u16 = cast(*u16) alloc(tex_halfs * size_of(u16));
defer free(packed);
src := ptr;
for pz: 0..n-1 for py: 0..n-1 for px: 0..n-1 {
probe_idx := px + py * n + pz * n * n;
s := src + probe_idx * 12;
for k: 0..2 {
tex_idx := (pz * n + py) * tex_w + (px * 3 + k);
d := packed + tex_idx * 4;
for ch: 0..3 {
(d + ch).* = f32_to_f16((s + k * 4 + ch).*);
chunks := NewArray(keys.count, Probe_Chunk,, temp);
for key, chunk_index: keys {
probes := NewArray(PROBES_PER_CHUNK, Probe);
for z: 0..N-1 for y: 0..N-1 for x: 0..N-1 {
probe := *probes[x + y * N + z * N * N];
wx, wy, wz := chunk_local_to_world(key, xx x, xx y, xx z);
centre := baked_probe(*baked, wx, wy, wz);
if !centre {
probe.sh[0] = half_from_float(-1);
continue;
}
sum : [12]float;
for 0..11 sum[it] = centre[it];
count := 1;
for n: 0..5 {
other := baked_probe(*baked, wx + NEIGHBOURS[n * 3], wy + NEIGHBOURS[n * 3 + 1], wz + NEIGHBOURS[n * 3 + 2]);
if !other continue;
for 0..11 sum[it] += other[it];
count += 1;
}
for 0..11 probe.sh[it] = half_from_float(sum[it] / count);
}
chunks[chunk_index] = .{key, probes};
}
tex_byte_size := cast(u64)(tex_halfs * size_of(u16));
imgdata : sg_image_data;
imgdata.subimage[0][0] = .{packed, tex_byte_size};
sh_desc : sg_image_desc = .{
width = tex_w,
height = n * n,
pixel_format = sg_pixel_format.RGBA16F,
sample_count = 1,
data = imgdata,
};
if chunk.sh_valid sg_destroy_image(chunk.sh_probe_grid);
chunk.sh_probe_grid = sg_make_image(*sh_desc);
chunk.sh_valid = true;
chunk.sh_dirty = false;
#if OS != .WASM {
shgrid_save_to_disk(curworld.world.name, chunk_key, ptr, n);
}
Tacoma.tacoma_free_result(ptr);
log_info("SH baked chunk % (%/%)", chunk_key, sh_bake.current_chunk, sh_bake.chunk_keys.count);
return chunks;
}
sh_bake_finish :: () {
tacoma_stop();
array_free(sh_bake.chunk_keys);
sh_bake = .{};
log_info("SH bake complete.");
half_from_float :: (f: float) -> u16 {
bits := (cast(*u32) *f).*;
sign := cast(u16) ((bits >> 16) & 0x8000);
exponent := cast(s32) ((bits >> 23) & 0xFF) - 127 + 15;
mantissa := bits & 0x7FFFFF;
if exponent <= 0 return sign;
if exponent >= 31 return sign | 0x7BFF;
half := sign | cast(u16) (exponent << 10) | cast(u16) (mantissa >> 13);
if mantissa & 0x1000 half += 1;
return half;
}
shgrid_save_to_disk :: (world_name: string, chunk_key: Chunk_Key, data: *float, probe_n: s32) {
#if OS != .WASM {
file :: #import "File";
path := shgrid_filename(world_name, chunk_key);
builder : String_Builder;
header := SH_Grid_File_Header.{
magic = SH_FILE_MAGIC,
version = 2,
probe_n = probe_n,
};
write_bytes(*builder, *header, size_of(SH_Grid_File_Header));
total_values := cast(s64) probe_n * probe_n * probe_n * 12;
halves := NewArray(total_values, u16,, temp);
for i: 0..total_values-1 halves[i] = f32_to_f16(data[i]);
write_bytes(*builder, halves.data, total_values * size_of(u16));
file.write_entire_file(path, builder_to_string(*builder));
}
}
rdm_save_global_atlas_to_disk :: (bake: *RDM_Global_Bake) {
#if OS != .WASM {
file :: #import "File";
curworld := get_current_world();
if !curworld.valid then return;
path := rdm_global_atlas_filename(curworld.world.name);
builder : String_Builder;
header := RDM_File_Header.{
magic = RDM_FILE_MAGIC,
width = bake.width,
height = bake.height,
};
write_bytes(*builder, *header, size_of(RDM_File_Header));
// Convert RGBA32F → RGBA16F for the on-disk atlas.
pixel_count := cast(s64) bake.width * cast(s64) bake.height * 4;
halves := NewArray(pixel_count, u16,, temp);
for i: 0..pixel_count - 1 halves[i] = f32_to_f16(bake.data[i]);
write_bytes(*builder, halves.data, pixel_count * size_of(u16));
file.write_entire_file(path, builder_to_string(*builder));
log_info("Saved RDM global atlas: %", path);
}
}
rdm_save_global_manifest_to_disk :: (world_name: string, entries: []Rdm_Atlas_Entry) {
#if OS != .WASM {
file :: #import "File";
path := rdm_global_manifest_filename(world_name);
s := Jaison.json_write_string(entries);
file.write_entire_file(path, s);
log_info("Saved RDM manifest: % (% entries)", path, entries.count);
}
}

View File

@ -1,145 +0,0 @@
#scope_file
subwindow : GR.Subwindow_Info;
subwindow_initted : bool = false;
pp_subwindow : GR.Subwindow_Info;
pp_subwindow_initted : bool = false;
lighting_subwindow : GR.Subwindow_Info;
lighting_subwindow_initted : bool = false;
// @Hack: This is probably kinda a bad idea, I don't really know atm how else to get the theme into the subwindow.
theme_ptr : GR.Overall_Theme;
current_pipeline : s32 = 0;
current_slot : s32 = 0;
pipeline_names : []string = .["shadowmap", "reflection", "main", "position", "normal", "ssao", "bloom", "dof", "rdm_atlas"];
draw_subwindow_texture_debug :: (state: *GR.Subwindow_State, r: GR.Rect, data: *void) {
r2 := r;
r2.h = ui_h(5,0);
r2.w = r.w;
GR.dropdown(r2, pipeline_names, *current_pipeline, *theme_ptr.dropdown_theme);
r2.y = r.y + r2.h;
r2.h = r.h - r2.h;
r2.x = r.x;
r2.w = r.w;
uiTex := New(Ui_Texture ,,temp);
image : sg_image;
if current_pipeline == {
case 0; image = g_shadowmap_img;
case 1; image = gPipelines.plane.bind.images[0];
case 2; image = g_rendertex;
case 3; image = g_gbuf_position;
case 4; image = g_gbuf_normal;
case 5; image = g_ssaobuf;
case 6; image = g_bloom_up_1;
case 7; image = g_dof_tex;
case 8; image = g_rdm_atlas;
}
uiTex.tex = image;
if uiTex.tex.id != INVALID_ID {
set_shader_for_images(uiTex);
immediate_quad(.{r2.x, r2.y}, .{r2.x + r2.w, r2.y}, .{r2.x + r2.w, r2.y + r2.h}, .{r2.x, r2.y + r2.h});
set_shader_for_color();
}
immediate_flush();
}
draw_subwindow_lighting :: (state: *GR.Subwindow_State, r: GR.Rect, data: *void) {
ui_add_mouse_occluder(r);
autoedit(r, *current_lighting_config, *theme_ptr);
}
draw_subwindow_post_process :: (state: *GR.Subwindow_State, r: GR.Rect, data: *void) {
r2 := r;
ui_add_mouse_occluder(r);
r3 := r;
r3.h = ui_h(5,0);
r2.h -= r3.h;
r2.y += r3.h;
if GR.button(r3, "Save postprocessing", *theme_ptr.button_theme) {
#if OS != .WASM {
file :: #import "File";
save_post_process();
}
}
r3.y += r3.h;
r2.h -= r3.h;
r2.y += r3.h;
GR.dropdown(r3, LUT_name_list, *g_current_lut_texture_index, *theme_ptr.dropdown_theme);
autoedit(r2, *current_post_process, *theme_ptr);
}
#scope_export
draw_texture_debug :: () {
}
toggle_texdebug :: () {
subwindow.open = !subwindow.open;
} @Command
toggle_pp :: () {
pp_subwindow.open = !pp_subwindow.open;
} @Command
toggle_lighting :: () {
lighting_subwindow.open = !lighting_subwindow.open;
} @Command
draw_postprocess_popup :: (theme: *GR.Overall_Theme) {
if !pp_subwindow.open then return;
if !pp_subwindow_initted {
theme_ptr = theme;
r := GR.get_rect(ui_w(40, 0), ui_w(40, 0), ui_h(50,0), ui_h(50,0));
pp_subwindow.rect = r;
pp_subwindow.draw = draw_subwindow_post_process;
pp_subwindow.title_text = "Post Process";
pp_subwindow.open = false;
pp_subwindow_initted = true;
}
if pp_subwindow.open { // The Subwindow starts open, but pressing the Close button can close it.
pp_subwindow_state := GR.add_subwindow(*pp_subwindow, *theme.subwindow_theme);
}
}
draw_lighting_popup :: (theme: *GR.Overall_Theme) {
if !lighting_subwindow.open then return;
if !lighting_subwindow_initted {
theme_ptr = theme;
r := GR.get_rect(ui_w(55, 0), ui_w(40, 0), ui_h(50,0), ui_h(40,0));
lighting_subwindow.rect = r;
lighting_subwindow.draw = draw_subwindow_lighting;
lighting_subwindow.title_text = "Lighting";
lighting_subwindow.open = false;
lighting_subwindow_initted = true;
}
if lighting_subwindow.open {
GR.add_subwindow(*lighting_subwindow, *theme.subwindow_theme);
}
}
draw_texture_debugger :: (theme: *GR.Overall_Theme) {
if !subwindow.open then return;
if !subwindow_initted {
theme_ptr = theme;
r := GR.get_rect(ui_w(40, 0), ui_w(40, 0), ui_h(50,0), ui_h(50,0));
subwindow.rect = r;
subwindow.draw = draw_subwindow_texture_debug;
subwindow.title_text = "Texture Debugger";
subwindow.open = false;
subwindow_initted = true;
}
if subwindow.open { // The Subwindow starts open, but pressing the Close button can close it.
subwindow_state := GR.add_subwindow(*subwindow, *theme.subwindow_theme);
}
}

View File

@ -5,10 +5,6 @@ zoom : float = 3.0;
brush_radius : int = 5;
roughness : u8 = 0;
metallic : u8 = 0;
emittance : u8 = 0;
hovered_trixel_x : int = -1;
hovered_trixel_y : int = -1;
hovered_trixel_z : int = -1;
@ -27,6 +23,7 @@ Trile_Editor_Tool :: enum {
PAINT;
ADD;
REMOVE;
PICK; // takes the clicked trixel's material
}
Trile_Editor_Tool_Mode :: enum {
@ -39,7 +36,6 @@ current_tab : Trile_Editor_Tab = .TOOLSET;
current_tool : Trile_Editor_Tool = .PAINT;
current_mode : Trile_Editor_Tool_Mode = .AREA;
colorMuls : [16][16][16]Vector3;
tiling_preview_active : bool;
tiling_axis : s32 = 0; // 0=+X, 1=+Z, 2=-X, 3=-Z
tiling_orientation : s32 = 0; // 0-23 = face(0..5)*4 + twist(0..3)
@ -47,10 +43,10 @@ tiling_neighbor_trile_name : string;
tiling_neighbor_trile_input : string;
UNDO_MAX :: 32;
undo_trixels : [UNDO_MAX][16][16][16] Trixel;
undo_trixels : [UNDO_MAX][16][16][16]u8;
undo_count : int = 0;
undo_head : int = 0;
redo_trixels : [UNDO_MAX][16][16][16] Trixel;
redo_trixels : [UNDO_MAX][16][16][16]u8;
redo_count : int = 0;
redo_head : int = 0;
@ -59,16 +55,19 @@ meta_name_input : string;
#scope_export
ntrile :: (name: string) {
set_trile_gfx(editor_current_trile.name, generate_trile_gfx_matias(editor_current_trile));
trile_changed(editor_current_trile);
newt : Trile;
newt.name = sprint("%", name);
swatch := current_swatch;
if !g_swatches[swatch].used swatch = first_used_swatch();
trile_fill(*newt, swatch);
set_trile(newt.name, newt);
editor_current_trile = get_trile(newt.name);
trile_gen_heightmap(editor_current_trile);
} @Command
cpytrile :: (trile: string, destination: string) {
set_trile_gfx(editor_current_trile.name, generate_trile_gfx_matias(editor_current_trile));
trile_changed(editor_current_trile);
newt : Trile;
newt.name = sprint("%", destination);
newt.trixels = get_trile(trile).trixels;
@ -78,7 +77,7 @@ cpytrile :: (trile: string, destination: string) {
} @Command
ltrile :: (name: string) {
set_trile_gfx(editor_current_trile.name, generate_trile_gfx_matias(editor_current_trile));
trile_changed(editor_current_trile);
nt := get_trile(name);
if !nt {
console_add_output_line("Failed to load a trile with that name...");
@ -108,6 +107,7 @@ do_undo :: () {
undo_count -= 1;
editor_current_trile.trixels = undo_trixels[undo_head];
trile_gen_heightmap(editor_current_trile);
trile_changed(editor_current_trile);
}
do_redo :: () {
@ -119,20 +119,15 @@ do_redo :: () {
redo_count -= 1;
editor_current_trile.trixels = redo_trixels[redo_head];
trile_gen_heightmap(editor_current_trile);
trile_changed(editor_current_trile);
}
apply_tool_to_trixel :: (x: s64, y: s64, z: s64) {
if current_tool == .PAINT {
editor_current_trile.trixels[x][y][z].material.color = current_color;
editor_current_trile.trixels[x][y][z].material.metallic = metallic;
editor_current_trile.trixels[x][y][z].material.roughness = roughness;
editor_current_trile.trixels[x][y][z].material.emittance = emittance;
}
if current_tool == .ADD {
editor_current_trile.trixels[x][y][z].empty = false;
}
if current_tool == .REMOVE {
editor_current_trile.trixels[x][y][z].empty = true;
trixel := *editor_current_trile.trixels[x][y][z];
if current_tool == {
case .PAINT; if trixel.* != 0 trixel.* = current_swatch;
case .ADD; if trixel.* == 0 trixel.* = current_swatch;
case .REMOVE; trixel.* = 0;
}
}
@ -143,6 +138,10 @@ area_active : bool;
handle_tool_click :: () {
if hovered_trixel_x < 0 && hovered_trixel_y < 0 && hovered_trixel_z < 0 then return;
if current_tool == .PICK {
current_swatch = editor_current_trile.trixels[hovered_trixel_x][hovered_trixel_y][hovered_trixel_z];
return;
}
if current_mode == .POINT {
push_undo();
if current_tool == .ADD {
@ -197,13 +196,13 @@ handle_tool_click :: () {
#scope_export
current_color : Vector3 = .{1.0, 0.0, 0.0};
current_swatch : u8 = 1;
reset_trile :: () {
for x: 0..15 {
for y: 0..15 {
for z: 0..15 {
editor_current_trile.trixels[x][y][z].empty = false;
editor_current_trile.trixels[x][y][z] = current_swatch;
}
}
}
@ -229,6 +228,7 @@ tick_trile_editor :: () {
if input_button_states[Key_Code.MOUSE_BUTTON_LEFT] & .START {
handle_tool_click();
trile_changed(editor_current_trile);
}
mindist : float = 999999;
@ -239,8 +239,7 @@ tick_trile_editor :: () {
for x: 0..15 {
for y: 0..15 {
for z: 0..15 {
t := editor_current_trile.trixels[x][y][z];
if t.empty then continue;
if editor_current_trile.trixels[x][y][z] == 0 then continue;
cube : Collision_Cube;
cube.position = Vector3.{cast(float) x, cast(float) y, cast(float) z} * TRIXEL_SIZE;
@ -259,25 +258,18 @@ tick_trile_editor :: () {
}
}
for x: 0..15 {
for y: 0..15 {
for z: 0..15 {
highlighted := false;
if hovered_trixel_x >= 0 {
if current_mode == .BRUSH {
center : Vector3 = .{xx hovered_trixel_x, xx hovered_trixel_y, xx hovered_trixel_z};
highlighted = length(Vector3.{xx x, xx y, xx z} - center) <= xx brush_radius;
} else if current_mode == .AREA && area_active {
highlighted = x >= min(area_start_x, hovered_trixel_x) && x <= max(area_start_x, hovered_trixel_x)
&& y >= min(area_start_y, hovered_trixel_y) && y <= max(area_start_y, hovered_trixel_y)
&& z >= min(area_start_z, hovered_trixel_z) && z <= max(area_start_z, hovered_trixel_z);
} else {
highlighted = x == hovered_trixel_x && y == hovered_trixel_y && z == hovered_trixel_z;
}
}
colorMuls[x][y][z] = ifx highlighted then Vector3.{0.6, 0.0, 0.0} else .{1.0, 1.0, 1.0};
}
if hovered_trixel_x >= 0 {
lo := Vector3.{xx hovered_trixel_x, xx hovered_trixel_y, xx hovered_trixel_z};
hi := lo;
if current_mode == .BRUSH {
lo -= Vector3.{1, 1, 1} * cast(float) brush_radius;
hi += Vector3.{1, 1, 1} * cast(float) brush_radius;
} else if current_mode == .AREA && area_active {
corner := Vector3.{xx area_start_x, xx area_start_y, xx area_start_z};
lo = min(lo, corner);
hi = max(hi, corner);
}
debug_aabb_3d_overlay(lo * TRIXEL_SIZE, (hi + Vector3.{1, 1, 1}) * TRIXEL_SIZE, .{0.9, 0.1, 0.1, 1});
}
if !input_button_states[Key_Code.CTRL] & .DOWN {
@ -324,10 +316,7 @@ get_trile_editor_camera :: () -> Camera {
return camera;
}
global_palette_scroll : float = 0.0;
trile_palette_scroll : float = 0.0;
use_color_picker : bool = false;
selected_palette : s32 = 0;
swatch_scroll : float = 0.0;
draw_tool_tab :: (theme: *GR.Overall_Theme, area: GR.Rect) {
r := area;
@ -337,7 +326,9 @@ draw_tool_tab :: (theme: *GR.Overall_Theme, area: GR.Rect) {
if keybind_button(r, "Add", .TRIXEL_TOOL_ADD, *t_button_selectable(theme, current_tool == .ADD)) then current_tool = .ADD;
r.y += r.h;
if keybind_button(r, "Remove", .TRIXEL_TOOL_REMOVE, *t_button_selectable(theme, current_tool == .REMOVE)) then current_tool = .REMOVE;
r.y += r.h * 3;
r.y += r.h;
if keybind_button(r, "Pick material", .TRIXEL_TOOL_PICK, *t_button_selectable(theme, current_tool == .PICK)) then current_tool = .PICK;
r.y += r.h * 2;
if keybind_button(r, "Point", .TRIXEL_MODE_POINT, *t_button_selectable(theme, current_mode == .POINT)) then current_mode = .POINT;
r.y += r.h;
if keybind_button(r, "Area", .TRIXEL_MODE_AREA, *t_button_selectable(theme, current_mode == .AREA)) then current_mode = .AREA;
@ -348,126 +339,60 @@ draw_tool_tab :: (theme: *GR.Overall_Theme, area: GR.Rect) {
GR.slider(r, *brush_radius, 0, 12, 1, *theme.slider_theme);
r.y += r.h * 2;
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));
trile_changed(editor_current_trile);
striles();
update_trile_thumbnail(editor_current_trile.name);
};
}
draw_swatches :: (entries: []Palette_Entry, inside: GR.Rect, block: float, scroll: *float, id_offset: s32, theme: *GR.Overall_Theme) -> (end_y: float) {
cols := max(1, cast(int)(inside.w / block));
for entry, idx: entries {
er : GR.Rect;
er.x = inside.x + (idx % cols) * block;
er.y = inside.y - scroll.* + (idx / cols) * block;
er.w = block; er.h = block;
btn := theme.button_theme;
btn.surface_color = .{entry.r, entry.g, entry.b, 1.0};
if GR.button(er, "", *btn, id_offset + cast(s32)idx) {
current_color = .{entry.r, entry.g, entry.b};
roughness = xx entry.roughness;
metallic = xx entry.metallic;
emittance = xx entry.emittance;
}
}
rows := ifx entries.count > 0 then (entries.count + cols - 1) / cols else 0;
return inside.y + rows * block;
}
draw_material_tab :: (theme: *GR.Overall_Theme, area: GR.Rect) {
r := area;
row_h := ui_h(4, 0);
block := ui_h(3, 2);
bottom := area.y + area.h;
sliders_h := ui_h(18, 0);
row_h := ui_h(3, 2);
r := area;
r.h = row_h;
half := r.w / 2;
r.w = half;
if GR.button(r, "Palette", *t_button_selectable(theme, !use_color_picker)) then use_color_picker = false;
r.x += half;
if GR.button(r, "Color Picker", *t_button_selectable(theme, use_color_picker)) then use_color_picker = true;
r.x = area.x; r.w = area.w;
GR.label(r, tprint("Selected %", swatch_label(current_swatch)), *t_label_left(theme));
r.y += row_h;
available := bottom - r.y - sliders_h;
top_h := ifx use_color_picker then ui_h(42, 0) else available / 2;
bot_h := available - top_h;
r.h = top_h;
if use_color_picker {
GR.color_picker(r, *current_color, *theme.color_picker_theme);
} else {
if g_palettes.count > 1 {
r.h = row_h;
pal_w := r.w / cast(float)g_palettes.count;
for pal, idx: g_palettes {
pr := r;
pr.x = area.x + idx * pal_w;
pr.w = pal_w;
if GR.button(pr, pal.name, *t_button_selectable(theme, cast(s32)idx == selected_palette), cast(s32)idx + 20000) {
selected_palette = cast(s32)idx;
global_palette_scroll = 0;
}
}
r.y += row_h;
top_h -= row_h;
r.h = top_h;
}
entries : []Palette_Entry;
if g_palettes.count > 0 {
selected_palette = clamp(selected_palette, 0, cast(s32)g_palettes.count - 1);
entries = g_palettes[selected_palette].entries;
}
region, inside := GR.begin_scrollable_region(r, *theme.scrollable_region_theme);
end_y := draw_swatches(entries, inside, block, *global_palette_scroll, 0, theme);
GR.end_scrollable_region(region, inside.x + inside.w, end_y, *global_palette_scroll);
hovered := "-";
if editor_current_trile && hovered_trixel_x >= 0 {
hovered = swatch_label(editor_current_trile.trixels[hovered_trixel_x][hovered_trixel_y][hovered_trixel_z]);
}
r.y += top_h;
GR.label(r, tprint("Hovered %", hovered), *t_label_left(theme));
r.y += row_h * 1.5;
unique_mats : [..]Material;
unique_mats.allocator = temp;
for x: 0..15 for y: 0..15 for z: 0..15 {
trix := editor_current_trile.trixels[x][y][z];
if trix.empty then continue;
mr, mg, mb, ma := material_to_rgba(trix.material);
key := (cast(u32)mr << 24) | (cast(u32)mg << 16) | (cast(u32)mb << 8) | cast(u32)ma;
already := false;
for um: unique_mats {
ur, ug, ub, ua := material_to_rgba(um);
if ((cast(u32)ur << 24) | (cast(u32)ug << 16) | (cast(u32)ub << 8) | cast(u32)ua) == key { already = true; break; }
}
if !already array_add(*unique_mats, trix.material);
grid := r;
grid.h = ui_h(30, 0);
region, inside := GR.begin_scrollable_region(grid, *theme.scrollable_region_theme);
end_y := draw_swatch_grid(inside, *swatch_scroll, *current_swatch, theme);
GR.end_scrollable_region(region, inside.x + inside.w, end_y, *swatch_scroll);
r.y += grid.h + row_h * 0.5;
if !editor_current_trile return;
GR.label(r, "In this trile (click to select)", *t_label_left(theme));
r.y += row_h;
counts := trile_swatch_counts(editor_current_trile);
for count, id: counts {
if count == 0 continue;
btn := t_button_selectable(theme, current_swatch == id);
if GR.button(r, tprint("% (%)", swatch_label(xx id), count), *btn, 1000 + id) current_swatch = xx id;
r.y += row_h;
}
as_entries : [..]Palette_Entry;
as_entries.allocator = temp;
for mat: unique_mats {
e : Palette_Entry;
e.r = mat.color.x; e.g = mat.color.y; e.b = mat.color.z;
e.roughness = mat.roughness; e.metallic = mat.metallic; e.emittance = mat.emittance;
array_add(*as_entries, e);
}
r.h = bot_h * 0.75;
region2, inside2 := GR.begin_scrollable_region(r, *theme.scrollable_region_theme);
end_y2 := draw_swatches(as_entries, inside2, block, *trile_palette_scroll, 10000, theme);
GR.end_scrollable_region(region2, inside2.x + inside2.w, end_y2, *trile_palette_scroll);
r.y += bot_h * 0.75;
r.h = ui_h(3, 2);
GR.label(r, "Roughness", *t_label_left(theme));
r.y += r.h;
GR.slider(r, *roughness, 0, 7, 1, *theme.slider_theme);
r.y += r.h;
GR.label(r, "Metallic", *t_label_left(theme));
r.y += r.h;
GR.slider(r, *metallic, 0, 3, 1, *theme.slider_theme);
r.y += r.h;
GR.label(r, "Emittance", *t_label_left(theme));
r.y += r.h;
GR.slider(r, *emittance, 0, 127, 1, *theme.slider_theme);
}
// Shared with the material studio. Returns the bottom of the grid.
draw_swatch_grid :: (inside: GR.Rect, scroll: *float, selected: *u8, theme: *GR.Overall_Theme) -> float {
block := ui_h(3, 2);
cols := max(1, cast(int)(inside.w / block));
n := 0;
for g_swatches {
if !it.used continue;
r := GR.Rect.{inside.x + (n % cols) * block, inside.y - scroll.* + (n / cols) * block, block, block};
btn := t_button_selectable(theme, selected.* == it_index);
c := swatch_color(cast(u8) it_index);
btn.surface_color = .{c.x, c.y, c.z, 1};
if GR.button(r, "", *btn, cast(s32) it_index) selected.* = cast(u8) it_index;
n += 1;
}
return inside.y + ((n + cols - 1) / cols) * block;
}
TILING_AXIS_NAMES :: string.["+ X", "+ Z", "- X", "- Z", "+ Y", "- Y"];
@ -485,53 +410,6 @@ get_tiling_camera_target :: () -> Vector3 {
return Vector3.{0.5, 0.5, 0.5} + off * 0.5;
}
// Build rotation matrices matching the same GLSL convention used in shader_trile.glsl.
// In Jai row-major passed as GLSL column-major: GLSL out[i] = sum_j M_jai[j][i]*v[j].
tiling_rot_x :: (a: float) -> Matrix4 {
c := cos(a); s := sin(a);
m : Matrix4;
m._11 = 1;
m._22 = c; m._23 = s;
m._32 = -s; m._33 = c;
m._44 = 1;
return m;
}
tiling_rot_y :: (a: float) -> Matrix4 {
c := cos(a); s := sin(a);
m : Matrix4;
m._11 = c; m._13 = s;
m._22 = 1;
m._31 = -s; m._33 = c;
m._44 = 1;
return m;
}
tiling_rot_z :: (a: float) -> Matrix4 {
c := cos(a); s := sin(a);
m : Matrix4;
m._11 = c; m._21 = s;
m._12 = -s; m._22 = c;
m._33 = 1;
m._44 = 1;
return m;
}
// Matches get_orientation_matrix(ori) from shader_trile.glsl.
// Jai A*B applies A_eff first in GLSL, so twist*base = twist applied second = same as GLSL base*rot_y(twist).
make_orientation_matrix :: (ori: s32) -> Matrix4 {
face := ori / 4;
twist := ori % 4;
twist_mat : Matrix4;
identity(*twist_mat);
if twist > 0 twist_mat = tiling_rot_y(cast(float)twist * PI / 2.0);
base_mat : Matrix4;
if face == 0 { identity(*base_mat); }
else if face == 1 { base_mat = tiling_rot_x(PI); }
else if face == 2 { base_mat = tiling_rot_z(-PI * 0.5); }
else if face == 3 { base_mat = tiling_rot_z( PI * 0.5); }
else if face == 4 { base_mat = tiling_rot_x( PI * 0.5); }
else { base_mat = tiling_rot_x(-PI * 0.5); }
return twist_mat * base_mat;
}
get_tiling_neighbor_trile :: () -> *Trile {
if tiling_neighbor_trile_name.count > 0 {
t := get_trile(tiling_neighbor_trile_name);
@ -541,13 +419,17 @@ get_tiling_neighbor_trile :: () -> *Trile {
}
draw_trile_editor :: () {
create_set_cam_rendering_task(get_trile_editor_camera(), 0.0);
w := New(World,, temp);
create_sky_rendering_task(*w.conf);
create_trixel_rendering_task(editor_current_trile, *colorMuls);
// A trile is drawn in the light of the world it will sit in.
environment := New(Environment,, temp);
curworld := get_current_world();
if curworld.valid environment = world_environment(*curworld.world);
view := add_view(.{camera = get_trile_editor_camera(), environment = environment, draw_world = false});
mesh, ok := get_trile_mesh(editor_current_trile.name);
if ok draw_trile(view, mesh, .{}, 0);
if tiling_preview_active {
neighbor_trile := get_tiling_neighbor_trile();
create_trixel_rendering_task(neighbor_trile, null, world_offset = get_tiling_world_offset(), brightness = 0.75, tile_rotation = make_orientation_matrix(tiling_orientation), is_secondary = true);
neighbor, neighbor_ok := get_trile_mesh(get_tiling_neighbor_trile().name);
if neighbor_ok draw_trile(view, neighbor, get_tiling_world_offset(), xx tiling_orientation);
}
}
@ -590,6 +472,16 @@ draw_meta_tab :: (theme: *GR.Overall_Theme, area: GR.Rect) {
r.y += row_h;
changed = GR.base_checkbox(r, "Is stairs", editor_current_trile.is_stairs, *theme.checkbox_theme);
if changed editor_current_trile.is_stairs = !editor_current_trile.is_stairs;
r.y += row_h;
for cut: Trile_Cut.[.ROOF, .WALL] {
label := ifx cut == .ROOF then "Roof (hidden from below)" else "Wall (cut away toward camera)";
if GR.base_checkbox(r, label, editor_current_trile.cut == cut, *theme.checkbox_theme, xx cut) {
editor_current_trile.cut = ifx editor_current_trile.cut == cut then .NONE else cut;
trile_changed(editor_current_trile);
}
r.y += row_h;
}
r.y -= row_h;
r.y += row_h * 2;
r.h = row_h;
@ -643,7 +535,7 @@ draw_trile_editor_ui :: (theme: *GR.Overall_Theme) {
// View mode buttons — bottom center of the 3D viewport.
btn_w := 11.0 * vw;
btn_h := cast(float) ui_h(4, 0);
bar_w := btn_w * 5.0;
bar_w := btn_w * 3.0;
bar_x := 100.0 * vw / 2.0 - bar_w / 2.0;
bar_y := 100.0 * vh - btn_h - 1.5 * vh;
@ -653,14 +545,6 @@ 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 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 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 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 keybind_button(r2, "Mixed", .TRIXEL_VIEW_MIXED, *t_button_selectable(theme, trixel_view_mode == 3)) then trixel_view_mode = 3;
r2.x += btn_w;
if keybind_button(r2, "Tile", .TRIXEL_VIEW_TILE, *t_button_selectable(theme, tiling_preview_active)) {
tiling_preview_active = !tiling_preview_active;
}

View File

@ -65,9 +65,9 @@ render_thumbnail :: (trile: *Trile, out: *[THUMB_SIZE * THUMB_SIZE * 4] u8) {
for 0..199 {
if ix >= 0 && ix < 16 && iy >= 0 && iy < 16 && iz >= 0 && iz < 16 {
if !trile.trixels[ix][iy][iz].empty {
if trile.trixels[ix][iy][iz] != 0 {
hit = true;
hc = trile.trixels[ix][iy][iz].material.color;
hc = swatch_color(trile.trixels[ix][iy][iz]);
break;
}
}
@ -106,9 +106,7 @@ render_thumbnail :: (trile: *Trile, out: *[THUMB_SIZE * THUMB_SIZE * 4] u8) {
}
upload_atlas :: () {
imgdata : sg_image_data;
imgdata.subimage[0][0] = .{ g_thumbnail_atlas_buf.data, cast(u64)(ATLAS_SIZE * ATLAS_SIZE * 4) };
sg_update_image(g_thumbnail_atlas.tex, *imgdata);
texture_update(g_thumbnail_atlas.tex, g_thumbnail_atlas_buf);
}
#scope_export
@ -147,7 +145,7 @@ update_trile_thumbnail :: (name: string) {
render_thumbnail(trile, *thumb);
blit_slot(*thumb, slot);
if g_thumbnail_atlas.tex.id != INVALID_ID {
if g_thumbnail_atlas.tex.id != 0 {
upload_atlas();
}
}
@ -167,12 +165,5 @@ init_trile_thumbnails :: () {
blit_slot(*thumb, slot);
}
desc := sg_image_desc.{
width = xx ATLAS_SIZE,
height = xx ATLAS_SIZE,
pixel_format = .RGBA8,
usage = .DYNAMIC,
};
g_thumbnail_atlas.tex = sg_make_image(*desc);
upload_atlas();
g_thumbnail_atlas.tex = texture_create(xx ATLAS_SIZE, xx ATLAS_SIZE, g_thumbnail_atlas_buf);
}

View File

@ -11,13 +11,13 @@
// EDITOR_MARKER :: "pack.animation"; // optional, editor-only billboard
// } @Entity
// entity_tick :: (using foo: *Foo, dt: float) {} // optional
// entity_draw :: (foo: *Foo) {} // optional
// entity_draw :: (foo: *Foo, view: View_Id) {} // optional
//
// Fields of type float, s32, bool, string or Vector3 are editable and saved;
// @Slider / @Color notes pick the editor widget.
//
// Each frame the game calls tick_entities, then tick_entity_emitters, then
// add_entity_render_tasks. The level editor calls the last two only: it shows
// draw_entities. The level editor calls the last two only: it shows
// entities and their particles without running their game logic.
#scope_export
@ -131,7 +131,7 @@ free_all_entities :: (world: *World) {
// Concrete per-type overloads in game code take precedence over these.
entity_tick :: (e: *$T/Entity, dt: float) {}
entity_draw :: (e: *$T/Entity) { draw_entity_parts(e); }
entity_draw :: (e: *$T/Entity, view: View_Id) { draw_entity_parts(e, view); }
tick_entities :: (world: *World, dt: float) {
for e: world.entities entity_dispatch_tick(e, dt);
@ -141,8 +141,8 @@ entity_dispatch_tick :: (e: *Entity, dt: float) {
#insert #run,stallable gen_entity_dispatch("entity_tick(cast(*%)e, dt)");
}
entity_dispatch_draw :: (e: *Entity) {
#insert #run,stallable gen_entity_dispatch("entity_draw(cast(*%)e)");
entity_dispatch_draw :: (e: *Entity, view: View_Id) {
#insert #run,stallable gen_entity_dispatch("entity_draw(cast(*%)e, view)");
}
// Dispatches a call on the entity's concrete type. '%' in 'call' becomes the type
@ -182,56 +182,28 @@ tick_entity_emitters :: (world: *World, dt: float) {
}
}
// Once per frame, from the game and from the editor. Trile draws are batched per
// (trile, chunk) and flushed as TRILE_DYNAMIC tasks at the end.
add_entity_render_tasks :: (world: *World) {
array_reset_keeping_memory(*entity_trile_batches);
for e: world.entities entity_dispatch_draw(e);
for *batch: entity_trile_batches {
task : Rendering_Task_Trile_Dynamic;
task.trile = batch.trile;
task.positions = batch.positions;
task.chunk_key = batch.chunk_key;
task.worldConf = *world.conf;
add_rendering_task(task);
}
// Once per frame, from the game and from the editor.
draw_entities :: (view: View_Id, world: *World) {
for e: world.entities entity_dispatch_draw(e, view);
}
entity_draw_trile :: (e: *Entity, trile: string, offset: Vector3, orientation: u8 = 0) {
pos := entity_trile_point(e, offset);
ori := compose_orientations(e.orientation, orientation);
key := world_to_chunk_coord(cast(s32) floor(pos.x), cast(s32) floor(pos.y), cast(s32) floor(pos.z));
instance := Vector4.{pos.x, pos.y, pos.z, cast(float) ori};
for *batch: entity_trile_batches {
if batch.trile == trile && batch.chunk_key == key {
array_add(*batch.positions, instance);
return;
}
}
batch : Entity_Trile_Batch;
batch.trile = trile;
batch.chunk_key = key;
batch.positions.allocator = temp;
array_add(*batch.positions, instance);
array_add(*entity_trile_batches, batch);
entity_draw_trile :: (e: *Entity, view: View_Id, trile: string, offset: Vector3, orientation: u8 = 0) {
mesh, ok := get_trile_mesh(trile);
if !ok return;
draw_trile(view, mesh, entity_trile_point(e, offset), compose_orientations(e.orientation, orientation));
}
entity_draw_billboard :: (e: *Entity, animation: string, offset: Vector3, frame: s32 = 0) {
entity_draw_billboard :: (e: *Entity, view: View_Id, animation: string, offset: Vector3, frame: s32 = 0) {
anim := get_animation_from_string(animation);
if anim == null return;
task : Rendering_Task_Billboard;
task.position = entity_point(e, offset);
task.animation = anim;
task.frame = frame;
add_rendering_task(task);
draw_animation_frame(view, anim, frame, entity_point(e, offset));
}
draw_entity_parts :: (e: *Entity) {
draw_entity_parts :: (e: *Entity, view: View_Id) {
for part: get_entity_parts(e.type) {
if part.kind == {
case .TRILE; entity_draw_trile(e, part.trile, part.offset, part.orientation);
case .BILLBOARD; entity_draw_billboard(e, part.animation, part.offset);
case .TRILE; entity_draw_trile(e, view, part.trile, part.offset, part.orientation);
case .BILLBOARD; entity_draw_billboard(e, view, part.animation, part.offset);
case .EMITTER; // tick_entity_emitters handles these
}
}
@ -308,14 +280,6 @@ entity_saved_members :: (type: Type) -> []Type_Info_Struct_Member {
return result;
}
Entity_Trile_Batch :: struct {
trile : string;
chunk_key : Chunk_Key;
positions : [..]Vector4;
}
entity_trile_batches : [..]Entity_Trile_Batch;
#if FLAG_TEST_ENGINE {
// The two placement helpers use different pivots, and getting them the wrong
// way round only shows up as parts drifting off a rotated entity, so both are

88
src/foliage.jai Normal file
View File

@ -0,0 +1,88 @@
// Our foliage system. Cells on a 2D grid.
Foliage_Type :: enum u8 {
GRASS; // For stuff that you want to just paint and gets rendered a lot. Grass or hay.
TREE; // For when you want single placements of something. Trees or bushes.
}
Foliage_Frame_Mode :: enum u8 {
VARIANT; // The seed picks one frame and it stays there.
LOOP; // Plays the animation, with the seed offsetting the start.
}
Foliage_Def :: struct {
name : string;
type : Foliage_Type;
// What we render
animation_name : string;
frame_mode : Foliage_Frame_Mode;
density : float = 0.5; // Only does anything when foliage type is grass.
scale_min : float = 1;
scale_max : float = 1;
jitter : float = 0.4;
sway_intensity : float;
sway_speed : float = 1;
}
FOLIAGE_NONE :: 0;
// Chunks in the world contain a 2D grid of these.
Foliage_Cell :: struct {
id : u8; // FOLIAGE_NONE when empty.
y : u8; // Local y inside the chunk, so we don't draw grass on top of a bridge.
}
g_foliage_defs : [..]Foliage_Def;
get_foliage_def :: (name: string) -> *Foliage_Def {
for *def: g_foliage_defs {
if def.name == name then return def;
}
return null;
}
register_foliage_def :: (def: Foliage_Def) {
for *existing: g_foliage_defs {
if existing.name == def.name {
existing.* = def;
return;
}
}
array_add(*g_foliage_defs, def);
}
get_foliage_def_names :: () -> []string {
names : [..]string;
names.allocator = temp;
for def: g_foliage_defs {
array_add(*names, def.name);
}
return names;
}
load_foliage_defs_from_json :: (s: string) {
success, defs := Jaison.json_parse_string(s, [..]Foliage_Def,, temp);
if !success {
log_error("Failed to parse foliage definitions");
return;
}
array_reset(*g_foliage_defs);
for defs {
def := it;
def.name = sprint("%", it.name);
def.animation_name = sprint("%", it.animation_name);
array_add(*g_foliage_defs, def);
}
log_info("Loaded % foliage definitions from pack", g_foliage_defs.count);
}
save_foliage_defs :: () {
#if OS != .WASM {
file :: #import "File";
json := Jaison.json_write_string(g_foliage_defs, " ");
file.write_entire_file(tprint("%/game_core/foliage.json", GAME_RESOURCES_DIR), json);
log_info("Saved % foliage definitions", g_foliage_defs.count);
}
}

View File

@ -39,11 +39,9 @@ Editor_Action :: enum {
STUDIO_TRILE;
STUDIO_LEVEL;
STUDIO_MATERIAL;
STUDIO_SWATCHES;
STUDIO_FOLIAGE;
// Trile editor — view modes
TRIXEL_VIEW_LIT;
TRIXEL_VIEW_NORMALS;
TRIXEL_VIEW_ALBEDO;
TRIXEL_VIEW_MIXED;
TRIXEL_VIEW_TILE;
// Trile editor — tiling controls
TRIXEL_TILING_AXIS;
@ -51,6 +49,7 @@ Editor_Action :: enum {
// Trile editor — undo/redo
TRIXEL_UNDO;
TRIXEL_REDO;
TRIXEL_TOOL_PICK;
}
#scope_file;
@ -214,13 +213,12 @@ set_default_bindings :: () {
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");
set(.STUDIO_SWATCHES, cast(Key_Code) #char "4", ctrl = true);
set(.STUDIO_FOLIAGE, cast(Key_Code) #char "5", ctrl = true);
set(.TRIXEL_VIEW_TILE, cast(Key_Code) #char "9");
set(.TRIXEL_TILING_AXIS, cast(Key_Code) #char "Q");
set(.TRIXEL_TILING_ROTATE, cast(Key_Code) #char "R");
set(.TRIXEL_UNDO, cast(Key_Code) #char "Z", ctrl = true);
set(.TRIXEL_REDO, cast(Key_Code) #char "Y", ctrl = true);
set(.TRIXEL_TOOL_PICK, cast(Key_Code) #char "K");
}

View File

@ -35,7 +35,6 @@ FLAG_USE_TEST_GAME :: FLAG_TEST_ENGINE || FLAG_TEST_EXE_ENGINE;
#load "rendering/rendering.jai";
#load "input/hotkeys.jai";
#load "ui/ui.jai";
#load "editor/rdm_disk.jai";
#if !FLAG_RELEASE_BUILD { #load "editor/editor.jai"; }
#load "time.jai";
#load "events.jai";
@ -43,6 +42,7 @@ FLAG_USE_TEST_GAME :: FLAG_TEST_ENGINE || FLAG_TEST_EXE_ENGINE;
#load "ray.jai";
#load "profiling.jai";
#load "particles/particles.jai";
#load "foliage.jai";
#load "orientation.jai";
#load "entities.jai";
#load "world.jai";
@ -51,7 +51,6 @@ FLAG_USE_TEST_GAME :: FLAG_TEST_ENGINE || FLAG_TEST_EXE_ENGINE;
#load "assets/asset_manager.jai";
#load "settings_menu.jai";
#load "loading_screen.jai";
#load "ui/demo.jai";
#if FLAG_USE_TEST_GAME {
#load "../test_game/game.jai";
@ -68,11 +67,7 @@ V_MAJOR :: 0;
V_MINOR :: 7;
state: struct {
pass_action_clear : sg_pass_action;
pass_action_clear_gbuf : sg_pass_action;
pass_action : sg_pass_action;
dpi_scale : float;
fons : *FONScontext;
font_default : Ui_Font;
};
@ -102,15 +97,7 @@ round_pow2 :: (v: float) -> s32 {
debug_font : *Font;
init :: () {
sg_setup(*(sg_desc.{
environment = cast,force(sg_environment) sglue_environment(),
logger = .{ func = slog_func },
attachments_pool_size = 64,
buffer_pool_size = 1024,
}));
sgl_setup(*(sgl_desc_t.{
logger = .{ func = slog_func },
}));
scene_init();
sfetch_setup(*(sfetch_desc_t.{
max_requests = 128,
num_channels = 2,
@ -128,18 +115,7 @@ init :: () {
stm_setup();
state.dpi_scale = sapp_dpi_scale();
atlas_dim := round_pow2(1024.0 * state.dpi_scale);
fons_context := sfons_create(*(sfons_desc_t.{
width = atlas_dim,
height = atlas_dim,
}));
state.fons = fons_context;
state.font_default.fons_font = FONS_INVALID;
create_pipelines();
state.pass_action_clear.colors[0] = .{ load_action = .CLEAR, clear_value = .{ r = 0, g = 0, b = 0, a = 0 } };
state.pass_action_clear_gbuf.colors[0] = .{ load_action = .CLEAR, clear_value = .{ r = 0, g = 0, b = 1000, a = 0 } };
state.pass_action_clear_gbuf.colors[2] = .{ load_action = .CLEAR, clear_value = .{ r = 0, g = 0, b = 0, a = 0 } };
state.pass_action.colors[0] = .{ load_action = .LOAD };
text_init(atlas_dim);
g_mixer.paused = true;
@ -159,16 +135,15 @@ init :: () {
}
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();
if tt.count == 0 {
set_trile("test", Trile.{});
test : Trile;
trile_fill(*test, first_used_swatch());
set_trile("test", test);
} else {
name : string;
for v : tt {
@ -182,8 +157,6 @@ init_after_core :: () {
init_keybinds();
init_settings_menu();
}
init_rendering();
load_post_process_from_pack();
audio_init();
@ -197,7 +170,6 @@ init_after_core :: () {
// #if UNCAPPED_FRAMES then sapp_glx_swapinterval(0);
}
is_in_reflection_pass : bool = false;
delta_time_accumulator : float64 = 0;
@ -219,7 +191,6 @@ frame :: () {
if show_loading_screen() {
input_per_frame_event_and_flag_update();
if init_after_core_done {
fonsClearState(state.fons);
draw_loading_screen();
tick_ui();
ui_pass();
@ -238,7 +209,6 @@ frame :: () {
g_mixer.paused = false;
}
fonsClearState(state.fons);
add_frame_profiling_point("After loading logic");
@ -266,7 +236,6 @@ frame :: () {
delta_time_accumulator -= (1.0/480.0);
}
}
fonsClearState(state.fons);
for event: Input.events_this_frame {
GR.getrect_handle_event(event);
}
@ -289,7 +258,6 @@ frame :: () {
draw_editor();
}
add_particle_render_tasks();
add_frame_profiling_point("After editor draw");
render();
add_frame_profiling_point("After rendering");
@ -308,7 +276,7 @@ frame :: () {
cleanup :: () {
log_info("Cleanup called....");
audio_cleanup();
sg_shutdown();
scene_shutdown();
}
get_window_size :: () -> (s32, s32) {

View File

@ -12,9 +12,8 @@ lint_checks :: (message: *Message) -> bool {
if message.kind != .TYPECHECKED then return true;
code := cast(*Message_Typechecked) message;
lint_ok := true;
lint_ok := lint_sokol_graphics(code);
for code.declarations {
import := it.expression.enclosing_load.enclosing_import;
if import.module_type != .MAIN_PROGRAM then return true;
@ -56,3 +55,39 @@ lint_procedure_name :: (name: string, node: Code_Node) -> bool {
return true;
}
}
lint_sokol_graphics :: (code: *Message_Typechecked) -> bool {
SOKOL_GRAPHICS_MODULES :: string.["gfx", "glue", "gl", "shape", "debugtext", "fontstash"];
is_sokol_graphics :: (path: string) -> bool {
for SOKOL_GRAPHICS_MODULES {
if contains(path, tprint("/sokol-jai/sokol/%/", it)) then return true;
}
return false;
}
ok := true;
for code.all {
load := it.expression.enclosing_load;
if !load || !load.enclosing_import || load.enclosing_import.module_type != .MAIN_PROGRAM then continue;
if contains(load.fully_pathed_filename, "/renderer_sokol/") then continue;
in_scene := ends_with(load.fully_pathed_filename, "/rendering/scene.jai");
for sub: it.subexpressions {
if sub.kind != .IDENT then continue;
decl := (cast(*Code_Ident) sub).resolved_declaration;
if !decl || !decl.enclosing_load then continue;
decl_path := decl.enclosing_load.fully_pathed_filename;
if is_sokol_graphics(decl_path) {
compiler_report(sprint("Linter: % is sokol graphics; only src/renderer_sokol/ may use it\n", decl.name), make_location(sub), .ERROR);
} else if contains(decl_path, "/renderer_sokol/") && !in_scene {
compiler_report(sprint("Linter: % is part of the renderer; only src/rendering/scene.jai may use it\n", decl.name), make_location(sub), .ERROR);
} else {
continue;
}
lint_errors_found += 1;
ok = false;
}
}
return ok;
}

View File

@ -5,7 +5,6 @@
#load "hacks.jai";
#load "console_commands.jai";
#load "entity_types.jai";
#load "shaderload.jai";
endframe_modified := false;
pointerimage_modified := false;

View File

@ -1,16 +0,0 @@
#scope_file
get_shader_paths :: () -> []string {
util :: #import "File_Utilities";
return util.file_list("./src/shaders/jai");
}
#scope_export
add_shaders_to_workspace :: (w: Workspace) {
file :: #import "File";
paths := get_shader_paths();
for paths {
add_build_file(file.get_absolute_path(it), w);
}
}

View File

@ -1,12 +1,7 @@
// The 24 axis-aligned cube rotations, encoded as 'face * 4 + twist' exactly as
// the trile shaders decode them (see get_orientation_matrix in
// shader_trile_shadow.glsl). Everything here mirrors that decode, so a rotation
// applied to a position on the CPU lines up with the geometry the GPU draws.
//
// Note the shaders build their mat3s from columns, which makes each of their
// rot_* helpers the transpose of the usual form. The matrices below are the
// effective row-major operators (v' = M * v), so they match what the shader
// actually does rather than what its helper names suggest.
// The 24 axis-aligned cube rotations, encoded as 'face * 4 + twist'. These
// matrices are the reference: the renderer has to turn an orientation into
// exactly this rotation, so that placement on the CPU lines up with what is
// drawn. They are row-major operators (v' = M * v).
ORIENTATION_COUNT :: 24;

View File

@ -19,6 +19,7 @@ Particle_Emitter_Config :: struct {
color_start : Vector4 = .{1, 1, 1, 1};
color_end : Vector4 = .{1, 1, 1, 0};
gravity : float = 2.0;
glow : float; // 0..1, like swatch emittance
blend_mode : Particle_Blend_Mode = .ADDITIVE;
}
@ -97,16 +98,14 @@ tick_emitter_instance :: (inst: *Particle_Emitter_Instance, dt: float) {
}
}
add_particle_render_tasks :: () {
// Live particles are global, so the game and each editor view draw them into
// their own view.
draw_live_particles :: (view: View_Id) {
Batch :: struct {
anim_name : string;
blend_mode : Particle_Blend_Mode;
anim : *Animation;
sheet : sg_image;
count : s32;
pos_size : *[MAX_PARTICLES]Vector4;
uv_rects : *[MAX_PARTICLES]Vector4;
colors : *[MAX_PARTICLES]Vector4;
particles : [..]Particle_Instance;
}
batches : [..] Batch;
@ -133,67 +132,34 @@ add_particle_render_tasks :: () {
anim := get_animation_from_string(def.animation_name);
if anim == null then continue;
if anim.frames.count == 0 then continue;
array_add(*batches, .{
anim_name = def.animation_name,
blend_mode = def.blend_mode,
anim = anim,
sheet = anim.sheet,
pos_size = New([MAX_PARTICLES]Vector4,, temp),
uv_rects = New([MAX_PARTICLES]Vector4,, temp),
colors = New([MAX_PARTICLES]Vector4,, temp),
});
batch = *batches[batches.count - 1];
batch = array_add(*batches);
batch.anim_name = def.animation_name;
batch.blend_mode = def.blend_mode;
batch.anim = anim;
batch.particles.allocator = temp;
}
if batch.count >= MAX_PARTICLES then continue;
t := p.age / p.lifetime;
size := def.size_start + (def.size_end - def.size_start) * t;
col := lerp_color(def.color_start, def.color_end, t);
idx := batch.count;
batch.pos_size.*[idx] = .{p.position.x, p.position.y, p.position.z, size};
anim := batch.anim;
frame_count := anim.frames.count;
frame := cast(s32)(t * cast(float)frame_count);
if frame < 0 then frame = 0;
if frame >= frame_count then frame = cast(s32)(frame_count - 1);
frame := clamp(cast(s32)(t * cast(float)anim.frames.count), 0, cast(s32)(anim.frames.count - 1));
f := anim.frames[frame];
batch.uv_rects.*[idx] = .{
cast(float)f.x / cast(float)anim.sheet_w,
cast(float)f.y / cast(float)anim.sheet_h,
cast(float)f.w / cast(float)anim.sheet_w,
cast(float)f.h / cast(float)anim.sheet_h,
};
batch.colors.*[idx] = col;
batch.count += 1;
array_add(*batch.particles, .{
position = p.position,
size = def.size_start + (def.size_end - def.size_start) * t,
uv_rect = .{
cast(float)f.x / cast(float)anim.sheet_w,
cast(float)f.y / cast(float)anim.sheet_h,
cast(float)f.w / cast(float)anim.sheet_w,
cast(float)f.h / cast(float)anim.sheet_h,
},
color = lerp_color(def.color_start, def.color_end, t),
glow = def.glow,
});
}
buf_task := New(Rendering_Task_Particles_Buffer,, temp);
total_count : s32 = 0;
for *b: batches {
if b.count <= 0 then continue;
instance_offset := total_count;
memcpy(*buf_task.pos_size[instance_offset], cast(*void)b.pos_size, b.count * size_of(Vector4));
memcpy(*buf_task.uv_rects[instance_offset], cast(*void)b.uv_rects, b.count * size_of(Vector4));
memcpy(*buf_task.colors[instance_offset], cast(*void)b.colors, b.count * size_of(Vector4));
total_count += b.count;
draw_task : Rendering_Task_Particles;
draw_task.count = b.count;
draw_task.instance_offset = instance_offset;
draw_task.blend_mode = b.blend_mode;
draw_task.sheet = b.sheet;
add_rendering_task(draw_task);
}
if total_count > 0 {
buf_task.total_count = total_count;
add_rendering_task(buf_task.*);
for batches {
blend := ifx it.blend_mode == .ADDITIVE then Blend_Mode.ADDITIVE else .ALPHA;
draw_particles(view, it.anim.sheet, blend, it.particles);
}
}
@ -202,7 +168,7 @@ particle_water_height :: () -> (has_water: bool, height: float) {
if in_editor_view && !editor_shows_water() return false, 0;
}
curworld := get_current_world();
if !curworld.valid return false, 0;
if !curworld.valid || curworld.world.conf.indoor return false, 0;
return true, effective_plane_height(*curworld.world.conf);
}

View File

@ -1,9 +1,4 @@
#import,dir "../../modules/sokol-jai/sokol/app"(DEBUG = !FLAG_RELEASE_BUILD);
#import,dir "../../modules/sokol-jai/sokol/gfx"(DEBUG = !FLAG_RELEASE_BUILD);
#import,dir "../../modules/sokol-jai/sokol/gl"(DEBUG = !FLAG_RELEASE_BUILD);
#import,dir "../../modules/sokol-jai/sokol/glue"(DEBUG = !FLAG_RELEASE_BUILD);
#import,dir "../../modules/sokol-jai/sokol/shape"(DEBUG = !FLAG_RELEASE_BUILD);
#import,dir "../../modules/sokol-jai/sokol/fontstash";
#import,dir "../../modules/sokol-jai/sokol/log"(DEBUG = !FLAG_RELEASE_BUILD);
#import,dir "../../modules/sokol-jai/sokol/time"(DEBUG = !FLAG_RELEASE_BUILD);
#import,dir "../../modules/sokol-jai/sokol/fetch"(DEBUG = !FLAG_RELEASE_BUILD);

212
src/renderer_sokol/gpu.jai Normal file
View File

@ -0,0 +1,212 @@
// Float, so brightness above 1 survives until post-processing.
VIEW_COLOR_FORMAT :: sg_pixel_format.RGBA16F;
VIEW_DEPTH_FORMAT :: sg_pixel_format.DEPTH;
VIEW_SCENE_FORMAT :: sg_pixel_format.R32F;
VIEW_GLOW_FORMAT :: sg_pixel_format.R16F;
SHADOW_TINT_FORMAT :: sg_pixel_format.RGBA16F; // glass colour, and the nearest glass depth in alpha
ALPHA_BLEND :: sg_blend_state.{
enabled = true,
src_factor_rgb = .SRC_ALPHA,
dst_factor_rgb = .ONE_MINUS_SRC_ALPHA,
};
MULTIPLY_BLEND :: sg_blend_state.{
enabled = true,
src_factor_rgb = .DST_COLOR,
dst_factor_rgb = .ZERO,
};
ADDITIVE_BLEND :: sg_blend_state.{
enabled = true,
src_factor_rgb = .SRC_ALPHA,
dst_factor_rgb = .ONE,
};
Pipeline_Target :: enum {
SCREEN;
VIEW_OPAQUE;
VIEW_TRANSPARENT;
SHADOW;
POST; // colour only, view format
}
samplers : struct {
nearest_clamp : sg_sampler;
linear_clamp : sg_sampler;
linear_repeat : sg_sampler;
shadow : sg_sampler;
}
samplers_init :: () {
samplers.nearest_clamp = sg_make_sampler(*(sg_sampler_desc.{ min_filter = .NEAREST, mag_filter = .NEAREST, wrap_u = .CLAMP_TO_EDGE, wrap_v = .CLAMP_TO_EDGE }));
samplers.linear_clamp = sg_make_sampler(*(sg_sampler_desc.{ min_filter = .LINEAR, mag_filter = .LINEAR, wrap_u = .CLAMP_TO_EDGE, wrap_v = .CLAMP_TO_EDGE }));
samplers.linear_repeat = sg_make_sampler(*(sg_sampler_desc.{ min_filter = .LINEAR, mag_filter = .LINEAR, wrap_u = .REPEAT, wrap_v = .REPEAT }));
samplers.shadow = sg_make_sampler(*(sg_sampler_desc.{ min_filter = .NEAREST, mag_filter = .NEAREST, wrap_u = .CLAMP_TO_EDGE, wrap_v = .CLAMP_TO_EDGE, compare = .LESS_EQUAL }));
}
// Vertex layout and anything else specific is filled in by the caller.
pipeline_desc :: (shader: sg_shader_desc, target: Pipeline_Target, blend := sg_blend_state.{}, depth_write := false) -> sg_pipeline_desc {
shader_desc := shader;
desc : sg_pipeline_desc;
desc.shader = sg_make_shader(*shader_desc);
desc.colors[0].blend = blend;
if target != .SCREEN {
desc.colors[0].pixel_format = VIEW_COLOR_FORMAT;
desc.depth.pixel_format = VIEW_DEPTH_FORMAT;
desc.depth.compare = .LESS_EQUAL;
desc.depth.write_enabled = depth_write;
desc.sample_count = 1;
}
// Glow is attachment 1 in both view passes, blended like colour.
if target == .VIEW_OPAQUE || target == .VIEW_TRANSPARENT {
desc.color_count = 2;
desc.colors[1].pixel_format = VIEW_GLOW_FORMAT;
desc.colors[1].blend = blend;
}
if target == .VIEW_OPAQUE {
desc.color_count = 3;
desc.colors[2].pixel_format = VIEW_SCENE_FORMAT;
}
// Shadow casters write depth only; glass turns the tint back on.
if target == .SHADOW {
desc.colors[0].pixel_format = SHADOW_TINT_FORMAT;
desc.colors[0].write_mask = .NONE;
}
if target == .POST desc.depth.pixel_format = .NONE;
return desc;
}
Pass_Kind :: enum {
MAIN;
REFLECTION;
SHADOW;
}
Pass :: struct {
scene : *Scene;
view_index : int;
view : View;
kind : Pass_Kind;
params : View_Params;
shadow : Shadow_Params;
}
make_pass :: (scene: *Scene, view_index: int, kind: Pass_Kind) -> Pass {
pass := Pass.{ scene = scene, view_index = view_index, view = scene.views[view_index], kind = kind };
env := view_environment(pass.view);
height := env.reflection_height;
camera := pass.view.camera.position;
view_proj := scene.view_proj[view_index];
pass.params.clip = .[0, 0, 0, 1];
if kind == .REFLECTION {
camera.y = 2 * height - camera.y;
view_proj = scene.reflection_view_proj[view_index];
pass.params.clip = .[0, 1, 0, -height];
}
if kind == .SHADOW {
// Camera-facing billboards turn to the sun, so they cast their full silhouette.
camera = pass.view.camera.target + env.sun_direction * 1000;
view_proj = scene.shadow_view_proj[view_index];
}
_, inv_view_proj := inverse(view_proj);
pass.params.view_proj = view_proj.floats;
pass.params.inv_view_proj = inv_view_proj.floats;
pass.params.camera = .[camera.x, camera.y, camera.z, scene.time];
pass.params.sun_direction = .[env.sun_direction.x, env.sun_direction.y, env.sun_direction.z, 0];
pass.params.sun_color = .[env.sun_color.x, env.sun_color.y, env.sun_color.z, 0];
pass.params.shade_color = .[env.shade_color.x, env.shade_color.y, env.shade_color.z, 0];
// From shadow clip space to shadow map uv and stored depth, which differ per backend.
gl := sg_query_backend() == .GLCORE || sg_query_backend() == .GLES3;
flip := sg_query_features().origin_top_left;
to_uv := Matrix4.{
0.5, 0, 0, 0.5,
0, ifx flip then -0.5 else 0.5, 0, 0.5,
0, 0, ifx gl then 0.5 else 1, ifx gl then 0.5 else 0,
0, 0, 0, 1,
};
pass.shadow.shadow_uv = (scene.shadow_view_proj[view_index] * transpose(to_uv)).floats;
return pass;
}
apply_uniforms :: (slot: s32, params: *$T) {
sg_apply_uniforms(slot, *(sg_range.{ params, size_of(T) }));
}
Slots :: struct (T: Type) {
items : [..]T;
free : [..]u32;
}
// Ids start at 1 so that 0 can mean none.
slot_add :: (slots: *Slots($T)) -> u32, *T {
if slots.free.count {
id := pop(*slots.free);
return id, *slots.items[id - 1];
}
item := array_add(*slots.items);
return xx slots.items.count, item;
}
slot_get :: (slots: *Slots($T), id: u32) -> *T {
if id == 0 || id > slots.items.count return null;
return *slots.items[id - 1];
}
slot_remove :: (slots: *Slots($T), id: u32) {
slots.items[id - 1] = .{};
array_add(*slots.free, id);
}
Stream_Buffer :: struct {
buffer : sg_buffer;
size : int;
}
stream_upload :: (stream: *Stream_Buffer, data: []$T) {
if data.count == 0 return;
size := data.count * size_of(T);
if size > stream.size {
if stream.size sg_destroy_buffer(stream.buffer);
stream.size = max(size, stream.size * 2);
stream.buffer = sg_make_buffer(*(sg_buffer_desc.{ size = xx stream.size, usage = .STREAM }));
}
sg_update_buffer(stream.buffer, *(sg_range.{ data.data, xx size }));
}
Keyed :: struct (Instance: Type) {
key : s64;
instance : Instance;
}
Batch :: struct {
view_index : s32;
key : s64;
first : s32;
count : s32;
}
// Sorts the view's draws by key and appends one batch per run of equal keys.
batch_instances :: (view_index: int, draws: []Keyed($I), batches: *[..]Batch, instances: *[..]I) {
quick_sort(draws, (a: Keyed(I), b: Keyed(I)) -> s64 { return a.key - b.key; });
for draws {
if it_index == 0 || draws[it_index - 1].key != it.key {
array_add(batches, .{view_index = xx view_index, key = it.key, first = xx instances.count});
}
array_add(instances, it.instance);
batches.*[batches.count - 1].count += 1;
}
}
bind_shadow :: (pass: *Pass, bind: *sg_bindings) {
bind.images[IMG_shadow_map] = view_shadow_image(pass.view_index);
bind.samplers[SMP_shadow_smp] = samplers.shadow;
bind.images[IMG_shadow_tint] = view_shadow_tint_image(pass.view_index);
bind.samplers[SMP_shadow_tint_smp] = samplers.nearest_clamp;
}
view_environment :: (view: View) -> Environment {
return ifx view.environment then view.environment.* else .{};
}

View File

@ -0,0 +1,49 @@
lines_init :: () {
make :: (depth_test: bool) -> sg_pipeline {
desc := pipeline_desc(line_shader_desc(sg_query_backend()), .VIEW_TRANSPARENT, ALPHA_BLEND);
desc.layout.buffers[0].step_func = .PER_INSTANCE;
desc.layout.attrs[ATTR_line_a] = .{ format = .FLOAT3 };
desc.layout.attrs[ATTR_line_b] = .{ format = .FLOAT3 };
desc.layout.attrs[ATTR_line_color] = .{ format = .FLOAT4 };
desc.layout.attrs[ATTR_line_width] = .{ format = .FLOAT };
if !depth_test desc.depth.compare = .ALWAYS;
return sg_make_pipeline(*desc);
}
lines.depth_tested = make(true);
lines.overlay = make(false);
}
lines_upload :: (scene: *Scene) {
array_reset_keeping_memory(*lines.all);
array_add(*lines.all, ..scene.debug_lines);
array_add(*lines.all, ..scene.overlay_lines);
stream_upload(*lines.stream, lines.all);
}
lines_draw :: (pass: *Pass, width: s32, height: s32) {
if pass.kind != .MAIN return;
params := Line_Params.{ viewport = .[width * 0.5, height * 0.5] };
draw :: (pipeline: sg_pipeline, first: int, count: int) #expand {
if count == 0 return;
sg_apply_pipeline(pipeline);
apply_uniforms(UB_view_params, *pass.params);
apply_uniforms(UB_line_params, *params);
bind : sg_bindings;
bind.vertex_buffers[0] = lines.stream.buffer;
bind.vertex_buffer_offsets[0] = xx (first * size_of(Debug_Line));
sg_apply_bindings(*bind);
sg_draw(0, 6, xx count);
}
draw(lines.depth_tested, 0, pass.scene.debug_lines.count);
draw(lines.overlay, pass.scene.debug_lines.count, pass.scene.overlay_lines.count);
}
#scope_file
lines : struct {
depth_tested : sg_pipeline;
overlay : sg_pipeline;
all : [..]Debug_Line;
stream : Stream_Buffer;
}

View File

@ -0,0 +1,107 @@
// Each chunk's probes are a brick in one 3D atlas, found through an index
// texture with one texel per chunk. The trile shader filters them itself.
PROBE_BRICKS_PER_COLUMN :: 16; // bricks stack along y, then the next column along z
probes_init :: () {
zero : [8]u8;
probes.empty_index = make_volume(1, 1, 1, .RGBA8, .{4, zero.data});
probes.empty_atlas = make_volume(1, 1, 1, .RGBA16F, .{8, zero.data});
probes.index = probes.empty_index;
probes.atlas = probes.empty_atlas;
}
renderer_probes_set :: (key: Chunk_Key, data: []Probe) {
brick := table_find_pointer(*probes.bricks, key);
if brick array_free(brick.*);
else brick = table_set(*probes.bricks, key, .[]);
brick.* = array_copy(data);
probes.dirty = true;
}
renderer_probes_clear :: () {
for probes.bricks array_free(it);
table_reset(*probes.bricks);
probes.dirty = true;
}
probes_upload :: () {
if !probes.dirty return;
probes.dirty = false;
if probes.index.id != probes.empty_index.id sg_destroy_image(probes.index);
if probes.atlas.id != probes.empty_atlas.id sg_destroy_image(probes.atlas);
probes.index = probes.empty_index;
probes.atlas = probes.empty_atlas;
probes.min = .[0, 0, 0, 0];
probes.size = .[0, 0, 0, 0];
count := probes.bricks.count;
if !count return;
lo := Chunk_Key.{S32_MAX, S32_MAX, S32_MAX};
hi := Chunk_Key.{S32_MIN, S32_MIN, S32_MIN};
for probes.bricks {
lo = .{min(lo.x, it_index.x), min(lo.y, it_index.y), min(lo.z, it_index.z)};
hi = .{max(hi.x, it_index.x), max(hi.y, it_index.y), max(hi.z, it_index.z)};
}
size := s32.[hi.x - lo.x + 1, hi.y - lo.y + 1, hi.z - lo.z + 1];
index := NewArray(size[0] * size[1] * size[2] * 4, u8,, temp);
N :: CHUNK_SIZE;
columns := min(count, PROBE_BRICKS_PER_COLUMN);
layers := (count + PROBE_BRICKS_PER_COLUMN - 1) / PROBE_BRICKS_PER_COLUMN;
atlas_w, atlas_h, atlas_d := N * 3, N * columns, N * layers;
atlas := NewArray(atlas_w * atlas_h * atlas_d * 4, u16,, temp);
brick_index := 0;
for brick, key: probes.bricks {
number := brick_index + 1;
i := ((key.z - lo.z) * size[1] + (key.y - lo.y)) * size[0] + (key.x - lo.x);
index[i * 4 + 0] = xx (number & 0xFF);
index[i * 4 + 1] = xx (number >> 8);
y0 := (brick_index % PROBE_BRICKS_PER_COLUMN) * N;
z0 := (brick_index / PROBE_BRICKS_PER_COLUMN) * N;
for z: 0..N-1 for y: 0..N-1 for x: 0..N-1 {
probe := *brick[x + y * N + z * N * N];
row := ((z0 + z) * atlas_h + (y0 + y)) * atlas_w + x * 3;
memcpy(*atlas[row * 4], probe.sh.data, size_of(Probe));
}
brick_index += 1;
}
probes.index = make_volume(size[0], size[1], size[2], .RGBA8, index);
probes.atlas = make_volume(xx atlas_w, xx atlas_h, xx atlas_d, .RGBA16F, .{atlas.count * size_of(u16), xx atlas.data});
probes.min = .[xx lo.x, xx lo.y, xx lo.z, 1];
probes.size = .[xx size[0], xx size[1], xx size[2], 0];
}
probes_set_params :: (params: *Trile_Fs_Params) {
params.probe_min = probes.min;
params.probe_size = probes.size;
}
probes_bind :: (bind: *sg_bindings) {
bind.images[IMG_probe_index] = probes.index;
bind.images[IMG_probe_atlas] = probes.atlas;
bind.samplers[SMP_probe_smp] = samplers.nearest_clamp;
}
#scope_file
probes : struct {
bricks : Table(Chunk_Key, []Probe, chunk_key_hash, chunk_key_compare);
dirty : bool;
index : sg_image;
atlas : sg_image;
empty_index : sg_image;
empty_atlas : sg_image;
min : [4]float; // first chunk in the index; w = 1 when there are probes
size : [4]float; // index size in chunks
}
make_volume :: (width: s32, height: s32, depth: s32, format: sg_pixel_format, data: []u8) -> sg_image {
desc := sg_image_desc.{ type = ._3D, width = width, height = height, num_slices = depth, pixel_format = format };
desc.data.subimage[0][0] = .{ data.data, xx data.count };
return sg_make_image(*desc);
}

View File

@ -0,0 +1,133 @@
#import,dir "../../modules/sokol-jai/sokol/gfx"(DEBUG = !FLAG_RELEASE_BUILD);
#import,dir "../../modules/sokol-jai/sokol/glue"(DEBUG = !FLAG_RELEASE_BUILD);
#import "Sort";
#load "shaders/jai/shaders.jai";
#load "gpu.jai";
#load "ui.jai";
#load "triles.jai";
#load "probes.jai";
#load "views.jai";
#load "water.jai";
#load "sprites.jai";
#load "sky.jai";
#load "lines.jai";
renderer_init :: (orientations: [ORIENTATION_COUNT]Matrix3) {
sg_setup(*(sg_desc.{
environment = cast,force(sg_environment) sglue_environment(),
logger = .{ func = slog_func },
// Each view holds 10 attachments and 15 images; each trile mesh 2 buffers.
attachments_pool_size = 64,
image_pool_size = 512,
buffer_pool_size = 1024,
}));
white := u8.[255, 255, 255, 255];
renderer.white = make_image(1, 1, white);
samplers_init();
ui_init();
triles_init(orientations);
probes_init();
views_init();
water_init();
sprites_init();
sky_init();
lines_init();
}
renderer_shutdown :: () {
sg_shutdown();
}
renderer_texture_create :: (width: s32, height: s32, pixels: []u8) -> u32 {
id, texture := slot_add(*renderer.textures);
texture.width = width;
texture.height = height;
texture.image = make_image(width, height, pixels);
return id;
}
// Immutable images are recreated rather than updated, so a texture can be
// updated any number of times in a frame.
renderer_texture_update :: (id: u32, pixels: []u8) {
texture := slot_get(*renderer.textures, id);
sg_destroy_image(texture.image);
texture.image = make_image(texture.width, texture.height, pixels);
}
renderer_texture_destroy :: (id: u32) {
sg_destroy_image(slot_get(*renderer.textures, id).image);
slot_remove(*renderer.textures, id);
}
renderer_render :: (scene: *Scene, width: s32, height: s32) {
triles_upload(scene);
probes_upload();
sprites_upload(scene);
lines_upload(scene);
ui_upload(scene);
for view, view_index: scene.views {
shadow := make_pass(scene, view_index, .SHADOW);
view_begin_shadow_pass(view_index);
triles_draw(*shadow);
sprites_draw(*shadow, transparent = false);
triles_draw_glass_shadow(*shadow);
sg_end_pass();
for kind: Pass_Kind.[.REFLECTION, .MAIN] {
pass := make_pass(scene, view_index, kind);
view_begin_pass(view_index, width, height, kind, opaque = true);
sky_draw(*pass);
water_draw_floor(*pass);
triles_draw(*pass);
sprites_draw(*pass, transparent = false);
sg_end_pass();
view_begin_pass(view_index, width, height, kind, opaque = false);
water_draw(*pass);
sprites_draw(*pass, transparent = true);
lines_draw(*pass, width, height);
sg_end_pass();
if kind == .MAIN view_shafts(*pass);
}
view_bloom(view_index);
}
action : sg_pass_action;
action.colors[0] = .{ load_action = .CLEAR, clear_value = .{0, 0, 0, 1} };
sg_begin_pass(*(sg_pass.{ action = action, swapchain = cast,force(sg_swapchain) sglue_swapchain() }));
for scene.views view_composite(it_index, view_environment(it));
ui_draw(scene, width, height);
sg_end_pass();
sg_commit();
}
texture_image :: (id: u32) -> sg_image {
texture := slot_get(*renderer.textures, id);
if !texture || !texture.image.id return renderer.white;
return texture.image;
}
#scope_file
Renderer_Texture :: struct {
image : sg_image;
width : s32;
height : s32;
}
renderer : struct {
textures : Slots(Renderer_Texture);
white : sg_image;
}
make_image :: (width: s32, height: s32, pixels: []u8) -> sg_image {
desc := sg_image_desc.{ width = width, height = height, pixel_format = .RGBA8 };
desc.data.subimage[0][0] = .{ pixels.data, xx pixels.count };
return sg_make_image(*desc);
}

View File

@ -0,0 +1,23 @@
compile_sokol_shaders :: () -> bool {
dir :: "src/renderer_sokol/shaders";
input :: "src/renderer_sokol/shaders/shaders.glsl";
output :: "src/renderer_sokol/shaders/jai/shaders.jai";
shdc :: #ifx OS == .MACOS then "src/renderer_sokol/shaders/sokol-shdc-mac" else "src/renderer_sokol/shaders/sokol-shdc";
out_time, _, out_exists := file_modtime_and_size(output);
stale := !out_exists;
for file_list(dir) {
if !ends_with(it, ".glsl") continue;
src_time := file_modtime_and_size(it);
if compare_apollo_times(src_time, out_time) > 0 stale = true;
}
if !stale return true;
result, out, error := run_command(shdc, "-i", input, "-o", output,
"-l", "glsl430:glsl300es:metal_macos", "-f", "sokol_jai", capture_and_return_output = true);
if result.exit_code != 0 {
log_error("sokol-shdc failed:\n%%", out, error);
return false;
}
return true;
}

View File

@ -0,0 +1,76 @@
@block view
layout(binding=0) uniform view_params {
mat4 view_proj;
mat4 inv_view_proj;
vec4 camera; // xyz = position, w = time
vec4 clip; // plane; geometry on its negative side is dropped
vec4 sun_direction;
vec4 sun_color;
vec4 shade_color;
};
@end
@block quad
vec2 quad_corner(int vertex_index) {
const vec2 corners[6] = vec2[6](vec2(0, 0), vec2(1, 0), vec2(1, 1), vec2(0, 0), vec2(1, 1), vec2(0, 1));
return corners[vertex_index];
}
@end
// Opaque passes also write how much each pixel glows, and its distance from the
// camera for water depth.
@block scene_out
layout(location=0) out vec4 frag_color;
layout(location=1) out vec4 frag_glow;
layout(location=2) out vec4 frag_scene;
void write_scene(vec3 to_camera, float glow) {
frag_glow = vec4(glow);
frag_scene = vec4(length(to_camera));
}
@end
// Transparent passes blend glow with the same alpha as colour.
@block transparent_out
layout(location=0) out vec4 frag_color;
layout(location=1) out vec4 frag_glow;
void write_transparent(vec4 color, float glow) {
frag_color = color;
frag_glow = vec4(glow, 0.0, 0.0, color.a);
}
@end
@block emissive
const float EMISSIVE_GLOW = 8.0; // bloom strength of something fully emissive
@end
@block shadow
layout(binding=3) uniform shadow_params {
mat4 shadow_uv; // world to shadow map uv and depth
};
layout(binding=7) uniform texture2D shadow_map;
layout(binding=7) uniform sampler shadow_smp;
layout(binding=8) uniform texture2D shadow_tint; // what colour glass gave the sunlight
layout(binding=8) uniform sampler shadow_tint_smp;
@image_sample_type shadow_map depth
@sampler_type shadow_smp comparison
float brightest(vec3 c) { return max(c.r, max(c.g, c.b)); }
// White in sunlight, black in shadow, coloured behind glass. Looked up at the
// centre of the trixel face, so shadow edges follow the trixel grid.
vec3 sun_shadow(vec3 world, vec3 normal) {
vec3 half_trixel = normal * (0.5 / 16.0);
vec3 face = (floor((world - half_trixel) * 16.0) + 0.5) / 16.0 + half_trixel;
vec4 p = shadow_uv * vec4(face + normal * 0.02, 1.0);
if (p.x < 0.0 || p.x > 1.0 || p.y < 0.0 || p.y > 1.0 || p.z > 1.0) return vec3(1.0);
float visible = texture(sampler2DShadow(shadow_map, shadow_smp), vec3(p.xy, p.z - 0.0005));
return visible * texture(sampler2D(shadow_tint, shadow_tint_smp), p.xy).rgb;
}
@end
@block fullscreen
// Clip-space corner of a triangle that covers the screen, for vertices 0..2.
vec2 fullscreen_position(int vertex_index) {
return vec2((vertex_index << 1) & 2, vertex_index & 2) * 2.0 - 1.0;
}
@end

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,41 @@
@vs vs_line
@include_block view
@include_block quad
layout(binding=1) uniform line_params {
vec2 viewport; // in pixels
};
in vec3 a;
in vec3 b;
in vec4 color;
in float width; // in pixels
out vec4 v_color;
// A quad from a to b, widened across the line in screen space.
void main() {
vec2 c = quad_corner(gl_VertexIndex); // x: a to b, y: side
vec4 clip_a = view_proj * vec4(a, 1.0);
vec4 clip_b = view_proj * vec4(b, 1.0);
vec2 screen_a = clip_a.xy / max(clip_a.w, 0.0001) * viewport;
vec2 screen_b = clip_b.xy / max(clip_b.w, 0.0001) * viewport;
vec2 dir = screen_b - screen_a;
dir = dot(dir, dir) > 0.0001 ? normalize(dir) : vec2(1.0, 0.0);
vec4 p = mix(clip_a, clip_b, c.x);
p.xy += vec2(-dir.y, dir.x) * (c.y - 0.5) * width / viewport * p.w;
gl_Position = p;
v_color = color;
}
@end
@fs fs_line
@include_block transparent_out
in vec4 v_color;
void main() {
write_transparent(v_color, 0.0);
}
@end
@program line vs_line fs_line

View File

@ -0,0 +1,194 @@
// Texture coordinates come from the pixel position, which lines up with
// render-target textures the same way on every backend.
@vs vs_fullscreen
@include_block fullscreen
void main() {
gl_Position = vec4(fullscreen_position(gl_VertexIndex), 0.0, 1.0);
}
@end
// The first level: colour times glow, averaged over each 2x2 block of view pixels.
@fs fs_bloom_glow
layout(binding=0) uniform texture2D bloom_source;
layout(binding=1) uniform texture2D bloom_glow;
layout(binding=0) uniform sampler bloom_smp;
out vec4 frag_color;
vec3 glowing(ivec2 p) {
return texelFetch(sampler2D(bloom_source, bloom_smp), p, 0).rgb * texelFetch(sampler2D(bloom_glow, bloom_smp), p, 0).r;
}
void main() {
ivec2 p = ivec2(gl_FragCoord.xy) * 2;
vec3 c = (glowing(p) + glowing(p + ivec2(1, 0)) + glowing(p + ivec2(0, 1)) + glowing(p + ivec2(1, 1))) * 0.25;
frag_color = vec4(c, 1.0);
}
@end
@fs fs_bloom_down
layout(binding=0) uniform texture2D bloom_source;
layout(binding=0) uniform sampler bloom_smp;
out vec4 frag_color;
vec3 tap(vec2 uv) { return texture(sampler2D(bloom_source, bloom_smp), uv).rgb; }
void main() {
vec2 texel = 1.0 / vec2(textureSize(sampler2D(bloom_source, bloom_smp), 0));
vec2 uv = gl_FragCoord.xy * 2.0 * texel;
vec3 c = (tap(uv + texel * vec2(-1, -1)) + tap(uv + texel * vec2(1, -1)) +
tap(uv + texel * vec2(-1, 1)) + tap(uv + texel * vec2(1, 1))) * 0.25;
frag_color = vec4(c, 1.0);
}
@end
@fs fs_bloom_up
layout(binding=0) uniform texture2D bloom_source;
layout(binding=0) uniform sampler bloom_smp;
out vec4 frag_color;
vec3 tap(vec2 uv) { return texture(sampler2D(bloom_source, bloom_smp), uv).rgb; }
// A 3x3 tent over the smaller level, added onto the larger one.
void main() {
vec2 texel = 1.0 / vec2(textureSize(sampler2D(bloom_source, bloom_smp), 0));
vec2 uv = gl_FragCoord.xy * 0.5 * texel;
vec3 c = tap(uv) * 4.0
+ (tap(uv + texel * vec2(-1, 0)) + tap(uv + texel * vec2(1, 0)) + tap(uv + texel * vec2(0, -1)) + tap(uv + texel * vec2(0, 1))) * 2.0
+ (tap(uv + texel * vec2(-1, -1)) + tap(uv + texel * vec2(1, -1)) + tap(uv + texel * vec2(-1, 1)) + tap(uv + texel * vec2(1, 1)));
frag_color = vec4(c / 16.0, 1.0);
}
@end
// Sunlight that came through glass, scattered toward the camera by the air between
// it and the first opaque surface. Half resolution.
@vs vs_shafts
@include_block view
@include_block fullscreen
out vec4 v_point;
out vec3 v_camera;
out vec3 v_sun;
out float v_time;
void main() {
vec2 p = fullscreen_position(gl_VertexIndex);
gl_Position = vec4(p, 0.0, 1.0);
v_point = inv_view_proj * vec4(p, 0.5, 1.0);
v_camera = camera.xyz;
v_sun = sun_color.rgb;
v_time = camera.w;
}
@end
@fs fs_shafts
@include_block shadow
layout(binding=1) uniform shaft_params {
float density; // how much light scatters per unit, and how fast it fades
float amount;
float max_distance;
float steps;
};
layout(binding=0) uniform texture2D shaft_scene;
layout(binding=0) uniform sampler shaft_scene_smp;
@image_sample_type shaft_scene unfilterable_float
@sampler_type shaft_scene_smp nonfiltering
in vec4 v_point;
in vec3 v_camera;
in vec3 v_sun;
in float v_time;
out vec4 frag_color;
const vec3 SHAFT_DRIFT = vec3(0.4, 0.15, 0.3); // how the air moves, units per second
const float SHAFT_SCALE = 0.8; // size of the dusty patches, inverse units
const float SHAFT_SHIMMER = 1.0; // how much the dust thins and thickens the light
const float SHAFT_TINT = 0.6; // how much of the glass colour the shafts keep
float hash(vec3 p) {
p = fract(p * 0.3183099 + 0.1);
p *= 17.0;
return fract(p.x * p.y * p.z * (p.x + p.y + p.z));
}
float value_noise(vec3 p) {
vec3 i = floor(p);
vec3 f = fract(p);
f = f * f * (3.0 - 2.0 * f);
return mix(mix(mix(hash(i), hash(i + vec3(1, 0, 0)), f.x),
mix(hash(i + vec3(0, 1, 0)), hash(i + vec3(1, 1, 0)), f.x), f.y),
mix(mix(hash(i + vec3(0, 0, 1)), hash(i + vec3(1, 0, 1)), f.x),
mix(hash(i + vec3(0, 1, 1)), hash(i + vec3(1, 1, 1)), f.x), f.y), f.z);
}
// Two layers drifting at different speeds, so the dust churns instead of sliding.
float dust(vec3 p) {
vec3 q = p * SHAFT_SCALE;
float n = value_noise(q + SHAFT_DRIFT * v_time * SHAFT_SCALE) * 0.65
+ value_noise(q * 2.3 - SHAFT_DRIFT.zxy * v_time * SHAFT_SCALE * 1.7) * 0.35;
// Sharpened, so the patches read as clear gaps and thick wisps rather than a soft wobble.
n = smoothstep(0.25, 0.75, n);
return mix(1.0 - SHAFT_SHIMMER, 1.0 + SHAFT_SHIMMER, n);
}
void main() {
vec3 dir = normalize(v_point.xyz / v_point.w - v_camera);
float len = min(texelFetch(sampler2D(shaft_scene, shaft_scene_smp), ivec2(gl_FragCoord.xy) * 2, 0).r, max_distance);
float step = len / steps;
// Interleaved gradient noise spreads the step banding into a fine dither.
float jitter = fract(52.9829189 * fract(dot(gl_FragCoord.xy, vec2(0.06711056, 0.00583715))));
vec3 light = vec3(0.0);
for (float i = 0.0; i < steps; i += 1.0) {
float t = (i + jitter) * step;
// Snapped to the trixel grid, so the shafts are blocky like the patches they make.
vec3 p = (floor((v_camera + dir * t) * 16.0) + 0.5) / 16.0;
vec4 s = shadow_uv * vec4(p, 1.0);
if (s.x < 0.0 || s.x > 1.0 || s.y < 0.0 || s.y > 1.0 || s.z > 1.0) continue;
vec4 tint = texture(sampler2D(shadow_tint, shadow_tint_smp), s.xy);
if (s.z < tint.a + 0.001) continue;
float visible = texture(sampler2DShadow(shadow_map, shadow_smp), vec3(s.xy, s.z - 0.0005));
vec3 color = mix(vec3(brightest(tint.rgb)), tint.rgb, SHAFT_TINT);
light += visible * color * exp(-density * t) * dust(p);
}
frag_color = vec4(light * v_sun * density * step * amount, 1.0);
}
@end
@fs fs_post
layout(binding=0) uniform post_params {
float exposure; // in stops
float contrast;
float saturation;
float bloom_amount;
};
layout(binding=0) uniform texture2D view_color;
layout(binding=1) uniform texture2D bloom;
layout(binding=2) uniform texture2D shafts;
layout(binding=0) uniform sampler view_smp;
layout(binding=1) uniform sampler bloom_view_smp;
out vec4 frag_color;
void main() {
vec2 uv = gl_FragCoord.xy / vec2(textureSize(sampler2D(view_color, view_smp), 0));
vec3 c = texture(sampler2D(view_color, view_smp), uv).rgb;
c += texture(sampler2D(bloom, bloom_view_smp), uv).rgb * bloom_amount;
// A small tent blur over the half resolution shafts hides their dither.
vec2 st = 1.0 / vec2(textureSize(sampler2D(shafts, bloom_view_smp), 0));
c += (texture(sampler2D(shafts, bloom_view_smp), uv).rgb * 2.0
+ texture(sampler2D(shafts, bloom_view_smp), uv + st * vec2( 1, 1)).rgb
+ texture(sampler2D(shafts, bloom_view_smp), uv + st * vec2(-1, 1)).rgb
+ texture(sampler2D(shafts, bloom_view_smp), uv + st * vec2( 1, -1)).rgb
+ texture(sampler2D(shafts, bloom_view_smp), uv + st * vec2(-1, -1)).rgb) / 6.0;
c *= exp2(exposure);
c = (c - 0.5) * contrast + 0.5;
c = mix(vec3(dot(c, vec3(0.2126, 0.7152, 0.0722))), c, saturation);
frag_color = vec4(clamp(c, 0.0, 1.0), 1.0);
}
@end
@program bloom_glow vs_fullscreen fs_bloom_glow
@program bloom_down vs_fullscreen fs_bloom_down
@program bloom_up vs_fullscreen fs_bloom_up
@program shafts vs_shafts fs_shafts
@program post vs_fullscreen fs_post

View File

@ -0,0 +1,8 @@
@include common.glsl
@include ui.glsl
@include post.glsl
@include trile.glsl
@include water.glsl
@include sprite.glsl
@include sky.glsl
@include line.glsl

View File

@ -0,0 +1,53 @@
@vs vs_sky
@include_block view
@include_block fullscreen
out vec4 v_point;
out vec3 v_camera;
void main() {
vec2 p = fullscreen_position(gl_VertexIndex);
gl_Position = vec4(p, 0.0, 1.0);
v_point = inv_view_proj * vec4(p, 0.5, 1.0);
v_camera = camera.xyz;
}
@end
@fs fs_sky
@include_block scene_out
in vec4 v_point;
in vec3 v_camera;
layout(binding=1) uniform sky_params {
vec4 sky_base;
vec4 sky_top;
vec4 sun_disk;
vec4 sun_halo;
vec4 horizon_halo;
vec4 sun; // xyz = direction, w = sky intensity
};
void main() {
vec3 dir = normalize(v_point.xyz / v_point.w - v_camera);
vec3 color = mix(sky_base.rgb, sky_top.rgb, clamp(dir.y * 2.0, 0.0, 0.7));
// The sun and its halo are squares in the sun's own frame.
vec3 sun_dir = sun.xyz;
vec3 sun_right = normalize(cross(sun_dir, vec3(0.0, 1.0, 0.0)));
vec3 sun_up = cross(sun_right, sun_dir);
vec3 off = dir - sun_dir * dot(dir, sun_dir);
float square = max(abs(dot(off, sun_right)), abs(dot(off, sun_up)));
float halo = clamp((0.25 - square) * 6.0, 0.0, 1.0);
color += sun_halo.rgb * halo * halo;
bool disk = square < 0.032 && dot(dir, sun_dir) > 0.0;
if (disk) color = sun_disk.rgb * 3.0;
color += horizon_halo.rgb * (1.0 - clamp(abs(dir.y) * 20.0, 0.0, 1.0)) * 0.8;
frag_color = vec4(color * sun.w, 1.0);
frag_glow = vec4(disk ? 1.0 : 0.0);
frag_scene = vec4(1.0e4);
}
@end
@program sky vs_sky fs_sky

View File

@ -0,0 +1,97 @@
@vs vs_sprite
@include_block view
@include_block quad
layout(binding=1) uniform sprite_params {
float lit;
};
in vec3 center; // bottom middle
in vec2 size;
in vec4 uv_rect;
in vec3 face;
in vec4 color;
in float glow;
out float v_clip;
out vec3 v_to_camera;
out vec2 v_uv;
out vec4 v_color;
out vec3 v_sun;
out vec3 v_shade;
out vec3 v_anchor;
out float v_glow;
void main() {
vec2 c = quad_corner(gl_VertexIndex);
vec3 look = face;
if (face.x < -10.0) look = vec3(center.x - camera.x, 0.0, center.z - camera.z);
if (dot(look.xz, look.xz) < 0.0001) look = vec3(0.0, 0.0, 1.0);
vec3 right = normalize(cross(vec3(0.0, 1.0, 0.0), look));
vec3 world = center + right * ((c.x - 0.5) * size.x) + vec3(0.0, c.y * size.y, 0.0);
gl_Position = view_proj * vec4(world, 1.0);
v_clip = dot(vec4(world, 1.0), clip);
v_to_camera = camera.xyz - world;
v_uv = vec2(uv_rect.x + c.x * uv_rect.z, uv_rect.y + (1.0 - c.y) * uv_rect.w);
v_color = color;
v_glow = glow;
v_sun = lit > 0.5 ? sun_color.rgb : vec3(1.0);
v_shade = lit > 0.5 ? shade_color.rgb : vec3(1.0);
// The whole sprite takes the shadow found inside its body, nudged toward the
// sun so it doesn't find its own shadow.
v_anchor = center + vec3(0.0, size.y * 0.5, 0.0) + sun_direction.xyz * 0.3;
}
@end
@block sprite_fs
in float v_clip;
in vec3 v_to_camera;
in vec2 v_uv;
in vec4 v_color;
in vec3 v_sun;
in vec3 v_shade;
in vec3 v_anchor;
in float v_glow;
layout(binding=0) uniform texture2D sprite;
layout(binding=0) uniform sampler sprite_smp;
vec4 sprite_color() {
if (v_clip < 0.0) discard;
vec4 sampled = texture(sampler2D(sprite, sprite_smp), v_uv);
if (sampled.a < 0.01) discard;
return sampled * v_color;
}
@end
@fs fs_sprite
@include_block scene_out
@include_block shadow
@include_block sprite_fs
void main() {
vec3 light = mix(v_shade, v_sun, sun_shadow(v_anchor, vec3(0.0, 1.0, 0.0)));
frag_color = sprite_color() * vec4(light, 1.0);
write_scene(v_to_camera, 0.0);
}
@end
@fs fs_particle
@include_block sprite_fs
@include_block transparent_out
@include_block emissive
void main() {
write_transparent(sprite_color(), v_glow * EMISSIVE_GLOW);
}
@end
@fs fs_sprite_shadow
@include_block sprite_fs
void main() {
sprite_color();
}
@end
@program sprite vs_sprite fs_sprite
@program particle vs_sprite fs_particle
@program sprite_shadow vs_sprite fs_sprite_shadow

View File

@ -0,0 +1,225 @@
@vs vs_trile
@include_block view
layout(binding=1) uniform trile_params {
vec4 orientations[72];
float show_hidden; // shadow and reflection passes still draw cut triles
};
in vec3 position;
in vec4 data_n; // bytes / 255: x = swatch, y = ao (0..3), z = normal index
in vec4 instance; // xyz = position, w = orientation
in float tint;
in float cut;
out float v_clip;
out vec3 v_to_camera;
out vec3 v_world;
out vec3 v_normal;
out float v_swatch;
out float v_facing;
out float v_ao;
out vec3 v_shade;
out vec3 v_sun;
out float v_tint;
out float v_cut;
void main() {
vec4 data = data_n * 255.0;
int ori = int(instance.w + 0.5) * 3;
mat3 rotation = transpose(mat3(orientations[ori].xyz, orientations[ori + 1].xyz, orientations[ori + 2].xyz));
vec3 world = rotation * (position - 0.5) + 0.5 + instance.xyz;
int n = int(data.z + 0.5);
vec3 normal = vec3(0.0);
normal[n / 2] = (n % 2 == 0) ? 1.0 : -1.0;
v_normal = rotation * normal;
v_facing = smoothstep(0.0, 0.3, dot(v_normal, sun_direction.xyz));
v_ao = data.y / 3.0;
v_shade = shade_color.rgb;
v_sun = sun_color.rgb;
gl_Position = view_proj * vec4(world, 1.0);
v_cut = show_hidden > 0.5 ? 0.0 : cut;
// Fully cut triles are collapsed outside the clip volume, so nothing is drawn.
if (v_cut > 0.999) gl_Position = vec4(0.0, 0.0, 2.0, 1.0);
v_to_camera = camera.xyz - world;
v_world = world;
v_clip = dot(vec4(world, 1.0), clip);
v_swatch = data.x;
v_tint = tint;
}
@end
@block trile_in
in float v_clip;
in vec3 v_to_camera;
in vec3 v_world;
in vec3 v_normal;
in float v_swatch;
in float v_facing;
in float v_ao;
in vec3 v_shade;
in vec3 v_sun;
in float v_tint;
in float v_cut;
@end
@block palette
layout(binding=0) uniform texture2D palette;
layout(binding=0) uniform sampler palette_smp;
@end
@fs fs_trile
@include_block scene_out
@include_block emissive
@include_block shadow
@include_block trile_in
@include_block palette
layout(binding=2) uniform trile_fs_params {
vec4 sun_dir; // towards the sun
vec4 probe_min; // xyz = first chunk in probe_index, w = 1 when there are probes
vec4 probe_size; // xyz = probe_index size in chunks
float use_reflection; // the reflection pass can't read its own image
float reflection_height;
};
layout(binding=1) uniform texture2D trile_reflection;
layout(binding=2) uniform texture2D trile_reflection_glow;
layout(binding=1) uniform sampler trile_reflection_smp;
layout(binding=3) uniform texture3D probe_index; // per chunk: brick number + 1 in r + g * 256, 0 = none
layout(binding=4) uniform texture3D probe_atlas; // per brick 32^3 probes, 3 texels each: red, green, blue
layout(binding=2) uniform sampler probe_smp;
const float GLOSS_GLOW = 4.0; // how much a full gloss highlight blooms
const float REFLECTED_GLOW_CURVE = 0.4; // below 1, reflected glow fades slower than reflected colour
const float GLASS_PROJECTION = 2.0; // how strongly coloured sunlight paints its colour on
const int PROBE_BRICKS_PER_COLUMN = 16;
// The probe at the centre of the trile at cell, unless there is none or it is inside geometry.
bool probe_at(ivec3 cell, out vec4 r, out vec4 g, out vec4 b) {
ivec3 chunk = ivec3(floor(vec3(cell) / 32.0));
ivec3 slot = chunk - ivec3(probe_min.xyz);
if (any(lessThan(slot, ivec3(0))) || any(greaterThanEqual(slot, ivec3(probe_size.xyz)))) return false;
vec2 number = texelFetch(sampler3D(probe_index, probe_smp), slot, 0).rg * 255.0 + 0.5;
int brick = int(number.x) + int(number.y) * 256 - 1;
if (brick < 0) return false;
ivec3 local = cell - chunk * 32;
ivec3 texel = ivec3(local.x * 3, (brick % PROBE_BRICKS_PER_COLUMN) * 32 + local.y, (brick / PROBE_BRICKS_PER_COLUMN) * 32 + local.z);
r = texelFetch(sampler3D(probe_atlas, probe_smp), texel, 0);
g = texelFetch(sampler3D(probe_atlas, probe_smp), texel + ivec3(1, 0, 0), 0);
b = texelFetch(sampler3D(probe_atlas, probe_smp), texel + ivec3(2, 0, 0), 0);
return r.x >= 0.0;
}
// Light from the eight probes around a point half a trile out from the surface,
// leaving out probes behind the surface or inside geometry. Like sun_shadow it is
// taken at the trixel face centre, so it steps per trixel. a = 0 when no probe counts.
vec4 probe_light(vec3 world, vec3 normal) {
vec3 half_trixel = normal * (0.5 / 16.0);
vec3 face = (floor((world - half_trixel) * 16.0) + 0.5) / 16.0 + half_trixel;
vec3 grid = face + normal * 0.5 - 0.5;
ivec3 base = ivec3(floor(grid));
vec3 f = grid - vec3(base);
vec4 sum_r = vec4(0.0), sum_g = vec4(0.0), sum_b = vec4(0.0);
float total = 0.0;
for (int i = 0; i < 8; i++) {
ivec3 offset = ivec3(i & 1, (i >> 1) & 1, i >> 2);
ivec3 cell = base + offset;
if (dot(vec3(cell) + 0.5 - face, normal) < 0.01) continue;
vec4 r, g, b;
if (!probe_at(cell, r, g, b)) continue;
vec3 t = mix(1.0 - f, f, vec3(offset));
float w = max(t.x * t.y * t.z, 0.0001);
sum_r += r * w;
sum_g += g * w;
sum_b += b * w;
total += w;
}
if (total == 0.0) return vec4(0.0);
// Irradiance over pi from the SH: the cosine lobe convolved, both bands.
vec4 lobe = vec4(0.282095, 0.325735 * normal.y, 0.325735 * normal.z, 0.325735 * normal.x);
return vec4(max(vec3(dot(sum_r, lobe), dot(sum_g, lobe), dot(sum_b, lobe)) / total, 0.0), 1.0);
}
// Ordered dither, so dissolving triles fade without blending.
float dither(vec2 pixel) {
const float bayer[16] = float[16](0.0, 8.0, 2.0, 10.0, 12.0, 4.0, 14.0, 6.0, 3.0, 11.0, 1.0, 9.0, 15.0, 7.0, 13.0, 5.0);
ivec2 p = ivec2(pixel) % 4;
return (bayer[p.y * 4 + p.x] + 0.5) / 16.0;
}
void main() {
if (v_clip < 0.0 || v_cut > dither(gl_FragCoord.xy)) discard;
int id = int(v_swatch + 0.5);
vec4 swatch = texelFetch(sampler2D(palette, palette_smp), ivec2(id, 0), 0);
vec4 material = texelFetch(sampler2D(palette, palette_smp), ivec2(id, 1), 0); // g = reflectivity, b = gloss
vec3 albedo = swatch.rgb;
if (v_tint > 1.5) albedo = mix(albedo, vec3(1.0, 0.2, 0.2), 0.5);
else if (v_tint > 0.5) albedo = mix(albedo, vec3(0.2, 1.0, 0.2), 0.5);
vec3 sun = v_facing * sun_shadow(v_world, v_normal);
vec3 lit = sun * mix(0.25, 1.0, v_ao);
vec4 probe = probe_min.w > 0.5 ? probe_light(v_world, v_normal) : vec4(0.0);
vec3 shade = v_shade + probe.rgb;
vec3 light = mix(shade * mix(0.6, 1.0, v_ao), v_sun, lit);
vec3 color = albedo * light;
// Light through glass paints the glass colour onto what it hits, so the pattern
// shows on dark surfaces too, not only where the albedo can reflect it.
float bright = brightest(sun);
if (bright > 0.001) {
float tinted = (bright - min(sun.r, min(sun.g, sun.b))) / bright;
color = mix(color, sun * v_sun, min(1.0, tinted * GLASS_PROJECTION));
}
float glow = swatch.a * EMISSIVE_GLOW;
// Glossier is both stronger and sharper.
if (material.b > 0.0) {
vec3 halfway = normalize(normalize(v_to_camera) + sun_dir.xyz);
float highlight = pow(max(dot(v_normal, halfway), 0.0), mix(4.0, 96.0, material.b)) * material.b;
color += v_sun * sun * highlight;
glow += highlight * brightest(sun) * GLOSS_GLOW;
}
// Only floors lying on the reflection plane can show the planar reflection.
if (use_reflection > 0.5 && material.g > 0.0 && v_normal.y > 0.5 && abs(v_world.y - reflection_height) < 0.02) {
vec2 screen = gl_FragCoord.xy / vec2(textureSize(sampler2D(trile_reflection, trile_reflection_smp), 0));
vec2 uv = vec2(screen.x, 1.0 - screen.y);
color = mix(color, texture(sampler2D(trile_reflection, trile_reflection_smp), uv).rgb, material.g);
glow = max(glow, texture(sampler2D(trile_reflection_glow, trile_reflection_smp), uv).r * pow(material.g, REFLECTED_GLOW_CURVE));
}
// Emissive swatches show their own colour whatever the lighting.
frag_color = vec4(mix(color, albedo, swatch.a), 1.0);
write_scene(v_to_camera, glow);
}
@end
@fs fs_trile_shadow
@include_block trile_in
@include_block palette
void main() {
// Glass lets the sun through.
if (texelFetch(sampler2D(palette, palette_smp), ivec2(int(v_swatch + 0.5), 1), 0).r > 0.5) discard;
}
@end
// Drawn after the opaque casters and multiplied into the shadow tint, so light
// through several panes takes all their colours.
@fs fs_trile_glass_shadow
@include_block trile_in
@include_block palette
out vec4 frag_color;
void main() {
int id = int(v_swatch + 0.5);
if (texelFetch(sampler2D(palette, palette_smp), ivec2(id, 1), 0).r < 0.5) discard;
vec3 c = texelFetch(sampler2D(palette, palette_smp), ivec2(id, 0), 0).rgb;
// Tinted rather than darkened: the glass's brightest channel passes fully.
frag_color = vec4(c / max(max(c.r, max(c.g, c.b)), 0.001), gl_FragCoord.z);
}
@end
@program trile vs_trile fs_trile
@program trile_shadow vs_trile fs_trile_shadow
@program trile_glass_shadow vs_trile fs_trile_glass_shadow

View File

@ -0,0 +1,34 @@
@vs vs_ui
in vec2 position;
in vec2 uv;
in vec4 color0;
layout(binding=0) uniform ui_vs_params {
vec2 screen_size;
};
out vec2 v_uv;
out vec4 v_color;
void main() {
vec2 ndc = position / screen_size * 2.0 - 1.0;
gl_Position = vec4(ndc.x, -ndc.y, 0.0, 1.0);
v_uv = uv;
v_color = color0;
}
@end
@fs fs_ui
in vec2 v_uv;
in vec4 v_color;
out vec4 frag_color;
layout(binding=0) uniform texture2D tex;
layout(binding=0) uniform sampler smp;
void main() {
frag_color = texture(sampler2D(tex, smp), v_uv) * v_color;
}
@end
@program ui vs_ui fs_ui

View File

@ -0,0 +1,87 @@
@vs vs_water
@include_block view
@include_block quad
layout(binding=1) uniform water_vs_params {
float height;
float half_size;
};
out vec3 v_to_camera;
out vec3 v_world;
out vec2 v_xz;
void main() {
v_xz = camera.xz + (quad_corner(gl_VertexIndex) * 2.0 - 1.0) * half_size;
vec3 world = vec3(v_xz.x, height, v_xz.y);
gl_Position = view_proj * vec4(world, 1.0);
v_to_camera = camera.xyz - world;
v_world = world;
}
@end
@fs fs_water_floor
@include_block scene_out
in vec3 v_to_camera;
in vec3 v_world;
in vec2 v_xz;
layout(binding=2) uniform water_floor_params {
vec3 floor_color;
};
void main() {
frag_color = vec4(floor_color, 1.0);
write_scene(v_to_camera, 0.0);
}
@end
@fs fs_water
@include_block shadow
@include_block transparent_out
in vec3 v_to_camera;
in vec3 v_world;
in vec2 v_xz;
layout(binding=2) uniform water_fs_params {
vec3 water_color;
vec3 sun_direction; float shininess;
vec3 sun_color; float time;
float reflectivity;
float distortion;
};
layout(binding=0) uniform texture2D reflection;
layout(binding=1) uniform texture2D normals;
layout(binding=2) uniform texture2D reflection_glow;
layout(binding=0) uniform sampler reflection_smp;
layout(binding=1) uniform sampler normals_smp;
void main() {
vec2 flow = time * vec2(-0.005, -0.012);
vec3 n1 = texture(sampler2D(normals, normals_smp), v_xz * 0.4 + flow * 1.5).xzy * 2.0 - 1.0;
vec3 n2 = texture(sampler2D(normals, normals_smp), v_xz * 0.1 + flow * 1.7).xzy * 2.0 - 1.0;
vec3 normal = normalize(n1 + n2);
vec3 view_dir = normalize(v_to_camera);
float facing = max(dot(view_dir, normal), 0.0);
float fresnel = min(1.0, 0.02 + 0.98 * pow(1.0 - facing, 5.0) + 0.45);
vec2 screen = gl_FragCoord.xy / vec2(textureSize(sampler2D(reflection, reflection_smp), 0));
vec2 reflect_uv = vec2(screen.x, 1.0 - screen.y) + normal.xz * distortion;
vec3 reflected = texture(sampler2D(reflection, reflection_smp), reflect_uv).rgb;
float reflect_amount = mix(fresnel, 1.0, reflectivity);
vec3 color = mix(water_color, reflected, reflect_amount);
float alpha = mix(mix(0.3, 0.5, fresnel), 1.0, reflectivity);
vec3 halfway = normalize(view_dir + sun_direction);
vec3 sun = sun_shadow(v_world, vec3(0.0, 1.0, 0.0));
float glint = smoothstep(0.5, 0.55, pow(max(dot(normal, halfway), 0.0), shininess)) * brightest(sun);
float reflected_glow = texture(sampler2D(reflection_glow, reflection_smp), reflect_uv).r * reflect_amount;
write_transparent(vec4(mix(color, sun_color, glint), max(alpha, glint)), max(glint, reflected_glow));
}
@end
@program water_floor vs_water fs_water_floor
@program water vs_water fs_water

View File

@ -0,0 +1,29 @@
sky_init :: () {
desc := pipeline_desc(sky_shader_desc(sg_query_backend()), .VIEW_OPAQUE);
desc.depth.compare = .ALWAYS;
sky.pipeline = sg_make_pipeline(*desc);
}
sky_draw :: (pass: *Pass) {
env := view_environment(pass.view);
if !env.sky return;
params := Sky_Params.{
sky_base = .[env.sky_base.x, env.sky_base.y, env.sky_base.z, 0],
sky_top = .[env.sky_top.x, env.sky_top.y, env.sky_top.z, 0],
sun_disk = .[env.sun_disk.x, env.sun_disk.y, env.sun_disk.z, 0],
sun_halo = .[env.sun_halo.x, env.sun_halo.y, env.sun_halo.z, 0],
horizon_halo = .[env.horizon_halo.x, env.horizon_halo.y, env.horizon_halo.z, 0],
sun = .[env.sun_direction.x, env.sun_direction.y, env.sun_direction.z, env.sky_intensity],
};
sg_apply_pipeline(sky.pipeline);
apply_uniforms(UB_view_params, *pass.params);
apply_uniforms(UB_sky_params, *params);
sg_draw(0, 3, 1);
}
#scope_file
sky : struct {
pipeline : sg_pipeline;
}

View File

@ -0,0 +1,101 @@
sprites_init :: () {
// Billboards and particles share the vertex shader, so they share attribute slots.
make :: (shader: sg_shader_desc, target: Pipeline_Target, blend := sg_blend_state.{}) -> sg_pipeline {
desc := pipeline_desc(shader, target, blend, depth_write = target != .VIEW_TRANSPARENT);
desc.layout.buffers[0].step_func = .PER_INSTANCE;
desc.layout.attrs[ATTR_sprite_center] = .{ format = .FLOAT3 };
desc.layout.attrs[ATTR_sprite_size] = .{ format = .FLOAT2 };
desc.layout.attrs[ATTR_sprite_uv_rect] = .{ format = .FLOAT4 };
desc.layout.attrs[ATTR_sprite_face] = .{ format = .FLOAT3 };
desc.layout.attrs[ATTR_sprite_color] = .{ format = .FLOAT4 };
desc.layout.attrs[ATTR_sprite_glow] = .{ format = .FLOAT };
return sg_make_pipeline(*desc);
}
backend := sg_query_backend();
sprites.pipelines[Kind.BILLBOARD] = make(sprite_shader_desc(backend), .VIEW_OPAQUE);
sprites.pipelines[Kind.PARTICLE_ALPHA] = make(particle_shader_desc(backend), .VIEW_TRANSPARENT, ALPHA_BLEND);
sprites.pipelines[Kind.PARTICLE_ADDITIVE] = make(particle_shader_desc(backend), .VIEW_TRANSPARENT, ADDITIVE_BLEND);
sprites.shadow_pipeline = make(sprite_shadow_shader_desc(backend), .SHADOW);
}
sprites_upload :: (scene: *Scene) {
array_reset_keeping_memory(*sprites.instances);
array_reset_keeping_memory(*sprites.batches);
draws : [..]Keyed(Instance);
draws.allocator = temp;
for view_index: 0..scene.views.count-1 {
array_reset_keeping_memory(*draws);
for scene.billboards {
if it.view.index != view_index continue;
array_add(*draws, .{key(.BILLBOARD, it.sheet), .{it.position, it.size, it.uv_rect, it.face, .{1, 1, 1, 1}, 0}});
}
for batch: scene.particles {
if batch.view.index != view_index continue;
kind := ifx batch.blend == .ADDITIVE then Kind.PARTICLE_ADDITIVE else .PARTICLE_ALPHA;
for batch.particles {
array_add(*draws, .{key(kind, batch.sheet), .{it.position, .{it.size, it.size}, it.uv_rect, BILLBOARD_FACE_CAMERA, it.color, it.glow}});
}
}
batch_instances(view_index, draws, *sprites.batches, *sprites.instances);
}
stream_upload(*sprites.stream, sprites.instances);
}
// Opaque sprites go before water, transparent ones after it. Only billboards cast shadows.
sprites_draw :: (pass: *Pass, transparent: bool) {
shadow := pass.kind == .SHADOW;
current : Kind = xx -1;
for sprites.batches {
if it.view_index != pass.view_index continue;
kind := cast(Kind) (it.key >> 32);
if (kind != .BILLBOARD) != transparent continue;
if kind != current {
current = kind;
sg_apply_pipeline(ifx shadow then sprites.shadow_pipeline else sprites.pipelines[kind]);
apply_uniforms(UB_view_params, *pass.params);
params := Sprite_Params.{ lit = xx (kind == .BILLBOARD) };
apply_uniforms(UB_sprite_params, *params);
if kind == .BILLBOARD && !shadow apply_uniforms(UB_shadow_params, *pass.shadow);
}
bind : sg_bindings;
bind.vertex_buffers[0] = sprites.stream.buffer;
bind.vertex_buffer_offsets[0] = it.first * size_of(Instance);
bind.images[IMG_sprite] = texture_image(xx (it.key & 0xFFFF_FFFF));
bind.samplers[SMP_sprite_smp] = samplers.nearest_clamp;
if kind == .BILLBOARD && !shadow bind_shadow(pass, *bind);
sg_apply_bindings(*bind);
sg_draw(0, 6, it.count);
}
}
#scope_file
Kind :: enum {
BILLBOARD;
PARTICLE_ALPHA;
PARTICLE_ADDITIVE;
}
Instance :: struct {
center : Vector3;
size : Vector2;
uv_rect : Vector4;
face : Vector3;
color : Vector4;
glow : float;
}
sprites : struct {
pipelines : [#run enum_highest_value(Kind) + 1]sg_pipeline;
shadow_pipeline : sg_pipeline;
instances : [..]Instance;
batches : [..]Batch;
stream : Stream_Buffer;
}
key :: (kind: Kind, sheet: Texture) -> s64 {
return (cast(s64) kind << 32) | sheet.id;
}

View File

@ -0,0 +1,211 @@
triles_init :: (orientations: [ORIENTATION_COUNT]Matrix3) {
desc := pipeline_desc(trile_shader_desc(sg_query_backend()), .VIEW_OPAQUE, depth_write = true);
desc.layout.buffers[1].step_func = .PER_INSTANCE;
desc.layout.attrs[ATTR_trile_position] = .{ format = .FLOAT3 };
desc.layout.attrs[ATTR_trile_data_n] = .{ format = .UBYTE4N };
desc.layout.attrs[ATTR_trile_instance] = .{ format = .FLOAT4, buffer_index = 1 };
desc.layout.attrs[ATTR_trile_tint] = .{ format = .FLOAT, buffer_index = 1 };
desc.layout.attrs[ATTR_trile_cut] = .{ format = .FLOAT, buffer_index = 1 };
desc.index_type = .UINT16;
desc.cull_mode = .BACK;
desc.face_winding = .CCW;
triles.pipeline = sg_make_pipeline(*desc);
// Back faces only, so lit faces don't shadow themselves.
shadow_desc := pipeline_desc(trile_shadow_shader_desc(sg_query_backend()), .SHADOW, depth_write = true);
shadow_desc.layout = desc.layout;
shadow_desc.index_type = .UINT16;
shadow_desc.cull_mode = .FRONT;
shadow_desc.face_winding = .CCW;
triles.shadow_pipeline = sg_make_pipeline(*shadow_desc);
// Alpha keeps the nearest glass depth, so light shafts start at the window.
glass_blend := MULTIPLY_BLEND;
glass_blend.src_factor_alpha = .ONE;
glass_blend.dst_factor_alpha = .ONE;
glass_blend.op_alpha = .MIN;
glass_desc := pipeline_desc(trile_glass_shadow_shader_desc(sg_query_backend()), .SHADOW, glass_blend);
glass_desc.colors[0].write_mask = .RGBA;
glass_desc.layout = desc.layout;
glass_desc.index_type = .UINT16;
glass_desc.cull_mode = .FRONT;
glass_desc.face_winding = .CCW;
triles.glass_shadow_pipeline = sg_make_pipeline(*glass_desc);
for orientations {
for r: 0..2 for c: 0..2 triles.params.orientations[it_index * 3 + r][c] = it.coef[r][c];
}
triles.palette_dirty = true;
}
renderer_trile_mesh_create :: (vertices: []Trile_Vertex, indices: []u16) -> u32 {
id, mesh := slot_add(*triles.meshes);
make_mesh(mesh, vertices, indices);
return id;
}
renderer_trile_mesh_update :: (id: u32, vertices: []Trile_Vertex, indices: []u16) {
mesh := slot_get(*triles.meshes, id);
free_mesh(mesh);
make_mesh(mesh, vertices, indices);
}
renderer_trile_mesh_destroy :: (id: u32) {
free_mesh(slot_get(*triles.meshes, id));
slot_remove(*triles.meshes, id);
}
renderer_swatch_set :: (id: u8, color: [3]u8, reflectivity: u8, gloss: u8, emittance: u8, glass: bool) {
for 0..2 triles.palette[0][id][it] = color[it];
triles.palette[0][id][3] = xx (min(cast(int) emittance, 127) * 255 / 127); // emittance is 0..127
triles.palette[1][id][0] = xx ifx glass then 255 else 0;
triles.palette[1][id][1] = reflectivity;
triles.palette[1][id][2] = gloss;
triles.palette_dirty = true;
}
triles_upload :: (scene: *Scene) {
if triles.palette_dirty {
triles.palette_dirty = false;
if triles.palette_image.id sg_destroy_image(triles.palette_image);
desc := sg_image_desc.{ width = 256, height = 2, pixel_format = .RGBA8 };
desc.data.subimage[0][0] = .{ triles.palette.data, size_of(type_of(triles.palette)) };
triles.palette_image = sg_make_image(*desc);
}
array_reset_keeping_memory(*triles.instances);
array_reset_keeping_memory(*triles.batches);
draws : [..]Keyed(Instance);
draws.allocator = temp;
for view, view_index: scene.views {
array_reset_keeping_memory(*draws);
if view.draw_world {
for chunk: scene.chunks for group: chunk.groups for group.instances {
position := chunk.origin + Vector3.{xx it.x, xx it.y, xx it.z};
cut := trile_cut(.{xx view_index}, group.mesh, position);
array_add(*draws, .{group.mesh.id, .{position, xx it.orientation, 0, cut}});
}
}
for scene.triles {
if it.view.index != view_index continue;
preview : s64 = ifx it.tint != .NONE then PREVIEW_KEY else 0;
cut := ifx preview then 0.0 else trile_cut(it.view, it.mesh, it.position);
array_add(*draws, .{preview | it.mesh.id, .{it.position, xx it.orientation, xx it.tint, cut}});
}
batch_instances(view_index, draws, *triles.batches, *triles.instances);
}
stream_upload(*triles.stream, triles.instances);
}
// After every opaque caster, so glass behind something solid doesn't tint.
triles_draw_glass_shadow :: (pass: *Pass) {
sg_apply_pipeline(triles.glass_shadow_pipeline);
apply_uniforms(UB_view_params, *pass.params);
triles.params.show_hidden = 1;
apply_uniforms(UB_trile_params, *triles.params);
for triles.batches {
if it.view_index != pass.view_index || it.key & PREVIEW_KEY continue;
mesh := slot_get(*triles.meshes, xx it.key);
if !mesh || mesh.index_count == 0 continue;
bind : sg_bindings;
bind.vertex_buffers[0] = mesh.vertices;
bind.index_buffer = mesh.indices;
bind.vertex_buffers[1] = triles.stream.buffer;
bind.vertex_buffer_offsets[1] = it.first * size_of(Instance);
bind.images[IMG_palette] = triles.palette_image;
bind.samplers[SMP_palette_smp] = samplers.nearest_clamp;
sg_apply_bindings(*bind);
sg_draw(0, mesh.index_count, it.count);
}
}
triles_draw :: (pass: *Pass) {
// Cut triles are only hidden from the camera itself, not from shadows or reflections.
triles.params.show_hidden = xx (pass.kind != .MAIN);
sg_apply_pipeline(ifx pass.kind == .SHADOW then triles.shadow_pipeline else triles.pipeline);
apply_uniforms(UB_view_params, *pass.params);
apply_uniforms(UB_trile_params, *triles.params);
if pass.kind != .SHADOW {
apply_uniforms(UB_shadow_params, *pass.shadow);
fs_params := Trile_Fs_Params.{
sun_dir = pass.params.sun_direction,
use_reflection = xx (pass.kind == .MAIN),
reflection_height = view_environment(pass.view).reflection_height,
};
probes_set_params(*fs_params);
apply_uniforms(UB_trile_fs_params, *fs_params);
}
for triles.batches {
if it.view_index != pass.view_index || (pass.kind != .MAIN && it.key & PREVIEW_KEY) continue;
mesh := slot_get(*triles.meshes, xx (it.key & ~PREVIEW_KEY));
if !mesh || mesh.index_count == 0 continue;
bind : sg_bindings;
bind.vertex_buffers[0] = mesh.vertices;
bind.index_buffer = mesh.indices;
bind.vertex_buffers[1] = triles.stream.buffer;
bind.vertex_buffer_offsets[1] = it.first * size_of(Instance);
bind.images[IMG_palette] = triles.palette_image;
bind.samplers[SMP_palette_smp] = samplers.nearest_clamp;
if pass.kind != .SHADOW {
bind_shadow(pass, *bind);
bind.images[IMG_trile_reflection] = ifx pass.kind == .MAIN then view_reflection_image(pass.view_index) else texture_image(0);
bind.images[IMG_trile_reflection_glow] = ifx pass.kind == .MAIN then view_reflection_glow_image(pass.view_index) else texture_image(0);
bind.samplers[SMP_trile_reflection_smp] = samplers.linear_clamp;
probes_bind(*bind);
}
sg_apply_bindings(*bind);
sg_draw(0, mesh.index_count, it.count);
}
}
#scope_file
Mesh :: struct {
vertices : sg_buffer;
indices : sg_buffer;
index_count : s32;
}
Instance :: struct {
position : Vector3;
orientation : float;
tint : float;
cut : float; // 0..1 dissolved away from the camera, still casts shadows
}
PREVIEW_KEY :: 1 << 32;
triles : struct {
pipeline : sg_pipeline;
shadow_pipeline : sg_pipeline;
glass_shadow_pipeline : sg_pipeline;
params : Trile_Params;
meshes : Slots(Mesh);
palette : [2][256][4]u8; // row 0: colour, emittance; row 1: glass, reflectivity, gloss
palette_image : sg_image;
palette_dirty : bool;
instances : [..]Instance;
batches : [..]Batch;
stream : Stream_Buffer;
}
make_mesh :: (mesh: *Mesh, vertices: []Trile_Vertex, indices: []u16) {
mesh.index_count = xx indices.count;
if indices.count {
mesh.vertices = sg_make_buffer(*(sg_buffer_desc.{ data = .{ vertices.data, xx (vertices.count * size_of(Trile_Vertex)) } }));
mesh.indices = sg_make_buffer(*(sg_buffer_desc.{ type = .INDEXBUFFER, data = .{ indices.data, xx (indices.count * size_of(u16)) } }));
}
}
free_mesh :: (mesh: *Mesh) {
if mesh.index_count {
sg_destroy_buffer(mesh.vertices);
sg_destroy_buffer(mesh.indices);
}
mesh.* = .{};
}

48
src/renderer_sokol/ui.jai Normal file
View File

@ -0,0 +1,48 @@
ui_init :: () {
desc := pipeline_desc(ui_shader_desc(sg_query_backend()), .SCREEN, blend = ALPHA_BLEND);
desc.layout.attrs[ATTR_ui_position] = .{ format = .FLOAT2 };
desc.layout.attrs[ATTR_ui_uv] = .{ format = .FLOAT2 };
desc.layout.attrs[ATTR_ui_color0] = .{ format = .FLOAT4 };
ui.pipeline = sg_make_pipeline(*desc);
}
ui_upload :: (scene: *Scene) {
array_reset_keeping_memory(*ui.vertices);
for scene.ui array_add(*ui.vertices, ..it.vertices);
stream_upload(*ui.stream, ui.vertices);
}
ui_draw :: (scene: *Scene, w: s32, h: s32) {
if ui.vertices.count == 0 return;
sg_apply_pipeline(ui.pipeline);
params := Ui_Vs_Params.{ screen_size = .[xx w, xx h] };
apply_uniforms(UB_ui_vs_params, *params);
bind : sg_bindings;
bind.vertex_buffers[0] = ui.stream.buffer;
bind.samplers[SMP_smp] = samplers.nearest_clamp;
first : s32;
for scene.ui {
if it.set_scissor {
s := it.scissor;
sg_apply_scissor_rect(s.x, s.y, max(s.w, 0), max(s.h, 0), true);
} else if it.clear_scissor {
sg_apply_scissor_rect(0, 0, w, h, true);
} else if it.vertices.count {
bind.images[IMG_tex] = texture_image(it.texture.id);
sg_apply_bindings(*bind);
sg_draw(first, xx it.vertices.count, 1);
first += xx it.vertices.count;
}
}
}
#scope_file
ui : struct {
pipeline : sg_pipeline;
stream : Stream_Buffer;
vertices : [..]Ui_Vertex;
}

View File

@ -0,0 +1,227 @@
BLOOM_LEVELS :: 5;
BLOOM_SCATTER :: 0.7;
SHAFT_STEPS :: 48;
SHAFT_MAX_DISTANCE :: 100.0;
views_init :: () {
backend := sg_query_backend();
post_desc := pipeline_desc(post_shader_desc(backend), .SCREEN);
views.post = sg_make_pipeline(*post_desc);
shafts_desc := pipeline_desc(shafts_shader_desc(backend), .POST);
views.shafts = sg_make_pipeline(*shafts_desc);
glow_desc := pipeline_desc(bloom_glow_shader_desc(backend), .POST);
views.bloom_glow = sg_make_pipeline(*glow_desc);
down_desc := pipeline_desc(bloom_down_shader_desc(backend), .POST);
views.bloom_down = sg_make_pipeline(*down_desc);
// Each level becomes a blend toward the blurrier level below it, so the glow is
// mostly wide blur rather than a copy of the bright pixels.
up_desc := pipeline_desc(bloom_up_shader_desc(backend), .POST, sg_blend_state.{ enabled = true, src_factor_rgb = .BLEND_COLOR, dst_factor_rgb = .ONE_MINUS_BLEND_COLOR });
up_desc.blend_color = .{ BLOOM_SCATTER, BLOOM_SCATTER, BLOOM_SCATTER, 1 };
views.bloom_up = sg_make_pipeline(*up_desc);
}
view_begin_pass :: (index: int, width: s32, height: s32, kind: Pass_Kind, opaque: bool) {
if width != views.width || height != views.height {
for views.targets {
destroy_target(it.main);
destroy_target(it.reflection);
for level: it.bloom {
sg_destroy_attachments(level.attachments);
sg_destroy_image(level.image);
}
sg_destroy_attachments(it.shafts.attachments);
sg_destroy_image(it.shafts.image);
}
array_reset_keeping_memory(*views.targets);
views.width = width;
views.height = height;
}
while views.targets.count <= index {
targets := array_add(*views.targets);
targets.main = make_target(width, height);
targets.reflection = make_target(width, height);
w, h := width, height;
for *level: targets.bloom {
w, h = max(w / 2, 1), max(h / 2, 1);
level.image = sg_make_image(*(sg_image_desc.{ render_target = true, width = w, height = h, pixel_format = VIEW_COLOR_FORMAT, sample_count = 1 }));
desc : sg_attachments_desc;
desc.colors[0].image = level.image;
level.attachments = sg_make_attachments(*desc);
}
targets.shafts.image = sg_make_image(*(sg_image_desc.{ render_target = true, width = max(width / 2, 1), height = max(height / 2, 1), pixel_format = VIEW_COLOR_FORMAT, sample_count = 1 }));
desc : sg_attachments_desc;
desc.colors[0].image = targets.shafts.image;
targets.shafts.attachments = sg_make_attachments(*desc);
}
targets := views.targets[index];
target := ifx kind == .REFLECTION then targets.reflection else targets.main;
action : sg_pass_action;
if opaque {
action.colors[0] = .{ load_action = .CLEAR, clear_value = .{0, 0, 0, 1} };
action.colors[1] = .{ load_action = .CLEAR, clear_value = .{0, 0, 0, 0} };
action.colors[2] = .{ load_action = .CLEAR, clear_value = .{1.0e4, 0, 0, 0} };
action.depth = .{ load_action = .CLEAR, clear_value = 1 };
sg_begin_pass(*(sg_pass.{ action = action, attachments = target.opaque }));
} else {
action.colors[0] = .{ load_action = .LOAD };
action.colors[1] = .{ load_action = .LOAD };
action.depth = .{ load_action = .LOAD };
sg_begin_pass(*(sg_pass.{ action = action, attachments = target.transparent }));
}
}
view_begin_shadow_pass :: (index: int) {
while views.shadows.count <= index {
shadow := array_add(*views.shadows);
shadow.tint = sg_make_image(*(sg_image_desc.{ render_target = true, width = SHADOW_MAP_SIZE, height = SHADOW_MAP_SIZE, pixel_format = SHADOW_TINT_FORMAT, sample_count = 1 }));
shadow.depth = sg_make_image(*(sg_image_desc.{ render_target = true, width = SHADOW_MAP_SIZE, height = SHADOW_MAP_SIZE, pixel_format = VIEW_DEPTH_FORMAT, sample_count = 1 }));
desc : sg_attachments_desc;
desc.colors[0].image = shadow.tint;
desc.depth_stencil.image = shadow.depth;
shadow.attachments = sg_make_attachments(*desc);
}
action : sg_pass_action;
action.depth = .{ load_action = .CLEAR, clear_value = 1 };
action.colors[0] = .{ load_action = .CLEAR, clear_value = .{1, 1, 1, 1} };
sg_begin_pass(*(sg_pass.{ action = action, attachments = views.shadows[index].attachments }));
}
view_shadow_image :: (index: int) -> sg_image {
return views.shadows[index].depth;
}
view_shadow_tint_image :: (index: int) -> sg_image {
return views.shadows[index].tint;
}
view_scene_image :: (index: int) -> sg_image {
return views.targets[index].main.scene;
}
view_reflection_image :: (index: int) -> sg_image {
return views.targets[index].reflection.color;
}
view_reflection_glow_image :: (index: int) -> sg_image {
return views.targets[index].reflection.glow;
}
// Halves the glowing parts of the view down a chain of levels, then adds the
// levels back up, leaving the glow in the first level.
view_bloom :: (index: int) {
targets := *views.targets[index];
run :: (pipeline: sg_pipeline, source: sg_image, target: sg_attachments, load: bool) #expand {
action : sg_pass_action;
action.colors[0] = ifx load then sg_color_attachment_action.{ load_action = .LOAD } else .{ load_action = .DONTCARE };
sg_begin_pass(*(sg_pass.{ action = action, attachments = target }));
sg_apply_pipeline(pipeline);
bind : sg_bindings;
bind.images[IMG_bloom_source] = source;
bind.samplers[SMP_bloom_smp] = samplers.linear_clamp;
if pipeline.id == views.bloom_glow.id bind.images[IMG_bloom_glow] = targets.main.glow;
sg_apply_bindings(*bind);
sg_draw(0, 3, 1);
sg_end_pass();
}
run(views.bloom_glow, targets.main.color, targets.bloom[0].attachments, false);
for 1..BLOOM_LEVELS-1 run(views.bloom_down, targets.bloom[it - 1].image, targets.bloom[it].attachments, false);
for < 1..BLOOM_LEVELS-1 run(views.bloom_up, targets.bloom[it].image, targets.bloom[it - 1].attachments, true);
}
// Marches each view ray through the coloured shadow map, after the main pass has
// written how far it reaches.
view_shafts :: (pass: *Pass) {
env := view_environment(pass.view);
action : sg_pass_action;
action.colors[0] = .{ load_action = .CLEAR, clear_value = .{0, 0, 0, 1} };
sg_begin_pass(*(sg_pass.{ action = action, attachments = views.targets[pass.view_index].shafts.attachments }));
if env.shaft_amount > 0 {
sg_apply_pipeline(views.shafts);
params := Shaft_Params.{
density = env.shaft_density,
amount = env.shaft_amount,
max_distance = SHAFT_MAX_DISTANCE,
steps = SHAFT_STEPS,
};
apply_uniforms(UB_view_params, *pass.params);
apply_uniforms(UB_shadow_params, *pass.shadow);
apply_uniforms(UB_shaft_params, *params);
bind : sg_bindings;
bind.images[IMG_shaft_scene] = views.targets[pass.view_index].main.scene;
bind.samplers[SMP_shaft_scene_smp] = samplers.nearest_clamp;
bind_shadow(pass, *bind);
sg_apply_bindings(*bind);
sg_draw(0, 3, 1);
}
sg_end_pass();
}
view_composite :: (index: int, env: Environment) {
sg_apply_pipeline(views.post);
params := Post_Params.{
exposure = env.exposure,
contrast = env.contrast,
saturation = env.saturation,
bloom_amount = env.bloom_amount,
};
apply_uniforms(UB_post_params, *params);
bind : sg_bindings;
bind.images[IMG_view_color] = views.targets[index].main.color;
bind.images[IMG_bloom] = views.targets[index].bloom[0].image;
bind.images[IMG_shafts] = views.targets[index].shafts.image;
bind.samplers[SMP_view_smp] = samplers.nearest_clamp;
bind.samplers[SMP_bloom_view_smp] = samplers.linear_clamp;
sg_apply_bindings(*bind);
sg_draw(0, 3, 1);
}
#scope_file
View_Target :: struct {
color : sg_image;
glow : sg_image;
scene : sg_image;
depth : sg_image;
opaque : sg_attachments;
transparent : sg_attachments;
}
views : struct {
post : sg_pipeline;
shafts : sg_pipeline;
bloom_glow : sg_pipeline;
bloom_down : sg_pipeline;
bloom_up : sg_pipeline;
targets : [..]struct { main, reflection: View_Target; bloom: [BLOOM_LEVELS]struct { image: sg_image; attachments: sg_attachments; }; shafts: struct { image: sg_image; attachments: sg_attachments; }; };
shadows : [..]struct { depth, tint: sg_image; attachments: sg_attachments; };
width : s32;
height : s32;
}
make_target :: (width: s32, height: s32) -> View_Target {
t : View_Target;
t.color = sg_make_image(*(sg_image_desc.{ render_target = true, width = width, height = height, pixel_format = VIEW_COLOR_FORMAT, sample_count = 1 }));
t.glow = sg_make_image(*(sg_image_desc.{ render_target = true, width = width, height = height, pixel_format = VIEW_GLOW_FORMAT, sample_count = 1 }));
t.scene = sg_make_image(*(sg_image_desc.{ render_target = true, width = width, height = height, pixel_format = VIEW_SCENE_FORMAT, sample_count = 1 }));
t.depth = sg_make_image(*(sg_image_desc.{ render_target = true, width = width, height = height, pixel_format = VIEW_DEPTH_FORMAT, sample_count = 1 }));
desc : sg_attachments_desc;
desc.colors[0].image = t.color;
desc.colors[1].image = t.glow;
desc.depth_stencil.image = t.depth;
t.transparent = sg_make_attachments(*desc);
desc.colors[2].image = t.scene;
t.opaque = sg_make_attachments(*desc);
return t;
}
destroy_target :: (t: View_Target) {
sg_destroy_attachments(t.opaque);
sg_destroy_attachments(t.transparent);
sg_destroy_image(t.color);
sg_destroy_image(t.glow);
sg_destroy_image(t.scene);
sg_destroy_image(t.depth);
}

View File

@ -0,0 +1,62 @@
WATER_HALF_SIZE :: 1000.0;
water_init :: () {
backend := sg_query_backend();
floor_desc := pipeline_desc(water_floor_shader_desc(backend), .VIEW_OPAQUE, depth_write = true);
water.floor = sg_make_pipeline(*floor_desc);
surface_desc := pipeline_desc(water_shader_desc(backend), .VIEW_TRANSPARENT, ALPHA_BLEND);
water.surface = sg_make_pipeline(*surface_desc);
}
// The deep plane is opaque, so the surface can measure how much water lies above it.
water_draw_floor :: (pass: *Pass) {
env := pass.view.environment;
if pass.kind != .MAIN || !pass.view.draw_world || !env || !env.water return;
sg_apply_pipeline(water.floor);
apply_uniforms(UB_view_params, *pass.params);
vs := Water_Vs_Params.{ height = 0, half_size = WATER_HALF_SIZE };
fs := Water_Floor_Params.{ floor_color = env.deep_color.component };
apply_uniforms(UB_water_vs_params, *vs);
apply_uniforms(UB_water_floor_params, *fs);
sg_draw(0, 6, 1);
}
water_draw :: (pass: *Pass) {
env := pass.view.environment;
if pass.kind != .MAIN || !pass.view.draw_world || !env || !env.water return;
sg_apply_pipeline(water.surface);
apply_uniforms(UB_view_params, *pass.params);
apply_uniforms(UB_shadow_params, *pass.shadow);
bind : sg_bindings;
bind.images[IMG_reflection] = view_reflection_image(pass.view_index);
bind.images[IMG_normals] = texture_image(env.water_normals.id);
bind.images[IMG_reflection_glow] = view_reflection_glow_image(pass.view_index);
bind.samplers[SMP_reflection_smp] = samplers.linear_clamp;
bind.samplers[SMP_normals_smp] = samplers.linear_repeat;
bind_shadow(pass, *bind);
sg_apply_bindings(*bind);
vs := Water_Vs_Params.{ height = env.reflection_height, half_size = WATER_HALF_SIZE };
fs := Water_Fs_Params.{
water_color = env.water_color.component,
sun_direction = env.sun_direction.component,
shininess = env.water_shininess,
sun_color = env.sun_color.component,
time = pass.scene.time,
reflectivity = env.water_reflectivity,
distortion = env.water_distortion,
};
apply_uniforms(UB_water_vs_params, *vs);
apply_uniforms(UB_water_fs_params, *fs);
sg_draw(0, 6, 1);
}
#scope_file
water : struct {
floor : sg_pipeline;
surface : sg_pipeline;
}

View File

@ -33,10 +33,26 @@ animation_player_tick :: (player: *Animation_Player) {
}
}
animation_draw :: (player: *Animation_Player, position: Vector3, flipX: bool = false, flipY: bool = false, faceDir : Vector3 = .{-100, -100, -100}) {
animation_draw :: (view: View_Id, player: *Animation_Player, position: Vector3, flip_x := false, face := BILLBOARD_FACE_CAMERA) {
animation_player_tick(player);
if player.current_animation == null then return;
create_billboard_rendering_task(position, player.current_animation, player.current_frame, flipX, flipY, faceDir);
draw_animation_frame(view, player.current_animation, player.current_frame, position, flip_x, face);
}
// Sprites are 16 pixels to a world unit.
draw_animation_frame :: (view: View_Id, anim: *Animation, frame_index: s32, position: Vector3, flip_x := false, face := BILLBOARD_FACE_CAMERA) {
frame := anim.frames[frame_index];
uv := Vector4.{
cast(float) frame.x / anim.sheet_w,
cast(float) frame.y / anim.sheet_h,
cast(float) frame.w / anim.sheet_w,
cast(float) frame.h / anim.sheet_h,
};
if flip_x {
uv.x += uv.z;
uv.z = -uv.z;
}
draw_billboard(view, anim.sheet, uv, .{cast(float)(frame.w / 16), cast(float)(frame.h / 16)}, position, face);
}
animation_set :: (player: *Animation_Player, animation: string) {
@ -70,7 +86,7 @@ Frame :: struct {
Animation :: struct {
name : string;
sheet : sg_image;
sheet : Texture;
sheet_w : s32;
sheet_h : s32;
frames : [..]Frame;

View File

@ -1,147 +0,0 @@
Arb_Tri :: struct {
pos : [3]Vector3;
col : [3]Vector4;
uv : [3]Vector2;
}
Arb_Draw_Command_Type :: enum {
INVALID;
DRAW_TEXT;
FLUSH_TRI;
SET_TEXTURE;
PREPARE_TEXT;
FONT_BOUNDARY;
QUAD_OCCLUDER;
REMOVE_TEXTURE;
SET_SCISSOR;
REMOVE_SCISSOR;
}
Arb_Draw_Command :: struct {
type : Arb_Draw_Command_Type = .INVALID;
// for triangles
tri_offset : int = 0;
tri_count : int = 0;
texture : *Ui_Texture;
// for text
layer: s32 = 0;
scissor: Ui_Rect;
}
Arb_Tri_State :: struct {
active : bool = false;
trilist : [..]Arb_Tri;
command_list : [..]Arb_Draw_Command;
latest_flush : int = 0;
}
arbTriState : Arb_Tri_State;
init_arb_state :: () {
gPipelines.arbtri.bind.images[0] = default_texture.tex;
array_reset_keeping_memory(*arbTriState.trilist);
array_reset_keeping_memory(*arbTriState.command_list);
arbTriState.active = true;
arbTriState.latest_flush = 0;
}
arb_tri_command_add :: (command: Arb_Draw_Command) {
if !arbTriState.active {
init_arb_state();
}
array_add(*arbTriState.command_list, command);
}
arb_tri_add :: (tri: Arb_Tri) {
if !arbTriState.active {
init_arb_state();
}
array_add(*arbTriState.trilist, tri);
}
transform_to_screen_x :: (coord: float) -> float {
w, h := get_window_size();
return (coord / cast(float) w) * 2.0 - 1.0;
}
transform_to_screen_y :: (coord: float) -> float {
w, h := get_window_size();
return (coord / cast(float) h) * 2.0 - 1.0;
}
arb_tri_flush :: () {
if !arbTriState.active {
return;
}
arbTriState.active = false;
w, h := get_window_size();
inv_w := 2.0 / cast(float) w;
inv_h := 2.0 / cast(float) h;
for tri, i : arbTriState.trilist {
bgn := i * 3 * 9;
for 0..2 {
gArbtriMem[bgn + it * 9 + 0] = tri.pos[it].x * inv_w - 1.0;
gArbtriMem[bgn + it * 9 + 1] = -(tri.pos[it].y * inv_h - 1.0);
gArbtriMem[bgn + it * 9 + 2] = 0;
gArbtriMem[bgn + it * 9 + 3] = tri.col[it].x;
gArbtriMem[bgn + it * 9 + 4] = tri.col[it].y;
gArbtriMem[bgn + it * 9 + 5] = tri.col[it].z;
gArbtriMem[bgn + it * 9 + 6] = tri.col[it].w;
gArbtriMem[bgn + it * 9 + 7] = tri.uv[it].x;
gArbtriMem[bgn + it * 9 + 8] = tri.uv[it].y;
}
}
upload_size := arbTriState.trilist.count * 3 * 9 * size_of(float);
if upload_size > 0 {
sg_update_buffer(gPipelines.arbtri.bind.vertex_buffers[0], *(sg_range.{ ptr = gArbtriMem.data, size = xx upload_size }));
}
flush_arb_commands();
}
debug_arb_flush : bool : false;
layer : s32 = 0;
flush_arb_commands :: () {
sfons_flush(state.fons); // All the text has been drawn, now flush it to the atlas.
layer = 0;
if debug_arb_flush then print(" --- !BEGIN FLUSH! ---- \n");
for arbTriState.command_list {
if debug_arb_flush then print("[command] %\n", it.type);
if it.type == {
case .SET_TEXTURE;
gPipelines.arbtri.bind.images[0] = it.texture.tex;
gCurrentTexture = it.texture;
case .REMOVE_TEXTURE;
gCurrentTexture = null;
case .FLUSH_TRI;
sg_apply_pipeline(gPipelines.arbtri.pipeline);
sg_apply_bindings(*gPipelines.arbtri.bind);
sg_draw(xx (it.tri_offset * 3), xx (it.tri_count * 3), 1);
case .PREPARE_TEXT;
case .SET_SCISSOR;
s := it.scissor;
w,h := get_window_size();
sgl_viewport(0,0,w,h,true);
sg_apply_scissor_rect(s.x, s.y, s.w, s.h, true);
case .REMOVE_SCISSOR;
w,h := get_window_size();
sg_apply_scissor_rect(0, 0, w, h, true);
case .DRAW_TEXT;
sgl_draw_layer(it.layer);
}
}
}

View File

@ -1,155 +0,0 @@
#scope_export
Render_Command_Buckets :: struct {
setup : [..]*Render_Command;
shadow : [..]*Render_Command;
reflection : [..]*Render_Command;
main : [..]*Render_Command;
gbuffer : [..]*Render_Command;
ui : [..]*Render_Command;
}
render_command_buckets : Render_Command_Buckets;
Render_Command_Type :: enum {
INVALID;
DRAW_SKY;
SET_CAMERA;
DRAW_GROUND;
ADD_TRILE_POSITIONS;
ADD_TRILE_POSITIONS_F32;
DRAW_TRILE_POSITIONS;
ADD_TRILE_RDM_POSITION;
DRAW_TRILE_RDM;
UPDATE_TRIXELS;
DRAW_TRIXELS;
SET_LIGHT;
DRAW_BILLBOARD;
UPDATE_PARTICLES;
DRAW_PARTICLES;
}
Render_Command :: struct {
type: Render_Command_Type = .INVALID;
}
Render_Command_Sky :: struct {
#as using c : Render_Command;
c.type = .DRAW_SKY;
worldConfig : *World_Config;
}
Render_Command_Set_Light :: struct {
#as using c : Render_Command;
c.type = .SET_LIGHT;
worldConfig : *World_Config;
}
Render_Command_Add_Trile_Positions :: struct {
#as using c : Render_Command;
c.type = .ADD_TRILE_POSITIONS;
positions : []Trile_Instance;
chunk : Chunk_Key;
}
// Like Add_Trile_Positions, but takes float world-space positions directly
// (xyz = position, w = orientation 0..23). Appends into the same instance
// buffer / offset list, so draws go through Render_Command_Draw_Trile_Positions.
Render_Command_Add_Trile_Positions_F32 :: struct {
#as using c : Render_Command;
c.type = .ADD_TRILE_POSITIONS_F32;
positions : []Vector4;
}
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;
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
lod_index : s32 = 0;
}
Render_Command_Add_Trile_RDM_Position :: struct {
#as using c : Render_Command;
c.type = .ADD_TRILE_RDM_POSITION;
position : Vector4;
}
Render_Command_Draw_Trile_RDM :: struct {
#as using c : Render_Command;
c.type = .DRAW_TRILE_RDM;
trile : string;
conf : *World_Config;
atlas_rect : Vector4;
offset_index : s32 = 0;
}
Render_Command_Update_Trixels :: struct {
#as using c : Render_Command;
c.type = .UPDATE_TRIXELS;
trile : *Trile;
colMultipliers : *[16][16][16]Vector3;
is_secondary : bool;
}
Render_Command_Draw_Billboard :: struct {
#as using c : Render_Command;
c.type = .DRAW_BILLBOARD;
position : Vector3;
animation : *Animation;
frame : s32;
flipX : bool;
flipY : bool;
faceDir : Vector3 = .{-100, -100, -100};
}
Render_Command_Draw_Trixels :: struct {
#as using c : Render_Command;
c.type = .DRAW_TRIXELS;
world_offset : Vector3;
brightness : float = 1.0;
tile_rotation : Matrix4 = .{_11=1, _22=1, _33=1, _44=1};
is_secondary : bool;
}
Render_Command_Update_Particles :: struct {
#as using c : Render_Command;
c.type = .UPDATE_PARTICLES;
total_count : s32;
pos_size : [MAX_PARTICLES]Vector4;
uv_rects : [MAX_PARTICLES]Vector4;
colors : [MAX_PARTICLES]Vector4;
}
Render_Command_Draw_Particles :: struct {
#as using c : Render_Command;
c.type = .DRAW_PARTICLES;
count : s32;
instance_offset : s32;
blend_mode : Particle_Blend_Mode;
sheet : sg_image;
}
Render_Command_Draw_Ground :: struct {
#as using c : Render_Command;
c.type = .DRAW_GROUND;
worldConfig : *World_Config;
}
Render_Command_Set_Camera :: struct {
#as using c : Render_Command;
c.type = .SET_CAMERA;
camera: Camera;
}
process_command_buckets :: () {
backend_process_command_buckets();
}
#scope_file
#load "backend_sokol.jai";

View File

@ -1,775 +0,0 @@
camera: Camera;
trixel_count : s32 = 0;
trixel_secondary_count : s32 = 0;
trixel_secondary_vbuf : sg_buffer;
trixel_view_mode : s32 = 0;
bypass_postprocess : bool = false;
bypass_shadows : bool = false;
bypass_reflections : bool = false;
trile_offsets : [..]s32;
trile_rdm_offsets : [..]s32;
current_world_config : *World_Config = null;
in_shadowmap_pass : bool = false;
in_reflection_pass : bool = false;
in_gbuffer_pass : bool = false;
shadow_mvp : Matrix4;
backend_handle_command :: (cmd: *Render_Command) {
if cmd.type == {
case .ADD_TRILE_POSITIONS;
add_command := cast(*Render_Command_Add_Trile_Positions)cmd;
backend_add_trile_positions(add_command.positions, add_command.chunk);
case .ADD_TRILE_POSITIONS_F32;
add_f32_command := cast(*Render_Command_Add_Trile_Positions_F32)cmd;
backend_add_trile_positions_f32(add_f32_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, draw_command.preview_mode, draw_command.offset_index, draw_command.lod_index);
case .ADD_TRILE_RDM_POSITION;
add_command := cast(*Render_Command_Add_Trile_RDM_Position)cmd;
backend_add_trile_rdm_position(add_command.position);
case .DRAW_TRILE_RDM;
draw_command := cast(*Render_Command_Draw_Trile_RDM)cmd;
backend_draw_trile_rdm(draw_command.trile, draw_command.conf, draw_command.atlas_rect, draw_command.offset_index);
case .DRAW_SKY;
sky_command := cast(*Render_Command_Sky)cmd;
backend_draw_sky(sky_command.worldConfig);
case .SET_CAMERA;
camera_command := cast(*Render_Command_Set_Camera)cmd;
camera = camera_command.camera;
case .DRAW_GROUND;
ground_command := cast(*Render_Command_Draw_Ground)cmd;
if in_gbuffer_pass {
backend_draw_ground_gbuf(ground_command.worldConfig);
} else {
backend_draw_ground(ground_command.worldConfig);
}
case .UPDATE_TRIXELS;
trixel_update_command := cast(*Render_Command_Update_Trixels)cmd;
backend_update_trixels(trixel_update_command);
case .DRAW_TRIXELS;
draw_trixels_cmd := cast(*Render_Command_Draw_Trixels)cmd;
backend_draw_trixels(draw_trixels_cmd.*);
case .SET_LIGHT;
set_light_command := cast(*Render_Command_Set_Light)cmd;
current_world_config = set_light_command.worldConfig;
case .DRAW_BILLBOARD;
command := cast(*Render_Command_Draw_Billboard)cmd;
if !in_gbuffer_pass {
backend_draw_billboard(command.position, command.animation, command.frame, command.flipX, command.faceDir);
} else {
backend_gbuffer_draw_billboard(command.position, command.animation, command.frame, command.flipX, command.faceDir);
}
case .UPDATE_PARTICLES;
update_cmd := cast(*Render_Command_Update_Particles)cmd;
backend_update_particle_buffers(update_cmd);
case .DRAW_PARTICLES;
particles_cmd := cast(*Render_Command_Draw_Particles)cmd;
backend_draw_particles(particles_cmd);
}
}
backend_update_trixels :: (cmd: Render_Command_Update_Trixels) {
if cmd.trile == null then return;
trixels : [4096]Position_Color;
count : s32 = 0;
for x: 0..15 {
for y: 0..15 {
for z: 0..15 {
if cmd.trile.trixels[x][y][z].empty then continue;
trixels[count].pos.x = x * (1.0 / 16.0) + TRIXEL_SIZE_HALF;
trixels[count].pos.y = y * (1.0 / 16.0) + TRIXEL_SIZE_HALF;
trixels[count].pos.z = z * (1.0 / 16.0) + TRIXEL_SIZE_HALF;
cm : Vector3 = .{1, 1, 1};
if cmd.colMultipliers cm = (cmd.colMultipliers.*)[x][y][z];
trixels[count].pos.w = ifx (cm.x == 1.0 && cm.y == 1.0 && cm.z == 1.0) then 0.0 else 1.0;
trixel_color := cmd.trile.trixels[x][y][z].material.color * cm;
trixels[count].col = .{trixel_color.x, trixel_color.y, trixel_color.z, material_encode_to_float(cmd.trile.trixels[x][y][z].material)};
count += 1;
}
}
}
range := sg_range.{ ptr = trixels.data, size = size_of(type_of(trixels)) };
if cmd.is_secondary {
trixel_secondary_count = count;
sg_update_buffer(trixel_secondary_vbuf, *range);
} else {
trixel_count = count;
sg_update_buffer(gPipelines.trixel.bind.vertex_buffers[2], *range);
}
}
backend_draw_trixels :: (cmd: Render_Command_Draw_Trixels) {
count := ifx cmd.is_secondary then trixel_secondary_count else trixel_count;
if count == 0 then return;
mvp := create_viewproj(*camera);
vs_params : Vs_Params;
vs_params.mvp = mvp.floats;
vs_params.camera = camera.position.component;
vs_params.world_offset = cmd.world_offset.component;
vs_params.tile_rotation = cmd.tile_rotation.floats;
world_conf : Trixel_World_Config;
wc : *World_Config = *(World_Config.{});
world_config_to_shader_type(wc, *world_conf);
fs_params : Trixel_Fs_Params;
fs_params.view_mode = trixel_view_mode;
fs_params.brightness = cmd.brightness;
bind := gPipelines.trixel.bind;
if cmd.is_secondary bind.vertex_buffers[2] = trixel_secondary_vbuf;
sg_apply_pipeline(gPipelines.trixel.pipeline);
sg_apply_bindings(*bind);
sg_apply_uniforms(UB_vs_params, *(sg_range.{ ptr = *vs_params, size = size_of(type_of(vs_params)) }));
sg_apply_uniforms(UB_trixel_world_config, *(sg_range.{ptr = *world_conf, size = size_of(type_of(world_conf))}));
sg_apply_uniforms(UB_trixel_fs_params, *(sg_range.{ ptr = *fs_params, size = size_of(type_of(fs_params)) }));
sg_draw(0, 36, count);
}
// @Note: We store these as Trile_Instances in the loaded world,
// and we need to transform them to Vector4 at some point, and
// this seems like the most convinient place to do that without
// having to constantly allocate.
trile_position_staging : [..]Vector4;
backend_add_trile_positions :: (positions : []Trile_Instance, chunk: Chunk_Key) {
array_reset_keeping_memory(*trile_position_staging);
for position : positions {
array_add(*trile_position_staging, Vector4.{
cast(float)(position.x + chunk.x * 32.0),
cast(float)(position.y + chunk.y * 32.0),
cast(float)(position.z + chunk.z * 32.0),
cast(float)(position.orientation)
});
}
offset := sg_append_buffer(gPipelines.trile.bind.vertex_buffers[3], *(sg_range.{
ptr = trile_position_staging.data,
size = size_of(Vector4) * cast(u64)trile_position_staging.count,
}));
array_add(*trile_offsets, offset);
}
backend_add_trile_positions_f32 :: (positions : []Vector4) {
offset := sg_append_buffer(gPipelines.trile.bind.vertex_buffers[3], *(sg_range.{
ptr = positions.data,
size = size_of(Vector4) * cast(u64)positions.count,
}));
array_add(*trile_offsets, offset);
}
backend_draw_trile_positions :: (trile : string, amount : s32, worldConf: *World_Config, chunk_key: Chunk_Key, preview_mode: s32 = 0, offset_index: s32 = 0, lod_index: s32 = 0) {
if in_gbuffer_pass {
backend_draw_trile_positions_gbuffer(trile, amount, worldConf, offset_index, lod_index);
} else {
backend_draw_trile_positions_main(trile, amount, worldConf, chunk_key, preview_mode, offset_index, lod_index);
}
}
backend_draw_trile_positions_gbuffer :: (trile : string, amount : s32, worldConf: *World_Config, offset_index: s32, lod_index: s32 = 0) {
if offset_index >= trile_offsets.count then return;
mvp := create_viewproj(*camera);
view := create_lookat(*camera);
vs_params : Gbuffer_Vs_Params;
vs_params.mvp = mvp.floats;
vs_params.view_matrix = view.floats;
sg_apply_pipeline(gPipelines.gbuffer.pipeline);
world_conf : Trile_World_Config;
world_config_to_shader_type(worldConf, *world_conf);
offset := trile_offsets[offset_index];
trilegfx, success := get_trile_gfx(trile);
if !success {
log_warn("Failed to get trile: %\n", trile);
return;
}
vbuf, nbuf, cbuf : sg_buffer;
vcount : s64;
if lod_index == 0 {
vbuf = trilegfx.vertex_buffer;
nbuf = trilegfx.normal_buffer;
cbuf = trilegfx.centre_buffer;
vcount = trilegfx.vertex_count;
} else {
lod := ifx lod_index == 1 then *trilegfx.lod_4 else *trilegfx.lod_2;
if lod.vertex_count == 0 return;
vbuf = lod.vertex_buffer;
nbuf = lod.normal_buffer;
cbuf = lod.color_buffer; // unused by gbuffer shader; bound to satisfy pipeline layout
vcount = lod.vertex_count;
}
bindings : sg_bindings;
bindings.vertex_buffers[0] = vbuf;
bindings.vertex_buffers[1] = nbuf;
bindings.vertex_buffers[2] = cbuf;
bindings.vertex_buffers[3] = gPipelines.trile.bind.vertex_buffers[3];
bindings.vertex_buffer_offsets[3] = offset;
bindings.samplers[0] = gPipelines.trile.bind.samplers[0];
bindings.images[0] = trilegfx.trixel_colors;
sg_apply_bindings(*bindings);
sg_apply_uniforms(UB_gbuffer_vs_params, *(sg_range.{ ptr = *vs_params, size = size_of(type_of(vs_params))}));
sg_draw(0, cast(s32) vcount, amount);
}
backend_draw_trile_positions_main :: (trile : string, amount : s32, worldConf: *World_Config, chunk_key: Chunk_Key, preview_mode: s32 = 0, offset_index: s32 = 0, lod_index: s32 = 0) {
start_frame_profiling_group("Draw trile positions");
if offset_index >= trile_offsets.count {
end_frame_profiling_group("Draw trile positions");
return;
}
trilegfx, success := get_trile_gfx(trile);
if !success {
log_warn("Failed to get trile: %\n", trile);
return;
}
offset := trile_offsets[offset_index];
// Pick mesh source based on LOD level. For shadow + gbuffer we keep the original pipeline
// and just swap which buffers feed it; the shader's centre attribute is unused so we bind
// the LOD color buffer as a placeholder to satisfy the pipeline layout.
vbuf, nbuf, cbuf : sg_buffer;
vcount : s64;
if lod_index == 0 {
vbuf = trilegfx.vertex_buffer;
nbuf = trilegfx.normal_buffer;
cbuf = trilegfx.centre_buffer;
vcount = trilegfx.vertex_count;
} else {
lod := ifx lod_index == 1 then *trilegfx.lod_4 else *trilegfx.lod_2;
if lod.vertex_count == 0 {
end_frame_profiling_group("Draw trile positions");
return;
}
vbuf = lod.vertex_buffer;
nbuf = lod.normal_buffer;
cbuf = lod.color_buffer;
vcount = lod.vertex_count;
}
if in_shadowmap_pass {
vs_params : Trile_Shadow_Vs_Params;
vs_params.mvp = shadow_mvp.floats;
bindings : sg_bindings;
bindings.vertex_buffers[0] = vbuf;
bindings.vertex_buffers[1] = nbuf;
bindings.vertex_buffers[2] = cbuf;
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) vcount, amount);
end_frame_profiling_group("Draw trile positions");
return;
}
mvp := create_viewproj(*camera);
if lod_index >= 1 {
// LOD path: dedicated shader, vertex color, no ray-march/SSAO/shadow/SH/BRDF.
sg_apply_pipeline(gPipelines.trile_lod.pipeline);
lod_vs : Trile_Lod_Vs_Params;
lod_vs.mvp = mvp.floats;
lod_vs.camera = camera.position.component;
lod_fs : Trile_Lod_Fs_Params;
lod_fs.skyBase = worldConf.skyBase.component;
lod_fs.sunPosition = worldConf.sunPosition.component;
lod_fs.sunLightColor = worldConf.sunLightColor.component;
lod_fs.sunIntensity = worldConf.sunIntensity;
lc := *current_lighting_config;
lod_fs.ambient_color = lc.ambient_color.component;
lod_fs.ambient_intensity = lc.ambient_intensity;
lod_fs.planeHeight = effective_plane_height(worldConf);
lod_fs.deepColor = worldConf.deepColor.component;
lod_fs.is_reflection = ifx in_reflection_pass then cast(s32)1 else cast(s32)0;
lod_fs.fog_start = FOG_START;
lod_fs.fog_end = FOG_END;
bindings : sg_bindings;
bindings.vertex_buffers[0] = vbuf;
bindings.vertex_buffers[1] = nbuf;
bindings.vertex_buffers[2] = cbuf;
bindings.vertex_buffers[3] = gPipelines.trile.bind.vertex_buffers[3];
bindings.vertex_buffer_offsets[3] = offset;
sg_apply_bindings(*bindings);
sg_apply_uniforms(UB_trile_lod_vs_params, *(sg_range.{ ptr = *lod_vs, size = size_of(type_of(lod_vs)) }));
sg_apply_uniforms(UB_trile_lod_fs_params, *(sg_range.{ ptr = *lod_fs, size = size_of(type_of(lod_fs)) }));
sg_draw(0, cast(s32) vcount, amount);
end_frame_profiling_group("Draw trile positions");
return;
}
vs_params : Trile_Vs_Params;
vs_params.mvp = mvp.floats;
vs_params.mvp_shadow = shadow_mvp.floats;
vs_params.camera = camera.position.component;
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);
bindings : sg_bindings;
bindings.vertex_buffers[0] = vbuf;
bindings.vertex_buffers[1] = nbuf;
bindings.vertex_buffers[2] = cbuf;
bindings.vertex_buffers[3] = gPipelines.trile.bind.vertex_buffers[3];
bindings.vertex_buffer_offsets[3] = offset;
bindings.samplers[0] = gPipelines.trile.bind.samplers[0];
bindings.images[0] = trilegfx.trixel_colors;
bindings.images[1] = g_ssaobuf;
bindings.samplers[2] = g_shadowmap_sampler;
bindings.images[2] = g_shadowmap;
bindings.images[3] = g_brdf_lut;
bindings.images[4] = g_sh_irradiance;
bindings.samplers[3] = gPipelines.trile.bind.samplers[3];
curworld := get_current_world();
chunk := table_find_pointer(*curworld.world.chunks, chunk_key);
fs_params : Trile_Fs_Params;
fs_params.mvp_shadow = shadow_mvp.floats;
fs_params.is_reflection = ifx in_reflection_pass then cast(s32)1 else cast(s32)0;
w, h := get_render_size();
fs_params.screen_w = w;
fs_params.screen_h = h;
lc := *current_lighting_config;
fs_params.ambient_intensity = lc.ambient_intensity;
fs_params.emissive_scale = lc.emissive_scale;
fs_params.indirect_diff_scale = lc.indirect_diff_scale;
fs_params.indirect_spec_scale = lc.indirect_spec_scale;
fs_params.ambient_color = lc.ambient_color.component;
fs_params.is_preview = preview_mode;
fs_params.indirect_tint = lc.indirect_tint.component;
fs_params.sh_enabled = ifx (chunk != null && chunk.sh_valid && !in_reflection_pass) then cast(s32)1 else cast(s32)0;
fs_params.fog_start = FOG_START;
fs_params.fog_end = FOG_END;
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))}));
sg_apply_uniforms(UB_trile_world_config, *(sg_range.{ptr = *world_conf, size = size_of(type_of(world_conf))}));
add_frame_profiling_point("After drawing setup");
sg_draw(0, cast(s32) vcount, amount);
end_frame_profiling_group("Draw trile positions");
}
backend_add_trile_rdm_position :: (position: Vector4) {
pos := position;
offset := sg_append_buffer(gPipelines.trile_rdm.bind.vertex_buffers[3], *(sg_range.{
ptr = *pos,
size = size_of(Vector4),
}));
array_add(*trile_rdm_offsets, offset);
}
backend_draw_trile_rdm :: (trile: string, worldConf: *World_Config, atlas_rect: Vector4, offset_index: s32) {
if offset_index >= trile_rdm_offsets.count then return;
trilegfx, success := get_trile_gfx(trile);
if !success {
log_warn("Failed to get trile: %\n", trile);
return;
}
offset := trile_rdm_offsets[offset_index];
mvp := create_viewproj(*camera);
vs_params : Trile_Rdm_Vs_Params;
vs_params.mvp = mvp.floats;
vs_params.mvp_shadow = shadow_mvp.floats;
vs_params.camera = camera.position.component;
sg_apply_pipeline(gPipelines.trile_rdm.pipeline);
world_conf : Trile_Rdm_World_Config;
world_config_to_shader_type(worldConf, *world_conf);
world_conf.planeHeight = effective_plane_height(worldConf);
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_rdm.bind.vertex_buffers[3];
bindings.vertex_buffer_offsets[3] = offset;
bindings.samplers[SMP_rdm_trilesmp] = gPipelines.trile_rdm.bind.samplers[SMP_rdm_trilesmp];
bindings.samplers[SMP_rdm_shadowsmp] = g_shadowmap_sampler;
bindings.samplers[SMP_rdm_linsmp] = gPipelines.trile_rdm.bind.samplers[SMP_rdm_linsmp];
bindings.images[IMG_rdm_triletex] = trilegfx.trixel_colors;
bindings.images[IMG_rdm_ssaotex] = g_ssaobuf;
bindings.images[IMG_rdm_shadowtex] = g_shadowmap;
bindings.images[IMG_rdm_brdflut] = g_brdf_lut;
bindings.images[IMG_rdm_shirradiance] = g_sh_irradiance;
bindings.images[IMG_rdm_atlas] = g_rdm_atlas;
curworld := get_current_world();
fs_params : Trile_Rdm_Fs_Params;
fs_params.mvp_shadow = shadow_mvp.floats;
fs_params.is_reflection = 0;
w, h := get_render_size();
fs_params.screen_w = w;
fs_params.screen_h = h;
lc := *current_lighting_config;
fs_params.ambient_intensity = lc.ambient_intensity;
fs_params.emissive_scale = lc.emissive_scale;
fs_params.indirect_diff_scale = lc.indirect_diff_scale;
fs_params.indirect_spec_scale = lc.indirect_spec_scale;
fs_params.ambient_color = lc.ambient_color.component;
fs_params.is_preview = 0;
fs_params.indirect_tint = lc.indirect_tint.component;
fs_params.sh_enabled = ifx curworld.valid then cast(s32)1 else cast(s32)0;
fs_params.atlas_rect = atlas_rect.component;
sg_apply_bindings(*bindings);
sg_apply_uniforms(UB_trile_rdm_fs_params, *(sg_range.{ ptr = *fs_params, size = size_of(type_of(fs_params)) }));
sg_apply_uniforms(UB_trile_rdm_vs_params, *(sg_range.{ ptr = *vs_params, size = size_of(type_of(vs_params)) }));
sg_apply_uniforms(UB_trile_rdm_world_config, *(sg_range.{ ptr = *world_conf, size = size_of(type_of(world_conf)) }));
sg_draw(0, cast(s32) trilegfx.vertex_count, 1);
}
backend_draw_sky :: (wc: *World_Config) {
mvp := create_viewproj(*camera);
vs_params : Sky_Vs_Params;
world_conf : Sky_World_Config;
world_config_to_shader_type(wc, *world_conf);
vs_params.mvp = mvp.floats;
sg_apply_pipeline(gPipelines.sky.pipeline);
sg_apply_bindings(*gPipelines.sky.bind);
sg_apply_uniforms(UB_sky_vs_params, *(sg_range.{ ptr = *vs_params, size = size_of(type_of(vs_params)) }));
sg_apply_uniforms(UB_sky_world_config, *(sg_range.{ptr = *world_conf, size = size_of(type_of(world_conf))}));
sg_draw(0, 36, 1);
}
backend_draw_ground :: (wc: *World_Config) {
mvp := create_viewproj(*camera);
vs_params : Plane_Vs_Params;
world_conf : Plane_World_Config;
plane_data : Plane_Data;
w, h := get_render_size();
plane_data.mvp_shadow = shadow_mvp.floats;
plane_data.screen_w = w;
plane_data.screen_h = h;
plane_data.cameraPosition = camera.position.component;
plane_data.reflectionDistortion = wc.waterDistortion;
plane_data.shininess = wc.waterShininess;
world_config_to_shader_type(wc, *world_conf);
vs_params.mvp = mvp.floats;
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;
sg_apply_bindings(*gPipelines.plane.bind);
sg_apply_uniforms(UB_plane_vs_params, *(sg_range.{ ptr = *vs_params, size = size_of(type_of(vs_params)) }));
sg_apply_uniforms(UB_plane_world_config, *(sg_range.{ptr = *world_conf, size = size_of(type_of(world_conf))}));
sg_apply_uniforms(UB_plane_data, *(sg_range.{ptr = *plane_data, size = size_of(type_of(plane_data))}));
sg_draw(0, 6, 2);
}
backend_draw_billboard :: (position: Vector3, anim: *Animation, frame_idx: s32, flipX: bool, faceDir: Vector3) {
if !anim then return;
mvp := create_viewproj(*camera);
vs_params : Billboard_Vs_Params;
gPipelines.billboard.bind.images[0] = anim.sheet;
frame := anim.frames[frame_idx];
vs_params.uvs = Vector4.{
cast(float) frame.x / cast(float)anim.sheet_w,
cast(float) frame.y / cast(float)anim.sheet_h,
cast(float) frame.w / cast(float)anim.sheet_w,
cast(float) frame.h / cast(float)anim.sheet_h,
}.component;
if flipX {
vs_params.uvs[0] += vs_params.uvs[2];
vs_params.uvs[2] *= -1.0;
}
vs_params.size = Vector2.{cast(float)(frame.w / 16), cast(float)(frame.h / 16)}.component;
vs_params.cam = camera.position.component;
vs_params.faceDir = faceDir.component;
if !in_shadowmap_pass {
vs_params.mvp = mvp.floats;
} else {
vs_params.mvp = shadow_mvp.floats;
}
vs_params.offset = position.component;
sg_apply_pipeline(gPipelines.billboard.pipeline);
sg_apply_bindings(*gPipelines.billboard.bind);
sg_apply_uniforms(UB_billboard_vs_params, *(sg_range.{ ptr = *vs_params, size = size_of(type_of(vs_params)) }));
sg_draw(0, 6, 1);
}
backend_gbuffer_draw_billboard :: (position: Vector3, anim: *Animation, frame_idx: s32, flipX: bool, faceDir: Vector3) {
if !anim then return;
mvp := create_viewproj(*camera);
view := create_lookat(*camera);
vs_params : Gbuffer_Billboard_Vs_Params;
vs_params.view_matrix = view.floats;
gPipelines.gbuffer_billboard.bind.images[0] = anim.sheet;
frame := anim.frames[frame_idx];
vs_params.uvs = Vector4.{
cast(float) frame.x / cast(float)anim.sheet_w,
cast(float) frame.y / cast(float)anim.sheet_h,
cast(float) frame.w / cast(float)anim.sheet_w,
cast(float) frame.h / cast(float)anim.sheet_h,
}.component;
if flipX {
vs_params.uvs[0] += vs_params.uvs[2];
vs_params.uvs[2] *= -1.0;
}
vs_params.size = Vector2.{cast(float)(frame.w / 16), cast(float)(frame.h / 16)}.component;
vs_params.cam = camera.position.component;
vs_params.faceDir = faceDir.component;
if !in_shadowmap_pass {
vs_params.mvp = mvp.floats;
} else {
vs_params.mvp = shadow_mvp.floats;
}
vs_params.offset = position.component;
sg_apply_pipeline(gPipelines.gbuffer_billboard.pipeline);
sg_apply_bindings(*gPipelines.gbuffer_billboard.bind);
sg_apply_uniforms(UB_gbuffer_billboard_vs_params, *(sg_range.{ ptr = *vs_params, size = size_of(type_of(vs_params)) }));
sg_draw(0, 6, 1);
}
backend_update_particle_buffers :: (cmd: *Render_Command_Update_Particles) {
if cmd.total_count <= 0 then return;
byte_size := cast(u64)(cmd.total_count * size_of(Vector4));
inst_buf1 := gPipelines.particle_additive.bind.vertex_buffers[1];
inst_buf2 := gPipelines.particle_additive.bind.vertex_buffers[2];
inst_buf3 := gPipelines.particle_additive.bind.vertex_buffers[3];
sg_update_buffer(inst_buf1, *(sg_range.{ ptr = cmd.pos_size.data, size = byte_size }));
sg_update_buffer(inst_buf2, *(sg_range.{ ptr = cmd.uv_rects.data, size = byte_size }));
sg_update_buffer(inst_buf3, *(sg_range.{ ptr = cmd.colors.data, size = byte_size }));
}
backend_draw_particles :: (cmd: *Render_Command_Draw_Particles) {
if cmd.count <= 0 then return;
pip := ifx cmd.blend_mode == .ALPHA then *gPipelines.particle_alpha else *gPipelines.particle_additive;
byte_offset := cmd.instance_offset * size_of(Vector4);
bind := pip.bind;
bind.vertex_buffer_offsets[1] = byte_offset;
bind.vertex_buffer_offsets[2] = byte_offset;
bind.vertex_buffer_offsets[3] = byte_offset;
mvp := create_viewproj(*camera);
vs_params : Particle_Vs_Params;
vs_params.mvp = mvp.floats;
vs_params.cam = camera.position.component;
sg_apply_pipeline(pip.pipeline);
bind.images[IMG_particle_sprite] = cmd.sheet;
sg_apply_bindings(*bind);
sg_apply_uniforms(UB_particle_vs_params, *(sg_range.{ ptr = *vs_params, size = size_of(type_of(vs_params)) }));
sg_draw(0, 6, cmd.count);
}
backend_draw_ground_gbuf :: (wc: *World_Config) {
mvp := create_viewproj(*camera);
view := create_lookat(*camera);
vs_params : Gbuffer_Vs_Params;
vs_params.mvp = mvp.floats;
vs_params.view_matrix = view.floats;
vs_params.isGround = 1;
vs_params.planeHeight = effective_plane_height(wc);
sg_apply_pipeline(gPipelines.gbuffer.pipeline);
bindings : sg_bindings;
bindings.vertex_buffers[0] = g_plane_gbuffer_vertex_buffer;
bindings.vertex_buffers[1] = g_plane_gbuffer_normal_buffer;
bindings.vertex_buffers[2] = g_plane_gbuffer_center_buffer;
bindings.vertex_buffers[3] = g_plane_gbuffer_instance_buffer;
sg_apply_bindings(*bindings);
sg_apply_uniforms(UB_gbuffer_vs_params, *(sg_range.{ ptr = *vs_params, size = size_of(type_of(vs_params))}));
sg_draw(0, 6, 1);
}
draw_sh_irradiance_pass :: () {
curworld := get_current_world();
if !curworld.valid then return;
sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, attachments = g_sh_irradiance_attach }));
sg_apply_pipeline(gPipelines.sh_irradiance.pipeline);
view := create_lookat(*camera);
inv_view := isometry_inverse(view);
lc := *current_lighting_config;
params : Sh_Deferred_Params;
params.inv_view = inv_view.floats;
params.ambient = .[lc.ambient_color.x, lc.ambient_color.y, lc.ambient_color.z, lc.ambient_intensity];
for *chunk: curworld.world.chunks {
if !chunk.sh_valid then continue;
gPipelines.sh_irradiance.bind.images[0] = g_gbuf_worldpos;
gPipelines.sh_irradiance.bind.images[1] = g_gbuf_normal;
gPipelines.sh_irradiance.bind.images[2] = chunk.sh_probe_grid;
sg_apply_bindings(*gPipelines.sh_irradiance.bind);
ck := chunk.coord;
params.chunk_origin = .[cast(float)(ck.x * 32), cast(float)(ck.y * 32), cast(float)(ck.z * 32), 0];
sg_apply_uniforms(UB_sh_deferred_params, *(sg_range.{ ptr = *params, size = size_of(type_of(params)) }));
sg_draw(0, 6, 1);
}
sg_end_pass();
}
backend_process_command_buckets :: () {
// 1. Set up textures and buffers.
start_frame_profiling_group("Setup");
for render_command_buckets.setup {
backend_handle_command(it);
}
end_frame_profiling_group("Setup");
start_frame_profiling_group("Shadow pass");
// 2. Shadow pass
if current_world_config != null {
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}));
if !bypass_shadows {
for render_command_buckets.shadow {
backend_handle_command(it);
}
}
sg_end_pass();
in_shadowmap_pass = false;
}
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}));
if !bypass_reflections {
in_reflection_pass = true;
for render_command_buckets.reflection {
backend_handle_command(it);
}
in_reflection_pass = false;
}
sg_end_pass();
end_frame_profiling_group("Reflection pass");
// 4. G-Buffer pass
start_frame_profiling_group("G-Buffer pass");
in_gbuffer_pass = true;
sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear_gbuf, attachments = g_gbuf_attachments}));
for render_command_buckets.gbuffer {
backend_handle_command(it);
}
sg_end_pass();
in_gbuffer_pass = false;
end_frame_profiling_group("G-Buffer pass");
start_frame_profiling_group("SSAO pass");
sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, attachments = g_ssao_attachments }));
sg_apply_pipeline(gPipelines.ssao.pipeline);
gPipelines.ssao.bind.images[0] = g_gbuf_position;
gPipelines.ssao.bind.images[1] = g_gbuf_normal;
gPipelines.ssao.bind.images[2] = g_ssao_noise_buf;
sg_apply_bindings(*gPipelines.ssao.bind);
ssao_fs_uniform : Ssao_Fs_Params;
mvp := create_perspective(*camera);
ssao_fs_uniform.projection = mvp.floats;
ssao_fs_uniform.samples = g_ssao_samples;
ssao_fs_uniform.ssao_power = current_post_process.ssao;
sg_apply_uniforms(UB_ssao_fs_params, *(sg_range.{ ptr = *ssao_fs_uniform, size = size_of(type_of(ssao_fs_uniform)) }));
sg_draw(0, 6, 1);
sg_end_pass();
end_frame_profiling_group("SSAO pass");
start_frame_profiling_group("SH irradiance pass");
draw_sh_irradiance_pass();
end_frame_profiling_group("SH irradiance pass");
// 5. Main pass
start_frame_profiling_group("Main pass");
sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, attachments = g_rendertex_attachments}));
for render_command_buckets.main {
backend_handle_command(it);
}
debug_draw_flush_gpu();
sg_end_pass();
end_frame_profiling_group("Main pass");
start_frame_profiling_group("Postprocess pass");
if !bypass_postprocess {
bloom_process();
dof_downsample_process();
dof_bokeh_process();
}
end_frame_profiling_group("Postprocess pass");
start_frame_profiling_group("Final pass");
// Begin drawing to swapchain
sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, swapchain = cast,force(sg_swapchain) sglue_swapchain() }));
// Draw the render texture and do post processing:
sg_apply_pipeline(gPipelines.postprocess.pipeline);
gPipelines.postprocess.bind.images[0] = g_rendertex;
gPipelines.postprocess.bind.images[1] = LUT_list[g_current_lut_texture_index].image;
gPipelines.postprocess.bind.images[2] = g_bloom_up_1;
gPipelines.postprocess.bind.images[3] = g_dof_tex;
gPipelines.postprocess.bind.images[4] = g_gbuf_position;
sg_apply_bindings(*gPipelines.postprocess.bind);
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);
}
sg_apply_uniforms(UB_post_process_config, *(sg_range.{ ptr = *post_process_config_uniform, size = size_of(type_of(post_process_config_uniform)) }));
dof_config_uniform : Dof_Config;
dof_config_uniform.dof_disabled = ifx disable_dof_post_process then cast(s32)1 else cast(s32)0;
dof_config_uniform.dof_max = current_post_process.dof_max;
dof_config_uniform.dof_point = current_post_process.dof_point;
sg_apply_uniforms(UB_dof_config, *(sg_range.{ ptr = *dof_config_uniform, size = size_of(type_of(dof_config_uniform)) }));
sg_draw(0, 6, 1);
sgl_defaults();
sgl_matrix_mode_projection();
sgl_ortho(0.0, sapp_widthf(), sapp_heightf(), 0.0, -1.0, +1.0);
arb_tri_flush();
sg_end_pass();
end_frame_profiling_group("Final pass");
sg_commit();
array_reset_keeping_memory(*render_command_buckets.setup);
array_reset_keeping_memory(*render_command_buckets.shadow);
array_reset_keeping_memory(*render_command_buckets.reflection);
array_reset_keeping_memory(*render_command_buckets.main);
array_reset_keeping_memory(*render_command_buckets.gbuffer);
array_reset_keeping_memory(*render_command_buckets.ui);
array_reset_keeping_memory(*trile_offsets);
array_reset_keeping_memory(*trile_rdm_offsets);
current_world_config = null;
}

View File

@ -1,81 +0,0 @@
bloom_process :: () {
w, h := get_render_size();
fw := cast(float)w;
fh := cast(float)h;
// Prefilter: threshold + downsample full-res → down_1 (w/2)
{
sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, attachments = g_bloom_down_1_attach }));
sg_apply_pipeline(gPipelines.bloom_prefilter.pipeline);
p : Bloom_Prefilter_Params;
p.src_texel_x = 1.0 / fw;
p.src_texel_y = 1.0 / fh;
p.threshold = current_post_process.bloom_treshold;
gPipelines.bloom_prefilter.bind.images[IMG_bloom_prefilter_src] = g_rendertex;
sg_apply_uniforms(UB_bloom_prefilter_params, *(sg_range.{ ptr = *p, size = size_of(type_of(p)) }));
sg_apply_bindings(*gPipelines.bloom_prefilter.bind);
sg_draw(0, 6, 1);
sg_end_pass();
}
// Downsample chain
bloom_downsample :: (src: sg_image, dst_attach: sg_attachments, src_w: float, src_h: float) {
sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, attachments = dst_attach }));
sg_apply_pipeline(gPipelines.bloom_downsample.pipeline);
p : Bloom_Downsample_Params;
p.src_texel_x = 1.0 / src_w;
p.src_texel_y = 1.0 / src_h;
gPipelines.bloom_downsample.bind.images[IMG_bloom_downsample_src] = src;
sg_apply_uniforms(UB_bloom_downsample_params, *(sg_range.{ ptr = *p, size = size_of(type_of(p)) }));
sg_apply_bindings(*gPipelines.bloom_downsample.bind);
sg_draw(0, 6, 1);
sg_end_pass();
}
bloom_downsample(g_bloom_down_1, g_bloom_down_2_attach, fw/2, fh/2);
bloom_downsample(g_bloom_down_2, g_bloom_down_3_attach, fw/4, fh/4);
bloom_downsample(g_bloom_down_3, g_bloom_down_4_attach, fw/8, fh/8);
// Upsample chain: tent(small) + large → dest
bloom_upsample :: (small: sg_image, large: sg_image, dst_attach: sg_attachments, small_w: float, small_h: float) {
sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, attachments = dst_attach }));
sg_apply_pipeline(gPipelines.bloom_upsample.pipeline);
p : Bloom_Upsample_Params;
p.src_texel_x = 1.0 / small_w;
p.src_texel_y = 1.0 / small_h;
gPipelines.bloom_upsample.bind.images[IMG_bloom_upsample_small] = small;
gPipelines.bloom_upsample.bind.images[IMG_bloom_upsample_large] = large;
sg_apply_uniforms(UB_bloom_upsample_params, *(sg_range.{ ptr = *p, size = size_of(type_of(p)) }));
sg_apply_bindings(*gPipelines.bloom_upsample.bind);
sg_draw(0, 6, 1);
sg_end_pass();
}
bloom_upsample(g_bloom_down_4, g_bloom_down_3, g_bloom_up_3_attach, fw/16, fh/16);
bloom_upsample(g_bloom_up_3, g_bloom_down_2, g_bloom_up_2_attach, fw/8, fh/8);
bloom_upsample(g_bloom_up_2, g_bloom_down_1, g_bloom_up_1_attach, fw/4, fh/4);
}
dof_downsample_process :: () {
sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, attachments = g_dof_downsample_attach }));
sg_apply_pipeline(gPipelines.dof_downsample.pipeline);
gPipelines.dof_downsample.bind.images[IMG_dof_downsample_src] = g_rendertex;
sg_apply_bindings(*gPipelines.dof_downsample.bind);
sg_draw(0, 6, 1);
sg_end_pass();
}
dof_bokeh_process :: () {
w, h := get_render_size();
half_w := cast(float)(w / 2);
half_h := cast(float)(h / 2);
radius := current_post_process.dof_blur_size * 3.0;
sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, attachments = g_dof_attach }));
sg_apply_pipeline(gPipelines.dof_blur.pipeline);
params : Dof_Blur_Params;
params.bokeh_radius_x = radius / half_w;
params.bokeh_radius_y = radius / half_h;
gPipelines.dof_blur.bind.images[IMG_dof_blur_src] = g_dof_downsample_tex;
sg_apply_uniforms(UB_dof_blur_params, *(sg_range.{ ptr = *params, size = size_of(type_of(params)) }));
sg_apply_bindings(*gPipelines.dof_blur.bind);
sg_draw(0, 6, 1);
sg_end_pass();
}

View File

@ -41,3 +41,26 @@ create_lookat :: (camera: *Camera) -> Matrix4 {
create_viewproj :: (camera: *Camera) -> Matrix4 {
return create_lookat(camera) * create_perspective(camera);
}
// An orthographic box around focus, seen from the sun. Depth goes 0..1 away from
// the sun. The box moves in whole shadow texels so shadows don't shimmer.
create_sun_viewproj :: (focus: Vector3, sun_direction: Vector3, radius: float, depth: float, map_size: int) -> Matrix4 {
A := normalize(sun_direction);
up := ifx abs(A.y) > 0.99 then Vector3.{0, 0, 1} else Vector3.{0, 1, 0};
B := normalize(cross(up, A));
C := cross(A, B);
texel := 2 * radius / map_size;
cx := floor(dot(B, focus) / texel) * texel;
cy := floor(dot(C, focus) / texel) * texel;
cz := dot(A, focus);
// Rows of the transform; stored transposed like create_lookat.
m := Matrix4.{
B.x / radius, B.y / radius, B.z / radius, -cx / radius,
C.x / radius, C.y / radius, C.z / radius, -cy / radius,
-A.x / (2 * depth), -A.y / (2 * depth), -A.z / (2 * depth), (cz + depth) / (2 * depth),
0, 0, 0, 1,
};
return transpose(m);
}

View File

@ -1,19 +0,0 @@
#scope_export
#load "backend.jai";
init_rendering :: () {
init_ssao();
}
// Core rendering function, runs several passes.
render :: () {
tasks_to_commands();
add_frame_profiling_point("After task->command conversion");
start_frame_profiling_group("Rendering command bucket processing");
process_command_buckets();
end_frame_profiling_group("Rendering command bucket processing");
}
#scope_file

View File

@ -1,8 +1,8 @@
DEBUG_LINE_MAX :: 65536;
DEBUG_OVERLAY_LINE_MAX :: 8192;
// One record per line, uploaded as instance data: the line pipeline expands each
// into a screen-space quad so lines can have a real pixel width.
// Debug lines are the one draw without a view: they are collected globally and
// drawn in every view that renders to the screen, then cleared by render().
Debug_Line :: struct {
a : Vector3;
b : Vector3;
@ -151,35 +151,3 @@ debug_aabb_3d :: (mn: Vector3, mx: Vector3, col: Vector4) {
debug_line(.{mn.x, mn.y, mx.z}, .{mn.x, mx.y, mx.z}, col);
debug_line(.{mx.x, mn.y, mx.z}, .{mx.x, mx.y, mx.z}, col);
}
flush_debug_lines :: (pipe: *Pipeline_Binding, lines: []Debug_Line, count: *int, params: *Debugline_Vs_Params) {
if count.* == 0 then return;
// Buffer 0 is the shared static quad; buffer 1 is this pipeline's instances.
sg_update_buffer(
pipe.bind.vertex_buffers[1],
*(sg_range.{
ptr = lines.data,
size = cast(u64)(count.* * size_of(Debug_Line)),
})
);
sg_apply_pipeline(pipe.pipeline);
sg_apply_bindings(*pipe.bind);
sg_apply_uniforms(UB_debugline_vs_params, *(sg_range.{ ptr = params, size = size_of(Debugline_Vs_Params) }));
sg_draw(0, 6, xx count.*);
count.* = 0;
}
debug_draw_flush_gpu :: () {
if g_debug_line_count == 0 && g_overlay_line_count == 0 then return;
w, h := get_window_size();
mvp := create_viewproj(*camera);
params : Debugline_Vs_Params;
params.mvp = mvp.floats;
params.viewport = .[cast(float)w, cast(float)h, 0, 0];
flush_debug_lines(*gPipelines.debugline, g_debug_lines, *g_debug_line_count, *params);
flush_debug_lines(*gPipelines.debugline_overlay, g_overlay_lines, *g_overlay_line_count, *params);
}
#assert size_of(Debug_Line) == 44 "Debug_Line must stay tightly packed: the pipeline layout hardcodes its field offsets.";

View File

@ -1,207 +0,0 @@
fill_uniform_with_engine_data :: (uniform: *$A, enginedata: *$B) {
generate_copy_code :: () -> string {
builder : String_Builder;
ti := type_info(A);
for ti.members {
if it.name == "_" then continue; // skip padding
if it.type == type_info(Vector3) then print_to_builder(*builder, "uniform.% = enginedata.%.component;\n", it.name, it.name);
else print_to_builder(*builder, "uniform.% = enginedata.%;\n", it.name, it.name);
}
return builder_to_string(*builder);
}
#insert #run,stallable generate_copy_code();
}
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 :: inline (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;
}
LOD_NEAR_DIST :: 40.0;
LOD_FAR_DIST :: 80.0;
// 3-band LOD selection: instances closer than LOD_DISTANCES[i] use LOD level i.
// i = 0 → full detail
// i = 1 → 4^3 cube grid
// i = 2 → 2^3 cube grid
// beyond LOD_DISTANCES[2] → culled.
LOD_DISTANCES :: float.[50.0, 100.0, 200.0];
FOG_START :: 60.0;
FOG_END :: 195.0;
shad_gathered : [..]Gathered_Positions;
rdm_extra : [..]Gathered_Positions;
rdm_main : [..]Gathered_Rdm_Position;
gathered_per_lod : [3][..]Gathered_Positions;
Gathered_Positions :: struct {
trile : string;
chunk_key : Chunk_Key;
positions : [..]Vector4;
}
Gathered_Rdm_Position :: struct {
name: string;
position: Vector4;
}
gathered_chunk_tasks : [..]Gathered_Positions;
create_world_rendering_tasks :: (world: *World, camera: Camera, plane_height: float = 0) {
create_sky_rendering_task(*world.conf);
create_set_light_rendering_task(*world.conf);
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);
reflect_cam := camera;
reflect_cam.position *= .{1, -1, 1};
reflect_cam.position.y += plane_height * 2;
reflect_cam.target *= .{1, -1, 1};
reflect_cam.target.y += plane_height * 2;
reflect_mvp := create_viewproj(*reflect_cam);
reflect_planes := extract_frustum_planes(reflect_mvp);
for chunk: world.chunks {
// Skip chunks that are completely out of view.
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_reflect := aabb_in_frustum(reflect_planes, bmin, bmax);
in_shad := aabb_in_frustum(shadow_planes, bmin, bmax);
vis := in_cam || in_reflect || in_shad;
if !vis then continue;
for group : chunk.groups {
if group.instances.count < 1 then continue;
gmin := group.bounding_min;
gmax := group.bounding_max;
gmin += Vector3.{cast(float)chunk.coord.x * 32, cast(float)chunk.coord.y * 32, cast(float)chunk.coord.z * 32};
gmax += Vector3.{cast(float)chunk.coord.x * 32, cast(float)chunk.coord.y * 32, cast(float)chunk.coord.z * 32};
in_cam := aabb_in_frustum(cam_planes, gmin, gmax);
in_reflect := aabb_in_frustum(reflect_planes, gmin, gmax);
in_shad := aabb_in_frustum(shadow_planes, gmin, gmax);
vis := in_cam || in_reflect || in_shad;
if !vis then continue;
diff := group.average_pos - camera.position;
dist := length(diff);
lod_index : s32 = 0;
for lod_dist : LOD_DISTANCES {
if dist < lod_dist then break;
lod_index += 1;
}
task := Rendering_Task_Trile.{
trile = group.trile_name,
chunk_key = chunk.coord,
positions = group.instances,
worldConf = *world.conf,
lod_index = lod_index
};
add_rendering_task(task);
}
}
create_ground_rendering_task(world);
}
create_sky_rendering_task :: (conf: *World_Config) {
skytask := Rendering_Task_Sky.{type = .SKY, worldConfig = conf};
add_rendering_task(skytask);
}
create_set_light_rendering_task :: (conf: *World_Config) {
lighttask := Rendering_Task_Set_Light.{type = .SET_LIGHT, worldConfig = conf};
add_rendering_task(lighttask);
}
TRIXEL_IDENTITY : Matrix4 : .{_11=1, _22=1, _33=1, _44=1};
create_trixel_rendering_task :: (trile: *Trile, muls: *[16][16][16]Vector3, world_offset: Vector3 = .{}, brightness: float = 1.0, tile_rotation: Matrix4 = TRIXEL_IDENTITY, is_secondary: bool = false) {
trixeltask := Rendering_Task_Trixels.{type = .TRIXELS, trile = trile, colMultipliers = muls, world_offset = world_offset, brightness = brightness, tile_rotation = tile_rotation, is_secondary = is_secondary};
add_rendering_task(trixeltask);
}
create_ground_rendering_task :: (world: *World) {
groundtask := Rendering_Task_Ground.{type = .GROUND, world = world};
add_rendering_task(groundtask);
}
create_billboard_rendering_task :: (position: Vector3, animation: *Animation, frame: s32, flipX: bool, flipY: bool, faceDir : Vector3 = .{-100, -100, -100}) {
billboardtask := Rendering_Task_Billboard.{type = .BILLBOARD, position = position, animation = animation, frame = frame, flipX = flipX, flipY = flipY, faceDir = faceDir };
add_rendering_task(billboardtask);
}
create_set_cam_rendering_task :: (cam: Camera, planeHeight: float) {
camtask := Rendering_Task_Set_Camera.{type = .SET_CAMERA, camera = cam, planeHeight = planeHeight};
add_rendering_task(camtask);
}
get_low_res :: (width: s32, height: s32, max_dimension: s32 = 720) -> (s32, s32) {
if width == 0 || height == 0 {
return 0, 0;
}
aspect_ratio := cast(float)width / cast(float)height;
w: s32;
h: s32;
if width > height {
w = max_dimension;
h = cast(s32)floor(cast(float)w / aspect_ratio);
} else {
h = max_dimension;
w = cast(s32)floor(cast(float)h * aspect_ratio);
}
return w, h;
}
get_render_size :: () -> (s32, s32) {
w,h := get_window_size();
// w, h = get_low_res(w,h, 480);
return w, h;
}
flip_y_if_plat :: inline (v: Vector2) -> Vector2 {
return .{v.x, flip_if_plat(v.y)};
}
// Some platforms draw UVs in weird reverse way
// so this function here does the flip on those platforms
// so we don't need to do the platform check in many places.
flip_if_plat :: inline (n: float) -> float {
#if OS == .MACOS {
return 1 - n;
} else {
return n;
}
}

View File

@ -1,153 +0,0 @@
// LOD bake for triles. Independent of meshgen.jai's quad-mesh path.
//
// Approach:
// 1. Downsample the 16^3 source trixels into a smaller N^3 grid of LOD voxels
// (avg color across non-empty source trixels in each block, empty if all empty).
// 2. Bake a cube-grid mesh: one cube per non-empty LOD voxel, only emit faces whose
// neighbor in the LOD grid is empty (or out of bounds). Color is baked into the
// vertex color buffer.
// 3. The result feeds a separate trile_lod pipeline that uses vertex color and skips
// texture sampling, ray-march, SSAO, shadow, SH, etc.
LOD_Voxel :: struct {
color : Vector3;
empty : bool;
}
downsample_trile :: (src: *Trile, target_size: int) -> []LOD_Voxel {
block := 16 / target_size; // source trixels per LOD voxel along one axis
out := NewArray(target_size * target_size * target_size, LOD_Voxel,, temp);
for lx: 0..target_size-1 {
for ly: 0..target_size-1 {
for lz: 0..target_size-1 {
sum_r, sum_g, sum_b : float;
count : int = 0;
for dx: 0..block-1 {
for dy: 0..block-1 {
for dz: 0..block-1 {
sx := lx * block + dx;
sy := ly * block + dy;
sz := lz * block + dz;
if src.trixels[sx][sy][sz].empty continue;
c := src.trixels[sx][sy][sz].material.color;
sum_r += c.x;
sum_g += c.y;
sum_b += c.z;
count += 1;
}
}
}
idx := (lx * target_size + ly) * target_size + lz;
if count == 0 {
out[idx].empty = true;
} else {
out[idx].color = .{ sum_r / count, sum_g / count, sum_b / count };
out[idx].empty = false;
}
}
}
}
return out;
}
bake_lod_cube_mesh :: (lod: []LOD_Voxel, target_size: int) -> Trile_GFX_LOD {
inv_n := 1.0 / cast(float)target_size;
verts : [..]float;
norms : [..]float;
colors : [..]float;
verts.allocator = temp;
norms.allocator = temp;
colors.allocator = temp;
voxel_at :: (lod: []LOD_Voxel, n: int, x: int, y: int, z: int) -> LOD_Voxel #expand {
idx := (x * n + y) * n + z;
return lod[idx];
}
// Each face: 4 corners (offsets in [0,1] within a unit voxel) + outward normal.
Face :: struct {
nx, ny, nz : float;
ax, ay, az : float;
bx, by, bz : float;
cx, cy, cz : float;
dx, dy, dz : float;
}
// Order: -X, +X, -Y, +Y, -Z, +Z. CCW winding when viewed from outside.
faces :: Face.[
.{ -1, 0, 0, 0,0,0, 0,0,1, 0,1,1, 0,1,0 },
.{ 1, 0, 0, 1,0,0, 1,1,0, 1,1,1, 1,0,1 },
.{ 0,-1, 0, 0,0,0, 1,0,0, 1,0,1, 0,0,1 },
.{ 0, 1, 0, 0,1,0, 0,1,1, 1,1,1, 1,1,0 },
.{ 0, 0,-1, 0,0,0, 0,1,0, 1,1,0, 1,0,0 },
.{ 0, 0, 1, 1,0,1, 1,1,1, 0,1,1, 0,0,1 },
];
neighbor_offsets :: int.[ -1, 1, -1, 1, -1, 1 ];
neighbor_axes :: int.[ 0, 0, 1, 1, 2, 2 ]; // 0=x, 1=y, 2=z
for lx: 0..target_size-1 {
for ly: 0..target_size-1 {
for lz: 0..target_size-1 {
v := voxel_at(lod, target_size, lx, ly, lz);
if v.empty continue;
base_x := cast(float)lx * inv_n;
base_y := cast(float)ly * inv_n;
base_z := cast(float)lz * inv_n;
for f: 0..5 {
nx, ny, nz := lx, ly, lz;
if neighbor_axes[f] == 0 nx += neighbor_offsets[f];
else if neighbor_axes[f] == 1 ny += neighbor_offsets[f];
else nz += neighbor_offsets[f];
visible := false;
if nx < 0 || nx >= target_size || ny < 0 || ny >= target_size || nz < 0 || nz >= target_size {
visible = true;
} else {
if voxel_at(lod, target_size, nx, ny, nz).empty visible = true;
}
if !visible continue;
face := faces[f];
push_vert :: (px: float, py: float, pz: float) #expand {
array_add(*verts, base_x + px * inv_n);
array_add(*verts, base_y + py * inv_n);
array_add(*verts, base_z + pz * inv_n);
array_add(*norms, face.nx);
array_add(*norms, face.ny);
array_add(*norms, face.nz);
array_add(*colors, v.color.x);
array_add(*colors, v.color.y);
array_add(*colors, v.color.z);
}
// tri 1: a b c
push_vert(face.ax, face.ay, face.az);
push_vert(face.bx, face.by, face.bz);
push_vert(face.cx, face.cy, face.cz);
// tri 2: a c d
push_vert(face.ax, face.ay, face.az);
push_vert(face.cx, face.cy, face.cz);
push_vert(face.dx, face.dy, face.dz);
}
}
}
}
out : Trile_GFX_LOD;
out.vertex_count = verts.count / 3;
if out.vertex_count == 0 return out;
out.vertex_buffer = sg_make_buffer(*(sg_buffer_desc.{ data = .{ ptr = verts.data, size = xx (verts.count * 4) } }));
out.normal_buffer = sg_make_buffer(*(sg_buffer_desc.{ data = .{ ptr = norms.data, size = xx (norms.count * 4) } }));
out.color_buffer = sg_make_buffer(*(sg_buffer_desc.{ data = .{ ptr = colors.data, size = xx (colors.count * 4) } }));
return out;
}
destroy_trile_gfx_lod :: (lod: *Trile_GFX_LOD) {
if lod.vertex_count == 0 return;
sg_destroy_buffer(lod.vertex_buffer);
sg_destroy_buffer(lod.normal_buffer);
sg_destroy_buffer(lod.color_buffer);
lod.vertex_count = 0;
}

View File

@ -1,509 +0,0 @@
Trile_Side :: enum_flags u8 {
TOP :: 0x1; // Larger Y
LEFT :: 0x2; // Larger Z
RIGHT :: 0x4; // Smaller Z
FRONT :: 0x8; // Larger X
BACK :: 0x10; // Smaller X
BOTTOM :: 0x20; // Smaller Ys
}
trileSideValues : [6]Trile_Side = .[.TOP, .LEFT, .RIGHT, .FRONT, .BACK, .BOTTOM];
sides_with_air_exposure :: (trileptr: *Trile, x: int, y: int, z: int) -> u8 {
res : u8 = 0;
if trileptr.trixels[x][y][z].empty then return res;
// Top
if y == 15 || trileptr.trixels[x][y+1][z].empty then res |= xx Trile_Side.TOP;
// Bottom
if y == 0 || trileptr.trixels[x][y-1][z].empty then res |= xx Trile_Side.BOTTOM;
// Left
if z == 15 || trileptr.trixels[x][y][z+1].empty then res |= xx Trile_Side.LEFT;
// Right
if z == 0 || trileptr.trixels[x][y][z-1].empty then res |= xx Trile_Side.RIGHT;
// Front
if x == 15 || trileptr.trixels[x+1][y][z].empty then res |= xx Trile_Side.FRONT;
// Back
if x == 0 || trileptr.trixels[x-1][y][z].empty then res |= xx Trile_Side.BACK;
return res;
}
draw_trile_side_triangles :: (vecs: *[]float, normals: *[]float, index: *int, side: Trile_Side, x: int, y: int, z: int) {
points : [4][3]float;
normal : [3]float;
if side == Trile_Side.TOP {
points[0][0] = 1; points[0][1] = 1; points[0][2] = 1;
points[1][0] = 1; points[1][1] = 1; points[1][2] = 0;
points[2][0] = 0; points[2][1] = 1; points[2][2] = 1;
points[3][0] = 0; points[3][1] = 1; points[3][2] = 0;
normal[0] = 0; normal[1] = 1; normal[2] = 0;
}
if side == Trile_Side.BOTTOM {
points[0][0] = 1; points[0][1] = 0; points[0][2] = 1;
points[2][0] = 1; points[2][1] = 0; points[2][2] = 0;
points[1][0] = 0; points[1][1] = 0; points[1][2] = 1;
points[3][0] = 0; points[3][1] = 0; points[3][2] = 0;
normal[0] = 0; normal[1] = -1; normal[2] = 0;
}
if side == Trile_Side.FRONT {
points[0][0] = 1; points[0][1] = 1; points[0][2] = 1;
points[2][0] = 1; points[2][1] = 1; points[2][2] = 0;
points[1][0] = 1; points[1][1] = 0; points[1][2] = 1;
points[3][0] = 1; points[3][1] = 0; points[3][2] = 0;
normal[0] = 1; normal[1] = 0; normal[2] = 0;
}
if side == Trile_Side.BACK {
points[0][0] = 0; points[0][1] = 1; points[0][2] = 1;
points[1][0] = 0; points[1][1] = 1; points[1][2] = 0;
points[2][0] = 0; points[2][1] = 0; points[2][2] = 1;
points[3][0] = 0; points[3][1] = 0; points[3][2] = 0;
normal[0] = -1; normal[1] = 0; normal[2] = 0;
}
if side == Trile_Side.LEFT {
points[0][0] = 1; points[0][1] = 1; points[0][2] = 1;
points[2][0] = 1; points[2][1] = 0; points[2][2] = 1;
points[1][0] = 0; points[1][1] = 1; points[1][2] = 1;
points[3][0] = 0; points[3][1] = 0; points[3][2] = 1;
normal[0] = 0; normal[1] = 0; normal[2] = 1;
}
if side == Trile_Side.RIGHT {
points[0][0] = 1; points[0][1] = 1; points[0][2] = 0;
points[1][0] = 1; points[1][1] = 0; points[1][2] = 0;
points[2][0] = 0; points[2][1] = 1; points[2][2] = 0;
points[3][0] = 0; points[3][1] = 0; points[3][2] = 0;
normal[0] = 0; normal[1] = 0; normal[2] = -1;
}
for 0..2 {
vecs.*[index.*] = (x + points[it][0]) * TRIXEL_SIZE;
vecs.*[index.*+1] = (y + points[it][1]) * TRIXEL_SIZE;
vecs.*[index.*+2] = (z + points[it][2]) * TRIXEL_SIZE;
normals.*[index.*] = normal[0];
normals.*[index.*+1] = normal[1];
normals.*[index.*+2] = normal[2];
index.* = index.* + 3;
}
for < 0..2 {
vecs.*[index.*] = (x + points[it][0]) * TRIXEL_SIZE;
vecs.*[index.*+1] = (y + points[it][1]) * TRIXEL_SIZE;
vecs.*[index.*+2] = (z + points[it][2]) * TRIXEL_SIZE;
normals.*[index.*] = normal[0];
normals.*[index.*+1] = normal[1];
normals.*[index.*+2] = normal[2];
index.* = index.* + 3;
}
}
draw_trile_side_quad :: (vecs: *[..]float, norms: *[..]float, side: Trile_Side, x: int, y: int, z: int) {
points : [4][3]float;
normal : [3]float;
if side == {
case Trile_Side.TOP;
points[0][0] = 1; points[0][1] = 1; points[0][2] = 1;
points[1][0] = 1; points[1][1] = 1; points[1][2] = 0;
points[2][0] = 0; points[2][1] = 1; points[2][2] = 1;
points[3][0] = 0; points[3][1] = 1; points[3][2] = 0;
normal[0] = 0; normal[1] = 1; normal[2] = 0;
case Trile_Side.BOTTOM;
points[0][0] = 1; points[0][1] = 0; points[0][2] = 1;
points[2][0] = 1; points[2][1] = 0; points[2][2] = 0;
points[1][0] = 0; points[1][1] = 0; points[1][2] = 1;
points[3][0] = 0; points[3][1] = 0; points[3][2] = 0;
normal[0] = 0; normal[1] = -1; normal[2] = 0;
case Trile_Side.FRONT;
points[0][0] = 1; points[0][1] = 1; points[0][2] = 1;
points[2][0] = 1; points[2][1] = 1; points[2][2] = 0;
points[1][0] = 1; points[1][1] = 0; points[1][2] = 1;
points[3][0] = 1; points[3][1] = 0; points[3][2] = 0;
normal[0] = 1; normal[1] = 0; normal[2] = 0;
case Trile_Side.BACK;
points[0][0] = 0; points[0][1] = 1; points[0][2] = 1;
points[1][0] = 0; points[1][1] = 1; points[1][2] = 0;
points[2][0] = 0; points[2][1] = 0; points[2][2] = 1;
points[3][0] = 0; points[3][1] = 0; points[3][2] = 0;
normal[0] = -1; normal[1] = 0; normal[2] = 0;
case Trile_Side.LEFT;
points[0][0] = 1; points[0][1] = 1; points[0][2] = 1;
points[2][0] = 1; points[2][1] = 0; points[2][2] = 1;
points[1][0] = 0; points[1][1] = 1; points[1][2] = 1;
points[3][0] = 0; points[3][1] = 0; points[3][2] = 1;
normal[0] = 0; normal[1] = 0; normal[2] = 1;
case Trile_Side.RIGHT;
points[0][0] = 1; points[0][1] = 1; points[0][2] = 0;
points[1][0] = 1; points[1][1] = 0; points[1][2] = 0;
points[2][0] = 0; points[2][1] = 1; points[2][2] = 0;
points[3][0] = 0; points[3][1] = 0; points[3][2] = 0;
normal[0] = 0; normal[1] = 0; normal[2] = -1;
}
order : [4]int = .[0,1,3,2];
coords : [3]int = .[x,y,z];
for i: 0..3 {
for j: 0..2 {
array_add(vecs, (coords[j]+points[order[i]][j])*TRIXEL_SIZE);
array_add(norms, normal[j]);
}
}
}
generate_basic_quad_mesh :: (trileptr: *Trile, vecs: *[..]float, norms: *[..]float) {
for x: 0..15 {
for y: 0..15 {
for z: 0..15 {
exposure: u8 = sides_with_air_exposure(trileptr, x, y, z);
for trileSideValues {
if (cast(u8)it) & exposure then draw_trile_side_quad(vecs, norms, it, x, y, z);
}
}
}
}
}
quads_to_triangles :: (quadVecs: *[..]float, triangleVecs: *[..]float, quadNorms: *[..]float, triangleNorms: *[..]float) {
assert(quadVecs.count % (3*4) == 0);
assert(quadVecs.count == quadNorms.count);
i := 0;
while i < quadVecs.count {
quadStart : *float = *(quadVecs.*[i]);
normStart : *float = *(quadNorms.*[i]);
for j : 0..4 {
for k : 0..2 {
array_add(triangleVecs, quadStart[(j%4)*3+k]);
array_add(triangleNorms, normStart[(j%4)*3+k]);
}
if j == 2 {
for k : 0..2 {
//add the third point twice to get 2 triangles
array_add(triangleVecs, quadStart[(j%4)*3+k]);
array_add(triangleNorms, normStart[(j%4)*3+k]);
}
}
}
i += 3*4;
}
}
Quad :: struct {
topRight : Vector2;
bottomLeft : Vector2;
};
operator < :: (a: Quad, b: Quad) -> bool {
if a.topRight.x == b.topRight.x then return a.topRight.y < b.topRight.y;
return a.topRight.x < b.topRight.x;
}
quad_comp :: (a: Quad, b: Quad) -> bool {
if a.topRight != b.topRight then return false;
if a.bottomLeft != b.bottomLeft then return false;
return true;
}
quad_hash :: (q: Quad) -> u32 {
return sdbm_hash(*q, size_of(Quad));
}
Quad_Set :: Table(Quad, bool, quad_hash, quad_comp);
Quads :: [6][..]Quad_Set;
side_to_quad_list_index :: (side: Trile_Side) -> s32 {
if #complete side == {
case Trile_Side.TOP;
return 0;
case Trile_Side.BOTTOM;
return 1;
case Trile_Side.FRONT;
return 2;
case Trile_Side.BACK;
return 3;
case Trile_Side.LEFT;
return 4;
case Trile_Side.RIGHT;
return 5;
}
}
init_quads :: (quads: *Quads) { // NOTE: unsure about if this is correctly ported.
for side : trileSideValues {
idx := side_to_quad_list_index(side);
for i : 0..15 {
quadset : Quad_Set;
table_add(*quadset, .{.{16,16}, .{0,0}}, true);
array_add(*(quads.*[idx]), quadset);
}
}
}
// Looking at the side, what axis should be used as x,y and z,
// so that x and z are parallel to the side.
// (And not all of it seems to work when the used x and y and normal of the side abide by the left hand rule)
change_perspective :: (x: *$T, y: *T, z: *T, side: Trile_Side) -> (*T,*T,*T) {
if #complete side == {
case Trile_Side.TOP;
return x, z, y;
case Trile_Side.BOTTOM;
return z, x, y;
case Trile_Side.FRONT;
return z, y, x;
case Trile_Side.BACK;
return y, z, x;
case Trile_Side.LEFT;
return y, x, z;
case Trile_Side.RIGHT;
return x, y, z;
}
}
quad2d_add_to_quads3d :: (quads2d: *[..]Vector2, quads3d: *[..]Vector3, side: Trile_Side, depth: int, normals: *[..]float) {
x, y, z : float;
normal : [3]float;
offset : float = 0.0;
ux, uy, uz := change_perspective(*x, *y, *z, side);
if side == {
case Trile_Side.TOP;
normal[0] = 0;
normal[1] = 1;
normal[2] = 0;
offset = 1;
case Trile_Side.BOTTOM;
normal[0] = 0;
normal[1] = -1;
normal[2] = 0;
case Trile_Side.FRONT;
normal[0] = 1;
normal[1] = 0;
normal[2] = 0;
offset = 1;
case Trile_Side.BACK;
normal[0] = -1;
normal[1] = 0;
normal[2] = 0;
case Trile_Side.LEFT;
normal[0] = 0;
normal[1] = 0;
normal[2] = 1;
offset = 1;
case Trile_Side.RIGHT;
normal[0] = 0;
normal[1] = 0;
normal[2] = -1;
}
for quad : quads2d.* {
uz.* = (depth + offset) * TRIXEL_SIZE;
ux.* = quad.x * TRIXEL_SIZE;
uy.* = quad.y * TRIXEL_SIZE;
array_add(quads3d, .{x,y,z});
array_add(normals, normal[0]);
array_add(normals, normal[1]);
array_add(normals, normal[2]);
}
}
quads_to_vecs :: (quads: *Quads, vecs: *[..]float, normals: *[..]float) {
quads3d : [..]Vector3;
for side : trileSideValues {
idx := side_to_quad_list_index(side);
for 0..quads.*[idx].count-1 {
quads2d : [..]Vector2;
table := *(quads.*[idx][it]);
for k, v : table {
array_add(*quads2d, v.bottomLeft);
array_add(*quads2d, .{v.bottomLeft.x, v.topRight.y});
array_add(*quads2d, v.topRight);
array_add(*quads2d, .{v.topRight.x, v.bottomLeft.y});
}
quad2d_add_to_quads3d(*quads2d, *quads3d, side, it, normals);
}
}
for quad : quads3d {
array_add(vecs, quad.x);
array_add(vecs, quad.y);
array_add(vecs, quad.z);
}
}
a_is_inside_b :: (a: Quad, b: Quad) -> bool {
if (b.topRight.x >= a.topRight.x) && (b.topRight.y >= a.topRight.y) {
if (b.bottomLeft.x <= a.bottomLeft.x) && (b.bottomLeft.y <= a.bottomLeft.y) {
return true;
}
}
return false;
}
remove_quad :: (quad: Quad, quadSet: *Quad_Set) {
parent : Quad;
for v, k : quadSet {
if k < quad then continue;
if a_is_inside_b(quad, k) {
parent = k;
table_remove(quadSet, k);
break;
}
}
topLeft : Vector2 = .{quad.bottomLeft.x,quad.topRight.y};
bottomRight : Vector2 = .{quad.topRight.x,quad.bottomLeft.y};
if quad.topRight.x != parent.topRight.x {
table_add(quadSet, .{parent.topRight,bottomRight}, true);
}
if quad.topRight.y != parent.topRight.y {
table_add(quadSet, .{.{quad.topRight.x,parent.topRight.y},.{parent.bottomLeft.x,quad.topRight.y}}, true);
}
if quad.bottomLeft.y != parent.bottomLeft.y {
table_add(quadSet, .{.{parent.topRight.x,quad.bottomLeft.y},.{quad.bottomLeft.x,parent.bottomLeft.y}}, true);
}
if quad.bottomLeft.x != parent.bottomLeft.x {
table_add(quadSet, .{topLeft,parent.bottomLeft}, true);
}
}
remove_not_seen :: (trilept: *Trile, quads: *Quads) {
for x: 0..15 {
for y: 0..15 {
for z: 0..15 {
exposure: u8 = sides_with_air_exposure(trilept, x, y, z);
for side: trileSideValues {
if !((cast(u8)side) & exposure) {
ux, uy, uz := change_perspective(*x, *y, *z, side);
remove_quad(.{.{cast(float)ux.*+1, cast(float)uy.*+1}, .{cast(float)ux.*, cast(float)uy.*}}, *quads.*[side_to_quad_list_index(side)][uz.*]);
}
}
}
}
}
}
generate_optimized_quad_mesh :: (trilept: *Trile, vecs: *[..]float, normals: *[..]float) {
quads : Quads;
init_quads(*quads);
remove_not_seen(trilept, *quads);
quads_to_vecs(*quads, vecs, normals);
}
Pool :: #import "Pool";
meshgenpool : Pool.Pool;
generate_trile_gfx_matias :: (trileptr : *Trile) -> Trile_GFX {
// @ToDo: Only do this if we haven't yet done it.
if !meshgenpool.block_allocator.proc then Pool.set_allocators(*meshgenpool);
old_alloc := context.allocator;
new_context := context;
new_context.allocator = .{Pool.pool_allocator_proc, *meshgenpool};
push_context new_context {
triangleVecs : [..]float;
triangleNorms : [..]float;
quadVecs : [..]float;
quadNorms : [..]float;
generate_optimized_quad_mesh(trileptr,*quadVecs,*quadNorms);
quads_to_triangles(*quadVecs, *triangleVecs,*quadNorms, *triangleNorms);
trile_vert_buffer_info := sg_buffer_desc.{ data = .{ ptr = triangleVecs.data, size = xx (triangleVecs.count * 4) } };
trile_vert_buffer := sg_make_buffer(*trile_vert_buffer_info);
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);
log_debug("Successfully generated mesh for trile with % triangles.", triangleVecs.count / 3 / 3);
centres : [..]float;
// Generate triangle centers.
for 0..(triangleVecs.count/3/3)-1 {
x1 := triangleVecs[it * 9 + 0];
x2 := triangleVecs[it * 9 + 3];
x3 := triangleVecs[it * 9 + 6];
xr := (x1+x2+x3) / 3.0;
y1 := triangleVecs[it * 9 + 1];
y2 := triangleVecs[it * 9 + 4];
y3 := triangleVecs[it * 9 + 7];
yr := (y1+y2+y3) / 3.0;
z1 := triangleVecs[it * 9 + 2];
z2 := triangleVecs[it * 9 + 5];
z3 := triangleVecs[it * 9 + 8];
zr := (z1+z2+z3) / 3.0;
for 0..2 {
array_add(*centres, xr);
array_add(*centres, yr);
array_add(*centres, zr);
}
}
trile_centre_buffer_info := sg_buffer_desc.{ data = .{ ptr = centres.data, size = xx (centres.count * 4) } };
trile_centre_buffer := sg_make_buffer(*trile_centre_buffer_info);
// Create the texture for the trile, from which it gets it's colors for trixels.
materialdata : [16*16*16*4]u8;
counter : int = 0;
for x: 0..15 {
for y: 0..15 {
for z: 0..15 {
if trileptr.trixels[x][y][z].empty {
// @ToDo: add some null pattern here to help in shader side.
materialdata[counter + 0] = 0;
materialdata[counter + 1] = 0;
materialdata[counter + 2] = 0;
materialdata[counter + 3] = 0;
counter += 4;
} else {
r,g,b,a := material_to_rgba(trileptr.trixels[x][y][z].material);
materialdata[counter + 0] = r;
materialdata[counter + 1] = g;
materialdata[counter + 2] = b;
materialdata[counter + 3] = a;
counter += 4;
}
}
}
}
imgdata : sg_image_data;
imgdata.subimage[0][0] = .{materialdata.data, materialdata.count};
texdesc : sg_image_desc = .{
render_target = false,
width = 16,
height = 16*16,
pixel_format = sg_pixel_format.RGBA8,
sample_count = 1,
data = imgdata
};
img := sg_make_image(*texdesc);
state := sg_query_image_state(img);
log_debug("IMG: %", state);
context.allocator = old_alloc;
vecsCopy := array_copy(triangleVecs);
Pool.reset(*meshgenpool);
lod4_voxels := downsample_trile(trileptr, 4);
lod_4 := bake_lod_cube_mesh(lod4_voxels, 4);
lod2_voxels := downsample_trile(trileptr, 2);
lod_2 := bake_lod_cube_mesh(lod2_voxels, 2);
return .{ img, trile_vert_buffer, trile_normal_buffer, trile_centre_buffer, vecsCopy, triangleVecs.count / 3, lod_4, lod_2 };
}
}

View File

@ -1,34 +0,0 @@
Trile_Side :: enum_flags u8 {
TOP :: 0x1; // Larger Y
LEFT :: 0x2; // Larger Z
RIGHT :: 0x4; // Smaller Z
FRONT :: 0x8; // Larger X
BACK :: 0x10; // Smaller X
BOTTOM :: 0x20; // Smaller Ys
}
trileSideValues : [6]Trile_Side = .[.TOP, .LEFT, .RIGHT, .FRONT, .BACK, .BOTTOM];
swap_xyz_for_side :: (x: int, y: int, z: int, Trile_Side) -> (int, int, int) {
}
sides_with_air_exposure :: (trileptr: *Trile, x: int, y: int, z: int) -> u8 {
res : u8 = 0;
if trileptr.trixels[x][y][z].empty then return res;
if y == 15 || trileptr.trixels[x][y+1][z].empty then res |= xx Trile_Side.TOP;
if y == 0 || trileptr.trixels[x][y-1][z].empty then res |= xx Trile_Side.BOTTOM;
if z == 15 || trileptr.trixels[x][y][z+1].empty then res |= xx Trile_Side.LEFT;
if z == 0 || trileptr.trixels[x][y][z-1].empty then res |= xx Trile_Side.RIGHT;
if x == 15 || trileptr.trixels[x+1][y][z].empty then res |= xx Trile_Side.FRONT;
if x == 0 || trileptr.trixels[x-1][y][z].empty then res |= xx Trile_Side.BACK;
return res;
}
meshgen :: (trile: *Trile) {
for trileSideValues {
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,107 +0,0 @@
disable_dof_post_process : bool = false;
Post_Process :: struct {
exposure : float = 1.0; @Slider,0,3,0.1;
contrast : float = 1.0; @Slider,0,3,0.1;
saturation : float = 1.0; @Slider,0.0,5.0,0.1;
gamma : float = 1.0; @Slider,0.3,3.0,0.1;
tonemap : float = 0.0; @Slider,0,1,1;
ssao : float = 0.0; @Slider,0,5,0.1;
ssao_size : s32 = 1; @Slider,0,5,1;
dilate_separation : float = 1.0; @Slider,0,6,0.1;
dilate_size : s32 = 0; @Slider,0,10,1;
dilate_min : float = 0.1; @Slider,0,1,0.1;
dilate_max : float = 0.3; @Slider,0,1,0.1;
dof_blur_size : float = 1.0; @Slider,0.0,2.0,0.1;
dof_min : float = 1.0; @Slider,0,10,1;
dof_max : float = 3.0; @Slider,0,50,1;
dof_point : float = 5.0; @Slider,0,30,1;
bloom_treshold : float = 0.4; @Slider,0,1,0.1;
bloom_amount : float = 0.0; @Slider,0,5,0.1;
vignette_intensity: float = 0.0; @Slider,0,1,0.1;
vignette_radius : float = 0.5; @Slider,0,1,0.1;
scanlines_intensity: float = 0.0; @Slider,0,1,0.1;
scanlines_density : float = 1.0; @Slider,0,10,0.1;
chromatic_aberration_intensity: float = 0.0; @Slider,0,0.05,0.001;
film_grain_intensity: float = 0.0; @Slider,0,0.5,0.001;
barrel_distortion_intensity: float = 0.0; @Slider,-2,2,0.1;
lut_mode: s32 = 0; @Slider,0,2,1; // 0 -> no LUT, 1 -> LUT with interpolation 2 -> LUT no iterpolate
dither_intensity: float = 0.0; @Slider,0,1,0.05;
}
current_post_process : Post_Process;
Lighting_Config :: struct {
ambient_intensity : float = 0.35; @Slider,0,2,0.05
emissive_scale : float = 5.0; @Slider,0,20,0.5
indirect_diff_scale : float = 1.0; @Slider,0,3,0.1
indirect_spec_scale : float = 1.0; @Slider,0,3,0.1
ambient_color : Vector3 = .{0.3,0.3,0.4}; @Color
indirect_tint : Vector3 = .{1.05,1.0,0.9}; @Color
}
current_lighting_config : Lighting_Config;
Post_Process_Save :: struct {
#as using pp: Post_Process;
lut_name: string;
}
load_post_process_from_pack :: () {
s := load_string_from_pack("game_core", "postprocess.json");
success, save := Jaison.json_parse_string(s, Post_Process_Save,, temp);
if success {
current_post_process = save.pp;
// Restore LUT selection by name.
if save.lut_name.count > 0 {
for LUT_list {
if it.name == save.lut_name {
g_current_lut_texture_index = cast(s32) it_index;
break;
}
}
}
}
}
save_post_process :: () {
#if OS != .WASM {
file :: #import "File";
save: Post_Process_Save;
save.pp = current_post_process;
if g_current_lut_texture_index >= 0 && g_current_lut_texture_index < LUT_list.count {
save.lut_name = LUT_list[g_current_lut_texture_index].name;
}
json := Jaison.json_write_string(save, " ");
file.write_entire_file(tprint("%/game_core/postprocess.json", GAME_RESOURCES_DIR), json);
}
}
reset_post_process :: () {
load_post_process_from_pack();
} @Command
Color_LUT :: struct {
name: string;
image: sg_image;
}
LUT_list : [..]Color_LUT;
LUT_name_list : [..]string;
g_current_lut_texture_index : s32 = 0;
add_image_to_lut_list :: (img: sg_image, name: string) {
for LUT_list {
if it.name == name then return;
}
newSheet := Color_LUT.{
name = sprint("%", name),
image = img,
};
array_add(*LUT_list, newSheet);
array_add(*LUT_name_list, newSheet.name);
}

View File

@ -1,49 +1,31 @@
/*
// Rendering. Everything outside this directory goes through the Scene API in
// scene.jai and text.jai.
The rendering pipeline.
@ToDo: Write something smart about our rendering
architecture.
*/
#load "sky.jai";
#load "ssao.jai";
#load "core.jai";
#load "tasks.jai";
#load "scene.jai";
#load "trile_mesher.jai";
#load "text.jai";
#load "camera.jai";
#load "arbtri.jai";
#load "debug_draw.jai";
#load "meshgen.jai";
#load "lodgen.jai";
#load "helpers.jai";
#load "animation.jai";
#load "pipelines.jai";
#load "post_processing.jai";
#load "backend_sokol_helpers.jai";
#scope_file
initted : bool;
old_w : int;
old_h : int;
on_window_resize :: () {
// Recreate textures that are rendering targets and dependent on window size.
create_plane_pipeline_reflection_images();
create_final_image();
create_ssao_images();
create_sh_irradiance_image();
// Reset glyph cache so stale sizes from resizing don't fill the atlas.
w, h : s32;
fonsGetAtlasSize(state.fons, *w, *h);
fonsResetAtlas(state.fons, w, h);
#if RENDERER == "sokol" {
#load "../renderer_sokol/renderer.jai";
} else {
#assert false "Unknown renderer; build with renderer=sokol.";
}
#scope_export
render :: () {
text_end_frame();
draw_debug_lines(.{g_debug_line_count, g_debug_lines.data}, overlay = false);
draw_debug_lines(.{g_overlay_line_count, g_overlay_lines.data}, overlay = true);
w, h := get_window_size();
scene_end_frame(w, h, xx get_time());
g_debug_line_count = 0;
g_overlay_line_count = 0;
}
check_and_handle_window_resize :: () {
w,h := get_window_size();
w, h := get_window_size();
if !initted {
old_w = w;
old_h = h;
@ -52,6 +34,13 @@ check_and_handle_window_resize :: () {
}
if w != old_w || h != old_h {
old_w = w; old_h = h;
on_window_resize();
// UI font sizes follow the window, so stale sizes would fill the atlas.
text_reset_atlas();
}
}
#scope_file
initted : bool;
old_w : int;
old_h : int;

395
src/rendering/scene.jai Normal file
View File

@ -0,0 +1,395 @@
// The new scene API. The idea is that what to draw is defined trough this,
// and the renderer can be nicely separated and tested.
//
// I'm also planning to maybe add a WGPU backend at some point or something.
Trile_Mesh :: struct { id: u32; }
Texture :: struct { id: u32; }
Font_Face :: struct { id: s32; }
View_Id :: struct { index: s32; }
Environment :: struct {
reflection_height : float;
water : bool;
sky : bool = true; // off: black outside the level
water_color : Vector3 = .{1, 1, 1};
deep_color : Vector3 = .{1, 1, 1};
water_reflectivity : float;
water_distortion : float = 0.007;
water_shininess : float = 64;
water_normals : Texture;
sun_direction : Vector3 = #run normalize(Vector3.{0.2, 0.3, 0.4}); // towards the sun
sun_color : Vector3 = .{1, 1, 1};
shade_color : Vector3 = .{0.45, 0.45, 0.75};
sky_base : Vector3 = .{0.38, 0.81, 0.95};
sky_top : Vector3 = .{0.17, 0.4, 0.95};
sun_disk : Vector3 = .{1, 1, 1};
sun_halo : Vector3 = .{1, 1, 1};
horizon_halo : Vector3 = .{1, 1, 1};
sky_intensity : float = 0.3;
exposure : float; // in stops
contrast : float = 1;
saturation : float = 1;
bloom_amount : float = 0.4;
shaft_density : float = 0.1; // light shafts through glass
shaft_amount : float = 1;
}
// With cut on, triles marked ROOF or WALL are hidden from the camera around the
// focus: everything marked from the lowest roof above the focus upward, so the
// storeys above go whole, and walls on the camera's side of the focus down to a
// one-trile stub. They dissolve in and out rather than popping, and still cast
// shadows and show in reflections.
View :: struct {
camera : Camera;
environment : *Environment;
draw_world : bool = true;
cut : bool;
focus : Vector3;
}
Trile_Cut :: enum u8 {
NONE;
ROOF;
WALL;
}
CUT_RADIUS :: 12.0; // horizontal reach from the focus, for roofs and walls
CUT_WALL_MARGIN :: 0.5; // walls this close to the focus, toward the camera, stay
CUT_FADE_TIME :: 0.25; // seconds to dissolve in or out
SHADOW_MAP_SIZE :: 2048;
SHADOW_RADIUS :: 40.0;
SHADOW_DEPTH :: 100.0;
Trile_Tint :: enum u8 {
NONE;
ADD_PREVIEW;
DELETE_PREVIEW;
}
// This direction means that the billboard should face the camera.
BILLBOARD_FACE_CAMERA :: Vector3.{-100, -100, -100};
Blend_Mode :: enum u8 {
ALPHA;
ADDITIVE;
}
Particle_Instance :: struct {
position : Vector3;
size : float;
uv_rect : Vector4; // x, y, w, h, 0..1
color : Vector4;
glow : float; // 0..1, like swatch emittance
}
// Pixels from top left.
Ui_Vertex :: struct {
position : Vector2;
uv : Vector2;
color : Vector4;
}
trile_mesh_create :: (trile: *Trile) -> Trile_Mesh {
vertices, indices := mesh_trile(trile);
mesh := Trile_Mesh.{renderer_trile_mesh_create(vertices, indices)};
set_mesh_cut(mesh, trile.cut);
return mesh;
}
trile_mesh_update :: (mesh: Trile_Mesh, trile: *Trile) {
vertices, indices := mesh_trile(trile);
renderer_trile_mesh_update(mesh.id, vertices, indices);
set_mesh_cut(mesh, trile.cut);
}
trile_mesh_destroy :: (mesh: Trile_Mesh) {
renderer_trile_mesh_destroy(mesh.id);
set_mesh_cut(mesh, .NONE);
}
swatch_set :: (id: u8, color: [3]u8, reflectivity: u8, gloss: u8, emittance: u8, glass: bool) {
renderer_swatch_set(id, color, reflectivity, gloss, emittance, glass);
}
// Pixels are RGBA8.
texture_create :: (width: s32, height: s32, pixels: []u8) -> Texture {
return .{renderer_texture_create(width, height, pixels)};
}
texture_update :: (texture: Texture, pixels: []u8) {
renderer_texture_update(texture.id, pixels);
}
texture_destroy :: (texture: Texture) {
renderer_texture_destroy(texture.id);
}
World_Group :: struct {
mesh : Trile_Mesh;
instances : []Trile_Instance;
}
// Baked light at a trile centre, as L1 spherical harmonics in half floats: red,
// green and blue, each (constant, y, z, x). A negative red constant marks a probe
// inside geometry.
Probe :: struct {
sh : [12]u16;
}
// One probe per trile, indexed x + y * CHUNK_SIZE + z * CHUNK_SIZE * CHUNK_SIZE.
PROBES_PER_CHUNK :: CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE;
world_set_chunk :: (key: Chunk_Key, origin: Vector3, groups: []World_Group) {
chunk := find_or_add(*scene.chunks, key);
chunk.origin = origin;
for chunk.groups array_free(it.instances);
array_reset_keeping_memory(*chunk.groups);
for groups {
group := array_add(*chunk.groups);
group.mesh = it.mesh;
group.instances = array_copy(it.instances);
}
}
world_remove_chunk :: (key: Chunk_Key) {
chunk := table_find_pointer(*scene.chunks, key);
if !chunk return;
for chunk.groups array_free(it.instances);
array_free(chunk.groups);
table_remove(*scene.chunks, key);
}
world_clear :: () {
for chunk: scene.chunks {
for chunk.groups array_free(it.instances);
array_free(chunk.groups);
}
table_reset(*scene.chunks);
table_reset(*scene.cut_fades);
renderer_probes_clear();
}
// Probe light is added to the shade colour, so baking only ever brightens.
world_set_chunk_probes :: (key: Chunk_Key, probes: []Probe) {
assert(probes.count == PROBES_PER_CHUNK);
renderer_probes_set(key, probes);
}
add_view :: (view: View) -> View_Id {
array_add(*scene.views, view);
camera := view.camera;
array_add(*scene.view_proj, create_viewproj(*camera));
env := ifx view.environment then view.environment.* else .{};
array_add(*scene.shadow_view_proj, create_sun_viewproj(camera.target, env.sun_direction, SHADOW_RADIUS, SHADOW_DEPTH, SHADOW_MAP_SIZE));
height := env.reflection_height;
camera.position.y = 2 * height - camera.position.y;
camera.target.y = 2 * height - camera.target.y;
array_add(*scene.reflection_view_proj, create_viewproj(*camera));
array_add(*scene.view_cuts, make_view_cut(view));
return .{xx (scene.views.count - 1)};
}
// How far the view's camera has dissolved this trile, 0 shown to 1 gone.
// position is the trile's corner. Call once per trile per frame; it advances the fade.
trile_cut :: (view: View_Id, mesh: Trile_Mesh, position: Vector3) -> float {
cut := scene.view_cuts[view.index];
kind := mesh_cut(mesh);
if !cut.enabled || kind == .NONE return 0;
target := 0.0;
to_trile := Vector2.{position.x + 0.5 - cut.focus.x, position.z + 0.5 - cut.focus.z};
if length(to_trile) <= CUT_RADIUS {
if position.y >= cut.height target = 1;
if kind == .WALL && position.y > cut.floor && dot(to_trile, cut.toward_camera) > CUT_WALL_MARGIN target = 1;
}
x, y, z := cast(s64) floor(position.x), cast(s64) floor(position.y), cast(s64) floor(position.z);
key := (cast(s64) view.index << 60) | ((x & 0xFFFFF) << 40) | ((y & 0xFFFFF) << 20) | (z & 0xFFFFF);
fade := table_find_pointer(*scene.cut_fades, key);
if !fade {
if target == 0 return 0;
fade = table_set(*scene.cut_fades, key, 0);
}
step := (scene.time - scene.cut_time) / CUT_FADE_TIME;
fade.* = ifx target > fade.* then min(target, fade.* + step) else max(target, fade.* - step);
result := fade.*;
if result == 0 table_remove(*scene.cut_fades, key);
return result;
}
draw_trile :: (view: View_Id, mesh: Trile_Mesh, position: Vector3, orientation: u8, tint := Trile_Tint.NONE) {
array_add(*scene.triles, .{view, mesh, position, orientation, tint});
}
// uv_rect is x, y, w, h in the sheet, normalized; a negative w mirrors it.
draw_billboard :: (view: View_Id, sheet: Texture, uv_rect: Vector4, size: Vector2, position: Vector3, face := BILLBOARD_FACE_CAMERA) {
array_add(*scene.billboards, .{view, sheet, uv_rect, size, position, face});
}
draw_particles :: (view: View_Id, sheet: Texture, blend: Blend_Mode, particles: []Particle_Instance) {
array_add(*scene.particles, .{view, sheet, blend, array_copy(particles,, temp)});
}
// Lines are drawn in every view; overlay lines ignore depth. The slice must stay
// valid until render().
draw_debug_lines :: (lines: []Debug_Line, overlay: bool) {
if overlay scene.overlay_lines = lines;
else scene.debug_lines = lines;
}
// Untextured triangles pass a zero texture.
ui_triangles :: (vertices: []Ui_Vertex, texture: Texture) {
array_add(*scene.ui, .{texture = texture, vertices = array_copy(vertices,, temp)});
}
ui_scissor :: (x: s32, y: s32, w: s32, h: s32) {
array_add(*scene.ui, .{scissor = .{x, y, w, h}, set_scissor = true});
}
ui_scissor_clear :: () {
array_add(*scene.ui, .{clear_scissor = true});
}
View_Cut :: struct {
enabled : bool;
focus : Vector3;
floor : float; // the trile layer the focus stands in
height : float; // marked triles from here up are hidden
toward_camera : Vector2; // horizontal, normalized
}
Scene_Chunk :: struct {
origin : Vector3;
groups : [..]World_Group;
}
Scene_Trile :: struct {
view : View_Id;
mesh : Trile_Mesh;
position : Vector3;
orientation : u8;
tint : Trile_Tint;
}
Scene_Billboard :: struct {
view : View_Id;
sheet : Texture;
uv_rect : Vector4;
size : Vector2;
position : Vector3;
face : Vector3;
}
Scene_Particles :: struct {
view : View_Id;
sheet : Texture;
blend : Blend_Mode;
particles : []Particle_Instance;
}
Scene_Ui :: struct {
texture : Texture;
vertices : []Ui_Vertex;
scissor : Ui_Rect;
set_scissor : bool;
clear_scissor : bool;
}
Trile_Vertex :: struct {
position : Vector3;
swatch : u8;
ao : u8; // 0 = fully occluded, 3 = open
normal : u8; // axis * 2, +1 when facing the negative direction
_ : u8;
}
Scene :: struct {
chunks : Table(Chunk_Key, Scene_Chunk, chunk_key_hash, chunk_key_compare);
mesh_cuts : [..]Trile_Cut; // by mesh id
views : [..]View;
view_proj : [..]Matrix4;
reflection_view_proj : [..]Matrix4;
shadow_view_proj : [..]Matrix4;
view_cuts : [..]View_Cut;
cut_fades : Table(s64, float); // dissolving or cut triles, by view and position
cut_time : float; // when the fades last advanced
time : float;
triles : [..]Scene_Trile;
billboards : [..]Scene_Billboard;
particles : [..]Scene_Particles;
ui : [..]Scene_Ui;
debug_lines : []Debug_Line;
overlay_lines : []Debug_Line;
}
scene_init :: () {
orientations : [ORIENTATION_COUNT]Matrix3;
for *orientations {
m := orientation_matrix(xx it_index).m;
for r: 0..2 for c: 0..2 it.coef[r][c] = xx m[r][c];
}
renderer_init(orientations);
}
scene_shutdown :: () {
renderer_shutdown();
}
scene_end_frame :: (width: s32, height: s32, time: float) {
scene.time = time;
renderer_render(*scene, width, height);
scene.cut_time = time;
array_reset_keeping_memory(*scene.views);
array_reset_keeping_memory(*scene.view_proj);
array_reset_keeping_memory(*scene.reflection_view_proj);
array_reset_keeping_memory(*scene.shadow_view_proj);
array_reset_keeping_memory(*scene.view_cuts);
array_reset_keeping_memory(*scene.triles);
array_reset_keeping_memory(*scene.billboards);
array_reset_keeping_memory(*scene.particles);
array_reset_keeping_memory(*scene.ui);
scene.debug_lines = .[];
scene.overlay_lines = .[];
}
#scope_file
scene : Scene;
set_mesh_cut :: (mesh: Trile_Mesh, cut: Trile_Cut) {
if scene.mesh_cuts.count <= mesh.id array_resize(*scene.mesh_cuts, mesh.id + 1);
scene.mesh_cuts[mesh.id] = cut;
}
mesh_cut :: (mesh: Trile_Mesh) -> Trile_Cut {
if mesh.id >= scene.mesh_cuts.count return .NONE;
return scene.mesh_cuts[mesh.id];
}
make_view_cut :: (view: View) -> View_Cut {
cut : View_Cut;
if !view.cut return cut;
cut.enabled = true;
cut.focus = view.focus;
cut.floor = floor(view.focus.y + 0.5);
cut.height = FLOAT32_MAX;
to_camera := Vector2.{view.camera.position.x - view.focus.x, view.camera.position.z - view.focus.z};
if length(to_camera) > 0.0001 cut.toward_camera = normalize(to_camera);
for chunk: scene.chunks for group: chunk.groups {
if mesh_cut(group.mesh) != .ROOF continue;
for group.instances {
p := chunk.origin + Vector3.{xx it.x, xx it.y, xx it.z};
if p.y <= cut.floor continue;
if length(Vector2.{p.x + 0.5 - view.focus.x, p.z + 0.5 - view.focus.z}) > CUT_RADIUS continue;
cut.height = min(cut.height, p.y);
}
}
return cut;
}

View File

@ -1,78 +0,0 @@
draw_sky :: (cam: *Camera, worldConfig: *World_Config = null) {
mvp := create_viewproj(cam);
vs_params : Sky_Vs_Params;
world_conf : Sky_World_Config;
wc : *World_Config = ifx worldConfig == null then *(World_Config.{}) else worldConfig;
world_config_to_shader_type(wc, *world_conf);
vs_params.mvp = mvp.floats;
sg_apply_pipeline(gPipelines.sky.pipeline);
sg_apply_bindings(*gPipelines.sky.bind);
sg_apply_uniforms(UB_sky_vs_params, *(sg_range.{ ptr = *vs_params, size = size_of(type_of(vs_params)) }));
sg_apply_uniforms(UB_sky_world_config, *(sg_range.{ptr = *world_conf, size = size_of(type_of(world_conf))}));
sg_draw(0, 36, 1);
}
get_frustum_corners :: (cam: *Camera) -> [8]Vector3 {
mat_view := create_lookat(cam);
mat_proj := create_perspective(cam);
corners : [8]Vector3;
corners[0] = unproject(Vector3.{-1, -1, -1}, mat_proj, mat_view);
corners[1] = unproject(Vector3.{1, -1, -1}, mat_proj, mat_view);
corners[2] = unproject(Vector3.{1, 1, -1}, mat_proj, mat_view);
corners[3] = unproject(Vector3.{-1, 1, -1}, mat_proj, mat_view);
corners[4] = unproject(Vector3.{-1, -1, 1}, mat_proj, mat_view);
corners[5] = unproject(Vector3.{1, -1, 1}, mat_proj, mat_view);
corners[6] = unproject(Vector3.{1, 1, 1}, mat_proj, mat_view);
corners[7] = unproject(Vector3.{-1, 1, 1}, mat_proj, mat_view);
return corners;
}
create_shadow_viewproj :: (cam: *Camera, conf: *World_Config) -> Matrix4 {
up: Vector3 = .{0, 1, 0};
targetToPos := conf.sunPosition;
A := normalize(targetToPos);
B := normalize(cross(up, A));
C := cross(A, B);
camcpy := cam.*;
camcpy.far = 50;
camcpy.near = 0.5;
frustum_corners := get_frustum_corners(*camcpy);
avg : Vector3;
for frustum_corners {
avg += it;
}
avg /= 8.0;
sunCameraPosition := -targetToPos * 50.0;
view := Matrix4.{
B.x, C.x, A.x, 0,
B.y, C.y, A.y, 0,
B.z, C.z, A.z, 0,
-dot(B, sunCameraPosition), -dot(C, sunCameraPosition), -dot(A, sunCameraPosition), 1
};
proj := matrix_ortho(-30, 30, -30, 30, 0, 100);
return view*proj;
}
// taken from raymath.h
matrix_ortho :: (left: float, right: float, bottom: float, top: float, near: float, far: float) -> Matrix4 {
rl := right - left;
tb := top - bottom;
fn := far - near;
return Matrix4.{
2.0/rl,0,0,0,
0,2.0/tb,0,0,
0,0,-2/fn,0,
-(left + right)/rl, -(top+bottom)/tb, (far+near)/fn, 1
};
}

View File

@ -1,33 +0,0 @@
#scope_file
Random :: #import "Random";
#scope_export
g_ssao_samples : [64][4]float;
g_ssao_noise : [16*4]float;
init_ssao :: () {
for 0..63 {
vec := Vector3.{
Random.random_get_zero_to_one() * 2 - 1,
Random.random_get_zero_to_one() * 2 - 1,
Random.random_get_zero_to_one(),
};
vec = normalize(vec);
vec *= Random.random_get_zero_to_one();
scale := cast(float)it/64.0;
scale = lerp(0.1, 1.0, scale*scale);
vec *= scale;
g_ssao_samples[it][0] = vec.x;
g_ssao_samples[it][1] = vec.y;
g_ssao_samples[it][2] = vec.z;
g_ssao_samples[it][3] = 0;
}
for 0..15 {
g_ssao_noise[it*4+0] = Random.random_get_zero_to_one() * 2 - 1;
g_ssao_noise[it*4+1] = Random.random_get_zero_to_one() * 2 - 1;
g_ssao_noise[it*4+2] = 0.0;
g_ssao_noise[it*4+3] = 0.0;
}
}

View File

@ -1,278 +0,0 @@
#scope_export
Rendering_Task_Type :: enum {
INVALID;
GROUND; // We need to add an ability to invalidate buffer here too.
SKY;
SET_CAMERA;
SET_LIGHT;
TRILE; // We need to add an ability to invalidate buffer instead of updating it constantly. Also probably have a buffer for static world triles and one for moving ones.
TRILE_DYNAMIC;
TRILE_RDM;
TRIXELS;
BILLBOARD;
PARTICLES;
PARTICLES_BUFFER;
};
Rendering_Task :: struct {
type : Rendering_Task_Type = .INVALID;
};
Rendering_Task_World :: struct {
#as using t : Rendering_Task;
world : *World;
}
Rendering_Task_Sky :: struct {
#as using t : Rendering_Task;
t.type = .SKY;
worldConfig : *World_Config;
}
Rendering_Task_Set_Light :: struct {
#as using t : Rendering_Task;
t.type = .SET_LIGHT;
worldConfig : *World_Config;
}
Rendering_Task_Ground :: struct {
#as using t : Rendering_Task;
t.type = .GROUND;
world : *World;
}
Rendering_Task_Billboard :: struct {
#as using t : Rendering_Task;
t.type = .BILLBOARD;
position : Vector3;
animation : *Animation;
frame : s32;
flipX : bool;
flipY : bool;
faceDir : Vector3 = .{-100, -100, -100};
}
Rendering_Task_Trile :: struct {
#as using t : Rendering_Task;
t.type = .TRILE;
trile : string;
chunk_key : Chunk_Key;
positions : []Trile_Instance;
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)
skip_main : bool = false; // RDM-flagged instances still cast shadows / write gbuffer / reflect, but main pass uses the RDM pipeline
lod_index : s32 = 0; // 0 = full detail, 1 = 4^3 LOD, 2 = 2^3 LOD
}
// Triles at arbitrary float world positions (entities, moving things).
// Shares the instance buffer and pipelines with the static TRILE path, so it
// participates in main/gbuffer/shadow/reflection just like world triles.
// chunk_key is the enclosing chunk, used only for SH probe lookup.
Rendering_Task_Trile_Dynamic :: struct {
#as using t : Rendering_Task;
t.type = .TRILE_DYNAMIC;
trile : string;
positions : []Vector4; // xyz = world position, w = orientation 0..23
chunk_key : Chunk_Key;
worldConf : *World_Config;
}
Rendering_Task_Trile_RDM :: struct {
#as using t : Rendering_Task;
t.type = .TRILE_RDM;
trile : string;
position : Vector4; // xyz=world position, w=orientation
atlas_rect : Vector4; // global atlas UV rect (zeros until Step 6 wires the manifest)
worldConf : *World_Config;
}
Rendering_Task_Trixels :: struct {
#as using t : Rendering_Task;
t.type = .TRIXELS;
colMultipliers : *[16][16][16]Vector3;
trile : *Trile;
world_offset : Vector3;
brightness : float = 1.0;
tile_rotation : Matrix4 = .{_11=1, _22=1, _33=1, _44=1};
is_secondary : bool;
}
Rendering_Task_Particles :: struct {
#as using t : Rendering_Task;
t.type = .PARTICLES;
count : s32;
instance_offset : s32;
blend_mode : Particle_Blend_Mode;
sheet : sg_image;
}
Rendering_Task_Particles_Buffer :: struct {
#as using t : Rendering_Task;
t.type = .PARTICLES_BUFFER;
total_count : s32;
pos_size : [MAX_PARTICLES]Vector4;
uv_rects : [MAX_PARTICLES]Vector4;
colors : [MAX_PARTICLES]Vector4;
}
Rendering_Task_Set_Camera :: struct {
#as using t : Rendering_Task;
camera : Camera;
planeHeight : float;
}
rendering_tasklist_clear :: () {
array_reset_keeping_memory(*rendering_tasklist);
}
add_rendering_task :: (task: $T) {
task_ptr := New(T,, temp);
task_ptr.* = task;
array_add(*rendering_tasklist, task_ptr);
}
rendering_tasklist : [..]*Rendering_Task;
tasks_to_commands :: () {
trile_add_counter: s32 = 0;
trile_rdm_add_counter: s32 = 0;
for rendering_tasklist {
if it.type == {
case .SET_LIGHT;
lighttask := (cast(*Rendering_Task_Set_Light)it);
lightcmd := New(Render_Command_Set_Light,, temp);
lightcmd.worldConfig = lighttask.worldConfig;
array_add(*render_command_buckets.setup, lightcmd);
case .TRIXELS;
trixelsTask := (cast(*Rendering_Task_Trixels)it);
updateCommand := New(Render_Command_Update_Trixels,, temp);
updateCommand.trile = trixelsTask.trile;
updateCommand.colMultipliers = trixelsTask.colMultipliers;
updateCommand.is_secondary = trixelsTask.is_secondary;
array_add(*render_command_buckets.setup, updateCommand);
drawCommand := New(Render_Command_Draw_Trixels,, temp);
drawCommand.world_offset = trixelsTask.world_offset;
drawCommand.brightness = trixelsTask.brightness;
drawCommand.tile_rotation = trixelsTask.tile_rotation;
drawCommand.is_secondary = trixelsTask.is_secondary;
array_add(*render_command_buckets.main, drawCommand);
// Currently no need to draw trixels anywhere but the editor so no
// need for drawing them in the planar reflection pass...
// array_add(*render_command_buckets.reflection, drawCommand);
case .TRILE;
trileTask := (cast(*Rendering_Task_Trile)it);
addPositionsCmd := New(Render_Command_Add_Trile_Positions,, temp);
addPositionsCmd.positions = trileTask.positions;
addPositionsCmd.chunk = trileTask.chunk_key;
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;
drawPositionsCmd.preview_mode = trileTask.preview_mode;
drawPositionsCmd.offset_index = trile_add_counter;
drawPositionsCmd.lod_index = trileTask.lod_index;
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 if trileTask.skip_main {
array_add(*render_command_buckets.reflection, drawPositionsCmd);
array_add(*render_command_buckets.gbuffer, drawPositionsCmd);
array_add(*render_command_buckets.shadow, 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 .TRILE_DYNAMIC;
dynTask := (cast(*Rendering_Task_Trile_Dynamic)it);
addF32Cmd := New(Render_Command_Add_Trile_Positions_F32,, temp);
addF32Cmd.positions = dynTask.positions;
array_add(*render_command_buckets.setup, addF32Cmd);
drawDynCmd := New(Render_Command_Draw_Trile_Positions,, temp);
drawDynCmd.trile = dynTask.trile;
drawDynCmd.chunk_key = dynTask.chunk_key;
drawDynCmd.amount = cast(s32)dynTask.positions.count;
drawDynCmd.conf = dynTask.worldConf;
drawDynCmd.offset_index = trile_add_counter;
trile_add_counter += 1;
array_add(*render_command_buckets.reflection, drawDynCmd);
array_add(*render_command_buckets.main, drawDynCmd);
array_add(*render_command_buckets.gbuffer, drawDynCmd);
array_add(*render_command_buckets.shadow, drawDynCmd);
case .TRILE_RDM;
rdmTask := (cast(*Rendering_Task_Trile_RDM)it);
addCmd := New(Render_Command_Add_Trile_RDM_Position,, temp);
addCmd.position = rdmTask.position;
array_add(*render_command_buckets.setup, addCmd);
drawCmd := New(Render_Command_Draw_Trile_RDM,, temp);
drawCmd.trile = rdmTask.trile;
drawCmd.conf = rdmTask.worldConf;
drawCmd.atlas_rect = rdmTask.atlas_rect;
drawCmd.offset_index = trile_rdm_add_counter;
trile_rdm_add_counter += 1;
array_add(*render_command_buckets.main, drawCmd);
case .SKY;
command := New(Render_Command_Sky,, temp);
command.worldConfig = (cast(*Rendering_Task_Sky)it).worldConfig;
array_add(*render_command_buckets.reflection, command);
array_add(*render_command_buckets.main, command);
case .GROUND;
commandDrawGround := New(Render_Command_Draw_Ground,, temp);
commandDrawGround.worldConfig = *(cast(*Rendering_Task_Ground)it).world.conf;
array_add(*render_command_buckets.main, commandDrawGround);
array_add(*render_command_buckets.gbuffer, commandDrawGround);
case .BILLBOARD;
billboardTask := (cast(*Rendering_Task_Billboard)it);
commandDrawBillboard := New(Render_Command_Draw_Billboard,, temp);
commandDrawBillboard.position = billboardTask.position;
commandDrawBillboard.frame = billboardTask.frame;
commandDrawBillboard.flipX = billboardTask.flipX;
commandDrawBillboard.flipY = billboardTask.flipY;
commandDrawBillboard.faceDir = billboardTask.faceDir;
commandDrawBillboard.animation = billboardTask.animation;
array_add(*render_command_buckets.gbuffer, commandDrawBillboard);
array_add(*render_command_buckets.main, commandDrawBillboard);
array_add(*render_command_buckets.shadow, commandDrawBillboard);
array_add(*render_command_buckets.reflection, commandDrawBillboard);
case .PARTICLES_BUFFER;
bufTask := cast(*Rendering_Task_Particles_Buffer)it;
uploadCmd := New(Render_Command_Update_Particles,, temp);
uploadCmd.total_count = bufTask.total_count;
memcpy(uploadCmd.pos_size.data, bufTask.pos_size.data, bufTask.total_count * size_of(Vector4));
memcpy(uploadCmd.uv_rects.data, bufTask.uv_rects.data, bufTask.total_count * size_of(Vector4));
memcpy(uploadCmd.colors.data, bufTask.colors.data, bufTask.total_count * size_of(Vector4));
array_add(*render_command_buckets.setup, uploadCmd);
case .PARTICLES;
particleTask := cast(*Rendering_Task_Particles)it;
drawCmd := New(Render_Command_Draw_Particles,, temp);
drawCmd.count = particleTask.count;
drawCmd.instance_offset = particleTask.instance_offset;
drawCmd.blend_mode = particleTask.blend_mode;
drawCmd.sheet = particleTask.sheet;
array_add(*render_command_buckets.main, drawCmd);
array_add(*render_command_buckets.reflection, drawCmd);
case .SET_CAMERA;
task := (cast(*Rendering_Task_Set_Camera)it);
command := New(Render_Command_Set_Camera,, temp);
command.camera = task.camera;
array_add(*render_command_buckets.main, command);
array_add(*render_command_buckets.gbuffer, command);
commandReflected := New(Render_Command_Set_Camera,, temp);
commandReflected.camera = task.camera;
commandReflected.camera.target *= Vector3.{1, -1, 1};
commandReflected.camera.position *= Vector3.{1, -1, 1};
commandReflected.camera.target.y += task.planeHeight * 2;
commandReflected.camera.position.y += task.planeHeight * 2;
array_add(*render_command_buckets.reflection, commandReflected);
}
}
rendering_tasklist_clear();
}

117
src/rendering/text.jai Normal file
View File

@ -0,0 +1,117 @@
// Text, as part of the Scene API. Fontstash lays out and rasterizes glyphs on
// the CPU into an atlas; the atlas is an ordinary Texture and the glyphs go into
// the UI stream as triangles, so nothing below the Scene API knows about fonts.
font_face_add :: (name: string, ttf: []u8) -> Font_Face {
return .{fonsAddFontMem(text.fons, temp_c_string(name), ttf.data, xx ttf.count, 0)};
}
text_measure :: (face: Font_Face, size: float, s: string) -> float {
if s.count < 1 return 0;
fonsSetFont(text.fons, face.id);
fonsSetSize(text.fons, size);
return fonsTextBounds(text.fons, 0, 0, s.data, s.data + s.count, null);
}
text_vertical_metrics :: (face: Font_Face, size: float) -> (ascender: float, descender: float, line_height: float) {
ascender, descender, line_height: float;
fonsSetFont(text.fons, face.id);
fonsSetSize(text.fons, size);
fonsVertMetrics(text.fons, *ascender, *descender, *line_height);
return ascender, descender, line_height;
}
// x, y is the left end of the baseline, in pixels from the top left.
ui_text :: (face: Font_Face, size: float, x: float, y: float, color: Vector4, s: string) {
if s.count < 1 return;
fonsSetFont(text.fons, face.id);
fonsSetSize(text.fons, size);
fonsSetColor(text.fons, pack_rgba8(color));
fonsDrawText(text.fons, x, y, s.data, s.data + s.count);
}
text_init :: (atlas_size: s32) {
params := FONSparams.{
width = atlas_size,
height = atlas_size,
flags = FONS_ZERO_TOPLEFT,
renderCreate = atlas_create,
renderResize = atlas_create,
renderUpdate = atlas_mark_dirty,
renderDraw = glyphs_draw,
};
text.fons = fonsCreateInternal(*params);
}
// Drops every rasterized glyph, e.g. when UI font sizes change with the window.
text_reset_atlas :: () {
fonsResetAtlas(text.fons, text.atlas_w, text.atlas_h);
}
// Before the UI stream is consumed: upload the atlas if glyphs were added.
text_end_frame :: () {
fonsClearState(text.fons);
if !text.atlas_dirty return;
text.atlas_dirty = false;
w, h: s32;
alpha := fonsGetTextureData(text.fons, *w, *h);
for i: 0..w*h-1 {
text.atlas_pixels[i*4 + 0] = 255;
text.atlas_pixels[i*4 + 1] = 255;
text.atlas_pixels[i*4 + 2] = 255;
text.atlas_pixels[i*4 + 3] = alpha[i];
}
texture_update(text.atlas, text.atlas_pixels);
}
#scope_file
#import "Fontstash";
text : struct {
fons : *FONScontext;
atlas : Texture;
atlas_w : s32;
atlas_h : s32;
atlas_pixels : []u8;
atlas_dirty : bool;
}
pack_rgba8 :: (c: Vector4) -> u32 {
byte :: (f: float) -> u32 { return cast(u32) clamp(f * 255 + 0.5, 0, 255); }
return byte(c.x) | (byte(c.y) << 8) | (byte(c.z) << 16) | (byte(c.w) << 24);
}
atlas_create :: (uptr: *void, width: s32, height: s32) -> s32 #c_call {
push_context,defer_pop default_context;
if text.atlas.id texture_destroy(text.atlas);
array_free(text.atlas_pixels);
text.atlas_w = width;
text.atlas_h = height;
text.atlas_pixels = NewArray(width * height * 4, u8);
text.atlas = texture_create(width, height, text.atlas_pixels);
text.atlas_dirty = true;
return 1;
}
atlas_mark_dirty :: (uptr: *void, rect: *s32, data: *u8) #c_call {
text.atlas_dirty = true;
}
glyphs_draw :: (uptr: *void, verts: *float, tcoords: *float, colors: *u32, nverts: s32) #c_call {
push_context,defer_pop default_context;
vertices := NewArray(nverts, Ui_Vertex,, temp);
for *v, i: vertices {
c := colors[i];
v.position = .{verts[i*2], verts[i*2 + 1]};
v.uv = .{tcoords[i*2], tcoords[i*2 + 1]};
v.color = .{
cast(float)( c & 0xFF) / 255,
cast(float)((c >> 8) & 0xFF) / 255,
cast(float)((c >> 16) & 0xFF) / 255,
cast(float)((c >> 24) & 0xFF) / 255,
};
}
ui_triangles(vertices, text.atlas);
}

View File

@ -0,0 +1,97 @@
mesh_trile :: (trile: *Trile) -> vertices: []Trile_Vertex, indices: []u16 {
vertices : [..]Trile_Vertex;
indices : [..]u16;
vertices.allocator = temp;
indices.allocator = temp;
for axis: 0..2 for sign: s32.[1, -1] {
u_axis := (axis + 1) % 3;
v_axis := (axis + 2) % 3;
for depth: 0..15 {
mask : [16][16]Face;
for u: 0..15 for v: 0..15 {
c : [3]s32;
c[axis] = xx depth; c[u_axis] = xx u; c[v_axis] = xx v;
swatch := trixel(trile, c);
c[axis] += sign;
if !swatch || trixel(trile, c) continue;
face := *mask[u][v];
face.swatch = swatch;
for corner: 0..3 {
side_u := c; side_u[u_axis] += xx ifx corner == 1 || corner == 2 then 1 else -1;
side_v := c; side_v[v_axis] += xx ifx corner >= 2 then 1 else -1;
diagonal := side_u; diagonal[v_axis] = side_v[v_axis];
a := trixel(trile, side_u) != 0;
b := trixel(trile, side_v) != 0;
d := trixel(trile, diagonal) != 0;
face.ao[corner] = xx ifx a && b then 0 else 3 - cast(int) a - cast(int) b - cast(int) d;
}
}
for u0: 0..15 for v0: 0..15 {
face := mask[u0][v0];
if !face.swatch continue;
// A face with an AO gradient keeps its own quad, so the gradient isn't stretched.
u1, v1 := u0 + 1, v0 + 1;
if flat(face) {
while v1 < 16 && mask[u0][v1] == face v1 += 1;
while u1 < 16 && row_matches(*mask, u1, v0, v1, face) u1 += 1;
}
for u: u0..u1-1 for v: v0..v1-1 mask[u][v] = .{};
plane := cast(float)(depth + ifx sign > 0 then 1 else 0);
normal := cast(u8)(axis * 2 + ifx sign < 0 then 1 else 0);
corner :: (u: int, v: int, ao: u8) -> Trile_Vertex #expand {
p : Vector3;
p.component[`axis] = `plane * TRIXEL_SIZE;
p.component[`u_axis] = u * TRIXEL_SIZE;
p.component[`v_axis] = v * TRIXEL_SIZE;
return .{p, `face.swatch, ao, `normal, 0};
}
q := Trile_Vertex.[
corner(u0, v0, face.ao[0]),
corner(u1, v0, face.ao[1]),
corner(u1, v1, face.ao[2]),
corner(u0, v1, face.ao[3]),
];
if sign < 0 q[1], q[3] = q[3], q[1];
// Split along the brighter diagonal so AO interpolates evenly.
base := cast(u16) vertices.count;
array_add(*vertices, ..q);
if face.ao[0] + face.ao[2] < face.ao[1] + face.ao[3] {
for u16.[1, 2, 3, 1, 3, 0] array_add(*indices, base + it);
} else {
for u16.[0, 1, 2, 0, 2, 3] array_add(*indices, base + it);
}
}
}
}
return vertices, indices;
}
#scope_file
// ao is per corner in the order (u0, v0), (u1, v0), (u1, v1), (u0, v1); 3 = open.
Face :: struct {
swatch : u8;
ao : [4]u8;
}
operator == :: (a: Face, b: Face) -> bool {
return a.swatch == b.swatch && a.ao[0] == b.ao[0] && a.ao[1] == b.ao[1] && a.ao[2] == b.ao[2] && a.ao[3] == b.ao[3];
}
flat :: (face: Face) -> bool {
return face.ao[0] == face.ao[1] && face.ao[1] == face.ao[2] && face.ao[2] == face.ao[3];
}
row_matches :: (mask: *[16][16]Face, u: int, v0: int, v1: int, face: Face) -> bool {
for v: v0..v1-1 if mask.*[u][v] != face return false;
return true;
}
trixel :: (trile: *Trile, c: [3]s32) -> u8 {
for c if it < 0 || it > 15 return 0;
return trile.trixels[c[0]][c[1]][c[2]];
}

View File

@ -1,8 +0,0 @@
rm -rf jai
mkdir jai
for filename in *.glsl; do
if [ -f "$filename" ]; then
./sokol-shdc -i "$filename" -o "./jai/${filename/.glsl/.jai}" -l glsl430:glsl300es:metal_macos -f sokol_jai
fi
done

View File

@ -1,7 +0,0 @@
rm -rf .jai
for filename in *.glsl; do
if [ -f "$filename" ]; then
./sokol-shdc-mac -i "$filename" -o "./jai/${filename/.glsl/.jai}" -l glsl430:glsl300es:metal_macos -f sokol_jai
fi
done

View File

@ -1,548 +0,0 @@
/*
#version:1# (machine generated, don't edit!)
Generated by sokol-shdc (https://github.com/floooh/sokol-tools)
Cmdline:
sokol-shdc -i shader_billboard.glsl -o ./jai/shader_billboard.jai -l glsl430:glsl300es:metal_macos -f sokol_jai
Overview:
=========
Shader program: 'billboard':
Get shader desc: billboard_shader_desc(sg_query_backend())
Vertex Shader: vs_billboard
Fragment Shader: fs_billboard
Attributes:
ATTR_billboard_position => 0
Bindings:
Uniform block 'billboard_vs_params':
Jai struct: Billboard_Vs_Params
Bind slot: UB_billboard_vs_params => 0
Image 'sprite':
Image type: ._2D
Sample type: .FLOAT
Multisampled: false
Bind slot: IMG_sprite => 0
Sampler 'spritesmp':
Type: .FILTERING
Bind slot: SMP_spritesmp => 0
*/
ATTR_billboard_position :: 0;
UB_billboard_vs_params :: 0;
IMG_sprite :: 0;
SMP_spritesmp :: 0;
Billboard_Vs_Params :: struct {
mvp: [16]float;
uvs: [4]float;
offset: [3]float;
_: [4]u8;
size: [2]float;
_: [8]u8;
cam: [3]float;
_: [4]u8;
faceDir: [3]float;
_: [4]u8;
};
/*
#version 430
uniform vec4 billboard_vs_params[9];
layout(location = 0) in vec3 position;
layout(location = 0) out vec2 uv_in;
void main()
{
vec3 _53 = billboard_vs_params[5].xyz - billboard_vs_params[7].xyz;
_53.y = 0.0;
vec3 look_dir = normalize(_53);
if (billboard_vs_params[8].x > (-10.0))
{
look_dir = billboard_vs_params[8].xyz;
}
gl_Position = mat4(billboard_vs_params[0], billboard_vs_params[1], billboard_vs_params[2], billboard_vs_params[3]) * vec4((billboard_vs_params[5].xyz + (normalize(cross(vec3(0.0, 1.0, 0.0), look_dir)) * ((position.x - 0.5) * billboard_vs_params[6].x))) + (vec3(0.0, 1.0, 0.0) * (position.y * billboard_vs_params[6].y)), 1.0);
uv_in = vec2(billboard_vs_params[4].x + (position.x * billboard_vs_params[4].z), billboard_vs_params[4].y + (position.y * billboard_vs_params[4].w));
}
*/
vs_billboard_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,0x62,0x69,0x6c,0x6c,0x62,
0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x39,
0x5d,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,0x33,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,0x30,0x29,0x20,0x6f,
0x75,0x74,0x20,0x76,0x65,0x63,0x32,0x20,0x75,0x76,0x5f,0x69,0x6e,0x3b,0x0a,0x0a,
0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,
0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x5f,0x35,0x33,0x20,0x3d,0x20,0x62,0x69,0x6c,
0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,
0x5b,0x35,0x5d,0x2e,0x78,0x79,0x7a,0x20,0x2d,0x20,0x62,0x69,0x6c,0x6c,0x62,0x6f,
0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x37,0x5d,
0x2e,0x78,0x79,0x7a,0x3b,0x0a,0x20,0x20,0x20,0x20,0x5f,0x35,0x33,0x2e,0x79,0x20,
0x3d,0x20,0x30,0x2e,0x30,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,
0x6c,0x6f,0x6f,0x6b,0x5f,0x64,0x69,0x72,0x20,0x3d,0x20,0x6e,0x6f,0x72,0x6d,0x61,
0x6c,0x69,0x7a,0x65,0x28,0x5f,0x35,0x33,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x69,
0x66,0x20,0x28,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,
0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x38,0x5d,0x2e,0x78,0x20,0x3e,0x20,0x28,0x2d,
0x31,0x30,0x2e,0x30,0x29,0x29,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x6c,0x6f,0x6f,0x6b,0x5f,0x64,0x69,0x72,0x20,0x3d,0x20,
0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,
0x61,0x6d,0x73,0x5b,0x38,0x5d,0x2e,0x78,0x79,0x7a,0x3b,0x0a,0x20,0x20,0x20,0x20,
0x7d,0x0a,0x20,0x20,0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,
0x6e,0x20,0x3d,0x20,0x6d,0x61,0x74,0x34,0x28,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,
0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d,0x2c,
0x20,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,
0x72,0x61,0x6d,0x73,0x5b,0x31,0x5d,0x2c,0x20,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,
0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x32,0x5d,0x2c,
0x20,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,
0x72,0x61,0x6d,0x73,0x5b,0x33,0x5d,0x29,0x20,0x2a,0x20,0x76,0x65,0x63,0x34,0x28,
0x28,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,
0x72,0x61,0x6d,0x73,0x5b,0x35,0x5d,0x2e,0x78,0x79,0x7a,0x20,0x2b,0x20,0x28,0x6e,
0x6f,0x72,0x6d,0x61,0x6c,0x69,0x7a,0x65,0x28,0x63,0x72,0x6f,0x73,0x73,0x28,0x76,
0x65,0x63,0x33,0x28,0x30,0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30,0x2c,0x20,0x30,0x2e,
0x30,0x29,0x2c,0x20,0x6c,0x6f,0x6f,0x6b,0x5f,0x64,0x69,0x72,0x29,0x29,0x20,0x2a,
0x20,0x28,0x28,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2e,0x78,0x20,0x2d,0x20,
0x30,0x2e,0x35,0x29,0x20,0x2a,0x20,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,
0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x36,0x5d,0x2e,0x78,0x29,
0x29,0x29,0x20,0x2b,0x20,0x28,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x30,0x2c,0x20,
0x31,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x29,0x20,0x2a,0x20,0x28,0x70,0x6f,0x73,
0x69,0x74,0x69,0x6f,0x6e,0x2e,0x79,0x20,0x2a,0x20,0x62,0x69,0x6c,0x6c,0x62,0x6f,
0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x36,0x5d,
0x2e,0x79,0x29,0x29,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,
0x75,0x76,0x5f,0x69,0x6e,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x62,0x69,0x6c,
0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,
0x5b,0x34,0x5d,0x2e,0x78,0x20,0x2b,0x20,0x28,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,
0x6e,0x2e,0x78,0x20,0x2a,0x20,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,
0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x34,0x5d,0x2e,0x7a,0x29,0x2c,
0x20,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,
0x72,0x61,0x6d,0x73,0x5b,0x34,0x5d,0x2e,0x79,0x20,0x2b,0x20,0x28,0x70,0x6f,0x73,
0x69,0x74,0x69,0x6f,0x6e,0x2e,0x79,0x20,0x2a,0x20,0x62,0x69,0x6c,0x6c,0x62,0x6f,
0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x34,0x5d,
0x2e,0x77,0x29,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#version 430
layout(binding = 16) uniform sampler2D sprite_spritesmp;
layout(location = 0) in vec2 uv_in;
layout(location = 0) out vec4 color;
void main()
{
vec2 _12 = uv_in;
_12.y = 1.0 - _12.y;
vec4 _35 = texture(sprite_spritesmp, _12);
if (_35.w < 0.00999999977648258209228515625)
{
discard;
}
color = vec4(_35.xyz * 0.5, 1.0);
}
*/
fs_billboard_source_glsl430 := u8.[
0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x34,0x33,0x30,0x0a,0x0a,0x6c,0x61,
0x79,0x6f,0x75,0x74,0x28,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x20,0x3d,0x20,0x31,
0x36,0x29,0x20,0x75,0x6e,0x69,0x66,0x6f,0x72,0x6d,0x20,0x73,0x61,0x6d,0x70,0x6c,
0x65,0x72,0x32,0x44,0x20,0x73,0x70,0x72,0x69,0x74,0x65,0x5f,0x73,0x70,0x72,0x69,
0x74,0x65,0x73,0x6d,0x70,0x3b,0x0a,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,0x32,0x20,0x75,0x76,0x5f,0x69,0x6e,0x3b,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,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,0x76,0x65,0x63,0x32,0x20,0x5f,0x31,0x32,0x20,0x3d,0x20,0x75,
0x76,0x5f,0x69,0x6e,0x3b,0x0a,0x20,0x20,0x20,0x20,0x5f,0x31,0x32,0x2e,0x79,0x20,
0x3d,0x20,0x31,0x2e,0x30,0x20,0x2d,0x20,0x5f,0x31,0x32,0x2e,0x79,0x3b,0x0a,0x20,
0x20,0x20,0x20,0x76,0x65,0x63,0x34,0x20,0x5f,0x33,0x35,0x20,0x3d,0x20,0x74,0x65,
0x78,0x74,0x75,0x72,0x65,0x28,0x73,0x70,0x72,0x69,0x74,0x65,0x5f,0x73,0x70,0x72,
0x69,0x74,0x65,0x73,0x6d,0x70,0x2c,0x20,0x5f,0x31,0x32,0x29,0x3b,0x0a,0x20,0x20,
0x20,0x20,0x69,0x66,0x20,0x28,0x5f,0x33,0x35,0x2e,0x77,0x20,0x3c,0x20,0x30,0x2e,
0x30,0x30,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x37,0x37,0x36,0x34,0x38,0x32,0x35,
0x38,0x32,0x30,0x39,0x32,0x32,0x38,0x35,0x31,0x35,0x36,0x32,0x35,0x29,0x0a,0x20,
0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x64,0x69,0x73,
0x63,0x61,0x72,0x64,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,
0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x76,0x65,0x63,0x34,0x28,0x5f,0x33,0x35,
0x2e,0x78,0x79,0x7a,0x20,0x2a,0x20,0x30,0x2e,0x35,0x2c,0x20,0x31,0x2e,0x30,0x29,
0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#version 300 es
uniform vec4 billboard_vs_params[9];
layout(location = 0) in vec3 position;
out vec2 uv_in;
void main()
{
vec3 _53 = billboard_vs_params[5].xyz - billboard_vs_params[7].xyz;
_53.y = 0.0;
vec3 look_dir = normalize(_53);
if (billboard_vs_params[8].x > (-10.0))
{
look_dir = billboard_vs_params[8].xyz;
}
gl_Position = mat4(billboard_vs_params[0], billboard_vs_params[1], billboard_vs_params[2], billboard_vs_params[3]) * vec4((billboard_vs_params[5].xyz + (normalize(cross(vec3(0.0, 1.0, 0.0), look_dir)) * ((position.x - 0.5) * billboard_vs_params[6].x))) + (vec3(0.0, 1.0, 0.0) * (position.y * billboard_vs_params[6].y)), 1.0);
uv_in = vec2(billboard_vs_params[4].x + (position.x * billboard_vs_params[4].z), billboard_vs_params[4].y + (position.y * billboard_vs_params[4].w));
}
*/
vs_billboard_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,0x62,0x69,
0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,
0x73,0x5b,0x39,0x5d,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,0x33,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x6f,0x75,0x74,
0x20,0x76,0x65,0x63,0x32,0x20,0x75,0x76,0x5f,0x69,0x6e,0x3b,0x0a,0x0a,0x76,0x6f,
0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,
0x76,0x65,0x63,0x33,0x20,0x5f,0x35,0x33,0x20,0x3d,0x20,0x62,0x69,0x6c,0x6c,0x62,
0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x35,
0x5d,0x2e,0x78,0x79,0x7a,0x20,0x2d,0x20,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,
0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x37,0x5d,0x2e,0x78,
0x79,0x7a,0x3b,0x0a,0x20,0x20,0x20,0x20,0x5f,0x35,0x33,0x2e,0x79,0x20,0x3d,0x20,
0x30,0x2e,0x30,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x6c,0x6f,
0x6f,0x6b,0x5f,0x64,0x69,0x72,0x20,0x3d,0x20,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x69,
0x7a,0x65,0x28,0x5f,0x35,0x33,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,
0x28,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,
0x72,0x61,0x6d,0x73,0x5b,0x38,0x5d,0x2e,0x78,0x20,0x3e,0x20,0x28,0x2d,0x31,0x30,
0x2e,0x30,0x29,0x29,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x6c,0x6f,0x6f,0x6b,0x5f,0x64,0x69,0x72,0x20,0x3d,0x20,0x62,0x69,
0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,
0x73,0x5b,0x38,0x5d,0x2e,0x78,0x79,0x7a,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,
0x20,0x20,0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,
0x3d,0x20,0x6d,0x61,0x74,0x34,0x28,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,
0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d,0x2c,0x20,0x62,
0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,
0x6d,0x73,0x5b,0x31,0x5d,0x2c,0x20,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,
0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x32,0x5d,0x2c,0x20,0x62,
0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,
0x6d,0x73,0x5b,0x33,0x5d,0x29,0x20,0x2a,0x20,0x76,0x65,0x63,0x34,0x28,0x28,0x62,
0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,
0x6d,0x73,0x5b,0x35,0x5d,0x2e,0x78,0x79,0x7a,0x20,0x2b,0x20,0x28,0x6e,0x6f,0x72,
0x6d,0x61,0x6c,0x69,0x7a,0x65,0x28,0x63,0x72,0x6f,0x73,0x73,0x28,0x76,0x65,0x63,
0x33,0x28,0x30,0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x29,
0x2c,0x20,0x6c,0x6f,0x6f,0x6b,0x5f,0x64,0x69,0x72,0x29,0x29,0x20,0x2a,0x20,0x28,
0x28,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2e,0x78,0x20,0x2d,0x20,0x30,0x2e,
0x35,0x29,0x20,0x2a,0x20,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,
0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x36,0x5d,0x2e,0x78,0x29,0x29,0x29,
0x20,0x2b,0x20,0x28,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x30,0x2c,0x20,0x31,0x2e,
0x30,0x2c,0x20,0x30,0x2e,0x30,0x29,0x20,0x2a,0x20,0x28,0x70,0x6f,0x73,0x69,0x74,
0x69,0x6f,0x6e,0x2e,0x79,0x20,0x2a,0x20,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,
0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x36,0x5d,0x2e,0x79,
0x29,0x29,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x75,0x76,
0x5f,0x69,0x6e,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x62,0x69,0x6c,0x6c,0x62,
0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x34,
0x5d,0x2e,0x78,0x20,0x2b,0x20,0x28,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2e,
0x78,0x20,0x2a,0x20,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,
0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x34,0x5d,0x2e,0x7a,0x29,0x2c,0x20,0x62,
0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,
0x6d,0x73,0x5b,0x34,0x5d,0x2e,0x79,0x20,0x2b,0x20,0x28,0x70,0x6f,0x73,0x69,0x74,
0x69,0x6f,0x6e,0x2e,0x79,0x20,0x2a,0x20,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,
0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x34,0x5d,0x2e,0x77,
0x29,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#version 300 es
precision mediump float;
precision highp int;
uniform highp sampler2D sprite_spritesmp;
in highp vec2 uv_in;
layout(location = 0) out highp vec4 color;
void main()
{
highp vec2 _12 = uv_in;
_12.y = 1.0 - _12.y;
highp vec4 _35 = texture(sprite_spritesmp, _12);
if (_35.w < 0.00999999977648258209228515625)
{
discard;
}
color = vec4(_35.xyz * 0.5, 1.0);
}
*/
fs_billboard_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,0x75,
0x6e,0x69,0x66,0x6f,0x72,0x6d,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x73,0x61,0x6d,
0x70,0x6c,0x65,0x72,0x32,0x44,0x20,0x73,0x70,0x72,0x69,0x74,0x65,0x5f,0x73,0x70,
0x72,0x69,0x74,0x65,0x73,0x6d,0x70,0x3b,0x0a,0x0a,0x69,0x6e,0x20,0x68,0x69,0x67,
0x68,0x70,0x20,0x76,0x65,0x63,0x32,0x20,0x75,0x76,0x5f,0x69,0x6e,0x3b,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,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,0x68,0x69,0x67,
0x68,0x70,0x20,0x76,0x65,0x63,0x32,0x20,0x5f,0x31,0x32,0x20,0x3d,0x20,0x75,0x76,
0x5f,0x69,0x6e,0x3b,0x0a,0x20,0x20,0x20,0x20,0x5f,0x31,0x32,0x2e,0x79,0x20,0x3d,
0x20,0x31,0x2e,0x30,0x20,0x2d,0x20,0x5f,0x31,0x32,0x2e,0x79,0x3b,0x0a,0x20,0x20,
0x20,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x76,0x65,0x63,0x34,0x20,0x5f,0x33,0x35,
0x20,0x3d,0x20,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x73,0x70,0x72,0x69,0x74,
0x65,0x5f,0x73,0x70,0x72,0x69,0x74,0x65,0x73,0x6d,0x70,0x2c,0x20,0x5f,0x31,0x32,
0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x5f,0x33,0x35,0x2e,0x77,
0x20,0x3c,0x20,0x30,0x2e,0x30,0x30,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x37,0x37,
0x36,0x34,0x38,0x32,0x35,0x38,0x32,0x30,0x39,0x32,0x32,0x38,0x35,0x31,0x35,0x36,
0x32,0x35,0x29,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x64,0x69,0x73,0x63,0x61,0x72,0x64,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,
0x0a,0x20,0x20,0x20,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x76,0x65,0x63,
0x34,0x28,0x5f,0x33,0x35,0x2e,0x78,0x79,0x7a,0x20,0x2a,0x20,0x30,0x2e,0x35,0x2c,
0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct billboard_vs_params
{
float4x4 mvp;
float4 uvs;
float3 offset;
float2 size;
float3 cam;
float3 faceDir;
};
struct main0_out
{
float2 uv_in [[user(locn0)]];
float4 gl_Position [[position]];
};
struct main0_in
{
float3 position [[attribute(0)]];
};
vertex main0_out main0(main0_in in [[stage_in]], constant billboard_vs_params& _24 [[buffer(0)]])
{
main0_out out = {};
float3 _53 = _24.offset - _24.cam;
_53.y = 0.0;
float3 look_dir = fast::normalize(_53);
if (_24.faceDir.x > (-10.0))
{
look_dir = _24.faceDir;
}
out.gl_Position = _24.mvp * float4((_24.offset + (fast::normalize(cross(float3(0.0, 1.0, 0.0), look_dir)) * ((in.position.x - 0.5) * _24.size.x))) + (float3(0.0, 1.0, 0.0) * (in.position.y * _24.size.y)), 1.0);
out.uv_in = float2(_24.uvs.x + (in.position.x * _24.uvs.z), _24.uvs.y + (in.position.y * _24.uvs.w));
return out;
}
*/
vs_billboard_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,0x62,
0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,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,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,
0x34,0x20,0x75,0x76,0x73,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,
0x33,0x20,0x6f,0x66,0x66,0x73,0x65,0x74,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,
0x6f,0x61,0x74,0x32,0x20,0x73,0x69,0x7a,0x65,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,
0x6c,0x6f,0x61,0x74,0x33,0x20,0x63,0x61,0x6d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,
0x6c,0x6f,0x61,0x74,0x33,0x20,0x66,0x61,0x63,0x65,0x44,0x69,0x72,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,0x32,
0x20,0x75,0x76,0x5f,0x69,0x6e,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,
0x63,0x6e,0x30,0x29,0x5d,0x5d,0x3b,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,0x33,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,0x7d,0x3b,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,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,
0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x26,0x20,0x5f,0x32,0x34,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,0x66,0x6c,0x6f,
0x61,0x74,0x33,0x20,0x5f,0x35,0x33,0x20,0x3d,0x20,0x5f,0x32,0x34,0x2e,0x6f,0x66,
0x66,0x73,0x65,0x74,0x20,0x2d,0x20,0x5f,0x32,0x34,0x2e,0x63,0x61,0x6d,0x3b,0x0a,
0x20,0x20,0x20,0x20,0x5f,0x35,0x33,0x2e,0x79,0x20,0x3d,0x20,0x30,0x2e,0x30,0x3b,
0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x33,0x20,0x6c,0x6f,0x6f,0x6b,
0x5f,0x64,0x69,0x72,0x20,0x3d,0x20,0x66,0x61,0x73,0x74,0x3a,0x3a,0x6e,0x6f,0x72,
0x6d,0x61,0x6c,0x69,0x7a,0x65,0x28,0x5f,0x35,0x33,0x29,0x3b,0x0a,0x20,0x20,0x20,
0x20,0x69,0x66,0x20,0x28,0x5f,0x32,0x34,0x2e,0x66,0x61,0x63,0x65,0x44,0x69,0x72,
0x2e,0x78,0x20,0x3e,0x20,0x28,0x2d,0x31,0x30,0x2e,0x30,0x29,0x29,0x0a,0x20,0x20,
0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x6c,0x6f,0x6f,0x6b,
0x5f,0x64,0x69,0x72,0x20,0x3d,0x20,0x5f,0x32,0x34,0x2e,0x66,0x61,0x63,0x65,0x44,
0x69,0x72,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,
0x74,0x2e,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,
0x5f,0x32,0x34,0x2e,0x6d,0x76,0x70,0x20,0x2a,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,
0x28,0x28,0x5f,0x32,0x34,0x2e,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2b,0x20,0x28,
0x66,0x61,0x73,0x74,0x3a,0x3a,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x69,0x7a,0x65,0x28,
0x63,0x72,0x6f,0x73,0x73,0x28,0x66,0x6c,0x6f,0x61,0x74,0x33,0x28,0x30,0x2e,0x30,
0x2c,0x20,0x31,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x29,0x2c,0x20,0x6c,0x6f,0x6f,
0x6b,0x5f,0x64,0x69,0x72,0x29,0x29,0x20,0x2a,0x20,0x28,0x28,0x69,0x6e,0x2e,0x70,
0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2e,0x78,0x20,0x2d,0x20,0x30,0x2e,0x35,0x29,
0x20,0x2a,0x20,0x5f,0x32,0x34,0x2e,0x73,0x69,0x7a,0x65,0x2e,0x78,0x29,0x29,0x29,
0x20,0x2b,0x20,0x28,0x66,0x6c,0x6f,0x61,0x74,0x33,0x28,0x30,0x2e,0x30,0x2c,0x20,
0x31,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x29,0x20,0x2a,0x20,0x28,0x69,0x6e,0x2e,
0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2e,0x79,0x20,0x2a,0x20,0x5f,0x32,0x34,
0x2e,0x73,0x69,0x7a,0x65,0x2e,0x79,0x29,0x29,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,
0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,0x75,0x76,0x5f,0x69,0x6e,0x20,0x3d,
0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,0x28,0x5f,0x32,0x34,0x2e,0x75,0x76,0x73,0x2e,
0x78,0x20,0x2b,0x20,0x28,0x69,0x6e,0x2e,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,
0x2e,0x78,0x20,0x2a,0x20,0x5f,0x32,0x34,0x2e,0x75,0x76,0x73,0x2e,0x7a,0x29,0x2c,
0x20,0x5f,0x32,0x34,0x2e,0x75,0x76,0x73,0x2e,0x79,0x20,0x2b,0x20,0x28,0x69,0x6e,
0x2e,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2e,0x79,0x20,0x2a,0x20,0x5f,0x32,
0x34,0x2e,0x75,0x76,0x73,0x2e,0x77,0x29,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 color [[color(0)]];
};
struct main0_in
{
float2 uv_in [[user(locn0)]];
};
fragment main0_out main0(main0_in in [[stage_in]], texture2d<float> sprite [[texture(0)]], sampler spritesmp [[sampler(0)]])
{
main0_out out = {};
float2 _12 = in.uv_in;
_12.y = 1.0 - _12.y;
float4 _35 = sprite.sample(spritesmp, _12);
if (_35.w < 0.00999999977648258209228515625)
{
discard_fragment();
}
out.color = float4(_35.xyz * 0.5, 1.0);
return out;
}
*/
fs_billboard_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,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x5b,0x5b,0x63,0x6f,
0x6c,0x6f,0x72,0x28,0x30,0x29,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,0x32,0x20,0x75,0x76,0x5f,0x69,0x6e,
0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,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,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,0x74,0x65,0x78,0x74,0x75,0x72,0x65,
0x32,0x64,0x3c,0x66,0x6c,0x6f,0x61,0x74,0x3e,0x20,0x73,0x70,0x72,0x69,0x74,0x65,
0x20,0x5b,0x5b,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x30,0x29,0x5d,0x5d,0x2c,
0x20,0x73,0x61,0x6d,0x70,0x6c,0x65,0x72,0x20,0x73,0x70,0x72,0x69,0x74,0x65,0x73,
0x6d,0x70,0x20,0x5b,0x5b,0x73,0x61,0x6d,0x70,0x6c,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,0x66,0x6c,0x6f,0x61,0x74,0x32,0x20,0x5f,0x31,0x32,0x20,0x3d,0x20,0x69,0x6e,
0x2e,0x75,0x76,0x5f,0x69,0x6e,0x3b,0x0a,0x20,0x20,0x20,0x20,0x5f,0x31,0x32,0x2e,
0x79,0x20,0x3d,0x20,0x31,0x2e,0x30,0x20,0x2d,0x20,0x5f,0x31,0x32,0x2e,0x79,0x3b,
0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x5f,0x33,0x35,0x20,
0x3d,0x20,0x73,0x70,0x72,0x69,0x74,0x65,0x2e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x28,
0x73,0x70,0x72,0x69,0x74,0x65,0x73,0x6d,0x70,0x2c,0x20,0x5f,0x31,0x32,0x29,0x3b,
0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x5f,0x33,0x35,0x2e,0x77,0x20,0x3c,
0x20,0x30,0x2e,0x30,0x30,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x37,0x37,0x36,0x34,
0x38,0x32,0x35,0x38,0x32,0x30,0x39,0x32,0x32,0x38,0x35,0x31,0x35,0x36,0x32,0x35,
0x29,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x64,0x69,0x73,0x63,0x61,0x72,0x64,0x5f,0x66,0x72,0x61,0x67,0x6d,0x65,0x6e,0x74,
0x28,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,
0x74,0x2e,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,
0x28,0x5f,0x33,0x35,0x2e,0x78,0x79,0x7a,0x20,0x2a,0x20,0x30,0x2e,0x35,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,
];
billboard_shader_desc :: (backend: sg_backend) -> sg_shader_desc {
desc: sg_shader_desc;
desc.label = "billboard_shader";
if backend == {
case .GLCORE;
desc.vertex_func.source = xx *vs_billboard_source_glsl430;
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_billboard_source_glsl430;
desc.fragment_func.entry = "main";
desc.attrs[0].base_type = .FLOAT;
desc.attrs[0].glsl_name = "position";
desc.uniform_blocks[0].stage = .VERTEX;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 144;
desc.uniform_blocks[0].glsl_uniforms[0].type = .FLOAT4;
desc.uniform_blocks[0].glsl_uniforms[0].array_count = 9;
desc.uniform_blocks[0].glsl_uniforms[0].glsl_name = "billboard_vs_params";
desc.images[0].stage = .FRAGMENT;
desc.images[0].multisampled = false;
desc.images[0].image_type = ._2D;
desc.images[0].sample_type = .FLOAT;
desc.samplers[0].stage = .FRAGMENT;
desc.samplers[0].sampler_type = .FILTERING;
desc.image_sampler_pairs[0].stage = .FRAGMENT;
desc.image_sampler_pairs[0].image_slot = 0;
desc.image_sampler_pairs[0].sampler_slot = 0;
desc.image_sampler_pairs[0].glsl_name = "sprite_spritesmp";
case .GLES3;
desc.vertex_func.source = xx *vs_billboard_source_glsl300es;
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_billboard_source_glsl300es;
desc.fragment_func.entry = "main";
desc.attrs[0].base_type = .FLOAT;
desc.attrs[0].glsl_name = "position";
desc.uniform_blocks[0].stage = .VERTEX;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 144;
desc.uniform_blocks[0].glsl_uniforms[0].type = .FLOAT4;
desc.uniform_blocks[0].glsl_uniforms[0].array_count = 9;
desc.uniform_blocks[0].glsl_uniforms[0].glsl_name = "billboard_vs_params";
desc.images[0].stage = .FRAGMENT;
desc.images[0].multisampled = false;
desc.images[0].image_type = ._2D;
desc.images[0].sample_type = .FLOAT;
desc.samplers[0].stage = .FRAGMENT;
desc.samplers[0].sampler_type = .FILTERING;
desc.image_sampler_pairs[0].stage = .FRAGMENT;
desc.image_sampler_pairs[0].image_slot = 0;
desc.image_sampler_pairs[0].sampler_slot = 0;
desc.image_sampler_pairs[0].glsl_name = "sprite_spritesmp";
case .METAL_MACOS;
desc.vertex_func.source = xx *vs_billboard_source_metal_macos;
desc.vertex_func.entry = "main0";
desc.fragment_func.source = xx *fs_billboard_source_metal_macos;
desc.fragment_func.entry = "main0";
desc.attrs[0].base_type = .FLOAT;
desc.uniform_blocks[0].stage = .VERTEX;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 144;
desc.uniform_blocks[0].msl_buffer_n = 0;
desc.images[0].stage = .FRAGMENT;
desc.images[0].multisampled = false;
desc.images[0].image_type = ._2D;
desc.images[0].sample_type = .FLOAT;
desc.images[0].msl_texture_n = 0;
desc.samplers[0].stage = .FRAGMENT;
desc.samplers[0].sampler_type = .FILTERING;
desc.samplers[0].msl_sampler_n = 0;
desc.image_sampler_pairs[0].stage = .FRAGMENT;
desc.image_sampler_pairs[0].image_slot = 0;
desc.image_sampler_pairs[0].sampler_slot = 0;
}
return desc;
}

View File

@ -1,491 +0,0 @@
/*
#version:1# (machine generated, don't edit!)
Generated by sokol-shdc (https://github.com/floooh/sokol-tools)
Cmdline:
sokol-shdc -i shader_bloom_downsample.glsl -o ./jai/shader_bloom_downsample.jai -l glsl430:glsl300es:metal_macos -f sokol_jai
Overview:
=========
Shader program: 'bloom_downsample':
Get shader desc: bloom_downsample_shader_desc(sg_query_backend())
Vertex Shader: vs_bloom_downsample
Fragment Shader: fs_bloom_downsample
Attributes:
ATTR_bloom_downsample_position => 0
ATTR_bloom_downsample_uv => 1
Bindings:
Uniform block 'bloom_downsample_params':
Jai struct: Bloom_Downsample_Params
Bind slot: UB_bloom_downsample_params => 0
Image 'bloom_downsample_src':
Image type: ._2D
Sample type: .FLOAT
Multisampled: false
Bind slot: IMG_bloom_downsample_src => 0
Sampler 'bloom_downsample_src_smp':
Type: .FILTERING
Bind slot: SMP_bloom_downsample_src_smp => 0
*/
ATTR_bloom_downsample_position :: 0;
ATTR_bloom_downsample_uv :: 1;
UB_bloom_downsample_params :: 0;
IMG_bloom_downsample_src :: 0;
SMP_bloom_downsample_src_smp :: 0;
Bloom_Downsample_Params :: struct {
src_texel_x: float;
src_texel_y: float;
_: [8]u8;
};
/*
#version 430
layout(location = 0) in vec2 position;
layout(location = 0) out vec2 texcoord;
layout(location = 1) in vec2 uv;
void main()
{
gl_Position = vec4(position, 0.5, 1.0);
texcoord = uv;
}
*/
vs_bloom_downsample_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,0x69,0x6e,0x20,0x76,0x65,0x63,0x32,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,0x30,0x29,0x20,0x6f,0x75,0x74,0x20,0x76,0x65,
0x63,0x32,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,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,0x32,0x20,0x75,0x76,0x3b,0x0a,0x0a,0x76,
0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,
0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x76,
0x65,0x63,0x34,0x28,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x30,0x2e,
0x35,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x74,0x65,0x78,
0x63,0x6f,0x6f,0x72,0x64,0x20,0x3d,0x20,0x75,0x76,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#version 430
uniform vec4 bloom_downsample_params[1];
layout(binding = 16) uniform sampler2D bloom_downsample_src_bloom_downsample_src_smp;
layout(location = 0) in vec2 texcoord;
layout(location = 0) out vec4 frag_color;
void main()
{
vec2 _23 = vec2(bloom_downsample_params[0].x, bloom_downsample_params[0].y) * 0.5;
float _44 = _23.x;
float _45 = -_44;
float _48 = _23.y;
float _49 = -_48;
frag_color = vec4((((texture(bloom_downsample_src_bloom_downsample_src_smp, texcoord + vec2(_45, _49)).xyz + texture(bloom_downsample_src_bloom_downsample_src_smp, texcoord + vec2(_44, _49)).xyz) + texture(bloom_downsample_src_bloom_downsample_src_smp, texcoord + vec2(_45, _48)).xyz) + texture(bloom_downsample_src_bloom_downsample_src_smp, texcoord + _23).xyz) * 0.25, 1.0);
}
*/
fs_bloom_downsample_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,0x62,0x6c,0x6f,0x6f,0x6d,
0x5f,0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x70,0x61,0x72,0x61,
0x6d,0x73,0x5b,0x31,0x5d,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x62,0x69,
0x6e,0x64,0x69,0x6e,0x67,0x20,0x3d,0x20,0x31,0x36,0x29,0x20,0x75,0x6e,0x69,0x66,
0x6f,0x72,0x6d,0x20,0x73,0x61,0x6d,0x70,0x6c,0x65,0x72,0x32,0x44,0x20,0x62,0x6c,
0x6f,0x6f,0x6d,0x5f,0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,
0x72,0x63,0x5f,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,
0x70,0x6c,0x65,0x5f,0x73,0x72,0x63,0x5f,0x73,0x6d,0x70,0x3b,0x0a,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,0x32,0x20,0x74,0x65,0x78,0x63,0x6f,
0x6f,0x72,0x64,0x3b,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,0x76,0x65,0x63,0x32,0x20,0x5f,0x32,0x33,0x20,0x3d,0x20,0x76,0x65,0x63,
0x32,0x28,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,0x70,
0x6c,0x65,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d,0x2e,0x78,0x2c,0x20,
0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,0x70,0x6c,0x65,
0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d,0x2e,0x79,0x29,0x20,0x2a,0x20,
0x30,0x2e,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,
0x34,0x34,0x20,0x3d,0x20,0x5f,0x32,0x33,0x2e,0x78,0x3b,0x0a,0x20,0x20,0x20,0x20,
0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x34,0x35,0x20,0x3d,0x20,0x2d,0x5f,0x34,0x34,
0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x34,0x38,0x20,
0x3d,0x20,0x5f,0x32,0x33,0x2e,0x79,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,
0x61,0x74,0x20,0x5f,0x34,0x39,0x20,0x3d,0x20,0x2d,0x5f,0x34,0x38,0x3b,0x0a,0x20,
0x20,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,
0x76,0x65,0x63,0x34,0x28,0x28,0x28,0x28,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,
0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,0x70,0x6c,0x65,
0x5f,0x73,0x72,0x63,0x5f,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x64,0x6f,0x77,0x6e,0x73,
0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x72,0x63,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x74,
0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,0x2b,0x20,0x76,0x65,0x63,0x32,0x28,0x5f,
0x34,0x35,0x2c,0x20,0x5f,0x34,0x39,0x29,0x29,0x2e,0x78,0x79,0x7a,0x20,0x2b,0x20,
0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x64,0x6f,
0x77,0x6e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x72,0x63,0x5f,0x62,0x6c,0x6f,
0x6f,0x6d,0x5f,0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x72,
0x63,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,
0x2b,0x20,0x76,0x65,0x63,0x32,0x28,0x5f,0x34,0x34,0x2c,0x20,0x5f,0x34,0x39,0x29,
0x29,0x2e,0x78,0x79,0x7a,0x29,0x20,0x2b,0x20,0x74,0x65,0x78,0x74,0x75,0x72,0x65,
0x28,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,0x70,0x6c,
0x65,0x5f,0x73,0x72,0x63,0x5f,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x64,0x6f,0x77,0x6e,
0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x72,0x63,0x5f,0x73,0x6d,0x70,0x2c,0x20,
0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,0x2b,0x20,0x76,0x65,0x63,0x32,0x28,
0x5f,0x34,0x35,0x2c,0x20,0x5f,0x34,0x38,0x29,0x29,0x2e,0x78,0x79,0x7a,0x29,0x20,
0x2b,0x20,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,
0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x72,0x63,0x5f,0x62,
0x6c,0x6f,0x6f,0x6d,0x5f,0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,
0x73,0x72,0x63,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,
0x64,0x20,0x2b,0x20,0x5f,0x32,0x33,0x29,0x2e,0x78,0x79,0x7a,0x29,0x20,0x2a,0x20,
0x30,0x2e,0x32,0x35,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#version 300 es
layout(location = 0) in vec2 position;
out vec2 texcoord;
layout(location = 1) in vec2 uv;
void main()
{
gl_Position = vec4(position, 0.5, 1.0);
texcoord = uv;
}
*/
vs_bloom_downsample_source_glsl300es := u8.[
0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x33,0x30,0x30,0x20,0x65,0x73,0x0a,
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,0x32,0x20,0x70,0x6f,
0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x32,
0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,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,0x32,0x20,0x75,0x76,0x3b,0x0a,0x0a,0x76,0x6f,0x69,
0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x67,
0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x76,0x65,0x63,
0x34,0x28,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x30,0x2e,0x35,0x2c,
0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x74,0x65,0x78,0x63,0x6f,
0x6f,0x72,0x64,0x20,0x3d,0x20,0x75,0x76,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#version 300 es
precision mediump float;
precision highp int;
uniform highp vec4 bloom_downsample_params[1];
uniform highp sampler2D bloom_downsample_src_bloom_downsample_src_smp;
in highp vec2 texcoord;
layout(location = 0) out highp vec4 frag_color;
void main()
{
highp vec2 _23 = vec2(bloom_downsample_params[0].x, bloom_downsample_params[0].y) * 0.5;
highp float _44 = _23.x;
highp float _45 = -_44;
highp float _48 = _23.y;
highp float _49 = -_48;
frag_color = vec4((((texture(bloom_downsample_src_bloom_downsample_src_smp, texcoord + vec2(_45, _49)).xyz + texture(bloom_downsample_src_bloom_downsample_src_smp, texcoord + vec2(_44, _49)).xyz) + texture(bloom_downsample_src_bloom_downsample_src_smp, texcoord + vec2(_45, _48)).xyz) + texture(bloom_downsample_src_bloom_downsample_src_smp, texcoord + _23).xyz) * 0.25, 1.0);
}
*/
fs_bloom_downsample_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,0x75,
0x6e,0x69,0x66,0x6f,0x72,0x6d,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x76,0x65,0x63,
0x34,0x20,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,0x70,
0x6c,0x65,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x31,0x5d,0x3b,0x0a,0x75,0x6e,
0x69,0x66,0x6f,0x72,0x6d,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x73,0x61,0x6d,0x70,
0x6c,0x65,0x72,0x32,0x44,0x20,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x64,0x6f,0x77,0x6e,
0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x72,0x63,0x5f,0x62,0x6c,0x6f,0x6f,0x6d,
0x5f,0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x72,0x63,0x5f,
0x73,0x6d,0x70,0x3b,0x0a,0x0a,0x69,0x6e,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x76,
0x65,0x63,0x32,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x3b,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,0x68,0x69,0x67,0x68,0x70,0x20,0x76,0x65,0x63,0x32,0x20,0x5f,0x32,0x33,0x20,
0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x64,0x6f,0x77,
0x6e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,
0x5d,0x2e,0x78,0x2c,0x20,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x64,0x6f,0x77,0x6e,0x73,
0x61,0x6d,0x70,0x6c,0x65,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d,0x2e,
0x79,0x29,0x20,0x2a,0x20,0x30,0x2e,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x68,0x69,
0x67,0x68,0x70,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x34,0x34,0x20,0x3d,0x20,
0x5f,0x32,0x33,0x2e,0x78,0x3b,0x0a,0x20,0x20,0x20,0x20,0x68,0x69,0x67,0x68,0x70,
0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x34,0x35,0x20,0x3d,0x20,0x2d,0x5f,0x34,
0x34,0x3b,0x0a,0x20,0x20,0x20,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x66,0x6c,0x6f,
0x61,0x74,0x20,0x5f,0x34,0x38,0x20,0x3d,0x20,0x5f,0x32,0x33,0x2e,0x79,0x3b,0x0a,
0x20,0x20,0x20,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,
0x5f,0x34,0x39,0x20,0x3d,0x20,0x2d,0x5f,0x34,0x38,0x3b,0x0a,0x20,0x20,0x20,0x20,
0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x76,0x65,0x63,
0x34,0x28,0x28,0x28,0x28,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x62,0x6c,0x6f,
0x6f,0x6d,0x5f,0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x72,
0x63,0x5f,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,0x70,
0x6c,0x65,0x5f,0x73,0x72,0x63,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x74,0x65,0x78,0x63,
0x6f,0x6f,0x72,0x64,0x20,0x2b,0x20,0x76,0x65,0x63,0x32,0x28,0x5f,0x34,0x35,0x2c,
0x20,0x5f,0x34,0x39,0x29,0x29,0x2e,0x78,0x79,0x7a,0x20,0x2b,0x20,0x74,0x65,0x78,
0x74,0x75,0x72,0x65,0x28,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x64,0x6f,0x77,0x6e,0x73,
0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x72,0x63,0x5f,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,
0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x72,0x63,0x5f,0x73,
0x6d,0x70,0x2c,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,0x2b,0x20,0x76,
0x65,0x63,0x32,0x28,0x5f,0x34,0x34,0x2c,0x20,0x5f,0x34,0x39,0x29,0x29,0x2e,0x78,
0x79,0x7a,0x29,0x20,0x2b,0x20,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x62,0x6c,
0x6f,0x6f,0x6d,0x5f,0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,
0x72,0x63,0x5f,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,
0x70,0x6c,0x65,0x5f,0x73,0x72,0x63,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x74,0x65,0x78,
0x63,0x6f,0x6f,0x72,0x64,0x20,0x2b,0x20,0x76,0x65,0x63,0x32,0x28,0x5f,0x34,0x35,
0x2c,0x20,0x5f,0x34,0x38,0x29,0x29,0x2e,0x78,0x79,0x7a,0x29,0x20,0x2b,0x20,0x74,
0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x64,0x6f,0x77,
0x6e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x72,0x63,0x5f,0x62,0x6c,0x6f,0x6f,
0x6d,0x5f,0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x72,0x63,
0x5f,0x73,0x6d,0x70,0x2c,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,0x2b,
0x20,0x5f,0x32,0x33,0x29,0x2e,0x78,0x79,0x7a,0x29,0x20,0x2a,0x20,0x30,0x2e,0x32,
0x35,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct main0_out
{
float2 texcoord [[user(locn0)]];
float4 gl_Position [[position]];
};
struct main0_in
{
float2 position [[attribute(0)]];
float2 uv [[attribute(1)]];
};
vertex main0_out main0(main0_in in [[stage_in]])
{
main0_out out = {};
out.gl_Position = float4(in.position, 0.5, 1.0);
out.texcoord = in.uv;
return out;
}
*/
vs_bloom_downsample_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,0x32,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,0x5b,
0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,0x30,0x29,0x5d,0x5d,0x3b,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,0x32,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,0x32,0x20,0x75,0x76,0x20,0x5b,
0x5b,0x61,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x28,0x31,0x29,0x5d,0x5d,0x3b,
0x0a,0x7d,0x3b,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,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,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,
0x69,0x6f,0x6e,0x20,0x3d,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x28,0x69,0x6e,0x2e,
0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x30,0x2e,0x35,0x2c,0x20,0x31,
0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,0x74,0x65,0x78,
0x63,0x6f,0x6f,0x72,0x64,0x20,0x3d,0x20,0x69,0x6e,0x2e,0x75,0x76,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 bloom_downsample_params
{
float src_texel_x;
float src_texel_y;
};
struct main0_out
{
float4 frag_color [[color(0)]];
};
struct main0_in
{
float2 texcoord [[user(locn0)]];
};
fragment main0_out main0(main0_in in [[stage_in]], constant bloom_downsample_params& _12 [[buffer(0)]], texture2d<float> bloom_downsample_src [[texture(0)]], sampler bloom_downsample_src_smp [[sampler(0)]])
{
main0_out out = {};
float2 _23 = float2(_12.src_texel_x, _12.src_texel_y) * 0.5;
float _44 = _23.x;
float _45 = -_44;
float _48 = _23.y;
float _49 = -_48;
out.frag_color = float4((((bloom_downsample_src.sample(bloom_downsample_src_smp, (in.texcoord + float2(_45, _49))).xyz + bloom_downsample_src.sample(bloom_downsample_src_smp, (in.texcoord + float2(_44, _49))).xyz) + bloom_downsample_src.sample(bloom_downsample_src_smp, (in.texcoord + float2(_45, _48))).xyz) + bloom_downsample_src.sample(bloom_downsample_src_smp, (in.texcoord + _23)).xyz) * 0.25, 1.0);
return out;
}
*/
fs_bloom_downsample_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,0x62,
0x6c,0x6f,0x6f,0x6d,0x5f,0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,
0x70,0x61,0x72,0x61,0x6d,0x73,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,
0x61,0x74,0x20,0x73,0x72,0x63,0x5f,0x74,0x65,0x78,0x65,0x6c,0x5f,0x78,0x3b,0x0a,
0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x73,0x72,0x63,0x5f,0x74,0x65,
0x78,0x65,0x6c,0x5f,0x79,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,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,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,0x32,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,0x5b,0x5b,0x75,0x73,
0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,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,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,0x62,0x6c,0x6f,
0x6f,0x6d,0x5f,0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x70,0x61,
0x72,0x61,0x6d,0x73,0x26,0x20,0x5f,0x31,0x32,0x20,0x5b,0x5b,0x62,0x75,0x66,0x66,
0x65,0x72,0x28,0x30,0x29,0x5d,0x5d,0x2c,0x20,0x74,0x65,0x78,0x74,0x75,0x72,0x65,
0x32,0x64,0x3c,0x66,0x6c,0x6f,0x61,0x74,0x3e,0x20,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,
0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x72,0x63,0x20,0x5b,
0x5b,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x30,0x29,0x5d,0x5d,0x2c,0x20,0x73,
0x61,0x6d,0x70,0x6c,0x65,0x72,0x20,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x64,0x6f,0x77,
0x6e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x72,0x63,0x5f,0x73,0x6d,0x70,0x20,
0x5b,0x5b,0x73,0x61,0x6d,0x70,0x6c,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,0x66,0x6c,
0x6f,0x61,0x74,0x32,0x20,0x5f,0x32,0x33,0x20,0x3d,0x20,0x66,0x6c,0x6f,0x61,0x74,
0x32,0x28,0x5f,0x31,0x32,0x2e,0x73,0x72,0x63,0x5f,0x74,0x65,0x78,0x65,0x6c,0x5f,
0x78,0x2c,0x20,0x5f,0x31,0x32,0x2e,0x73,0x72,0x63,0x5f,0x74,0x65,0x78,0x65,0x6c,
0x5f,0x79,0x29,0x20,0x2a,0x20,0x30,0x2e,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,
0x6c,0x6f,0x61,0x74,0x20,0x5f,0x34,0x34,0x20,0x3d,0x20,0x5f,0x32,0x33,0x2e,0x78,
0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x34,0x35,0x20,
0x3d,0x20,0x2d,0x5f,0x34,0x34,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,
0x74,0x20,0x5f,0x34,0x38,0x20,0x3d,0x20,0x5f,0x32,0x33,0x2e,0x79,0x3b,0x0a,0x20,
0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x34,0x39,0x20,0x3d,0x20,0x2d,
0x5f,0x34,0x38,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,0x28,0x28,0x28,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x64,0x6f,0x77,0x6e,0x73,0x61,
0x6d,0x70,0x6c,0x65,0x5f,0x73,0x72,0x63,0x2e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x28,
0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,0x70,0x6c,0x65,
0x5f,0x73,0x72,0x63,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x28,0x69,0x6e,0x2e,0x74,0x65,
0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,0x2b,0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,0x28,
0x5f,0x34,0x35,0x2c,0x20,0x5f,0x34,0x39,0x29,0x29,0x29,0x2e,0x78,0x79,0x7a,0x20,
0x2b,0x20,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,0x70,
0x6c,0x65,0x5f,0x73,0x72,0x63,0x2e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x28,0x62,0x6c,
0x6f,0x6f,0x6d,0x5f,0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,
0x72,0x63,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x28,0x69,0x6e,0x2e,0x74,0x65,0x78,0x63,
0x6f,0x6f,0x72,0x64,0x20,0x2b,0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,0x28,0x5f,0x34,
0x34,0x2c,0x20,0x5f,0x34,0x39,0x29,0x29,0x29,0x2e,0x78,0x79,0x7a,0x29,0x20,0x2b,
0x20,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,0x70,0x6c,
0x65,0x5f,0x73,0x72,0x63,0x2e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x28,0x62,0x6c,0x6f,
0x6f,0x6d,0x5f,0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x72,
0x63,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x28,0x69,0x6e,0x2e,0x74,0x65,0x78,0x63,0x6f,
0x6f,0x72,0x64,0x20,0x2b,0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,0x28,0x5f,0x34,0x35,
0x2c,0x20,0x5f,0x34,0x38,0x29,0x29,0x29,0x2e,0x78,0x79,0x7a,0x29,0x20,0x2b,0x20,
0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,0x70,0x6c,0x65,
0x5f,0x73,0x72,0x63,0x2e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x28,0x62,0x6c,0x6f,0x6f,
0x6d,0x5f,0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x72,0x63,
0x5f,0x73,0x6d,0x70,0x2c,0x20,0x28,0x69,0x6e,0x2e,0x74,0x65,0x78,0x63,0x6f,0x6f,
0x72,0x64,0x20,0x2b,0x20,0x5f,0x32,0x33,0x29,0x29,0x2e,0x78,0x79,0x7a,0x29,0x20,
0x2a,0x20,0x30,0x2e,0x32,0x35,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,
];
bloom_downsample_shader_desc :: (backend: sg_backend) -> sg_shader_desc {
desc: sg_shader_desc;
desc.label = "bloom_downsample_shader";
if backend == {
case .GLCORE;
desc.vertex_func.source = xx *vs_bloom_downsample_source_glsl430;
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_bloom_downsample_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 = "uv";
desc.uniform_blocks[0].stage = .FRAGMENT;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 16;
desc.uniform_blocks[0].glsl_uniforms[0].type = .FLOAT4;
desc.uniform_blocks[0].glsl_uniforms[0].array_count = 1;
desc.uniform_blocks[0].glsl_uniforms[0].glsl_name = "bloom_downsample_params";
desc.images[0].stage = .FRAGMENT;
desc.images[0].multisampled = false;
desc.images[0].image_type = ._2D;
desc.images[0].sample_type = .FLOAT;
desc.samplers[0].stage = .FRAGMENT;
desc.samplers[0].sampler_type = .FILTERING;
desc.image_sampler_pairs[0].stage = .FRAGMENT;
desc.image_sampler_pairs[0].image_slot = 0;
desc.image_sampler_pairs[0].sampler_slot = 0;
desc.image_sampler_pairs[0].glsl_name = "bloom_downsample_src_bloom_downsample_src_smp";
case .GLES3;
desc.vertex_func.source = xx *vs_bloom_downsample_source_glsl300es;
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_bloom_downsample_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 = "uv";
desc.uniform_blocks[0].stage = .FRAGMENT;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 16;
desc.uniform_blocks[0].glsl_uniforms[0].type = .FLOAT4;
desc.uniform_blocks[0].glsl_uniforms[0].array_count = 1;
desc.uniform_blocks[0].glsl_uniforms[0].glsl_name = "bloom_downsample_params";
desc.images[0].stage = .FRAGMENT;
desc.images[0].multisampled = false;
desc.images[0].image_type = ._2D;
desc.images[0].sample_type = .FLOAT;
desc.samplers[0].stage = .FRAGMENT;
desc.samplers[0].sampler_type = .FILTERING;
desc.image_sampler_pairs[0].stage = .FRAGMENT;
desc.image_sampler_pairs[0].image_slot = 0;
desc.image_sampler_pairs[0].sampler_slot = 0;
desc.image_sampler_pairs[0].glsl_name = "bloom_downsample_src_bloom_downsample_src_smp";
case .METAL_MACOS;
desc.vertex_func.source = xx *vs_bloom_downsample_source_metal_macos;
desc.vertex_func.entry = "main0";
desc.fragment_func.source = xx *fs_bloom_downsample_source_metal_macos;
desc.fragment_func.entry = "main0";
desc.attrs[0].base_type = .FLOAT;
desc.attrs[1].base_type = .FLOAT;
desc.uniform_blocks[0].stage = .FRAGMENT;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 16;
desc.uniform_blocks[0].msl_buffer_n = 0;
desc.images[0].stage = .FRAGMENT;
desc.images[0].multisampled = false;
desc.images[0].image_type = ._2D;
desc.images[0].sample_type = .FLOAT;
desc.images[0].msl_texture_n = 0;
desc.samplers[0].stage = .FRAGMENT;
desc.samplers[0].sampler_type = .FILTERING;
desc.samplers[0].msl_sampler_n = 0;
desc.image_sampler_pairs[0].stage = .FRAGMENT;
desc.image_sampler_pairs[0].image_slot = 0;
desc.image_sampler_pairs[0].sampler_slot = 0;
}
return desc;
}

View File

@ -1,552 +0,0 @@
/*
#version:1# (machine generated, don't edit!)
Generated by sokol-shdc (https://github.com/floooh/sokol-tools)
Cmdline:
sokol-shdc -i shader_bloom_prefilter.glsl -o ./jai/shader_bloom_prefilter.jai -l glsl430:glsl300es:metal_macos -f sokol_jai
Overview:
=========
Shader program: 'bloom_prefilter':
Get shader desc: bloom_prefilter_shader_desc(sg_query_backend())
Vertex Shader: vs_bloom_prefilter
Fragment Shader: fs_bloom_prefilter
Attributes:
ATTR_bloom_prefilter_position => 0
ATTR_bloom_prefilter_uv => 1
Bindings:
Uniform block 'bloom_prefilter_params':
Jai struct: Bloom_Prefilter_Params
Bind slot: UB_bloom_prefilter_params => 0
Image 'bloom_prefilter_src':
Image type: ._2D
Sample type: .FLOAT
Multisampled: false
Bind slot: IMG_bloom_prefilter_src => 0
Sampler 'bloom_prefilter_src_smp':
Type: .FILTERING
Bind slot: SMP_bloom_prefilter_src_smp => 0
*/
ATTR_bloom_prefilter_position :: 0;
ATTR_bloom_prefilter_uv :: 1;
UB_bloom_prefilter_params :: 0;
IMG_bloom_prefilter_src :: 0;
SMP_bloom_prefilter_src_smp :: 0;
Bloom_Prefilter_Params :: struct {
src_texel_x: float;
src_texel_y: float;
threshold: float;
_: [4]u8;
};
/*
#version 430
layout(location = 0) in vec2 position;
layout(location = 0) out vec2 texcoord;
layout(location = 1) in vec2 uv;
void main()
{
gl_Position = vec4(position, 0.5, 1.0);
texcoord = uv;
}
*/
vs_bloom_prefilter_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,0x69,0x6e,0x20,0x76,0x65,0x63,0x32,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,0x30,0x29,0x20,0x6f,0x75,0x74,0x20,0x76,0x65,
0x63,0x32,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,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,0x32,0x20,0x75,0x76,0x3b,0x0a,0x0a,0x76,
0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,
0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x76,
0x65,0x63,0x34,0x28,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x30,0x2e,
0x35,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x74,0x65,0x78,
0x63,0x6f,0x6f,0x72,0x64,0x20,0x3d,0x20,0x75,0x76,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#version 430
uniform vec4 bloom_prefilter_params[1];
layout(binding = 16) uniform sampler2D bloom_prefilter_src_bloom_prefilter_src_smp;
layout(location = 0) in vec2 texcoord;
layout(location = 0) out vec4 frag_color;
void main()
{
vec2 _23 = vec2(bloom_prefilter_params[0].x, bloom_prefilter_params[0].y) * 0.5;
float _44 = _23.x;
float _45 = -_44;
float _48 = _23.y;
float _49 = -_48;
vec3 _105 = (((texture(bloom_prefilter_src_bloom_prefilter_src_smp, texcoord + vec2(_45, _49)).xyz + texture(bloom_prefilter_src_bloom_prefilter_src_smp, texcoord + vec2(_44, _49)).xyz) + texture(bloom_prefilter_src_bloom_prefilter_src_smp, texcoord + vec2(_45, _48)).xyz) + texture(bloom_prefilter_src_bloom_prefilter_src_smp, texcoord + _23).xyz) * 0.25;
vec3 color = _105;
if (dot(_105, vec3(0.2125999927520751953125, 0.715200006961822509765625, 0.072200000286102294921875)) < bloom_prefilter_params[0].z)
{
color = vec3(0.0);
}
frag_color = vec4(color, 1.0);
}
*/
fs_bloom_prefilter_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,0x62,0x6c,0x6f,0x6f,0x6d,
0x5f,0x70,0x72,0x65,0x66,0x69,0x6c,0x74,0x65,0x72,0x5f,0x70,0x61,0x72,0x61,0x6d,
0x73,0x5b,0x31,0x5d,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x62,0x69,0x6e,
0x64,0x69,0x6e,0x67,0x20,0x3d,0x20,0x31,0x36,0x29,0x20,0x75,0x6e,0x69,0x66,0x6f,
0x72,0x6d,0x20,0x73,0x61,0x6d,0x70,0x6c,0x65,0x72,0x32,0x44,0x20,0x62,0x6c,0x6f,
0x6f,0x6d,0x5f,0x70,0x72,0x65,0x66,0x69,0x6c,0x74,0x65,0x72,0x5f,0x73,0x72,0x63,
0x5f,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x70,0x72,0x65,0x66,0x69,0x6c,0x74,0x65,0x72,
0x5f,0x73,0x72,0x63,0x5f,0x73,0x6d,0x70,0x3b,0x0a,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,0x32,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,
0x3b,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,0x76,
0x65,0x63,0x32,0x20,0x5f,0x32,0x33,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x62,
0x6c,0x6f,0x6f,0x6d,0x5f,0x70,0x72,0x65,0x66,0x69,0x6c,0x74,0x65,0x72,0x5f,0x70,
0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d,0x2e,0x78,0x2c,0x20,0x62,0x6c,0x6f,0x6f,
0x6d,0x5f,0x70,0x72,0x65,0x66,0x69,0x6c,0x74,0x65,0x72,0x5f,0x70,0x61,0x72,0x61,
0x6d,0x73,0x5b,0x30,0x5d,0x2e,0x79,0x29,0x20,0x2a,0x20,0x30,0x2e,0x35,0x3b,0x0a,
0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x34,0x34,0x20,0x3d,0x20,
0x5f,0x32,0x33,0x2e,0x78,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,
0x20,0x5f,0x34,0x35,0x20,0x3d,0x20,0x2d,0x5f,0x34,0x34,0x3b,0x0a,0x20,0x20,0x20,
0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x34,0x38,0x20,0x3d,0x20,0x5f,0x32,0x33,
0x2e,0x79,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x34,
0x39,0x20,0x3d,0x20,0x2d,0x5f,0x34,0x38,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,
0x63,0x33,0x20,0x5f,0x31,0x30,0x35,0x20,0x3d,0x20,0x28,0x28,0x28,0x74,0x65,0x78,
0x74,0x75,0x72,0x65,0x28,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x70,0x72,0x65,0x66,0x69,
0x6c,0x74,0x65,0x72,0x5f,0x73,0x72,0x63,0x5f,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x70,
0x72,0x65,0x66,0x69,0x6c,0x74,0x65,0x72,0x5f,0x73,0x72,0x63,0x5f,0x73,0x6d,0x70,
0x2c,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,0x2b,0x20,0x76,0x65,0x63,
0x32,0x28,0x5f,0x34,0x35,0x2c,0x20,0x5f,0x34,0x39,0x29,0x29,0x2e,0x78,0x79,0x7a,
0x20,0x2b,0x20,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x62,0x6c,0x6f,0x6f,0x6d,
0x5f,0x70,0x72,0x65,0x66,0x69,0x6c,0x74,0x65,0x72,0x5f,0x73,0x72,0x63,0x5f,0x62,
0x6c,0x6f,0x6f,0x6d,0x5f,0x70,0x72,0x65,0x66,0x69,0x6c,0x74,0x65,0x72,0x5f,0x73,
0x72,0x63,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,
0x20,0x2b,0x20,0x76,0x65,0x63,0x32,0x28,0x5f,0x34,0x34,0x2c,0x20,0x5f,0x34,0x39,
0x29,0x29,0x2e,0x78,0x79,0x7a,0x29,0x20,0x2b,0x20,0x74,0x65,0x78,0x74,0x75,0x72,
0x65,0x28,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x70,0x72,0x65,0x66,0x69,0x6c,0x74,0x65,
0x72,0x5f,0x73,0x72,0x63,0x5f,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x70,0x72,0x65,0x66,
0x69,0x6c,0x74,0x65,0x72,0x5f,0x73,0x72,0x63,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x74,
0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,0x2b,0x20,0x76,0x65,0x63,0x32,0x28,0x5f,
0x34,0x35,0x2c,0x20,0x5f,0x34,0x38,0x29,0x29,0x2e,0x78,0x79,0x7a,0x29,0x20,0x2b,
0x20,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x70,
0x72,0x65,0x66,0x69,0x6c,0x74,0x65,0x72,0x5f,0x73,0x72,0x63,0x5f,0x62,0x6c,0x6f,
0x6f,0x6d,0x5f,0x70,0x72,0x65,0x66,0x69,0x6c,0x74,0x65,0x72,0x5f,0x73,0x72,0x63,
0x5f,0x73,0x6d,0x70,0x2c,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,0x2b,
0x20,0x5f,0x32,0x33,0x29,0x2e,0x78,0x79,0x7a,0x29,0x20,0x2a,0x20,0x30,0x2e,0x32,
0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x63,0x6f,0x6c,0x6f,
0x72,0x20,0x3d,0x20,0x5f,0x31,0x30,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,
0x20,0x28,0x64,0x6f,0x74,0x28,0x5f,0x31,0x30,0x35,0x2c,0x20,0x76,0x65,0x63,0x33,
0x28,0x30,0x2e,0x32,0x31,0x32,0x35,0x39,0x39,0x39,0x39,0x32,0x37,0x35,0x32,0x30,
0x37,0x35,0x31,0x39,0x35,0x33,0x31,0x32,0x35,0x2c,0x20,0x30,0x2e,0x37,0x31,0x35,
0x32,0x30,0x30,0x30,0x30,0x36,0x39,0x36,0x31,0x38,0x32,0x32,0x35,0x30,0x39,0x37,
0x36,0x35,0x36,0x32,0x35,0x2c,0x20,0x30,0x2e,0x30,0x37,0x32,0x32,0x30,0x30,0x30,
0x30,0x30,0x32,0x38,0x36,0x31,0x30,0x32,0x32,0x39,0x34,0x39,0x32,0x31,0x38,0x37,
0x35,0x29,0x29,0x20,0x3c,0x20,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x70,0x72,0x65,0x66,
0x69,0x6c,0x74,0x65,0x72,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d,0x2e,
0x7a,0x29,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,
0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x66,0x72,
0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x76,0x65,0x63,0x34,0x28,
0x63,0x6f,0x6c,0x6f,0x72,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,
0x00,
];
/*
#version 300 es
layout(location = 0) in vec2 position;
out vec2 texcoord;
layout(location = 1) in vec2 uv;
void main()
{
gl_Position = vec4(position, 0.5, 1.0);
texcoord = uv;
}
*/
vs_bloom_prefilter_source_glsl300es := u8.[
0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x33,0x30,0x30,0x20,0x65,0x73,0x0a,
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,0x32,0x20,0x70,0x6f,
0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x32,
0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,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,0x32,0x20,0x75,0x76,0x3b,0x0a,0x0a,0x76,0x6f,0x69,
0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x67,
0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x76,0x65,0x63,
0x34,0x28,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x30,0x2e,0x35,0x2c,
0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x74,0x65,0x78,0x63,0x6f,
0x6f,0x72,0x64,0x20,0x3d,0x20,0x75,0x76,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#version 300 es
precision mediump float;
precision highp int;
uniform highp vec4 bloom_prefilter_params[1];
uniform highp sampler2D bloom_prefilter_src_bloom_prefilter_src_smp;
in highp vec2 texcoord;
layout(location = 0) out highp vec4 frag_color;
void main()
{
highp vec2 _23 = vec2(bloom_prefilter_params[0].x, bloom_prefilter_params[0].y) * 0.5;
highp float _44 = _23.x;
highp float _45 = -_44;
highp float _48 = _23.y;
highp float _49 = -_48;
highp vec3 _105 = (((texture(bloom_prefilter_src_bloom_prefilter_src_smp, texcoord + vec2(_45, _49)).xyz + texture(bloom_prefilter_src_bloom_prefilter_src_smp, texcoord + vec2(_44, _49)).xyz) + texture(bloom_prefilter_src_bloom_prefilter_src_smp, texcoord + vec2(_45, _48)).xyz) + texture(bloom_prefilter_src_bloom_prefilter_src_smp, texcoord + _23).xyz) * 0.25;
highp vec3 color = _105;
if (dot(_105, vec3(0.2125999927520751953125, 0.715200006961822509765625, 0.072200000286102294921875)) < bloom_prefilter_params[0].z)
{
color = vec3(0.0);
}
frag_color = vec4(color, 1.0);
}
*/
fs_bloom_prefilter_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,0x75,
0x6e,0x69,0x66,0x6f,0x72,0x6d,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x76,0x65,0x63,
0x34,0x20,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x70,0x72,0x65,0x66,0x69,0x6c,0x74,0x65,
0x72,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x31,0x5d,0x3b,0x0a,0x75,0x6e,0x69,
0x66,0x6f,0x72,0x6d,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x73,0x61,0x6d,0x70,0x6c,
0x65,0x72,0x32,0x44,0x20,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x70,0x72,0x65,0x66,0x69,
0x6c,0x74,0x65,0x72,0x5f,0x73,0x72,0x63,0x5f,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x70,
0x72,0x65,0x66,0x69,0x6c,0x74,0x65,0x72,0x5f,0x73,0x72,0x63,0x5f,0x73,0x6d,0x70,
0x3b,0x0a,0x0a,0x69,0x6e,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x76,0x65,0x63,0x32,
0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x3b,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,0x68,0x69,
0x67,0x68,0x70,0x20,0x76,0x65,0x63,0x32,0x20,0x5f,0x32,0x33,0x20,0x3d,0x20,0x76,
0x65,0x63,0x32,0x28,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x70,0x72,0x65,0x66,0x69,0x6c,
0x74,0x65,0x72,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d,0x2e,0x78,0x2c,
0x20,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x70,0x72,0x65,0x66,0x69,0x6c,0x74,0x65,0x72,
0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d,0x2e,0x79,0x29,0x20,0x2a,0x20,
0x30,0x2e,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x66,
0x6c,0x6f,0x61,0x74,0x20,0x5f,0x34,0x34,0x20,0x3d,0x20,0x5f,0x32,0x33,0x2e,0x78,
0x3b,0x0a,0x20,0x20,0x20,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x66,0x6c,0x6f,0x61,
0x74,0x20,0x5f,0x34,0x35,0x20,0x3d,0x20,0x2d,0x5f,0x34,0x34,0x3b,0x0a,0x20,0x20,
0x20,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x34,
0x38,0x20,0x3d,0x20,0x5f,0x32,0x33,0x2e,0x79,0x3b,0x0a,0x20,0x20,0x20,0x20,0x68,
0x69,0x67,0x68,0x70,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x34,0x39,0x20,0x3d,
0x20,0x2d,0x5f,0x34,0x38,0x3b,0x0a,0x20,0x20,0x20,0x20,0x68,0x69,0x67,0x68,0x70,
0x20,0x76,0x65,0x63,0x33,0x20,0x5f,0x31,0x30,0x35,0x20,0x3d,0x20,0x28,0x28,0x28,
0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x70,0x72,
0x65,0x66,0x69,0x6c,0x74,0x65,0x72,0x5f,0x73,0x72,0x63,0x5f,0x62,0x6c,0x6f,0x6f,
0x6d,0x5f,0x70,0x72,0x65,0x66,0x69,0x6c,0x74,0x65,0x72,0x5f,0x73,0x72,0x63,0x5f,
0x73,0x6d,0x70,0x2c,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,0x2b,0x20,
0x76,0x65,0x63,0x32,0x28,0x5f,0x34,0x35,0x2c,0x20,0x5f,0x34,0x39,0x29,0x29,0x2e,
0x78,0x79,0x7a,0x20,0x2b,0x20,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x62,0x6c,
0x6f,0x6f,0x6d,0x5f,0x70,0x72,0x65,0x66,0x69,0x6c,0x74,0x65,0x72,0x5f,0x73,0x72,
0x63,0x5f,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x70,0x72,0x65,0x66,0x69,0x6c,0x74,0x65,
0x72,0x5f,0x73,0x72,0x63,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x74,0x65,0x78,0x63,0x6f,
0x6f,0x72,0x64,0x20,0x2b,0x20,0x76,0x65,0x63,0x32,0x28,0x5f,0x34,0x34,0x2c,0x20,
0x5f,0x34,0x39,0x29,0x29,0x2e,0x78,0x79,0x7a,0x29,0x20,0x2b,0x20,0x74,0x65,0x78,
0x74,0x75,0x72,0x65,0x28,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x70,0x72,0x65,0x66,0x69,
0x6c,0x74,0x65,0x72,0x5f,0x73,0x72,0x63,0x5f,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x70,
0x72,0x65,0x66,0x69,0x6c,0x74,0x65,0x72,0x5f,0x73,0x72,0x63,0x5f,0x73,0x6d,0x70,
0x2c,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,0x2b,0x20,0x76,0x65,0x63,
0x32,0x28,0x5f,0x34,0x35,0x2c,0x20,0x5f,0x34,0x38,0x29,0x29,0x2e,0x78,0x79,0x7a,
0x29,0x20,0x2b,0x20,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x62,0x6c,0x6f,0x6f,
0x6d,0x5f,0x70,0x72,0x65,0x66,0x69,0x6c,0x74,0x65,0x72,0x5f,0x73,0x72,0x63,0x5f,
0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x70,0x72,0x65,0x66,0x69,0x6c,0x74,0x65,0x72,0x5f,
0x73,0x72,0x63,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,
0x64,0x20,0x2b,0x20,0x5f,0x32,0x33,0x29,0x2e,0x78,0x79,0x7a,0x29,0x20,0x2a,0x20,
0x30,0x2e,0x32,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x68,0x69,0x67,0x68,0x70,0x20,
0x76,0x65,0x63,0x33,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x5f,0x31,0x30,
0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x64,0x6f,0x74,0x28,0x5f,
0x31,0x30,0x35,0x2c,0x20,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x32,0x31,0x32,0x35,
0x39,0x39,0x39,0x39,0x32,0x37,0x35,0x32,0x30,0x37,0x35,0x31,0x39,0x35,0x33,0x31,
0x32,0x35,0x2c,0x20,0x30,0x2e,0x37,0x31,0x35,0x32,0x30,0x30,0x30,0x30,0x36,0x39,
0x36,0x31,0x38,0x32,0x32,0x35,0x30,0x39,0x37,0x36,0x35,0x36,0x32,0x35,0x2c,0x20,
0x30,0x2e,0x30,0x37,0x32,0x32,0x30,0x30,0x30,0x30,0x30,0x32,0x38,0x36,0x31,0x30,
0x32,0x32,0x39,0x34,0x39,0x32,0x31,0x38,0x37,0x35,0x29,0x29,0x20,0x3c,0x20,0x62,
0x6c,0x6f,0x6f,0x6d,0x5f,0x70,0x72,0x65,0x66,0x69,0x6c,0x74,0x65,0x72,0x5f,0x70,
0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d,0x2e,0x7a,0x29,0x0a,0x20,0x20,0x20,0x20,
0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,
0x3d,0x20,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,
0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,
0x72,0x20,0x3d,0x20,0x76,0x65,0x63,0x34,0x28,0x63,0x6f,0x6c,0x6f,0x72,0x2c,0x20,
0x31,0x2e,0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct main0_out
{
float2 texcoord [[user(locn0)]];
float4 gl_Position [[position]];
};
struct main0_in
{
float2 position [[attribute(0)]];
float2 uv [[attribute(1)]];
};
vertex main0_out main0(main0_in in [[stage_in]])
{
main0_out out = {};
out.gl_Position = float4(in.position, 0.5, 1.0);
out.texcoord = in.uv;
return out;
}
*/
vs_bloom_prefilter_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,0x32,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,0x5b,
0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,0x30,0x29,0x5d,0x5d,0x3b,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,0x32,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,0x32,0x20,0x75,0x76,0x20,0x5b,
0x5b,0x61,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x28,0x31,0x29,0x5d,0x5d,0x3b,
0x0a,0x7d,0x3b,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,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,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,
0x69,0x6f,0x6e,0x20,0x3d,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x28,0x69,0x6e,0x2e,
0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x30,0x2e,0x35,0x2c,0x20,0x31,
0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,0x74,0x65,0x78,
0x63,0x6f,0x6f,0x72,0x64,0x20,0x3d,0x20,0x69,0x6e,0x2e,0x75,0x76,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 bloom_prefilter_params
{
float src_texel_x;
float src_texel_y;
float threshold;
};
struct main0_out
{
float4 frag_color [[color(0)]];
};
struct main0_in
{
float2 texcoord [[user(locn0)]];
};
fragment main0_out main0(main0_in in [[stage_in]], constant bloom_prefilter_params& _12 [[buffer(0)]], texture2d<float> bloom_prefilter_src [[texture(0)]], sampler bloom_prefilter_src_smp [[sampler(0)]])
{
main0_out out = {};
float2 _23 = float2(_12.src_texel_x, _12.src_texel_y) * 0.5;
float _44 = _23.x;
float _45 = -_44;
float _48 = _23.y;
float _49 = -_48;
float3 _105 = (((bloom_prefilter_src.sample(bloom_prefilter_src_smp, (in.texcoord + float2(_45, _49))).xyz + bloom_prefilter_src.sample(bloom_prefilter_src_smp, (in.texcoord + float2(_44, _49))).xyz) + bloom_prefilter_src.sample(bloom_prefilter_src_smp, (in.texcoord + float2(_45, _48))).xyz) + bloom_prefilter_src.sample(bloom_prefilter_src_smp, (in.texcoord + _23)).xyz) * 0.25;
float3 color = _105;
if (dot(_105, float3(0.2125999927520751953125, 0.715200006961822509765625, 0.072200000286102294921875)) < _12.threshold)
{
color = float3(0.0);
}
out.frag_color = float4(color, 1.0);
return out;
}
*/
fs_bloom_prefilter_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,0x62,
0x6c,0x6f,0x6f,0x6d,0x5f,0x70,0x72,0x65,0x66,0x69,0x6c,0x74,0x65,0x72,0x5f,0x70,
0x61,0x72,0x61,0x6d,0x73,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,
0x74,0x20,0x73,0x72,0x63,0x5f,0x74,0x65,0x78,0x65,0x6c,0x5f,0x78,0x3b,0x0a,0x20,
0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x73,0x72,0x63,0x5f,0x74,0x65,0x78,
0x65,0x6c,0x5f,0x79,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,
0x74,0x68,0x72,0x65,0x73,0x68,0x6f,0x6c,0x64,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,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,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,0x32,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,
0x5b,0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,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,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,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x70,0x72,0x65,0x66,0x69,0x6c,0x74,0x65,0x72,
0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x26,0x20,0x5f,0x31,0x32,0x20,0x5b,0x5b,0x62,
0x75,0x66,0x66,0x65,0x72,0x28,0x30,0x29,0x5d,0x5d,0x2c,0x20,0x74,0x65,0x78,0x74,
0x75,0x72,0x65,0x32,0x64,0x3c,0x66,0x6c,0x6f,0x61,0x74,0x3e,0x20,0x62,0x6c,0x6f,
0x6f,0x6d,0x5f,0x70,0x72,0x65,0x66,0x69,0x6c,0x74,0x65,0x72,0x5f,0x73,0x72,0x63,
0x20,0x5b,0x5b,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x30,0x29,0x5d,0x5d,0x2c,
0x20,0x73,0x61,0x6d,0x70,0x6c,0x65,0x72,0x20,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x70,
0x72,0x65,0x66,0x69,0x6c,0x74,0x65,0x72,0x5f,0x73,0x72,0x63,0x5f,0x73,0x6d,0x70,
0x20,0x5b,0x5b,0x73,0x61,0x6d,0x70,0x6c,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,0x66,
0x6c,0x6f,0x61,0x74,0x32,0x20,0x5f,0x32,0x33,0x20,0x3d,0x20,0x66,0x6c,0x6f,0x61,
0x74,0x32,0x28,0x5f,0x31,0x32,0x2e,0x73,0x72,0x63,0x5f,0x74,0x65,0x78,0x65,0x6c,
0x5f,0x78,0x2c,0x20,0x5f,0x31,0x32,0x2e,0x73,0x72,0x63,0x5f,0x74,0x65,0x78,0x65,
0x6c,0x5f,0x79,0x29,0x20,0x2a,0x20,0x30,0x2e,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,
0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x34,0x34,0x20,0x3d,0x20,0x5f,0x32,0x33,0x2e,
0x78,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x34,0x35,
0x20,0x3d,0x20,0x2d,0x5f,0x34,0x34,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,
0x61,0x74,0x20,0x5f,0x34,0x38,0x20,0x3d,0x20,0x5f,0x32,0x33,0x2e,0x79,0x3b,0x0a,
0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x34,0x39,0x20,0x3d,0x20,
0x2d,0x5f,0x34,0x38,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x33,
0x20,0x5f,0x31,0x30,0x35,0x20,0x3d,0x20,0x28,0x28,0x28,0x62,0x6c,0x6f,0x6f,0x6d,
0x5f,0x70,0x72,0x65,0x66,0x69,0x6c,0x74,0x65,0x72,0x5f,0x73,0x72,0x63,0x2e,0x73,
0x61,0x6d,0x70,0x6c,0x65,0x28,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x70,0x72,0x65,0x66,
0x69,0x6c,0x74,0x65,0x72,0x5f,0x73,0x72,0x63,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x28,
0x69,0x6e,0x2e,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,0x2b,0x20,0x66,0x6c,
0x6f,0x61,0x74,0x32,0x28,0x5f,0x34,0x35,0x2c,0x20,0x5f,0x34,0x39,0x29,0x29,0x29,
0x2e,0x78,0x79,0x7a,0x20,0x2b,0x20,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x70,0x72,0x65,
0x66,0x69,0x6c,0x74,0x65,0x72,0x5f,0x73,0x72,0x63,0x2e,0x73,0x61,0x6d,0x70,0x6c,
0x65,0x28,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x70,0x72,0x65,0x66,0x69,0x6c,0x74,0x65,
0x72,0x5f,0x73,0x72,0x63,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x28,0x69,0x6e,0x2e,0x74,
0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,0x2b,0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,
0x28,0x5f,0x34,0x34,0x2c,0x20,0x5f,0x34,0x39,0x29,0x29,0x29,0x2e,0x78,0x79,0x7a,
0x29,0x20,0x2b,0x20,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x70,0x72,0x65,0x66,0x69,0x6c,
0x74,0x65,0x72,0x5f,0x73,0x72,0x63,0x2e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x28,0x62,
0x6c,0x6f,0x6f,0x6d,0x5f,0x70,0x72,0x65,0x66,0x69,0x6c,0x74,0x65,0x72,0x5f,0x73,
0x72,0x63,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x28,0x69,0x6e,0x2e,0x74,0x65,0x78,0x63,
0x6f,0x6f,0x72,0x64,0x20,0x2b,0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,0x28,0x5f,0x34,
0x35,0x2c,0x20,0x5f,0x34,0x38,0x29,0x29,0x29,0x2e,0x78,0x79,0x7a,0x29,0x20,0x2b,
0x20,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x70,0x72,0x65,0x66,0x69,0x6c,0x74,0x65,0x72,
0x5f,0x73,0x72,0x63,0x2e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x28,0x62,0x6c,0x6f,0x6f,
0x6d,0x5f,0x70,0x72,0x65,0x66,0x69,0x6c,0x74,0x65,0x72,0x5f,0x73,0x72,0x63,0x5f,
0x73,0x6d,0x70,0x2c,0x20,0x28,0x69,0x6e,0x2e,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,
0x64,0x20,0x2b,0x20,0x5f,0x32,0x33,0x29,0x29,0x2e,0x78,0x79,0x7a,0x29,0x20,0x2a,
0x20,0x30,0x2e,0x32,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,
0x33,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x5f,0x31,0x30,0x35,0x3b,0x0a,
0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x64,0x6f,0x74,0x28,0x5f,0x31,0x30,0x35,
0x2c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x33,0x28,0x30,0x2e,0x32,0x31,0x32,0x35,0x39,
0x39,0x39,0x39,0x32,0x37,0x35,0x32,0x30,0x37,0x35,0x31,0x39,0x35,0x33,0x31,0x32,
0x35,0x2c,0x20,0x30,0x2e,0x37,0x31,0x35,0x32,0x30,0x30,0x30,0x30,0x36,0x39,0x36,
0x31,0x38,0x32,0x32,0x35,0x30,0x39,0x37,0x36,0x35,0x36,0x32,0x35,0x2c,0x20,0x30,
0x2e,0x30,0x37,0x32,0x32,0x30,0x30,0x30,0x30,0x30,0x32,0x38,0x36,0x31,0x30,0x32,
0x32,0x39,0x34,0x39,0x32,0x31,0x38,0x37,0x35,0x29,0x29,0x20,0x3c,0x20,0x5f,0x31,
0x32,0x2e,0x74,0x68,0x72,0x65,0x73,0x68,0x6f,0x6c,0x64,0x29,0x0a,0x20,0x20,0x20,
0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x6f,0x6c,0x6f,0x72,
0x20,0x3d,0x20,0x66,0x6c,0x6f,0x61,0x74,0x33,0x28,0x30,0x2e,0x30,0x29,0x3b,0x0a,
0x20,0x20,0x20,0x20,0x7d,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,0x63,0x6f,0x6c,0x6f,0x72,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,
];
bloom_prefilter_shader_desc :: (backend: sg_backend) -> sg_shader_desc {
desc: sg_shader_desc;
desc.label = "bloom_prefilter_shader";
if backend == {
case .GLCORE;
desc.vertex_func.source = xx *vs_bloom_prefilter_source_glsl430;
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_bloom_prefilter_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 = "uv";
desc.uniform_blocks[0].stage = .FRAGMENT;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 16;
desc.uniform_blocks[0].glsl_uniforms[0].type = .FLOAT4;
desc.uniform_blocks[0].glsl_uniforms[0].array_count = 1;
desc.uniform_blocks[0].glsl_uniforms[0].glsl_name = "bloom_prefilter_params";
desc.images[0].stage = .FRAGMENT;
desc.images[0].multisampled = false;
desc.images[0].image_type = ._2D;
desc.images[0].sample_type = .FLOAT;
desc.samplers[0].stage = .FRAGMENT;
desc.samplers[0].sampler_type = .FILTERING;
desc.image_sampler_pairs[0].stage = .FRAGMENT;
desc.image_sampler_pairs[0].image_slot = 0;
desc.image_sampler_pairs[0].sampler_slot = 0;
desc.image_sampler_pairs[0].glsl_name = "bloom_prefilter_src_bloom_prefilter_src_smp";
case .GLES3;
desc.vertex_func.source = xx *vs_bloom_prefilter_source_glsl300es;
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_bloom_prefilter_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 = "uv";
desc.uniform_blocks[0].stage = .FRAGMENT;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 16;
desc.uniform_blocks[0].glsl_uniforms[0].type = .FLOAT4;
desc.uniform_blocks[0].glsl_uniforms[0].array_count = 1;
desc.uniform_blocks[0].glsl_uniforms[0].glsl_name = "bloom_prefilter_params";
desc.images[0].stage = .FRAGMENT;
desc.images[0].multisampled = false;
desc.images[0].image_type = ._2D;
desc.images[0].sample_type = .FLOAT;
desc.samplers[0].stage = .FRAGMENT;
desc.samplers[0].sampler_type = .FILTERING;
desc.image_sampler_pairs[0].stage = .FRAGMENT;
desc.image_sampler_pairs[0].image_slot = 0;
desc.image_sampler_pairs[0].sampler_slot = 0;
desc.image_sampler_pairs[0].glsl_name = "bloom_prefilter_src_bloom_prefilter_src_smp";
case .METAL_MACOS;
desc.vertex_func.source = xx *vs_bloom_prefilter_source_metal_macos;
desc.vertex_func.entry = "main0";
desc.fragment_func.source = xx *fs_bloom_prefilter_source_metal_macos;
desc.fragment_func.entry = "main0";
desc.attrs[0].base_type = .FLOAT;
desc.attrs[1].base_type = .FLOAT;
desc.uniform_blocks[0].stage = .FRAGMENT;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 16;
desc.uniform_blocks[0].msl_buffer_n = 0;
desc.images[0].stage = .FRAGMENT;
desc.images[0].multisampled = false;
desc.images[0].image_type = ._2D;
desc.images[0].sample_type = .FLOAT;
desc.images[0].msl_texture_n = 0;
desc.samplers[0].stage = .FRAGMENT;
desc.samplers[0].sampler_type = .FILTERING;
desc.samplers[0].msl_sampler_n = 0;
desc.image_sampler_pairs[0].stage = .FRAGMENT;
desc.image_sampler_pairs[0].image_slot = 0;
desc.image_sampler_pairs[0].sampler_slot = 0;
}
return desc;
}

View File

@ -1,563 +0,0 @@
/*
#version:1# (machine generated, don't edit!)
Generated by sokol-shdc (https://github.com/floooh/sokol-tools)
Cmdline:
sokol-shdc -i shader_bloom_upsample.glsl -o ./jai/shader_bloom_upsample.jai -l glsl430:glsl300es:metal_macos -f sokol_jai
Overview:
=========
Shader program: 'bloom_upsample':
Get shader desc: bloom_upsample_shader_desc(sg_query_backend())
Vertex Shader: vs_bloom_upsample
Fragment Shader: fs_bloom_upsample
Attributes:
ATTR_bloom_upsample_position => 0
ATTR_bloom_upsample_uv => 1
Bindings:
Uniform block 'bloom_upsample_params':
Jai struct: Bloom_Upsample_Params
Bind slot: UB_bloom_upsample_params => 0
Image 'bloom_upsample_small':
Image type: ._2D
Sample type: .FLOAT
Multisampled: false
Bind slot: IMG_bloom_upsample_small => 0
Image 'bloom_upsample_large':
Image type: ._2D
Sample type: .FLOAT
Multisampled: false
Bind slot: IMG_bloom_upsample_large => 1
Sampler 'bloom_upsample_small_smp':
Type: .FILTERING
Bind slot: SMP_bloom_upsample_small_smp => 0
Sampler 'bloom_upsample_large_smp':
Type: .FILTERING
Bind slot: SMP_bloom_upsample_large_smp => 1
*/
ATTR_bloom_upsample_position :: 0;
ATTR_bloom_upsample_uv :: 1;
UB_bloom_upsample_params :: 0;
IMG_bloom_upsample_small :: 0;
IMG_bloom_upsample_large :: 1;
SMP_bloom_upsample_small_smp :: 0;
SMP_bloom_upsample_large_smp :: 1;
Bloom_Upsample_Params :: struct {
src_texel_x: float;
src_texel_y: float;
_: [8]u8;
};
/*
#version 430
layout(location = 0) in vec2 position;
layout(location = 0) out vec2 texcoord;
layout(location = 1) in vec2 uv;
void main()
{
gl_Position = vec4(position, 0.5, 1.0);
texcoord = uv;
}
*/
vs_bloom_upsample_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,0x69,0x6e,0x20,0x76,0x65,0x63,0x32,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,0x30,0x29,0x20,0x6f,0x75,0x74,0x20,0x76,0x65,
0x63,0x32,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,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,0x32,0x20,0x75,0x76,0x3b,0x0a,0x0a,0x76,
0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,
0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x76,
0x65,0x63,0x34,0x28,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x30,0x2e,
0x35,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x74,0x65,0x78,
0x63,0x6f,0x6f,0x72,0x64,0x20,0x3d,0x20,0x75,0x76,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#version 430
uniform vec4 bloom_upsample_params[1];
layout(binding = 16) uniform sampler2D bloom_upsample_small_bloom_upsample_small_smp;
layout(binding = 17) uniform sampler2D bloom_upsample_large_bloom_upsample_large_smp;
layout(location = 0) in vec2 texcoord;
layout(location = 0) out vec4 frag_color;
void main()
{
vec2 _23 = vec2(bloom_upsample_params[0].x, bloom_upsample_params[0].y) * 0.5;
float _44 = _23.x;
float _45 = -_44;
float _48 = _23.y;
float _49 = -_48;
frag_color = vec4(((((texture(bloom_upsample_small_bloom_upsample_small_smp, texcoord + vec2(_45, _49)).xyz + texture(bloom_upsample_small_bloom_upsample_small_smp, texcoord + vec2(_44, _49)).xyz) + texture(bloom_upsample_small_bloom_upsample_small_smp, texcoord + vec2(_45, _48)).xyz) + texture(bloom_upsample_small_bloom_upsample_small_smp, texcoord + _23).xyz) * 0.25) + texture(bloom_upsample_large_bloom_upsample_large_smp, texcoord).xyz, 1.0);
}
*/
fs_bloom_upsample_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,0x62,0x6c,0x6f,0x6f,0x6d,
0x5f,0x75,0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,
0x5b,0x31,0x5d,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x62,0x69,0x6e,0x64,
0x69,0x6e,0x67,0x20,0x3d,0x20,0x31,0x36,0x29,0x20,0x75,0x6e,0x69,0x66,0x6f,0x72,
0x6d,0x20,0x73,0x61,0x6d,0x70,0x6c,0x65,0x72,0x32,0x44,0x20,0x62,0x6c,0x6f,0x6f,
0x6d,0x5f,0x75,0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x6d,0x61,0x6c,0x6c,
0x5f,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,
0x73,0x6d,0x61,0x6c,0x6c,0x5f,0x73,0x6d,0x70,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,
0x74,0x28,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x20,0x3d,0x20,0x31,0x37,0x29,0x20,
0x75,0x6e,0x69,0x66,0x6f,0x72,0x6d,0x20,0x73,0x61,0x6d,0x70,0x6c,0x65,0x72,0x32,
0x44,0x20,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,
0x5f,0x6c,0x61,0x72,0x67,0x65,0x5f,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,
0x61,0x6d,0x70,0x6c,0x65,0x5f,0x6c,0x61,0x72,0x67,0x65,0x5f,0x73,0x6d,0x70,0x3b,
0x0a,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,0x32,0x20,0x74,
0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x3b,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,0x76,0x65,0x63,0x32,0x20,0x5f,0x32,0x33,0x20,0x3d,
0x20,0x76,0x65,0x63,0x32,0x28,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,0x61,
0x6d,0x70,0x6c,0x65,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d,0x2e,0x78,
0x2c,0x20,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,
0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d,0x2e,0x79,0x29,0x20,0x2a,0x20,
0x30,0x2e,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,
0x34,0x34,0x20,0x3d,0x20,0x5f,0x32,0x33,0x2e,0x78,0x3b,0x0a,0x20,0x20,0x20,0x20,
0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x34,0x35,0x20,0x3d,0x20,0x2d,0x5f,0x34,0x34,
0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x34,0x38,0x20,
0x3d,0x20,0x5f,0x32,0x33,0x2e,0x79,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,
0x61,0x74,0x20,0x5f,0x34,0x39,0x20,0x3d,0x20,0x2d,0x5f,0x34,0x38,0x3b,0x0a,0x20,
0x20,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,
0x76,0x65,0x63,0x34,0x28,0x28,0x28,0x28,0x28,0x74,0x65,0x78,0x74,0x75,0x72,0x65,
0x28,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,
0x73,0x6d,0x61,0x6c,0x6c,0x5f,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,0x61,
0x6d,0x70,0x6c,0x65,0x5f,0x73,0x6d,0x61,0x6c,0x6c,0x5f,0x73,0x6d,0x70,0x2c,0x20,
0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,0x2b,0x20,0x76,0x65,0x63,0x32,0x28,
0x5f,0x34,0x35,0x2c,0x20,0x5f,0x34,0x39,0x29,0x29,0x2e,0x78,0x79,0x7a,0x20,0x2b,
0x20,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,
0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x6d,0x61,0x6c,0x6c,0x5f,0x62,0x6c,
0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x6d,0x61,
0x6c,0x6c,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,
0x20,0x2b,0x20,0x76,0x65,0x63,0x32,0x28,0x5f,0x34,0x34,0x2c,0x20,0x5f,0x34,0x39,
0x29,0x29,0x2e,0x78,0x79,0x7a,0x29,0x20,0x2b,0x20,0x74,0x65,0x78,0x74,0x75,0x72,
0x65,0x28,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,
0x5f,0x73,0x6d,0x61,0x6c,0x6c,0x5f,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,
0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x6d,0x61,0x6c,0x6c,0x5f,0x73,0x6d,0x70,0x2c,
0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,0x2b,0x20,0x76,0x65,0x63,0x32,
0x28,0x5f,0x34,0x35,0x2c,0x20,0x5f,0x34,0x38,0x29,0x29,0x2e,0x78,0x79,0x7a,0x29,
0x20,0x2b,0x20,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x62,0x6c,0x6f,0x6f,0x6d,
0x5f,0x75,0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x6d,0x61,0x6c,0x6c,0x5f,
0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,
0x6d,0x61,0x6c,0x6c,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,
0x72,0x64,0x20,0x2b,0x20,0x5f,0x32,0x33,0x29,0x2e,0x78,0x79,0x7a,0x29,0x20,0x2a,
0x20,0x30,0x2e,0x32,0x35,0x29,0x20,0x2b,0x20,0x74,0x65,0x78,0x74,0x75,0x72,0x65,
0x28,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,
0x6c,0x61,0x72,0x67,0x65,0x5f,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,0x61,
0x6d,0x70,0x6c,0x65,0x5f,0x6c,0x61,0x72,0x67,0x65,0x5f,0x73,0x6d,0x70,0x2c,0x20,
0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x29,0x2e,0x78,0x79,0x7a,0x2c,0x20,0x31,
0x2e,0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#version 300 es
layout(location = 0) in vec2 position;
out vec2 texcoord;
layout(location = 1) in vec2 uv;
void main()
{
gl_Position = vec4(position, 0.5, 1.0);
texcoord = uv;
}
*/
vs_bloom_upsample_source_glsl300es := u8.[
0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x33,0x30,0x30,0x20,0x65,0x73,0x0a,
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,0x32,0x20,0x70,0x6f,
0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x32,
0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,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,0x32,0x20,0x75,0x76,0x3b,0x0a,0x0a,0x76,0x6f,0x69,
0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x67,
0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x76,0x65,0x63,
0x34,0x28,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x30,0x2e,0x35,0x2c,
0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x74,0x65,0x78,0x63,0x6f,
0x6f,0x72,0x64,0x20,0x3d,0x20,0x75,0x76,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#version 300 es
precision mediump float;
precision highp int;
uniform highp vec4 bloom_upsample_params[1];
uniform highp sampler2D bloom_upsample_small_bloom_upsample_small_smp;
uniform highp sampler2D bloom_upsample_large_bloom_upsample_large_smp;
in highp vec2 texcoord;
layout(location = 0) out highp vec4 frag_color;
void main()
{
highp vec2 _23 = vec2(bloom_upsample_params[0].x, bloom_upsample_params[0].y) * 0.5;
highp float _44 = _23.x;
highp float _45 = -_44;
highp float _48 = _23.y;
highp float _49 = -_48;
frag_color = vec4(((((texture(bloom_upsample_small_bloom_upsample_small_smp, texcoord + vec2(_45, _49)).xyz + texture(bloom_upsample_small_bloom_upsample_small_smp, texcoord + vec2(_44, _49)).xyz) + texture(bloom_upsample_small_bloom_upsample_small_smp, texcoord + vec2(_45, _48)).xyz) + texture(bloom_upsample_small_bloom_upsample_small_smp, texcoord + _23).xyz) * 0.25) + texture(bloom_upsample_large_bloom_upsample_large_smp, texcoord).xyz, 1.0);
}
*/
fs_bloom_upsample_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,0x75,
0x6e,0x69,0x66,0x6f,0x72,0x6d,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x76,0x65,0x63,
0x34,0x20,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,
0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x31,0x5d,0x3b,0x0a,0x75,0x6e,0x69,0x66,
0x6f,0x72,0x6d,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x73,0x61,0x6d,0x70,0x6c,0x65,
0x72,0x32,0x44,0x20,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,0x61,0x6d,0x70,
0x6c,0x65,0x5f,0x73,0x6d,0x61,0x6c,0x6c,0x5f,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,
0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x6d,0x61,0x6c,0x6c,0x5f,0x73,0x6d,
0x70,0x3b,0x0a,0x75,0x6e,0x69,0x66,0x6f,0x72,0x6d,0x20,0x68,0x69,0x67,0x68,0x70,
0x20,0x73,0x61,0x6d,0x70,0x6c,0x65,0x72,0x32,0x44,0x20,0x62,0x6c,0x6f,0x6f,0x6d,
0x5f,0x75,0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x6c,0x61,0x72,0x67,0x65,0x5f,
0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x6c,
0x61,0x72,0x67,0x65,0x5f,0x73,0x6d,0x70,0x3b,0x0a,0x0a,0x69,0x6e,0x20,0x68,0x69,
0x67,0x68,0x70,0x20,0x76,0x65,0x63,0x32,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,
0x64,0x3b,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,0x68,0x69,0x67,0x68,0x70,0x20,0x76,0x65,0x63,0x32,
0x20,0x5f,0x32,0x33,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x62,0x6c,0x6f,0x6f,
0x6d,0x5f,0x75,0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x70,0x61,0x72,0x61,0x6d,
0x73,0x5b,0x30,0x5d,0x2e,0x78,0x2c,0x20,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,
0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d,
0x2e,0x79,0x29,0x20,0x2a,0x20,0x30,0x2e,0x35,0x3b,0x0a,0x20,0x20,0x20,0x20,0x68,
0x69,0x67,0x68,0x70,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x34,0x34,0x20,0x3d,
0x20,0x5f,0x32,0x33,0x2e,0x78,0x3b,0x0a,0x20,0x20,0x20,0x20,0x68,0x69,0x67,0x68,
0x70,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x34,0x35,0x20,0x3d,0x20,0x2d,0x5f,
0x34,0x34,0x3b,0x0a,0x20,0x20,0x20,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x66,0x6c,
0x6f,0x61,0x74,0x20,0x5f,0x34,0x38,0x20,0x3d,0x20,0x5f,0x32,0x33,0x2e,0x79,0x3b,
0x0a,0x20,0x20,0x20,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x66,0x6c,0x6f,0x61,0x74,
0x20,0x5f,0x34,0x39,0x20,0x3d,0x20,0x2d,0x5f,0x34,0x38,0x3b,0x0a,0x20,0x20,0x20,
0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x76,0x65,
0x63,0x34,0x28,0x28,0x28,0x28,0x28,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x62,
0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x6d,
0x61,0x6c,0x6c,0x5f,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,0x61,0x6d,0x70,
0x6c,0x65,0x5f,0x73,0x6d,0x61,0x6c,0x6c,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x74,0x65,
0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,0x2b,0x20,0x76,0x65,0x63,0x32,0x28,0x5f,0x34,
0x35,0x2c,0x20,0x5f,0x34,0x39,0x29,0x29,0x2e,0x78,0x79,0x7a,0x20,0x2b,0x20,0x74,
0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,
0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x6d,0x61,0x6c,0x6c,0x5f,0x62,0x6c,0x6f,0x6f,
0x6d,0x5f,0x75,0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x6d,0x61,0x6c,0x6c,
0x5f,0x73,0x6d,0x70,0x2c,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,0x2b,
0x20,0x76,0x65,0x63,0x32,0x28,0x5f,0x34,0x34,0x2c,0x20,0x5f,0x34,0x39,0x29,0x29,
0x2e,0x78,0x79,0x7a,0x29,0x20,0x2b,0x20,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,
0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,
0x6d,0x61,0x6c,0x6c,0x5f,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,0x61,0x6d,
0x70,0x6c,0x65,0x5f,0x73,0x6d,0x61,0x6c,0x6c,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x74,
0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,0x2b,0x20,0x76,0x65,0x63,0x32,0x28,0x5f,
0x34,0x35,0x2c,0x20,0x5f,0x34,0x38,0x29,0x29,0x2e,0x78,0x79,0x7a,0x29,0x20,0x2b,
0x20,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,
0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x6d,0x61,0x6c,0x6c,0x5f,0x62,0x6c,
0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x6d,0x61,
0x6c,0x6c,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,
0x20,0x2b,0x20,0x5f,0x32,0x33,0x29,0x2e,0x78,0x79,0x7a,0x29,0x20,0x2a,0x20,0x30,
0x2e,0x32,0x35,0x29,0x20,0x2b,0x20,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x62,
0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x6c,0x61,
0x72,0x67,0x65,0x5f,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,0x61,0x6d,0x70,
0x6c,0x65,0x5f,0x6c,0x61,0x72,0x67,0x65,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x74,0x65,
0x78,0x63,0x6f,0x6f,0x72,0x64,0x29,0x2e,0x78,0x79,0x7a,0x2c,0x20,0x31,0x2e,0x30,
0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct main0_out
{
float2 texcoord [[user(locn0)]];
float4 gl_Position [[position]];
};
struct main0_in
{
float2 position [[attribute(0)]];
float2 uv [[attribute(1)]];
};
vertex main0_out main0(main0_in in [[stage_in]])
{
main0_out out = {};
out.gl_Position = float4(in.position, 0.5, 1.0);
out.texcoord = in.uv;
return out;
}
*/
vs_bloom_upsample_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,0x32,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,0x5b,
0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,0x30,0x29,0x5d,0x5d,0x3b,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,0x32,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,0x32,0x20,0x75,0x76,0x20,0x5b,
0x5b,0x61,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x28,0x31,0x29,0x5d,0x5d,0x3b,
0x0a,0x7d,0x3b,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,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,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,
0x69,0x6f,0x6e,0x20,0x3d,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x28,0x69,0x6e,0x2e,
0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x30,0x2e,0x35,0x2c,0x20,0x31,
0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,0x74,0x65,0x78,
0x63,0x6f,0x6f,0x72,0x64,0x20,0x3d,0x20,0x69,0x6e,0x2e,0x75,0x76,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 bloom_upsample_params
{
float src_texel_x;
float src_texel_y;
};
struct main0_out
{
float4 frag_color [[color(0)]];
};
struct main0_in
{
float2 texcoord [[user(locn0)]];
};
fragment main0_out main0(main0_in in [[stage_in]], constant bloom_upsample_params& _12 [[buffer(0)]], texture2d<float> bloom_upsample_small [[texture(0)]], texture2d<float> bloom_upsample_large [[texture(1)]], sampler bloom_upsample_small_smp [[sampler(0)]], sampler bloom_upsample_large_smp [[sampler(1)]])
{
main0_out out = {};
float2 _23 = float2(_12.src_texel_x, _12.src_texel_y) * 0.5;
float _44 = _23.x;
float _45 = -_44;
float _48 = _23.y;
float _49 = -_48;
out.frag_color = float4(((((bloom_upsample_small.sample(bloom_upsample_small_smp, (in.texcoord + float2(_45, _49))).xyz + bloom_upsample_small.sample(bloom_upsample_small_smp, (in.texcoord + float2(_44, _49))).xyz) + bloom_upsample_small.sample(bloom_upsample_small_smp, (in.texcoord + float2(_45, _48))).xyz) + bloom_upsample_small.sample(bloom_upsample_small_smp, (in.texcoord + _23)).xyz) * 0.25) + bloom_upsample_large.sample(bloom_upsample_large_smp, in.texcoord).xyz, 1.0);
return out;
}
*/
fs_bloom_upsample_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,0x62,
0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x70,0x61,
0x72,0x61,0x6d,0x73,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,
0x20,0x73,0x72,0x63,0x5f,0x74,0x65,0x78,0x65,0x6c,0x5f,0x78,0x3b,0x0a,0x20,0x20,
0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x73,0x72,0x63,0x5f,0x74,0x65,0x78,0x65,
0x6c,0x5f,0x79,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,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,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,0x32,
0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,
0x28,0x6c,0x6f,0x63,0x6e,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,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,0x62,0x6c,0x6f,0x6f,0x6d,
0x5f,0x75,0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,
0x26,0x20,0x5f,0x31,0x32,0x20,0x5b,0x5b,0x62,0x75,0x66,0x66,0x65,0x72,0x28,0x30,
0x29,0x5d,0x5d,0x2c,0x20,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x32,0x64,0x3c,0x66,
0x6c,0x6f,0x61,0x74,0x3e,0x20,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,0x61,
0x6d,0x70,0x6c,0x65,0x5f,0x73,0x6d,0x61,0x6c,0x6c,0x20,0x5b,0x5b,0x74,0x65,0x78,
0x74,0x75,0x72,0x65,0x28,0x30,0x29,0x5d,0x5d,0x2c,0x20,0x74,0x65,0x78,0x74,0x75,
0x72,0x65,0x32,0x64,0x3c,0x66,0x6c,0x6f,0x61,0x74,0x3e,0x20,0x62,0x6c,0x6f,0x6f,
0x6d,0x5f,0x75,0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x6c,0x61,0x72,0x67,0x65,
0x20,0x5b,0x5b,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x31,0x29,0x5d,0x5d,0x2c,
0x20,0x73,0x61,0x6d,0x70,0x6c,0x65,0x72,0x20,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,
0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x6d,0x61,0x6c,0x6c,0x5f,0x73,0x6d,
0x70,0x20,0x5b,0x5b,0x73,0x61,0x6d,0x70,0x6c,0x65,0x72,0x28,0x30,0x29,0x5d,0x5d,
0x2c,0x20,0x73,0x61,0x6d,0x70,0x6c,0x65,0x72,0x20,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,
0x75,0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x6c,0x61,0x72,0x67,0x65,0x5f,0x73,
0x6d,0x70,0x20,0x5b,0x5b,0x73,0x61,0x6d,0x70,0x6c,0x65,0x72,0x28,0x31,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,0x66,0x6c,0x6f,0x61,0x74,0x32,0x20,0x5f,0x32,0x33,0x20,0x3d,0x20,0x66,0x6c,
0x6f,0x61,0x74,0x32,0x28,0x5f,0x31,0x32,0x2e,0x73,0x72,0x63,0x5f,0x74,0x65,0x78,
0x65,0x6c,0x5f,0x78,0x2c,0x20,0x5f,0x31,0x32,0x2e,0x73,0x72,0x63,0x5f,0x74,0x65,
0x78,0x65,0x6c,0x5f,0x79,0x29,0x20,0x2a,0x20,0x30,0x2e,0x35,0x3b,0x0a,0x20,0x20,
0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x34,0x34,0x20,0x3d,0x20,0x5f,0x32,
0x33,0x2e,0x78,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,
0x34,0x35,0x20,0x3d,0x20,0x2d,0x5f,0x34,0x34,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,
0x6c,0x6f,0x61,0x74,0x20,0x5f,0x34,0x38,0x20,0x3d,0x20,0x5f,0x32,0x33,0x2e,0x79,
0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x34,0x39,0x20,
0x3d,0x20,0x2d,0x5f,0x34,0x38,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,0x28,0x28,0x28,0x28,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,
0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x6d,0x61,0x6c,0x6c,0x2e,0x73,0x61,0x6d,
0x70,0x6c,0x65,0x28,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,0x61,0x6d,0x70,
0x6c,0x65,0x5f,0x73,0x6d,0x61,0x6c,0x6c,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x28,0x69,
0x6e,0x2e,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,0x2b,0x20,0x66,0x6c,0x6f,
0x61,0x74,0x32,0x28,0x5f,0x34,0x35,0x2c,0x20,0x5f,0x34,0x39,0x29,0x29,0x29,0x2e,
0x78,0x79,0x7a,0x20,0x2b,0x20,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,0x61,
0x6d,0x70,0x6c,0x65,0x5f,0x73,0x6d,0x61,0x6c,0x6c,0x2e,0x73,0x61,0x6d,0x70,0x6c,
0x65,0x28,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,
0x5f,0x73,0x6d,0x61,0x6c,0x6c,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x28,0x69,0x6e,0x2e,
0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,0x2b,0x20,0x66,0x6c,0x6f,0x61,0x74,
0x32,0x28,0x5f,0x34,0x34,0x2c,0x20,0x5f,0x34,0x39,0x29,0x29,0x29,0x2e,0x78,0x79,
0x7a,0x29,0x20,0x2b,0x20,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,0x61,0x6d,
0x70,0x6c,0x65,0x5f,0x73,0x6d,0x61,0x6c,0x6c,0x2e,0x73,0x61,0x6d,0x70,0x6c,0x65,
0x28,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,
0x73,0x6d,0x61,0x6c,0x6c,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x28,0x69,0x6e,0x2e,0x74,
0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,0x2b,0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,
0x28,0x5f,0x34,0x35,0x2c,0x20,0x5f,0x34,0x38,0x29,0x29,0x29,0x2e,0x78,0x79,0x7a,
0x29,0x20,0x2b,0x20,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,0x61,0x6d,0x70,
0x6c,0x65,0x5f,0x73,0x6d,0x61,0x6c,0x6c,0x2e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x28,
0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,
0x6d,0x61,0x6c,0x6c,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x28,0x69,0x6e,0x2e,0x74,0x65,
0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,0x2b,0x20,0x5f,0x32,0x33,0x29,0x29,0x2e,0x78,
0x79,0x7a,0x29,0x20,0x2a,0x20,0x30,0x2e,0x32,0x35,0x29,0x20,0x2b,0x20,0x62,0x6c,
0x6f,0x6f,0x6d,0x5f,0x75,0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x6c,0x61,0x72,
0x67,0x65,0x2e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x28,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,
0x75,0x70,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x6c,0x61,0x72,0x67,0x65,0x5f,0x73,
0x6d,0x70,0x2c,0x20,0x69,0x6e,0x2e,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x29,
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,
];
bloom_upsample_shader_desc :: (backend: sg_backend) -> sg_shader_desc {
desc: sg_shader_desc;
desc.label = "bloom_upsample_shader";
if backend == {
case .GLCORE;
desc.vertex_func.source = xx *vs_bloom_upsample_source_glsl430;
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_bloom_upsample_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 = "uv";
desc.uniform_blocks[0].stage = .FRAGMENT;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 16;
desc.uniform_blocks[0].glsl_uniforms[0].type = .FLOAT4;
desc.uniform_blocks[0].glsl_uniforms[0].array_count = 1;
desc.uniform_blocks[0].glsl_uniforms[0].glsl_name = "bloom_upsample_params";
desc.images[0].stage = .FRAGMENT;
desc.images[0].multisampled = false;
desc.images[0].image_type = ._2D;
desc.images[0].sample_type = .FLOAT;
desc.images[1].stage = .FRAGMENT;
desc.images[1].multisampled = false;
desc.images[1].image_type = ._2D;
desc.images[1].sample_type = .FLOAT;
desc.samplers[0].stage = .FRAGMENT;
desc.samplers[0].sampler_type = .FILTERING;
desc.samplers[1].stage = .FRAGMENT;
desc.samplers[1].sampler_type = .FILTERING;
desc.image_sampler_pairs[0].stage = .FRAGMENT;
desc.image_sampler_pairs[0].image_slot = 0;
desc.image_sampler_pairs[0].sampler_slot = 0;
desc.image_sampler_pairs[0].glsl_name = "bloom_upsample_small_bloom_upsample_small_smp";
desc.image_sampler_pairs[1].stage = .FRAGMENT;
desc.image_sampler_pairs[1].image_slot = 1;
desc.image_sampler_pairs[1].sampler_slot = 1;
desc.image_sampler_pairs[1].glsl_name = "bloom_upsample_large_bloom_upsample_large_smp";
case .GLES3;
desc.vertex_func.source = xx *vs_bloom_upsample_source_glsl300es;
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_bloom_upsample_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 = "uv";
desc.uniform_blocks[0].stage = .FRAGMENT;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 16;
desc.uniform_blocks[0].glsl_uniforms[0].type = .FLOAT4;
desc.uniform_blocks[0].glsl_uniforms[0].array_count = 1;
desc.uniform_blocks[0].glsl_uniforms[0].glsl_name = "bloom_upsample_params";
desc.images[0].stage = .FRAGMENT;
desc.images[0].multisampled = false;
desc.images[0].image_type = ._2D;
desc.images[0].sample_type = .FLOAT;
desc.images[1].stage = .FRAGMENT;
desc.images[1].multisampled = false;
desc.images[1].image_type = ._2D;
desc.images[1].sample_type = .FLOAT;
desc.samplers[0].stage = .FRAGMENT;
desc.samplers[0].sampler_type = .FILTERING;
desc.samplers[1].stage = .FRAGMENT;
desc.samplers[1].sampler_type = .FILTERING;
desc.image_sampler_pairs[0].stage = .FRAGMENT;
desc.image_sampler_pairs[0].image_slot = 0;
desc.image_sampler_pairs[0].sampler_slot = 0;
desc.image_sampler_pairs[0].glsl_name = "bloom_upsample_small_bloom_upsample_small_smp";
desc.image_sampler_pairs[1].stage = .FRAGMENT;
desc.image_sampler_pairs[1].image_slot = 1;
desc.image_sampler_pairs[1].sampler_slot = 1;
desc.image_sampler_pairs[1].glsl_name = "bloom_upsample_large_bloom_upsample_large_smp";
case .METAL_MACOS;
desc.vertex_func.source = xx *vs_bloom_upsample_source_metal_macos;
desc.vertex_func.entry = "main0";
desc.fragment_func.source = xx *fs_bloom_upsample_source_metal_macos;
desc.fragment_func.entry = "main0";
desc.attrs[0].base_type = .FLOAT;
desc.attrs[1].base_type = .FLOAT;
desc.uniform_blocks[0].stage = .FRAGMENT;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 16;
desc.uniform_blocks[0].msl_buffer_n = 0;
desc.images[0].stage = .FRAGMENT;
desc.images[0].multisampled = false;
desc.images[0].image_type = ._2D;
desc.images[0].sample_type = .FLOAT;
desc.images[0].msl_texture_n = 0;
desc.images[1].stage = .FRAGMENT;
desc.images[1].multisampled = false;
desc.images[1].image_type = ._2D;
desc.images[1].sample_type = .FLOAT;
desc.images[1].msl_texture_n = 1;
desc.samplers[0].stage = .FRAGMENT;
desc.samplers[0].sampler_type = .FILTERING;
desc.samplers[0].msl_sampler_n = 0;
desc.samplers[1].stage = .FRAGMENT;
desc.samplers[1].sampler_type = .FILTERING;
desc.samplers[1].msl_sampler_n = 1;
desc.image_sampler_pairs[0].stage = .FRAGMENT;
desc.image_sampler_pairs[0].image_slot = 0;
desc.image_sampler_pairs[0].sampler_slot = 0;
desc.image_sampler_pairs[1].stage = .FRAGMENT;
desc.image_sampler_pairs[1].image_slot = 1;
desc.image_sampler_pairs[1].sampler_slot = 1;
}
return desc;
}

View File

@ -1,538 +0,0 @@
/*
#version:1# (machine generated, don't edit!)
Generated by sokol-shdc (https://github.com/floooh/sokol-tools)
Cmdline:
sokol-shdc -i shader_debugline.glsl -o ./jai/shader_debugline.jai -l glsl430:glsl300es:metal_macos -f sokol_jai
Overview:
=========
Shader program: 'debugline':
Get shader desc: debugline_shader_desc(sg_query_backend())
Vertex Shader: vs_debugline
Fragment Shader: fs_debugline
Attributes:
ATTR_debugline_a_corner => 0
ATTR_debugline_a_pos_a => 1
ATTR_debugline_a_pos_b => 2
ATTR_debugline_a_col => 3
ATTR_debugline_a_width => 4
Bindings:
Uniform block 'debugline_vs_params':
Jai struct: Debugline_Vs_Params
Bind slot: UB_debugline_vs_params => 0
*/
ATTR_debugline_a_corner :: 0;
ATTR_debugline_a_pos_a :: 1;
ATTR_debugline_a_pos_b :: 2;
ATTR_debugline_a_col :: 3;
ATTR_debugline_a_width :: 4;
UB_debugline_vs_params :: 0;
Debugline_Vs_Params :: struct {
mvp: [16]float;
viewport: [4]float;
};
/*
#version 430
uniform vec4 debugline_vs_params[5];
layout(location = 1) in vec3 a_pos_a;
layout(location = 2) in vec3 a_pos_b;
layout(location = 0) in vec2 a_corner;
layout(location = 4) in float a_width;
layout(location = 0) out vec4 v_col;
layout(location = 3) in vec4 a_col;
void main()
{
mat4 _18 = mat4(debugline_vs_params[0], debugline_vs_params[1], debugline_vs_params[2], debugline_vs_params[3]);
vec4 _28 = _18 * vec4(a_pos_a, 1.0);
vec4 _38 = _18 * vec4(a_pos_b, 1.0);
vec2 _78 = ((_38.xy / vec2(max(_38.w, 9.9999997473787516355514526367188e-05))) * debugline_vs_params[4].xy) - ((_28.xy / vec2(max(_28.w, 9.9999997473787516355514526367188e-05))) * debugline_vs_params[4].xy);
float _81 = length(_78);
vec2 _86;
if (_81 > 9.9999997473787516355514526367188e-05)
{
_86 = _78 / vec2(_81);
}
else
{
_86 = vec2(1.0, 0.0);
}
vec4 _115 = mix(_28, _38, vec4(a_corner.y));
gl_Position = _115 + vec4((((vec2(-_86.y, _86.x) * a_corner.x) * ((a_width * 0.5) + 0.5)) / debugline_vs_params[4].xy) * _115.w, 0.0, 0.0);
v_col = a_col;
}
*/
vs_debugline_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,0x64,0x65,0x62,0x75,0x67,
0x6c,0x69,0x6e,0x65,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x35,
0x5d,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,0x33,0x20,
0x61,0x5f,0x70,0x6f,0x73,0x5f,0x61,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,0x33,0x20,0x61,0x5f,0x70,0x6f,0x73,0x5f,0x62,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,0x32,0x20,0x61,0x5f,0x63,0x6f,
0x72,0x6e,0x65,0x72,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,
0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x34,0x29,0x20,0x69,0x6e,0x20,0x66,0x6c,
0x6f,0x61,0x74,0x20,0x61,0x5f,0x77,0x69,0x64,0x74,0x68,0x3b,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,0x76,0x5f,0x63,0x6f,0x6c,
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,0x61,
0x5f,0x63,0x6f,0x6c,0x3b,0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,
0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x6d,0x61,0x74,0x34,0x20,0x5f,0x31,
0x38,0x20,0x3d,0x20,0x6d,0x61,0x74,0x34,0x28,0x64,0x65,0x62,0x75,0x67,0x6c,0x69,
0x6e,0x65,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d,0x2c,
0x20,0x64,0x65,0x62,0x75,0x67,0x6c,0x69,0x6e,0x65,0x5f,0x76,0x73,0x5f,0x70,0x61,
0x72,0x61,0x6d,0x73,0x5b,0x31,0x5d,0x2c,0x20,0x64,0x65,0x62,0x75,0x67,0x6c,0x69,
0x6e,0x65,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x32,0x5d,0x2c,
0x20,0x64,0x65,0x62,0x75,0x67,0x6c,0x69,0x6e,0x65,0x5f,0x76,0x73,0x5f,0x70,0x61,
0x72,0x61,0x6d,0x73,0x5b,0x33,0x5d,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,
0x63,0x34,0x20,0x5f,0x32,0x38,0x20,0x3d,0x20,0x5f,0x31,0x38,0x20,0x2a,0x20,0x76,
0x65,0x63,0x34,0x28,0x61,0x5f,0x70,0x6f,0x73,0x5f,0x61,0x2c,0x20,0x31,0x2e,0x30,
0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x34,0x20,0x5f,0x33,0x38,0x20,
0x3d,0x20,0x5f,0x31,0x38,0x20,0x2a,0x20,0x76,0x65,0x63,0x34,0x28,0x61,0x5f,0x70,
0x6f,0x73,0x5f,0x62,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,
0x76,0x65,0x63,0x32,0x20,0x5f,0x37,0x38,0x20,0x3d,0x20,0x28,0x28,0x5f,0x33,0x38,
0x2e,0x78,0x79,0x20,0x2f,0x20,0x76,0x65,0x63,0x32,0x28,0x6d,0x61,0x78,0x28,0x5f,
0x33,0x38,0x2e,0x77,0x2c,0x20,0x39,0x2e,0x39,0x39,0x39,0x39,0x39,0x39,0x37,0x34,
0x37,0x33,0x37,0x38,0x37,0x35,0x31,0x36,0x33,0x35,0x35,0x35,0x31,0x34,0x35,0x32,
0x36,0x33,0x36,0x37,0x31,0x38,0x38,0x65,0x2d,0x30,0x35,0x29,0x29,0x29,0x20,0x2a,
0x20,0x64,0x65,0x62,0x75,0x67,0x6c,0x69,0x6e,0x65,0x5f,0x76,0x73,0x5f,0x70,0x61,
0x72,0x61,0x6d,0x73,0x5b,0x34,0x5d,0x2e,0x78,0x79,0x29,0x20,0x2d,0x20,0x28,0x28,
0x5f,0x32,0x38,0x2e,0x78,0x79,0x20,0x2f,0x20,0x76,0x65,0x63,0x32,0x28,0x6d,0x61,
0x78,0x28,0x5f,0x32,0x38,0x2e,0x77,0x2c,0x20,0x39,0x2e,0x39,0x39,0x39,0x39,0x39,
0x39,0x37,0x34,0x37,0x33,0x37,0x38,0x37,0x35,0x31,0x36,0x33,0x35,0x35,0x35,0x31,
0x34,0x35,0x32,0x36,0x33,0x36,0x37,0x31,0x38,0x38,0x65,0x2d,0x30,0x35,0x29,0x29,
0x29,0x20,0x2a,0x20,0x64,0x65,0x62,0x75,0x67,0x6c,0x69,0x6e,0x65,0x5f,0x76,0x73,
0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x34,0x5d,0x2e,0x78,0x79,0x29,0x3b,0x0a,
0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x38,0x31,0x20,0x3d,0x20,
0x6c,0x65,0x6e,0x67,0x74,0x68,0x28,0x5f,0x37,0x38,0x29,0x3b,0x0a,0x20,0x20,0x20,
0x20,0x76,0x65,0x63,0x32,0x20,0x5f,0x38,0x36,0x3b,0x0a,0x20,0x20,0x20,0x20,0x69,
0x66,0x20,0x28,0x5f,0x38,0x31,0x20,0x3e,0x20,0x39,0x2e,0x39,0x39,0x39,0x39,0x39,
0x39,0x37,0x34,0x37,0x33,0x37,0x38,0x37,0x35,0x31,0x36,0x33,0x35,0x35,0x35,0x31,
0x34,0x35,0x32,0x36,0x33,0x36,0x37,0x31,0x38,0x38,0x65,0x2d,0x30,0x35,0x29,0x0a,
0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x5f,0x38,
0x36,0x20,0x3d,0x20,0x5f,0x37,0x38,0x20,0x2f,0x20,0x76,0x65,0x63,0x32,0x28,0x5f,
0x38,0x31,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,0x5f,0x38,0x36,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x31,0x2e,0x30,
0x2c,0x20,0x30,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,
0x20,0x20,0x76,0x65,0x63,0x34,0x20,0x5f,0x31,0x31,0x35,0x20,0x3d,0x20,0x6d,0x69,
0x78,0x28,0x5f,0x32,0x38,0x2c,0x20,0x5f,0x33,0x38,0x2c,0x20,0x76,0x65,0x63,0x34,
0x28,0x61,0x5f,0x63,0x6f,0x72,0x6e,0x65,0x72,0x2e,0x79,0x29,0x29,0x3b,0x0a,0x20,
0x20,0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,
0x20,0x5f,0x31,0x31,0x35,0x20,0x2b,0x20,0x76,0x65,0x63,0x34,0x28,0x28,0x28,0x28,
0x76,0x65,0x63,0x32,0x28,0x2d,0x5f,0x38,0x36,0x2e,0x79,0x2c,0x20,0x5f,0x38,0x36,
0x2e,0x78,0x29,0x20,0x2a,0x20,0x61,0x5f,0x63,0x6f,0x72,0x6e,0x65,0x72,0x2e,0x78,
0x29,0x20,0x2a,0x20,0x28,0x28,0x61,0x5f,0x77,0x69,0x64,0x74,0x68,0x20,0x2a,0x20,
0x30,0x2e,0x35,0x29,0x20,0x2b,0x20,0x30,0x2e,0x35,0x29,0x29,0x20,0x2f,0x20,0x64,
0x65,0x62,0x75,0x67,0x6c,0x69,0x6e,0x65,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,
0x6d,0x73,0x5b,0x34,0x5d,0x2e,0x78,0x79,0x29,0x20,0x2a,0x20,0x5f,0x31,0x31,0x35,
0x2e,0x77,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x29,0x3b,0x0a,0x20,
0x20,0x20,0x20,0x76,0x5f,0x63,0x6f,0x6c,0x20,0x3d,0x20,0x61,0x5f,0x63,0x6f,0x6c,
0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#version 430
layout(location = 0) out vec4 frag_color;
layout(location = 0) in vec4 v_col;
void main()
{
frag_color = v_col;
}
*/
fs_debugline_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,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,0x76,0x5f,0x63,0x6f,0x6c,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,0x5f,0x63,0x6f,
0x6c,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#version 300 es
uniform vec4 debugline_vs_params[5];
layout(location = 1) in vec3 a_pos_a;
layout(location = 2) in vec3 a_pos_b;
layout(location = 0) in vec2 a_corner;
layout(location = 4) in float a_width;
out vec4 v_col;
layout(location = 3) in vec4 a_col;
void main()
{
mat4 _18 = mat4(debugline_vs_params[0], debugline_vs_params[1], debugline_vs_params[2], debugline_vs_params[3]);
vec4 _28 = _18 * vec4(a_pos_a, 1.0);
vec4 _38 = _18 * vec4(a_pos_b, 1.0);
vec2 _78 = ((_38.xy / vec2(max(_38.w, 9.9999997473787516355514526367188e-05))) * debugline_vs_params[4].xy) - ((_28.xy / vec2(max(_28.w, 9.9999997473787516355514526367188e-05))) * debugline_vs_params[4].xy);
float _81 = length(_78);
vec2 _86;
if (_81 > 9.9999997473787516355514526367188e-05)
{
_86 = _78 / vec2(_81);
}
else
{
_86 = vec2(1.0, 0.0);
}
vec4 _115 = mix(_28, _38, vec4(a_corner.y));
gl_Position = _115 + vec4((((vec2(-_86.y, _86.x) * a_corner.x) * ((a_width * 0.5) + 0.5)) / debugline_vs_params[4].xy) * _115.w, 0.0, 0.0);
v_col = a_col;
}
*/
vs_debugline_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,0x64,0x65,
0x62,0x75,0x67,0x6c,0x69,0x6e,0x65,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,
0x73,0x5b,0x35,0x5d,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,0x33,0x20,0x61,0x5f,0x70,0x6f,0x73,0x5f,0x61,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,0x33,0x20,0x61,0x5f,0x70,0x6f,0x73,0x5f,0x62,
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,0x32,0x20,0x61,
0x5f,0x63,0x6f,0x72,0x6e,0x65,0x72,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,
0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x34,0x29,0x20,0x69,0x6e,
0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x61,0x5f,0x77,0x69,0x64,0x74,0x68,0x3b,0x0a,
0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x34,0x20,0x76,0x5f,0x63,0x6f,0x6c,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,0x61,0x5f,0x63,
0x6f,0x6c,0x3b,0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,
0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x6d,0x61,0x74,0x34,0x20,0x5f,0x31,0x38,0x20,
0x3d,0x20,0x6d,0x61,0x74,0x34,0x28,0x64,0x65,0x62,0x75,0x67,0x6c,0x69,0x6e,0x65,
0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d,0x2c,0x20,0x64,
0x65,0x62,0x75,0x67,0x6c,0x69,0x6e,0x65,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,
0x6d,0x73,0x5b,0x31,0x5d,0x2c,0x20,0x64,0x65,0x62,0x75,0x67,0x6c,0x69,0x6e,0x65,
0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x32,0x5d,0x2c,0x20,0x64,
0x65,0x62,0x75,0x67,0x6c,0x69,0x6e,0x65,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,
0x6d,0x73,0x5b,0x33,0x5d,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x34,
0x20,0x5f,0x32,0x38,0x20,0x3d,0x20,0x5f,0x31,0x38,0x20,0x2a,0x20,0x76,0x65,0x63,
0x34,0x28,0x61,0x5f,0x70,0x6f,0x73,0x5f,0x61,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,
0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x34,0x20,0x5f,0x33,0x38,0x20,0x3d,0x20,
0x5f,0x31,0x38,0x20,0x2a,0x20,0x76,0x65,0x63,0x34,0x28,0x61,0x5f,0x70,0x6f,0x73,
0x5f,0x62,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,
0x63,0x32,0x20,0x5f,0x37,0x38,0x20,0x3d,0x20,0x28,0x28,0x5f,0x33,0x38,0x2e,0x78,
0x79,0x20,0x2f,0x20,0x76,0x65,0x63,0x32,0x28,0x6d,0x61,0x78,0x28,0x5f,0x33,0x38,
0x2e,0x77,0x2c,0x20,0x39,0x2e,0x39,0x39,0x39,0x39,0x39,0x39,0x37,0x34,0x37,0x33,
0x37,0x38,0x37,0x35,0x31,0x36,0x33,0x35,0x35,0x35,0x31,0x34,0x35,0x32,0x36,0x33,
0x36,0x37,0x31,0x38,0x38,0x65,0x2d,0x30,0x35,0x29,0x29,0x29,0x20,0x2a,0x20,0x64,
0x65,0x62,0x75,0x67,0x6c,0x69,0x6e,0x65,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,
0x6d,0x73,0x5b,0x34,0x5d,0x2e,0x78,0x79,0x29,0x20,0x2d,0x20,0x28,0x28,0x5f,0x32,
0x38,0x2e,0x78,0x79,0x20,0x2f,0x20,0x76,0x65,0x63,0x32,0x28,0x6d,0x61,0x78,0x28,
0x5f,0x32,0x38,0x2e,0x77,0x2c,0x20,0x39,0x2e,0x39,0x39,0x39,0x39,0x39,0x39,0x37,
0x34,0x37,0x33,0x37,0x38,0x37,0x35,0x31,0x36,0x33,0x35,0x35,0x35,0x31,0x34,0x35,
0x32,0x36,0x33,0x36,0x37,0x31,0x38,0x38,0x65,0x2d,0x30,0x35,0x29,0x29,0x29,0x20,
0x2a,0x20,0x64,0x65,0x62,0x75,0x67,0x6c,0x69,0x6e,0x65,0x5f,0x76,0x73,0x5f,0x70,
0x61,0x72,0x61,0x6d,0x73,0x5b,0x34,0x5d,0x2e,0x78,0x79,0x29,0x3b,0x0a,0x20,0x20,
0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x38,0x31,0x20,0x3d,0x20,0x6c,0x65,
0x6e,0x67,0x74,0x68,0x28,0x5f,0x37,0x38,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,
0x65,0x63,0x32,0x20,0x5f,0x38,0x36,0x3b,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,
0x28,0x5f,0x38,0x31,0x20,0x3e,0x20,0x39,0x2e,0x39,0x39,0x39,0x39,0x39,0x39,0x37,
0x34,0x37,0x33,0x37,0x38,0x37,0x35,0x31,0x36,0x33,0x35,0x35,0x35,0x31,0x34,0x35,
0x32,0x36,0x33,0x36,0x37,0x31,0x38,0x38,0x65,0x2d,0x30,0x35,0x29,0x0a,0x20,0x20,
0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x5f,0x38,0x36,0x20,
0x3d,0x20,0x5f,0x37,0x38,0x20,0x2f,0x20,0x76,0x65,0x63,0x32,0x28,0x5f,0x38,0x31,
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,
0x5f,0x38,0x36,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x31,0x2e,0x30,0x2c,0x20,
0x30,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,
0x76,0x65,0x63,0x34,0x20,0x5f,0x31,0x31,0x35,0x20,0x3d,0x20,0x6d,0x69,0x78,0x28,
0x5f,0x32,0x38,0x2c,0x20,0x5f,0x33,0x38,0x2c,0x20,0x76,0x65,0x63,0x34,0x28,0x61,
0x5f,0x63,0x6f,0x72,0x6e,0x65,0x72,0x2e,0x79,0x29,0x29,0x3b,0x0a,0x20,0x20,0x20,
0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x5f,
0x31,0x31,0x35,0x20,0x2b,0x20,0x76,0x65,0x63,0x34,0x28,0x28,0x28,0x28,0x76,0x65,
0x63,0x32,0x28,0x2d,0x5f,0x38,0x36,0x2e,0x79,0x2c,0x20,0x5f,0x38,0x36,0x2e,0x78,
0x29,0x20,0x2a,0x20,0x61,0x5f,0x63,0x6f,0x72,0x6e,0x65,0x72,0x2e,0x78,0x29,0x20,
0x2a,0x20,0x28,0x28,0x61,0x5f,0x77,0x69,0x64,0x74,0x68,0x20,0x2a,0x20,0x30,0x2e,
0x35,0x29,0x20,0x2b,0x20,0x30,0x2e,0x35,0x29,0x29,0x20,0x2f,0x20,0x64,0x65,0x62,
0x75,0x67,0x6c,0x69,0x6e,0x65,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,
0x5b,0x34,0x5d,0x2e,0x78,0x79,0x29,0x20,0x2a,0x20,0x5f,0x31,0x31,0x35,0x2e,0x77,
0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,
0x20,0x76,0x5f,0x63,0x6f,0x6c,0x20,0x3d,0x20,0x61,0x5f,0x63,0x6f,0x6c,0x3b,0x0a,
0x7d,0x0a,0x0a,0x00,
];
/*
#version 300 es
precision mediump float;
precision highp int;
layout(location = 0) out highp vec4 frag_color;
in highp vec4 v_col;
void main()
{
frag_color = v_col;
}
*/
fs_debugline_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,0x69,
0x6e,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x76,0x65,0x63,0x34,0x20,0x76,0x5f,0x63,
0x6f,0x6c,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,0x5f,0x63,0x6f,0x6c,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct debugline_vs_params
{
float4x4 mvp;
float4 viewport;
};
struct main0_out
{
float4 v_col [[user(locn0)]];
float4 gl_Position [[position]];
};
struct main0_in
{
float2 a_corner [[attribute(0)]];
float3 a_pos_a [[attribute(1)]];
float3 a_pos_b [[attribute(2)]];
float4 a_col [[attribute(3)]];
float a_width [[attribute(4)]];
};
vertex main0_out main0(main0_in in [[stage_in]], constant debugline_vs_params& _13 [[buffer(0)]])
{
main0_out out = {};
float4 _28 = _13.mvp * float4(in.a_pos_a, 1.0);
float4 _38 = _13.mvp * float4(in.a_pos_b, 1.0);
float2 _78 = ((_38.xy / float2(fast::max(_38.w, 9.9999997473787516355514526367188e-05))) * _13.viewport.xy) - ((_28.xy / float2(fast::max(_28.w, 9.9999997473787516355514526367188e-05))) * _13.viewport.xy);
float _81 = length(_78);
float2 _86;
if (_81 > 9.9999997473787516355514526367188e-05)
{
_86 = _78 / float2(_81);
}
else
{
_86 = float2(1.0, 0.0);
}
float4 _115 = mix(_28, _38, float4(in.a_corner.y));
out.gl_Position = _115 + float4((((float2(-_86.y, _86.x) * in.a_corner.x) * ((in.a_width * 0.5) + 0.5)) / _13.viewport.xy) * _115.w, 0.0, 0.0);
out.v_col = in.a_col;
return out;
}
*/
vs_debugline_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,0x64,
0x65,0x62,0x75,0x67,0x6c,0x69,0x6e,0x65,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,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,
0x34,0x20,0x76,0x69,0x65,0x77,0x70,0x6f,0x72,0x74,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,0x76,0x5f,
0x63,0x6f,0x6c,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,0x30,
0x29,0x5d,0x5d,0x3b,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,0x32,0x20,0x61,0x5f,0x63,0x6f,0x72,
0x6e,0x65,0x72,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,0x33,
0x20,0x61,0x5f,0x70,0x6f,0x73,0x5f,0x61,0x20,0x5b,0x5b,0x61,0x74,0x74,0x72,0x69,
0x62,0x75,0x74,0x65,0x28,0x31,0x29,0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,
0x6c,0x6f,0x61,0x74,0x33,0x20,0x61,0x5f,0x70,0x6f,0x73,0x5f,0x62,0x20,0x5b,0x5b,
0x61,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x28,0x32,0x29,0x5d,0x5d,0x3b,0x0a,
0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x61,0x5f,0x63,0x6f,0x6c,
0x20,0x5b,0x5b,0x61,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x28,0x33,0x29,0x5d,
0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x61,0x5f,0x77,
0x69,0x64,0x74,0x68,0x20,0x5b,0x5b,0x61,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,
0x28,0x34,0x29,0x5d,0x5d,0x3b,0x0a,0x7d,0x3b,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,0x64,0x65,0x62,0x75,0x67,0x6c,0x69,0x6e,0x65,0x5f,0x76,
0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x26,0x20,0x5f,0x31,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,0x66,0x6c,0x6f,0x61,0x74,
0x34,0x20,0x5f,0x32,0x38,0x20,0x3d,0x20,0x5f,0x31,0x33,0x2e,0x6d,0x76,0x70,0x20,
0x2a,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x28,0x69,0x6e,0x2e,0x61,0x5f,0x70,0x6f,
0x73,0x5f,0x61,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,
0x6c,0x6f,0x61,0x74,0x34,0x20,0x5f,0x33,0x38,0x20,0x3d,0x20,0x5f,0x31,0x33,0x2e,
0x6d,0x76,0x70,0x20,0x2a,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x28,0x69,0x6e,0x2e,
0x61,0x5f,0x70,0x6f,0x73,0x5f,0x62,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,
0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,0x20,0x5f,0x37,0x38,0x20,0x3d,0x20,
0x28,0x28,0x5f,0x33,0x38,0x2e,0x78,0x79,0x20,0x2f,0x20,0x66,0x6c,0x6f,0x61,0x74,
0x32,0x28,0x66,0x61,0x73,0x74,0x3a,0x3a,0x6d,0x61,0x78,0x28,0x5f,0x33,0x38,0x2e,
0x77,0x2c,0x20,0x39,0x2e,0x39,0x39,0x39,0x39,0x39,0x39,0x37,0x34,0x37,0x33,0x37,
0x38,0x37,0x35,0x31,0x36,0x33,0x35,0x35,0x35,0x31,0x34,0x35,0x32,0x36,0x33,0x36,
0x37,0x31,0x38,0x38,0x65,0x2d,0x30,0x35,0x29,0x29,0x29,0x20,0x2a,0x20,0x5f,0x31,
0x33,0x2e,0x76,0x69,0x65,0x77,0x70,0x6f,0x72,0x74,0x2e,0x78,0x79,0x29,0x20,0x2d,
0x20,0x28,0x28,0x5f,0x32,0x38,0x2e,0x78,0x79,0x20,0x2f,0x20,0x66,0x6c,0x6f,0x61,
0x74,0x32,0x28,0x66,0x61,0x73,0x74,0x3a,0x3a,0x6d,0x61,0x78,0x28,0x5f,0x32,0x38,
0x2e,0x77,0x2c,0x20,0x39,0x2e,0x39,0x39,0x39,0x39,0x39,0x39,0x37,0x34,0x37,0x33,
0x37,0x38,0x37,0x35,0x31,0x36,0x33,0x35,0x35,0x35,0x31,0x34,0x35,0x32,0x36,0x33,
0x36,0x37,0x31,0x38,0x38,0x65,0x2d,0x30,0x35,0x29,0x29,0x29,0x20,0x2a,0x20,0x5f,
0x31,0x33,0x2e,0x76,0x69,0x65,0x77,0x70,0x6f,0x72,0x74,0x2e,0x78,0x79,0x29,0x3b,
0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x38,0x31,0x20,0x3d,
0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x28,0x5f,0x37,0x38,0x29,0x3b,0x0a,0x20,0x20,
0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,0x20,0x5f,0x38,0x36,0x3b,0x0a,0x20,0x20,
0x20,0x20,0x69,0x66,0x20,0x28,0x5f,0x38,0x31,0x20,0x3e,0x20,0x39,0x2e,0x39,0x39,
0x39,0x39,0x39,0x39,0x37,0x34,0x37,0x33,0x37,0x38,0x37,0x35,0x31,0x36,0x33,0x35,
0x35,0x35,0x31,0x34,0x35,0x32,0x36,0x33,0x36,0x37,0x31,0x38,0x38,0x65,0x2d,0x30,
0x35,0x29,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x5f,0x38,0x36,0x20,0x3d,0x20,0x5f,0x37,0x38,0x20,0x2f,0x20,0x66,0x6c,0x6f,
0x61,0x74,0x32,0x28,0x5f,0x38,0x31,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,0x5f,0x38,0x36,0x20,0x3d,0x20,0x66,0x6c,0x6f,
0x61,0x74,0x32,0x28,0x31,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x29,0x3b,0x0a,0x20,
0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,
0x5f,0x31,0x31,0x35,0x20,0x3d,0x20,0x6d,0x69,0x78,0x28,0x5f,0x32,0x38,0x2c,0x20,
0x5f,0x33,0x38,0x2c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x28,0x69,0x6e,0x2e,0x61,
0x5f,0x63,0x6f,0x72,0x6e,0x65,0x72,0x2e,0x79,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,0x31,0x35,0x20,0x2b,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,
0x28,0x28,0x28,0x28,0x66,0x6c,0x6f,0x61,0x74,0x32,0x28,0x2d,0x5f,0x38,0x36,0x2e,
0x79,0x2c,0x20,0x5f,0x38,0x36,0x2e,0x78,0x29,0x20,0x2a,0x20,0x69,0x6e,0x2e,0x61,
0x5f,0x63,0x6f,0x72,0x6e,0x65,0x72,0x2e,0x78,0x29,0x20,0x2a,0x20,0x28,0x28,0x69,
0x6e,0x2e,0x61,0x5f,0x77,0x69,0x64,0x74,0x68,0x20,0x2a,0x20,0x30,0x2e,0x35,0x29,
0x20,0x2b,0x20,0x30,0x2e,0x35,0x29,0x29,0x20,0x2f,0x20,0x5f,0x31,0x33,0x2e,0x76,
0x69,0x65,0x77,0x70,0x6f,0x72,0x74,0x2e,0x78,0x79,0x29,0x20,0x2a,0x20,0x5f,0x31,
0x31,0x35,0x2e,0x77,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x29,0x3b,
0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,0x76,0x5f,0x63,0x6f,0x6c,0x20,0x3d,
0x20,0x69,0x6e,0x2e,0x61,0x5f,0x63,0x6f,0x6c,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)]];
};
struct main0_in
{
float4 v_col [[user(locn0)]];
};
fragment main0_out main0(main0_in in [[stage_in]])
{
main0_out out = {};
out.frag_color = in.v_col;
return out;
}
*/
fs_debugline_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,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,
0x76,0x5f,0x63,0x6f,0x6c,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,
0x6e,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,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x69,0x6e,0x20,0x69,0x6e,0x20,
0x5b,0x5b,0x73,0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,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,0x6f,0x75,0x74,0x2e,
0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x69,0x6e,0x2e,
0x76,0x5f,0x63,0x6f,0x6c,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,
0x6e,0x20,0x6f,0x75,0x74,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
debugline_shader_desc :: (backend: sg_backend) -> sg_shader_desc {
desc: sg_shader_desc;
desc.label = "debugline_shader";
if backend == {
case .GLCORE;
desc.vertex_func.source = xx *vs_debugline_source_glsl430;
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_debugline_source_glsl430;
desc.fragment_func.entry = "main";
desc.attrs[0].base_type = .FLOAT;
desc.attrs[0].glsl_name = "a_corner";
desc.attrs[1].base_type = .FLOAT;
desc.attrs[1].glsl_name = "a_pos_a";
desc.attrs[2].base_type = .FLOAT;
desc.attrs[2].glsl_name = "a_pos_b";
desc.attrs[3].base_type = .FLOAT;
desc.attrs[3].glsl_name = "a_col";
desc.attrs[4].base_type = .FLOAT;
desc.attrs[4].glsl_name = "a_width";
desc.uniform_blocks[0].stage = .VERTEX;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 80;
desc.uniform_blocks[0].glsl_uniforms[0].type = .FLOAT4;
desc.uniform_blocks[0].glsl_uniforms[0].array_count = 5;
desc.uniform_blocks[0].glsl_uniforms[0].glsl_name = "debugline_vs_params";
case .GLES3;
desc.vertex_func.source = xx *vs_debugline_source_glsl300es;
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_debugline_source_glsl300es;
desc.fragment_func.entry = "main";
desc.attrs[0].base_type = .FLOAT;
desc.attrs[0].glsl_name = "a_corner";
desc.attrs[1].base_type = .FLOAT;
desc.attrs[1].glsl_name = "a_pos_a";
desc.attrs[2].base_type = .FLOAT;
desc.attrs[2].glsl_name = "a_pos_b";
desc.attrs[3].base_type = .FLOAT;
desc.attrs[3].glsl_name = "a_col";
desc.attrs[4].base_type = .FLOAT;
desc.attrs[4].glsl_name = "a_width";
desc.uniform_blocks[0].stage = .VERTEX;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 80;
desc.uniform_blocks[0].glsl_uniforms[0].type = .FLOAT4;
desc.uniform_blocks[0].glsl_uniforms[0].array_count = 5;
desc.uniform_blocks[0].glsl_uniforms[0].glsl_name = "debugline_vs_params";
case .METAL_MACOS;
desc.vertex_func.source = xx *vs_debugline_source_metal_macos;
desc.vertex_func.entry = "main0";
desc.fragment_func.source = xx *fs_debugline_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.attrs[4].base_type = .FLOAT;
desc.uniform_blocks[0].stage = .VERTEX;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 80;
desc.uniform_blocks[0].msl_buffer_n = 0;
}
return desc;
}

View File

@ -1,566 +0,0 @@
/*
#version:1# (machine generated, don't edit!)
Generated by sokol-shdc (https://github.com/floooh/sokol-tools)
Cmdline:
sokol-shdc -i shader_dof_blur.glsl -o ./jai/shader_dof_blur.jai -l glsl430:glsl300es:metal_macos -f sokol_jai
Overview:
=========
Shader program: 'dof_blur':
Get shader desc: dof_blur_shader_desc(sg_query_backend())
Vertex Shader: vs_dof_blur
Fragment Shader: fs_dof_blur
Attributes:
ATTR_dof_blur_position => 0
ATTR_dof_blur_uv => 1
Bindings:
Uniform block 'dof_blur_params':
Jai struct: Dof_Blur_Params
Bind slot: UB_dof_blur_params => 0
Image 'dof_blur_src':
Image type: ._2D
Sample type: .FLOAT
Multisampled: false
Bind slot: IMG_dof_blur_src => 0
Sampler 'dof_blur_src_smp':
Type: .FILTERING
Bind slot: SMP_dof_blur_src_smp => 0
*/
ATTR_dof_blur_position :: 0;
ATTR_dof_blur_uv :: 1;
UB_dof_blur_params :: 0;
IMG_dof_blur_src :: 0;
SMP_dof_blur_src_smp :: 0;
Dof_Blur_Params :: struct {
bokeh_radius_x: float;
bokeh_radius_y: float;
_: [8]u8;
};
/*
#version 430
layout(location = 0) in vec2 position;
layout(location = 0) out vec2 texcoord;
layout(location = 1) in vec2 uv;
void main()
{
gl_Position = vec4(position, 0.5, 1.0);
texcoord = uv;
}
*/
vs_dof_blur_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,0x69,0x6e,0x20,0x76,0x65,0x63,0x32,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,0x30,0x29,0x20,0x6f,0x75,0x74,0x20,0x76,0x65,
0x63,0x32,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,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,0x32,0x20,0x75,0x76,0x3b,0x0a,0x0a,0x76,
0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,
0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x76,
0x65,0x63,0x34,0x28,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x30,0x2e,
0x35,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x74,0x65,0x78,
0x63,0x6f,0x6f,0x72,0x64,0x20,0x3d,0x20,0x75,0x76,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#version 430
uniform vec4 dof_blur_params[1];
layout(binding = 16) uniform sampler2D dof_blur_src_dof_blur_src_smp;
layout(location = 0) in vec2 texcoord;
layout(location = 0) out vec4 frag_color;
void main()
{
vec4 _24 = texture(dof_blur_src_dof_blur_src_smp, texcoord);
vec4 best = _24;
float best_lum = dot(_24.xyz, vec3(0.2125999927520751953125, 0.715200006961822509765625, 0.072200000286102294921875));
for (int i = 0; i < 32; i++)
{
float _50 = float(i);
float _52 = _50 * 2.3999631404876708984375;
vec4 _88 = texture(dof_blur_src_dof_blur_src_smp, texcoord + ((vec2(cos(_52), sin(_52)) * sqrt((_50 * 0.0322580635547637939453125) + 0.001000000047497451305389404296875)) * vec2(dof_blur_params[0].x, dof_blur_params[0].y)));
float _92 = dot(_88.xyz, vec3(0.2125999927520751953125, 0.715200006961822509765625, 0.072200000286102294921875));
if (_92 > best_lum)
{
best = _88;
best_lum = _92;
}
}
frag_color = best;
}
*/
fs_dof_blur_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,0x64,0x6f,0x66,0x5f,0x62,
0x6c,0x75,0x72,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x31,0x5d,0x3b,0x0a,0x6c,
0x61,0x79,0x6f,0x75,0x74,0x28,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x20,0x3d,0x20,
0x31,0x36,0x29,0x20,0x75,0x6e,0x69,0x66,0x6f,0x72,0x6d,0x20,0x73,0x61,0x6d,0x70,
0x6c,0x65,0x72,0x32,0x44,0x20,0x64,0x6f,0x66,0x5f,0x62,0x6c,0x75,0x72,0x5f,0x73,
0x72,0x63,0x5f,0x64,0x6f,0x66,0x5f,0x62,0x6c,0x75,0x72,0x5f,0x73,0x72,0x63,0x5f,
0x73,0x6d,0x70,0x3b,0x0a,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,0x32,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x3b,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,0x76,0x65,0x63,0x34,0x20,0x5f,
0x32,0x34,0x20,0x3d,0x20,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x64,0x6f,0x66,
0x5f,0x62,0x6c,0x75,0x72,0x5f,0x73,0x72,0x63,0x5f,0x64,0x6f,0x66,0x5f,0x62,0x6c,
0x75,0x72,0x5f,0x73,0x72,0x63,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x74,0x65,0x78,0x63,
0x6f,0x6f,0x72,0x64,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x34,0x20,
0x62,0x65,0x73,0x74,0x20,0x3d,0x20,0x5f,0x32,0x34,0x3b,0x0a,0x20,0x20,0x20,0x20,
0x66,0x6c,0x6f,0x61,0x74,0x20,0x62,0x65,0x73,0x74,0x5f,0x6c,0x75,0x6d,0x20,0x3d,
0x20,0x64,0x6f,0x74,0x28,0x5f,0x32,0x34,0x2e,0x78,0x79,0x7a,0x2c,0x20,0x76,0x65,
0x63,0x33,0x28,0x30,0x2e,0x32,0x31,0x32,0x35,0x39,0x39,0x39,0x39,0x32,0x37,0x35,
0x32,0x30,0x37,0x35,0x31,0x39,0x35,0x33,0x31,0x32,0x35,0x2c,0x20,0x30,0x2e,0x37,
0x31,0x35,0x32,0x30,0x30,0x30,0x30,0x36,0x39,0x36,0x31,0x38,0x32,0x32,0x35,0x30,
0x39,0x37,0x36,0x35,0x36,0x32,0x35,0x2c,0x20,0x30,0x2e,0x30,0x37,0x32,0x32,0x30,
0x30,0x30,0x30,0x30,0x32,0x38,0x36,0x31,0x30,0x32,0x32,0x39,0x34,0x39,0x32,0x31,
0x38,0x37,0x35,0x29,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6f,0x72,0x20,0x28,
0x69,0x6e,0x74,0x20,0x69,0x20,0x3d,0x20,0x30,0x3b,0x20,0x69,0x20,0x3c,0x20,0x33,
0x32,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x35,0x30,0x20,
0x3d,0x20,0x66,0x6c,0x6f,0x61,0x74,0x28,0x69,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x35,0x32,0x20,0x3d,0x20,
0x5f,0x35,0x30,0x20,0x2a,0x20,0x32,0x2e,0x33,0x39,0x39,0x39,0x36,0x33,0x31,0x34,
0x30,0x34,0x38,0x37,0x36,0x37,0x30,0x38,0x39,0x38,0x34,0x33,0x37,0x35,0x3b,0x0a,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x34,0x20,0x5f,0x38,0x38,
0x20,0x3d,0x20,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x64,0x6f,0x66,0x5f,0x62,
0x6c,0x75,0x72,0x5f,0x73,0x72,0x63,0x5f,0x64,0x6f,0x66,0x5f,0x62,0x6c,0x75,0x72,
0x5f,0x73,0x72,0x63,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,
0x72,0x64,0x20,0x2b,0x20,0x28,0x28,0x76,0x65,0x63,0x32,0x28,0x63,0x6f,0x73,0x28,
0x5f,0x35,0x32,0x29,0x2c,0x20,0x73,0x69,0x6e,0x28,0x5f,0x35,0x32,0x29,0x29,0x20,
0x2a,0x20,0x73,0x71,0x72,0x74,0x28,0x28,0x5f,0x35,0x30,0x20,0x2a,0x20,0x30,0x2e,
0x30,0x33,0x32,0x32,0x35,0x38,0x30,0x36,0x33,0x35,0x35,0x34,0x37,0x36,0x33,0x37,
0x39,0x33,0x39,0x34,0x35,0x33,0x31,0x32,0x35,0x29,0x20,0x2b,0x20,0x30,0x2e,0x30,
0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x34,0x37,0x34,0x39,0x37,0x34,0x35,
0x31,0x33,0x30,0x35,0x33,0x38,0x39,0x34,0x30,0x34,0x32,0x39,0x36,0x38,0x37,0x35,
0x29,0x29,0x20,0x2a,0x20,0x76,0x65,0x63,0x32,0x28,0x64,0x6f,0x66,0x5f,0x62,0x6c,
0x75,0x72,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d,0x2e,0x78,0x2c,0x20,
0x64,0x6f,0x66,0x5f,0x62,0x6c,0x75,0x72,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,
0x30,0x5d,0x2e,0x79,0x29,0x29,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x39,0x32,0x20,0x3d,0x20,0x64,0x6f,0x74,
0x28,0x5f,0x38,0x38,0x2e,0x78,0x79,0x7a,0x2c,0x20,0x76,0x65,0x63,0x33,0x28,0x30,
0x2e,0x32,0x31,0x32,0x35,0x39,0x39,0x39,0x39,0x32,0x37,0x35,0x32,0x30,0x37,0x35,
0x31,0x39,0x35,0x33,0x31,0x32,0x35,0x2c,0x20,0x30,0x2e,0x37,0x31,0x35,0x32,0x30,
0x30,0x30,0x30,0x36,0x39,0x36,0x31,0x38,0x32,0x32,0x35,0x30,0x39,0x37,0x36,0x35,
0x36,0x32,0x35,0x2c,0x20,0x30,0x2e,0x30,0x37,0x32,0x32,0x30,0x30,0x30,0x30,0x30,
0x32,0x38,0x36,0x31,0x30,0x32,0x32,0x39,0x34,0x39,0x32,0x31,0x38,0x37,0x35,0x29,
0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x5f,
0x39,0x32,0x20,0x3e,0x20,0x62,0x65,0x73,0x74,0x5f,0x6c,0x75,0x6d,0x29,0x0a,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x62,0x65,0x73,0x74,0x20,0x3d,0x20,0x5f,0x38,0x38,0x3b,
0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x65,0x73,
0x74,0x5f,0x6c,0x75,0x6d,0x20,0x3d,0x20,0x5f,0x39,0x32,0x3b,0x0a,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,
0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x62,0x65,
0x73,0x74,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#version 300 es
layout(location = 0) in vec2 position;
out vec2 texcoord;
layout(location = 1) in vec2 uv;
void main()
{
gl_Position = vec4(position, 0.5, 1.0);
texcoord = uv;
}
*/
vs_dof_blur_source_glsl300es := u8.[
0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x33,0x30,0x30,0x20,0x65,0x73,0x0a,
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,0x32,0x20,0x70,0x6f,
0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x32,
0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,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,0x32,0x20,0x75,0x76,0x3b,0x0a,0x0a,0x76,0x6f,0x69,
0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x67,
0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x76,0x65,0x63,
0x34,0x28,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x30,0x2e,0x35,0x2c,
0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x74,0x65,0x78,0x63,0x6f,
0x6f,0x72,0x64,0x20,0x3d,0x20,0x75,0x76,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#version 300 es
precision mediump float;
precision highp int;
uniform highp vec4 dof_blur_params[1];
uniform highp sampler2D dof_blur_src_dof_blur_src_smp;
in highp vec2 texcoord;
layout(location = 0) out highp vec4 frag_color;
void main()
{
highp vec4 _24 = texture(dof_blur_src_dof_blur_src_smp, texcoord);
highp vec4 best = _24;
highp float best_lum = dot(_24.xyz, vec3(0.2125999927520751953125, 0.715200006961822509765625, 0.072200000286102294921875));
for (int i = 0; i < 32; i++)
{
highp float _50 = float(i);
highp float _52 = _50 * 2.3999631404876708984375;
highp vec4 _88 = texture(dof_blur_src_dof_blur_src_smp, texcoord + ((vec2(cos(_52), sin(_52)) * sqrt((_50 * 0.0322580635547637939453125) + 0.001000000047497451305389404296875)) * vec2(dof_blur_params[0].x, dof_blur_params[0].y)));
highp float _92 = dot(_88.xyz, vec3(0.2125999927520751953125, 0.715200006961822509765625, 0.072200000286102294921875));
if (_92 > best_lum)
{
best = _88;
best_lum = _92;
}
}
frag_color = best;
}
*/
fs_dof_blur_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,0x75,
0x6e,0x69,0x66,0x6f,0x72,0x6d,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x76,0x65,0x63,
0x34,0x20,0x64,0x6f,0x66,0x5f,0x62,0x6c,0x75,0x72,0x5f,0x70,0x61,0x72,0x61,0x6d,
0x73,0x5b,0x31,0x5d,0x3b,0x0a,0x75,0x6e,0x69,0x66,0x6f,0x72,0x6d,0x20,0x68,0x69,
0x67,0x68,0x70,0x20,0x73,0x61,0x6d,0x70,0x6c,0x65,0x72,0x32,0x44,0x20,0x64,0x6f,
0x66,0x5f,0x62,0x6c,0x75,0x72,0x5f,0x73,0x72,0x63,0x5f,0x64,0x6f,0x66,0x5f,0x62,
0x6c,0x75,0x72,0x5f,0x73,0x72,0x63,0x5f,0x73,0x6d,0x70,0x3b,0x0a,0x0a,0x69,0x6e,
0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x76,0x65,0x63,0x32,0x20,0x74,0x65,0x78,0x63,
0x6f,0x6f,0x72,0x64,0x3b,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,0x68,0x69,0x67,0x68,0x70,0x20,0x76,
0x65,0x63,0x34,0x20,0x5f,0x32,0x34,0x20,0x3d,0x20,0x74,0x65,0x78,0x74,0x75,0x72,
0x65,0x28,0x64,0x6f,0x66,0x5f,0x62,0x6c,0x75,0x72,0x5f,0x73,0x72,0x63,0x5f,0x64,
0x6f,0x66,0x5f,0x62,0x6c,0x75,0x72,0x5f,0x73,0x72,0x63,0x5f,0x73,0x6d,0x70,0x2c,
0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,
0x68,0x69,0x67,0x68,0x70,0x20,0x76,0x65,0x63,0x34,0x20,0x62,0x65,0x73,0x74,0x20,
0x3d,0x20,0x5f,0x32,0x34,0x3b,0x0a,0x20,0x20,0x20,0x20,0x68,0x69,0x67,0x68,0x70,
0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x62,0x65,0x73,0x74,0x5f,0x6c,0x75,0x6d,0x20,
0x3d,0x20,0x64,0x6f,0x74,0x28,0x5f,0x32,0x34,0x2e,0x78,0x79,0x7a,0x2c,0x20,0x76,
0x65,0x63,0x33,0x28,0x30,0x2e,0x32,0x31,0x32,0x35,0x39,0x39,0x39,0x39,0x32,0x37,
0x35,0x32,0x30,0x37,0x35,0x31,0x39,0x35,0x33,0x31,0x32,0x35,0x2c,0x20,0x30,0x2e,
0x37,0x31,0x35,0x32,0x30,0x30,0x30,0x30,0x36,0x39,0x36,0x31,0x38,0x32,0x32,0x35,
0x30,0x39,0x37,0x36,0x35,0x36,0x32,0x35,0x2c,0x20,0x30,0x2e,0x30,0x37,0x32,0x32,
0x30,0x30,0x30,0x30,0x30,0x32,0x38,0x36,0x31,0x30,0x32,0x32,0x39,0x34,0x39,0x32,
0x31,0x38,0x37,0x35,0x29,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6f,0x72,0x20,
0x28,0x69,0x6e,0x74,0x20,0x69,0x20,0x3d,0x20,0x30,0x3b,0x20,0x69,0x20,0x3c,0x20,
0x33,0x32,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x66,0x6c,0x6f,
0x61,0x74,0x20,0x5f,0x35,0x30,0x20,0x3d,0x20,0x66,0x6c,0x6f,0x61,0x74,0x28,0x69,
0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x68,0x69,0x67,0x68,0x70,
0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x35,0x32,0x20,0x3d,0x20,0x5f,0x35,0x30,
0x20,0x2a,0x20,0x32,0x2e,0x33,0x39,0x39,0x39,0x36,0x33,0x31,0x34,0x30,0x34,0x38,
0x37,0x36,0x37,0x30,0x38,0x39,0x38,0x34,0x33,0x37,0x35,0x3b,0x0a,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x76,0x65,0x63,0x34,0x20,
0x5f,0x38,0x38,0x20,0x3d,0x20,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x64,0x6f,
0x66,0x5f,0x62,0x6c,0x75,0x72,0x5f,0x73,0x72,0x63,0x5f,0x64,0x6f,0x66,0x5f,0x62,
0x6c,0x75,0x72,0x5f,0x73,0x72,0x63,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x74,0x65,0x78,
0x63,0x6f,0x6f,0x72,0x64,0x20,0x2b,0x20,0x28,0x28,0x76,0x65,0x63,0x32,0x28,0x63,
0x6f,0x73,0x28,0x5f,0x35,0x32,0x29,0x2c,0x20,0x73,0x69,0x6e,0x28,0x5f,0x35,0x32,
0x29,0x29,0x20,0x2a,0x20,0x73,0x71,0x72,0x74,0x28,0x28,0x5f,0x35,0x30,0x20,0x2a,
0x20,0x30,0x2e,0x30,0x33,0x32,0x32,0x35,0x38,0x30,0x36,0x33,0x35,0x35,0x34,0x37,
0x36,0x33,0x37,0x39,0x33,0x39,0x34,0x35,0x33,0x31,0x32,0x35,0x29,0x20,0x2b,0x20,
0x30,0x2e,0x30,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x34,0x37,0x34,0x39,
0x37,0x34,0x35,0x31,0x33,0x30,0x35,0x33,0x38,0x39,0x34,0x30,0x34,0x32,0x39,0x36,
0x38,0x37,0x35,0x29,0x29,0x20,0x2a,0x20,0x76,0x65,0x63,0x32,0x28,0x64,0x6f,0x66,
0x5f,0x62,0x6c,0x75,0x72,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d,0x2e,
0x78,0x2c,0x20,0x64,0x6f,0x66,0x5f,0x62,0x6c,0x75,0x72,0x5f,0x70,0x61,0x72,0x61,
0x6d,0x73,0x5b,0x30,0x5d,0x2e,0x79,0x29,0x29,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,
0x5f,0x39,0x32,0x20,0x3d,0x20,0x64,0x6f,0x74,0x28,0x5f,0x38,0x38,0x2e,0x78,0x79,
0x7a,0x2c,0x20,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x32,0x31,0x32,0x35,0x39,0x39,
0x39,0x39,0x32,0x37,0x35,0x32,0x30,0x37,0x35,0x31,0x39,0x35,0x33,0x31,0x32,0x35,
0x2c,0x20,0x30,0x2e,0x37,0x31,0x35,0x32,0x30,0x30,0x30,0x30,0x36,0x39,0x36,0x31,
0x38,0x32,0x32,0x35,0x30,0x39,0x37,0x36,0x35,0x36,0x32,0x35,0x2c,0x20,0x30,0x2e,
0x30,0x37,0x32,0x32,0x30,0x30,0x30,0x30,0x30,0x32,0x38,0x36,0x31,0x30,0x32,0x32,
0x39,0x34,0x39,0x32,0x31,0x38,0x37,0x35,0x29,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x5f,0x39,0x32,0x20,0x3e,0x20,0x62,0x65,
0x73,0x74,0x5f,0x6c,0x75,0x6d,0x29,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x65,
0x73,0x74,0x20,0x3d,0x20,0x5f,0x38,0x38,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x65,0x73,0x74,0x5f,0x6c,0x75,0x6d,0x20,0x3d,
0x20,0x5f,0x39,0x32,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,
0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,
0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x62,0x65,0x73,0x74,0x3b,0x0a,0x7d,0x0a,0x0a,
0x00,
];
/*
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct main0_out
{
float2 texcoord [[user(locn0)]];
float4 gl_Position [[position]];
};
struct main0_in
{
float2 position [[attribute(0)]];
float2 uv [[attribute(1)]];
};
vertex main0_out main0(main0_in in [[stage_in]])
{
main0_out out = {};
out.gl_Position = float4(in.position, 0.5, 1.0);
out.texcoord = in.uv;
return out;
}
*/
vs_dof_blur_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,0x32,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,0x5b,
0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,0x30,0x29,0x5d,0x5d,0x3b,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,0x32,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,0x32,0x20,0x75,0x76,0x20,0x5b,
0x5b,0x61,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x28,0x31,0x29,0x5d,0x5d,0x3b,
0x0a,0x7d,0x3b,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,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,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,
0x69,0x6f,0x6e,0x20,0x3d,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x28,0x69,0x6e,0x2e,
0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x30,0x2e,0x35,0x2c,0x20,0x31,
0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,0x74,0x65,0x78,
0x63,0x6f,0x6f,0x72,0x64,0x20,0x3d,0x20,0x69,0x6e,0x2e,0x75,0x76,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 dof_blur_params
{
float bokeh_radius_x;
float bokeh_radius_y;
};
struct main0_out
{
float4 frag_color [[color(0)]];
};
struct main0_in
{
float2 texcoord [[user(locn0)]];
};
fragment main0_out main0(main0_in in [[stage_in]], constant dof_blur_params& _72 [[buffer(0)]], texture2d<float> dof_blur_src [[texture(0)]], sampler dof_blur_src_smp [[sampler(0)]])
{
main0_out out = {};
float4 _24 = dof_blur_src.sample(dof_blur_src_smp, in.texcoord);
float4 best = _24;
float best_lum = dot(_24.xyz, float3(0.2125999927520751953125, 0.715200006961822509765625, 0.072200000286102294921875));
for (int i = 0; i < 32; i++)
{
float _50 = float(i);
float _52 = _50 * 2.3999631404876708984375;
float4 _88 = dof_blur_src.sample(dof_blur_src_smp, (in.texcoord + ((float2(cos(_52), sin(_52)) * sqrt((_50 * 0.0322580635547637939453125) + 0.001000000047497451305389404296875)) * float2(_72.bokeh_radius_x, _72.bokeh_radius_y))));
float _92 = dot(_88.xyz, float3(0.2125999927520751953125, 0.715200006961822509765625, 0.072200000286102294921875));
if (_92 > best_lum)
{
best = _88;
best_lum = _92;
}
}
out.frag_color = best;
return out;
}
*/
fs_dof_blur_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,0x64,
0x6f,0x66,0x5f,0x62,0x6c,0x75,0x72,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x0a,0x7b,
0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x62,0x6f,0x6b,0x65,0x68,
0x5f,0x72,0x61,0x64,0x69,0x75,0x73,0x5f,0x78,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,
0x6c,0x6f,0x61,0x74,0x20,0x62,0x6f,0x6b,0x65,0x68,0x5f,0x72,0x61,0x64,0x69,0x75,
0x73,0x5f,0x79,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,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,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,0x32,
0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,
0x28,0x6c,0x6f,0x63,0x6e,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,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,0x64,0x6f,0x66,0x5f,0x62,
0x6c,0x75,0x72,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x26,0x20,0x5f,0x37,0x32,0x20,
0x5b,0x5b,0x62,0x75,0x66,0x66,0x65,0x72,0x28,0x30,0x29,0x5d,0x5d,0x2c,0x20,0x74,
0x65,0x78,0x74,0x75,0x72,0x65,0x32,0x64,0x3c,0x66,0x6c,0x6f,0x61,0x74,0x3e,0x20,
0x64,0x6f,0x66,0x5f,0x62,0x6c,0x75,0x72,0x5f,0x73,0x72,0x63,0x20,0x5b,0x5b,0x74,
0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x30,0x29,0x5d,0x5d,0x2c,0x20,0x73,0x61,0x6d,
0x70,0x6c,0x65,0x72,0x20,0x64,0x6f,0x66,0x5f,0x62,0x6c,0x75,0x72,0x5f,0x73,0x72,
0x63,0x5f,0x73,0x6d,0x70,0x20,0x5b,0x5b,0x73,0x61,0x6d,0x70,0x6c,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,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x5f,0x32,0x34,0x20,0x3d,
0x20,0x64,0x6f,0x66,0x5f,0x62,0x6c,0x75,0x72,0x5f,0x73,0x72,0x63,0x2e,0x73,0x61,
0x6d,0x70,0x6c,0x65,0x28,0x64,0x6f,0x66,0x5f,0x62,0x6c,0x75,0x72,0x5f,0x73,0x72,
0x63,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x69,0x6e,0x2e,0x74,0x65,0x78,0x63,0x6f,0x6f,
0x72,0x64,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,
0x62,0x65,0x73,0x74,0x20,0x3d,0x20,0x5f,0x32,0x34,0x3b,0x0a,0x20,0x20,0x20,0x20,
0x66,0x6c,0x6f,0x61,0x74,0x20,0x62,0x65,0x73,0x74,0x5f,0x6c,0x75,0x6d,0x20,0x3d,
0x20,0x64,0x6f,0x74,0x28,0x5f,0x32,0x34,0x2e,0x78,0x79,0x7a,0x2c,0x20,0x66,0x6c,
0x6f,0x61,0x74,0x33,0x28,0x30,0x2e,0x32,0x31,0x32,0x35,0x39,0x39,0x39,0x39,0x32,
0x37,0x35,0x32,0x30,0x37,0x35,0x31,0x39,0x35,0x33,0x31,0x32,0x35,0x2c,0x20,0x30,
0x2e,0x37,0x31,0x35,0x32,0x30,0x30,0x30,0x30,0x36,0x39,0x36,0x31,0x38,0x32,0x32,
0x35,0x30,0x39,0x37,0x36,0x35,0x36,0x32,0x35,0x2c,0x20,0x30,0x2e,0x30,0x37,0x32,
0x32,0x30,0x30,0x30,0x30,0x30,0x32,0x38,0x36,0x31,0x30,0x32,0x32,0x39,0x34,0x39,
0x32,0x31,0x38,0x37,0x35,0x29,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6f,0x72,
0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x20,0x3d,0x20,0x30,0x3b,0x20,0x69,0x20,0x3c,
0x20,0x33,0x32,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x35,
0x30,0x20,0x3d,0x20,0x66,0x6c,0x6f,0x61,0x74,0x28,0x69,0x29,0x3b,0x0a,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x35,0x32,0x20,
0x3d,0x20,0x5f,0x35,0x30,0x20,0x2a,0x20,0x32,0x2e,0x33,0x39,0x39,0x39,0x36,0x33,
0x31,0x34,0x30,0x34,0x38,0x37,0x36,0x37,0x30,0x38,0x39,0x38,0x34,0x33,0x37,0x35,
0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,
0x20,0x5f,0x38,0x38,0x20,0x3d,0x20,0x64,0x6f,0x66,0x5f,0x62,0x6c,0x75,0x72,0x5f,
0x73,0x72,0x63,0x2e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x28,0x64,0x6f,0x66,0x5f,0x62,
0x6c,0x75,0x72,0x5f,0x73,0x72,0x63,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x28,0x69,0x6e,
0x2e,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,0x2b,0x20,0x28,0x28,0x66,0x6c,
0x6f,0x61,0x74,0x32,0x28,0x63,0x6f,0x73,0x28,0x5f,0x35,0x32,0x29,0x2c,0x20,0x73,
0x69,0x6e,0x28,0x5f,0x35,0x32,0x29,0x29,0x20,0x2a,0x20,0x73,0x71,0x72,0x74,0x28,
0x28,0x5f,0x35,0x30,0x20,0x2a,0x20,0x30,0x2e,0x30,0x33,0x32,0x32,0x35,0x38,0x30,
0x36,0x33,0x35,0x35,0x34,0x37,0x36,0x33,0x37,0x39,0x33,0x39,0x34,0x35,0x33,0x31,
0x32,0x35,0x29,0x20,0x2b,0x20,0x30,0x2e,0x30,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
0x30,0x30,0x34,0x37,0x34,0x39,0x37,0x34,0x35,0x31,0x33,0x30,0x35,0x33,0x38,0x39,
0x34,0x30,0x34,0x32,0x39,0x36,0x38,0x37,0x35,0x29,0x29,0x20,0x2a,0x20,0x66,0x6c,
0x6f,0x61,0x74,0x32,0x28,0x5f,0x37,0x32,0x2e,0x62,0x6f,0x6b,0x65,0x68,0x5f,0x72,
0x61,0x64,0x69,0x75,0x73,0x5f,0x78,0x2c,0x20,0x5f,0x37,0x32,0x2e,0x62,0x6f,0x6b,
0x65,0x68,0x5f,0x72,0x61,0x64,0x69,0x75,0x73,0x5f,0x79,0x29,0x29,0x29,0x29,0x3b,
0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,
0x39,0x32,0x20,0x3d,0x20,0x64,0x6f,0x74,0x28,0x5f,0x38,0x38,0x2e,0x78,0x79,0x7a,
0x2c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x33,0x28,0x30,0x2e,0x32,0x31,0x32,0x35,0x39,
0x39,0x39,0x39,0x32,0x37,0x35,0x32,0x30,0x37,0x35,0x31,0x39,0x35,0x33,0x31,0x32,
0x35,0x2c,0x20,0x30,0x2e,0x37,0x31,0x35,0x32,0x30,0x30,0x30,0x30,0x36,0x39,0x36,
0x31,0x38,0x32,0x32,0x35,0x30,0x39,0x37,0x36,0x35,0x36,0x32,0x35,0x2c,0x20,0x30,
0x2e,0x30,0x37,0x32,0x32,0x30,0x30,0x30,0x30,0x30,0x32,0x38,0x36,0x31,0x30,0x32,
0x32,0x39,0x34,0x39,0x32,0x31,0x38,0x37,0x35,0x29,0x29,0x3b,0x0a,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x5f,0x39,0x32,0x20,0x3e,0x20,0x62,
0x65,0x73,0x74,0x5f,0x6c,0x75,0x6d,0x29,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x62,
0x65,0x73,0x74,0x20,0x3d,0x20,0x5f,0x38,0x38,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x65,0x73,0x74,0x5f,0x6c,0x75,0x6d,0x20,
0x3d,0x20,0x5f,0x39,0x32,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,
0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,0x66,
0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x62,0x65,0x73,0x74,
0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6f,0x75,0x74,
0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
dof_blur_shader_desc :: (backend: sg_backend) -> sg_shader_desc {
desc: sg_shader_desc;
desc.label = "dof_blur_shader";
if backend == {
case .GLCORE;
desc.vertex_func.source = xx *vs_dof_blur_source_glsl430;
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_dof_blur_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 = "uv";
desc.uniform_blocks[0].stage = .FRAGMENT;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 16;
desc.uniform_blocks[0].glsl_uniforms[0].type = .FLOAT4;
desc.uniform_blocks[0].glsl_uniforms[0].array_count = 1;
desc.uniform_blocks[0].glsl_uniforms[0].glsl_name = "dof_blur_params";
desc.images[0].stage = .FRAGMENT;
desc.images[0].multisampled = false;
desc.images[0].image_type = ._2D;
desc.images[0].sample_type = .FLOAT;
desc.samplers[0].stage = .FRAGMENT;
desc.samplers[0].sampler_type = .FILTERING;
desc.image_sampler_pairs[0].stage = .FRAGMENT;
desc.image_sampler_pairs[0].image_slot = 0;
desc.image_sampler_pairs[0].sampler_slot = 0;
desc.image_sampler_pairs[0].glsl_name = "dof_blur_src_dof_blur_src_smp";
case .GLES3;
desc.vertex_func.source = xx *vs_dof_blur_source_glsl300es;
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_dof_blur_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 = "uv";
desc.uniform_blocks[0].stage = .FRAGMENT;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 16;
desc.uniform_blocks[0].glsl_uniforms[0].type = .FLOAT4;
desc.uniform_blocks[0].glsl_uniforms[0].array_count = 1;
desc.uniform_blocks[0].glsl_uniforms[0].glsl_name = "dof_blur_params";
desc.images[0].stage = .FRAGMENT;
desc.images[0].multisampled = false;
desc.images[0].image_type = ._2D;
desc.images[0].sample_type = .FLOAT;
desc.samplers[0].stage = .FRAGMENT;
desc.samplers[0].sampler_type = .FILTERING;
desc.image_sampler_pairs[0].stage = .FRAGMENT;
desc.image_sampler_pairs[0].image_slot = 0;
desc.image_sampler_pairs[0].sampler_slot = 0;
desc.image_sampler_pairs[0].glsl_name = "dof_blur_src_dof_blur_src_smp";
case .METAL_MACOS;
desc.vertex_func.source = xx *vs_dof_blur_source_metal_macos;
desc.vertex_func.entry = "main0";
desc.fragment_func.source = xx *fs_dof_blur_source_metal_macos;
desc.fragment_func.entry = "main0";
desc.attrs[0].base_type = .FLOAT;
desc.attrs[1].base_type = .FLOAT;
desc.uniform_blocks[0].stage = .FRAGMENT;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 16;
desc.uniform_blocks[0].msl_buffer_n = 0;
desc.images[0].stage = .FRAGMENT;
desc.images[0].multisampled = false;
desc.images[0].image_type = ._2D;
desc.images[0].sample_type = .FLOAT;
desc.images[0].msl_texture_n = 0;
desc.samplers[0].stage = .FRAGMENT;
desc.samplers[0].sampler_type = .FILTERING;
desc.samplers[0].msl_sampler_n = 0;
desc.image_sampler_pairs[0].stage = .FRAGMENT;
desc.image_sampler_pairs[0].image_slot = 0;
desc.image_sampler_pairs[0].sampler_slot = 0;
}
return desc;
}

View File

@ -1,339 +0,0 @@
/*
#version:1# (machine generated, don't edit!)
Generated by sokol-shdc (https://github.com/floooh/sokol-tools)
Cmdline:
sokol-shdc -i shader_dof_downsample.glsl -o ./jai/shader_dof_downsample.jai -l glsl430:glsl300es:metal_macos -f sokol_jai
Overview:
=========
Shader program: 'dof_downsample':
Get shader desc: dof_downsample_shader_desc(sg_query_backend())
Vertex Shader: vs_dof_downsample
Fragment Shader: fs_dof_downsample
Attributes:
ATTR_dof_downsample_position => 0
ATTR_dof_downsample_uv => 1
Bindings:
Image 'dof_downsample_src':
Image type: ._2D
Sample type: .FLOAT
Multisampled: false
Bind slot: IMG_dof_downsample_src => 0
Sampler 'dof_downsample_src_smp':
Type: .FILTERING
Bind slot: SMP_dof_downsample_src_smp => 0
*/
ATTR_dof_downsample_position :: 0;
ATTR_dof_downsample_uv :: 1;
IMG_dof_downsample_src :: 0;
SMP_dof_downsample_src_smp :: 0;
/*
#version 430
layout(location = 0) in vec2 position;
layout(location = 0) out vec2 texcoord;
layout(location = 1) in vec2 uv;
void main()
{
gl_Position = vec4(position, 0.5, 1.0);
texcoord = uv;
}
*/
vs_dof_downsample_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,0x69,0x6e,0x20,0x76,0x65,0x63,0x32,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,0x30,0x29,0x20,0x6f,0x75,0x74,0x20,0x76,0x65,
0x63,0x32,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,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,0x32,0x20,0x75,0x76,0x3b,0x0a,0x0a,0x76,
0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,
0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x76,
0x65,0x63,0x34,0x28,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x30,0x2e,
0x35,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x74,0x65,0x78,
0x63,0x6f,0x6f,0x72,0x64,0x20,0x3d,0x20,0x75,0x76,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#version 430
layout(binding = 16) uniform sampler2D dof_downsample_src_dof_downsample_src_smp;
layout(location = 0) out vec4 frag_color;
layout(location = 0) in vec2 texcoord;
void main()
{
frag_color = vec4(texture(dof_downsample_src_dof_downsample_src_smp, texcoord).xyz, 1.0);
}
*/
fs_dof_downsample_source_glsl430 := u8.[
0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x34,0x33,0x30,0x0a,0x0a,0x6c,0x61,
0x79,0x6f,0x75,0x74,0x28,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x20,0x3d,0x20,0x31,
0x36,0x29,0x20,0x75,0x6e,0x69,0x66,0x6f,0x72,0x6d,0x20,0x73,0x61,0x6d,0x70,0x6c,
0x65,0x72,0x32,0x44,0x20,0x64,0x6f,0x66,0x5f,0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,
0x70,0x6c,0x65,0x5f,0x73,0x72,0x63,0x5f,0x64,0x6f,0x66,0x5f,0x64,0x6f,0x77,0x6e,
0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x72,0x63,0x5f,0x73,0x6d,0x70,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,0x76,0x65,0x63,0x34,0x20,0x66,
0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,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,0x32,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,
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,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x64,
0x6f,0x66,0x5f,0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x72,
0x63,0x5f,0x64,0x6f,0x66,0x5f,0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,0x70,0x6c,0x65,
0x5f,0x73,0x72,0x63,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,
0x72,0x64,0x29,0x2e,0x78,0x79,0x7a,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x7d,
0x0a,0x0a,0x00,
];
/*
#version 300 es
layout(location = 0) in vec2 position;
out vec2 texcoord;
layout(location = 1) in vec2 uv;
void main()
{
gl_Position = vec4(position, 0.5, 1.0);
texcoord = uv;
}
*/
vs_dof_downsample_source_glsl300es := u8.[
0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x33,0x30,0x30,0x20,0x65,0x73,0x0a,
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,0x32,0x20,0x70,0x6f,
0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x32,
0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,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,0x32,0x20,0x75,0x76,0x3b,0x0a,0x0a,0x76,0x6f,0x69,
0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x67,
0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x76,0x65,0x63,
0x34,0x28,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x30,0x2e,0x35,0x2c,
0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x74,0x65,0x78,0x63,0x6f,
0x6f,0x72,0x64,0x20,0x3d,0x20,0x75,0x76,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#version 300 es
precision mediump float;
precision highp int;
uniform highp sampler2D dof_downsample_src_dof_downsample_src_smp;
layout(location = 0) out highp vec4 frag_color;
in highp vec2 texcoord;
void main()
{
frag_color = vec4(texture(dof_downsample_src_dof_downsample_src_smp, texcoord).xyz, 1.0);
}
*/
fs_dof_downsample_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,0x75,
0x6e,0x69,0x66,0x6f,0x72,0x6d,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x73,0x61,0x6d,
0x70,0x6c,0x65,0x72,0x32,0x44,0x20,0x64,0x6f,0x66,0x5f,0x64,0x6f,0x77,0x6e,0x73,
0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x72,0x63,0x5f,0x64,0x6f,0x66,0x5f,0x64,0x6f,
0x77,0x6e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x72,0x63,0x5f,0x73,0x6d,0x70,
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,0x69,0x6e,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x76,0x65,0x63,0x32,
0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,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,
0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x64,0x6f,0x66,0x5f,0x64,0x6f,0x77,0x6e,
0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x72,0x63,0x5f,0x64,0x6f,0x66,0x5f,0x64,
0x6f,0x77,0x6e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x72,0x63,0x5f,0x73,0x6d,
0x70,0x2c,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x29,0x2e,0x78,0x79,0x7a,
0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct main0_out
{
float2 texcoord [[user(locn0)]];
float4 gl_Position [[position]];
};
struct main0_in
{
float2 position [[attribute(0)]];
float2 uv [[attribute(1)]];
};
vertex main0_out main0(main0_in in [[stage_in]])
{
main0_out out = {};
out.gl_Position = float4(in.position, 0.5, 1.0);
out.texcoord = in.uv;
return out;
}
*/
vs_dof_downsample_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,0x32,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,0x5b,
0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,0x30,0x29,0x5d,0x5d,0x3b,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,0x32,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,0x32,0x20,0x75,0x76,0x20,0x5b,
0x5b,0x61,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x28,0x31,0x29,0x5d,0x5d,0x3b,
0x0a,0x7d,0x3b,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,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,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,
0x69,0x6f,0x6e,0x20,0x3d,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x28,0x69,0x6e,0x2e,
0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x30,0x2e,0x35,0x2c,0x20,0x31,
0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,0x74,0x65,0x78,
0x63,0x6f,0x6f,0x72,0x64,0x20,0x3d,0x20,0x69,0x6e,0x2e,0x75,0x76,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)]];
};
struct main0_in
{
float2 texcoord [[user(locn0)]];
};
fragment main0_out main0(main0_in in [[stage_in]], texture2d<float> dof_downsample_src [[texture(0)]], sampler dof_downsample_src_smp [[sampler(0)]])
{
main0_out out = {};
out.frag_color = float4(dof_downsample_src.sample(dof_downsample_src_smp, in.texcoord).xyz, 1.0);
return out;
}
*/
fs_dof_downsample_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,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,0x32,0x20,
0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,0x28,
0x6c,0x6f,0x63,0x6e,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,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,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x32,0x64,0x3c,0x66,0x6c,0x6f,0x61,0x74,
0x3e,0x20,0x64,0x6f,0x66,0x5f,0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,0x70,0x6c,0x65,
0x5f,0x73,0x72,0x63,0x20,0x5b,0x5b,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x30,
0x29,0x5d,0x5d,0x2c,0x20,0x73,0x61,0x6d,0x70,0x6c,0x65,0x72,0x20,0x64,0x6f,0x66,
0x5f,0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x72,0x63,0x5f,
0x73,0x6d,0x70,0x20,0x5b,0x5b,0x73,0x61,0x6d,0x70,0x6c,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,0x6f,0x75,0x74,0x2e,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,
0x20,0x3d,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x28,0x64,0x6f,0x66,0x5f,0x64,0x6f,
0x77,0x6e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x5f,0x73,0x72,0x63,0x2e,0x73,0x61,0x6d,
0x70,0x6c,0x65,0x28,0x64,0x6f,0x66,0x5f,0x64,0x6f,0x77,0x6e,0x73,0x61,0x6d,0x70,
0x6c,0x65,0x5f,0x73,0x72,0x63,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x69,0x6e,0x2e,0x74,
0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x29,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,
];
dof_downsample_shader_desc :: (backend: sg_backend) -> sg_shader_desc {
desc: sg_shader_desc;
desc.label = "dof_downsample_shader";
if backend == {
case .GLCORE;
desc.vertex_func.source = xx *vs_dof_downsample_source_glsl430;
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_dof_downsample_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 = "uv";
desc.images[0].stage = .FRAGMENT;
desc.images[0].multisampled = false;
desc.images[0].image_type = ._2D;
desc.images[0].sample_type = .FLOAT;
desc.samplers[0].stage = .FRAGMENT;
desc.samplers[0].sampler_type = .FILTERING;
desc.image_sampler_pairs[0].stage = .FRAGMENT;
desc.image_sampler_pairs[0].image_slot = 0;
desc.image_sampler_pairs[0].sampler_slot = 0;
desc.image_sampler_pairs[0].glsl_name = "dof_downsample_src_dof_downsample_src_smp";
case .GLES3;
desc.vertex_func.source = xx *vs_dof_downsample_source_glsl300es;
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_dof_downsample_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 = "uv";
desc.images[0].stage = .FRAGMENT;
desc.images[0].multisampled = false;
desc.images[0].image_type = ._2D;
desc.images[0].sample_type = .FLOAT;
desc.samplers[0].stage = .FRAGMENT;
desc.samplers[0].sampler_type = .FILTERING;
desc.image_sampler_pairs[0].stage = .FRAGMENT;
desc.image_sampler_pairs[0].image_slot = 0;
desc.image_sampler_pairs[0].sampler_slot = 0;
desc.image_sampler_pairs[0].glsl_name = "dof_downsample_src_dof_downsample_src_smp";
case .METAL_MACOS;
desc.vertex_func.source = xx *vs_dof_downsample_source_metal_macos;
desc.vertex_func.entry = "main0";
desc.fragment_func.source = xx *fs_dof_downsample_source_metal_macos;
desc.fragment_func.entry = "main0";
desc.attrs[0].base_type = .FLOAT;
desc.attrs[1].base_type = .FLOAT;
desc.images[0].stage = .FRAGMENT;
desc.images[0].multisampled = false;
desc.images[0].image_type = ._2D;
desc.images[0].sample_type = .FLOAT;
desc.images[0].msl_texture_n = 0;
desc.samplers[0].stage = .FRAGMENT;
desc.samplers[0].sampler_type = .FILTERING;
desc.samplers[0].msl_sampler_n = 0;
desc.image_sampler_pairs[0].stage = .FRAGMENT;
desc.image_sampler_pairs[0].image_slot = 0;
desc.image_sampler_pairs[0].sampler_slot = 0;
}
return desc;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,696 +0,0 @@
/*
#version:1# (machine generated, don't edit!)
Generated by sokol-shdc (https://github.com/floooh/sokol-tools)
Cmdline:
sokol-shdc -i shader_gbuffer_billboard.glsl -o ./jai/shader_gbuffer_billboard.jai -l glsl430:glsl300es:metal_macos -f sokol_jai
Overview:
=========
Shader program: 'gbuffer_billboard':
Get shader desc: gbuffer_billboard_shader_desc(sg_query_backend())
Vertex Shader: vs_gbuffer_billboard
Fragment Shader: fs_gbuffer_billboard
Attributes:
ATTR_gbuffer_billboard_position => 0
Bindings:
Uniform block 'gbuffer_billboard_vs_params':
Jai struct: Gbuffer_Billboard_Vs_Params
Bind slot: UB_gbuffer_billboard_vs_params => 0
Image 'gsprite':
Image type: ._2D
Sample type: .FLOAT
Multisampled: false
Bind slot: IMG_gsprite => 0
Sampler 'gspritesmp':
Type: .FILTERING
Bind slot: SMP_gspritesmp => 0
*/
ATTR_gbuffer_billboard_position :: 0;
UB_gbuffer_billboard_vs_params :: 0;
IMG_gsprite :: 0;
SMP_gspritesmp :: 0;
Gbuffer_Billboard_Vs_Params :: struct {
mvp: [16]float;
uvs: [4]float;
offset: [3]float;
_: [4]u8;
size: [2]float;
_: [8]u8;
cam: [3]float;
_: [4]u8;
view_matrix: [16]float;
faceDir: [3]float;
_: [4]u8;
};
/*
#version 430
uniform vec4 gbuffer_billboard_vs_params[13];
layout(location = 0) in vec3 position;
layout(location = 1) out vec3 view_space_pos;
layout(location = 2) out vec3 view_space_normal;
layout(location = 0) out vec2 uv_in;
void main()
{
vec3 _53 = gbuffer_billboard_vs_params[5].xyz - gbuffer_billboard_vs_params[7].xyz;
_53.y = 0.0;
vec3 look_dir = normalize(_53);
if (gbuffer_billboard_vs_params[12].x > (-10.0))
{
look_dir = gbuffer_billboard_vs_params[12].xyz;
}
vec4 _98 = vec4((gbuffer_billboard_vs_params[5].xyz + (normalize(cross(vec3(0.0, 1.0, 0.0), look_dir)) * ((position.x - 0.5) * gbuffer_billboard_vs_params[6].x))) + (vec3(0.0, 1.0, 0.0) * (position.y * gbuffer_billboard_vs_params[6].y)), 1.0);
gl_Position = mat4(gbuffer_billboard_vs_params[0], gbuffer_billboard_vs_params[1], gbuffer_billboard_vs_params[2], gbuffer_billboard_vs_params[3]) * _98;
mat4 _106 = mat4(gbuffer_billboard_vs_params[8], gbuffer_billboard_vs_params[9], gbuffer_billboard_vs_params[10], gbuffer_billboard_vs_params[11]);
view_space_pos = (_106 * _98).xyz;
view_space_normal = mat3(_106[0].xyz, _106[1].xyz, _106[2].xyz) * vec3(0.0, 1.0, 0.0);
uv_in = vec2(gbuffer_billboard_vs_params[4].x + (position.x * gbuffer_billboard_vs_params[4].z), gbuffer_billboard_vs_params[4].y + (position.y * gbuffer_billboard_vs_params[4].w));
}
*/
vs_gbuffer_billboard_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,0x67,0x62,0x75,0x66,0x66,
0x65,0x72,0x5f,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,
0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x31,0x33,0x5d,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,0x33,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,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x33,
0x20,0x76,0x69,0x65,0x77,0x5f,0x73,0x70,0x61,0x63,0x65,0x5f,0x70,0x6f,0x73,0x3b,
0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,
0x20,0x3d,0x20,0x32,0x29,0x20,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x33,0x20,0x76,
0x69,0x65,0x77,0x5f,0x73,0x70,0x61,0x63,0x65,0x5f,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,0x30,0x29,0x20,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x32,0x20,
0x75,0x76,0x5f,0x69,0x6e,0x3b,0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,
0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x5f,
0x35,0x33,0x20,0x3d,0x20,0x67,0x62,0x75,0x66,0x66,0x65,0x72,0x5f,0x62,0x69,0x6c,
0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,
0x5b,0x35,0x5d,0x2e,0x78,0x79,0x7a,0x20,0x2d,0x20,0x67,0x62,0x75,0x66,0x66,0x65,
0x72,0x5f,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,
0x61,0x72,0x61,0x6d,0x73,0x5b,0x37,0x5d,0x2e,0x78,0x79,0x7a,0x3b,0x0a,0x20,0x20,
0x20,0x20,0x5f,0x35,0x33,0x2e,0x79,0x20,0x3d,0x20,0x30,0x2e,0x30,0x3b,0x0a,0x20,
0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x6c,0x6f,0x6f,0x6b,0x5f,0x64,0x69,0x72,
0x20,0x3d,0x20,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x69,0x7a,0x65,0x28,0x5f,0x35,0x33,
0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x67,0x62,0x75,0x66,0x66,
0x65,0x72,0x5f,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,
0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x31,0x32,0x5d,0x2e,0x78,0x20,0x3e,0x20,0x28,
0x2d,0x31,0x30,0x2e,0x30,0x29,0x29,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x6c,0x6f,0x6f,0x6b,0x5f,0x64,0x69,0x72,0x20,0x3d,
0x20,0x67,0x62,0x75,0x66,0x66,0x65,0x72,0x5f,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,
0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x31,0x32,0x5d,
0x2e,0x78,0x79,0x7a,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,
0x76,0x65,0x63,0x34,0x20,0x5f,0x39,0x38,0x20,0x3d,0x20,0x76,0x65,0x63,0x34,0x28,
0x28,0x67,0x62,0x75,0x66,0x66,0x65,0x72,0x5f,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,
0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x35,0x5d,0x2e,
0x78,0x79,0x7a,0x20,0x2b,0x20,0x28,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x69,0x7a,0x65,
0x28,0x63,0x72,0x6f,0x73,0x73,0x28,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x30,0x2c,
0x20,0x31,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x29,0x2c,0x20,0x6c,0x6f,0x6f,0x6b,
0x5f,0x64,0x69,0x72,0x29,0x29,0x20,0x2a,0x20,0x28,0x28,0x70,0x6f,0x73,0x69,0x74,
0x69,0x6f,0x6e,0x2e,0x78,0x20,0x2d,0x20,0x30,0x2e,0x35,0x29,0x20,0x2a,0x20,0x67,
0x62,0x75,0x66,0x66,0x65,0x72,0x5f,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,
0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x36,0x5d,0x2e,0x78,0x29,
0x29,0x29,0x20,0x2b,0x20,0x28,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x30,0x2c,0x20,
0x31,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x29,0x20,0x2a,0x20,0x28,0x70,0x6f,0x73,
0x69,0x74,0x69,0x6f,0x6e,0x2e,0x79,0x20,0x2a,0x20,0x67,0x62,0x75,0x66,0x66,0x65,
0x72,0x5f,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,
0x61,0x72,0x61,0x6d,0x73,0x5b,0x36,0x5d,0x2e,0x79,0x29,0x29,0x2c,0x20,0x31,0x2e,
0x30,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,0x67,0x62,0x75,0x66,0x66,
0x65,0x72,0x5f,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,
0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d,0x2c,0x20,0x67,0x62,0x75,0x66,0x66,
0x65,0x72,0x5f,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,
0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x31,0x5d,0x2c,0x20,0x67,0x62,0x75,0x66,0x66,
0x65,0x72,0x5f,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,
0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x32,0x5d,0x2c,0x20,0x67,0x62,0x75,0x66,0x66,
0x65,0x72,0x5f,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,
0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x33,0x5d,0x29,0x20,0x2a,0x20,0x5f,0x39,0x38,
0x3b,0x0a,0x20,0x20,0x20,0x20,0x6d,0x61,0x74,0x34,0x20,0x5f,0x31,0x30,0x36,0x20,
0x3d,0x20,0x6d,0x61,0x74,0x34,0x28,0x67,0x62,0x75,0x66,0x66,0x65,0x72,0x5f,0x62,
0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,
0x6d,0x73,0x5b,0x38,0x5d,0x2c,0x20,0x67,0x62,0x75,0x66,0x66,0x65,0x72,0x5f,0x62,
0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,
0x6d,0x73,0x5b,0x39,0x5d,0x2c,0x20,0x67,0x62,0x75,0x66,0x66,0x65,0x72,0x5f,0x62,
0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,
0x6d,0x73,0x5b,0x31,0x30,0x5d,0x2c,0x20,0x67,0x62,0x75,0x66,0x66,0x65,0x72,0x5f,
0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,
0x61,0x6d,0x73,0x5b,0x31,0x31,0x5d,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x69,
0x65,0x77,0x5f,0x73,0x70,0x61,0x63,0x65,0x5f,0x70,0x6f,0x73,0x20,0x3d,0x20,0x28,
0x5f,0x31,0x30,0x36,0x20,0x2a,0x20,0x5f,0x39,0x38,0x29,0x2e,0x78,0x79,0x7a,0x3b,
0x0a,0x20,0x20,0x20,0x20,0x76,0x69,0x65,0x77,0x5f,0x73,0x70,0x61,0x63,0x65,0x5f,
0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x20,0x3d,0x20,0x6d,0x61,0x74,0x33,0x28,0x5f,0x31,
0x30,0x36,0x5b,0x30,0x5d,0x2e,0x78,0x79,0x7a,0x2c,0x20,0x5f,0x31,0x30,0x36,0x5b,
0x31,0x5d,0x2e,0x78,0x79,0x7a,0x2c,0x20,0x5f,0x31,0x30,0x36,0x5b,0x32,0x5d,0x2e,
0x78,0x79,0x7a,0x29,0x20,0x2a,0x20,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x30,0x2c,
0x20,0x31,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,
0x75,0x76,0x5f,0x69,0x6e,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x67,0x62,0x75,
0x66,0x66,0x65,0x72,0x5f,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,
0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x34,0x5d,0x2e,0x78,0x20,0x2b,0x20,
0x28,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2e,0x78,0x20,0x2a,0x20,0x67,0x62,
0x75,0x66,0x66,0x65,0x72,0x5f,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,
0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x34,0x5d,0x2e,0x7a,0x29,0x2c,
0x20,0x67,0x62,0x75,0x66,0x66,0x65,0x72,0x5f,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,
0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x34,0x5d,0x2e,
0x79,0x20,0x2b,0x20,0x28,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2e,0x79,0x20,
0x2a,0x20,0x67,0x62,0x75,0x66,0x66,0x65,0x72,0x5f,0x62,0x69,0x6c,0x6c,0x62,0x6f,
0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x34,0x5d,
0x2e,0x77,0x29,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#version 430
layout(binding = 16) uniform sampler2D gsprite_gspritesmp;
layout(location = 0) in vec2 uv_in;
layout(location = 0) out vec4 out_position;
layout(location = 1) in vec3 view_space_pos;
layout(location = 1) out vec4 out_normal;
layout(location = 2) in vec3 view_space_normal;
void main()
{
vec2 _12 = uv_in;
_12.y = 1.0 - _12.y;
if (texture(gsprite_gspritesmp, _12).w < 0.00999999977648258209228515625)
{
discard;
}
out_position = vec4(view_space_pos, 1.0);
out_normal = vec4(normalize(view_space_normal), 1.0);
}
*/
fs_gbuffer_billboard_source_glsl430 := u8.[
0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x34,0x33,0x30,0x0a,0x0a,0x6c,0x61,
0x79,0x6f,0x75,0x74,0x28,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x20,0x3d,0x20,0x31,
0x36,0x29,0x20,0x75,0x6e,0x69,0x66,0x6f,0x72,0x6d,0x20,0x73,0x61,0x6d,0x70,0x6c,
0x65,0x72,0x32,0x44,0x20,0x67,0x73,0x70,0x72,0x69,0x74,0x65,0x5f,0x67,0x73,0x70,
0x72,0x69,0x74,0x65,0x73,0x6d,0x70,0x3b,0x0a,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,0x32,0x20,0x75,0x76,0x5f,0x69,0x6e,0x3b,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,0x6f,0x75,0x74,0x5f,
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,0x33,0x20,0x76,0x69,0x65,0x77,0x5f,0x73,0x70,0x61,0x63,
0x65,0x5f,0x70,0x6f,0x73,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,
0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x31,0x29,0x20,0x6f,0x75,0x74,0x20,
0x76,0x65,0x63,0x34,0x20,0x6f,0x75,0x74,0x5f,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,0x33,0x20,0x76,0x69,
0x65,0x77,0x5f,0x73,0x70,0x61,0x63,0x65,0x5f,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x3b,
0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,
0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x5f,0x31,0x32,0x20,0x3d,0x20,0x75,
0x76,0x5f,0x69,0x6e,0x3b,0x0a,0x20,0x20,0x20,0x20,0x5f,0x31,0x32,0x2e,0x79,0x20,
0x3d,0x20,0x31,0x2e,0x30,0x20,0x2d,0x20,0x5f,0x31,0x32,0x2e,0x79,0x3b,0x0a,0x20,
0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x67,
0x73,0x70,0x72,0x69,0x74,0x65,0x5f,0x67,0x73,0x70,0x72,0x69,0x74,0x65,0x73,0x6d,
0x70,0x2c,0x20,0x5f,0x31,0x32,0x29,0x2e,0x77,0x20,0x3c,0x20,0x30,0x2e,0x30,0x30,
0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x37,0x37,0x36,0x34,0x38,0x32,0x35,0x38,0x32,
0x30,0x39,0x32,0x32,0x38,0x35,0x31,0x35,0x36,0x32,0x35,0x29,0x0a,0x20,0x20,0x20,
0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x64,0x69,0x73,0x63,0x61,
0x72,0x64,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,
0x74,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x76,0x65,0x63,
0x34,0x28,0x76,0x69,0x65,0x77,0x5f,0x73,0x70,0x61,0x63,0x65,0x5f,0x70,0x6f,0x73,
0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x5f,
0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x20,0x3d,0x20,0x76,0x65,0x63,0x34,0x28,0x6e,0x6f,
0x72,0x6d,0x61,0x6c,0x69,0x7a,0x65,0x28,0x76,0x69,0x65,0x77,0x5f,0x73,0x70,0x61,
0x63,0x65,0x5f,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x29,0x2c,0x20,0x31,0x2e,0x30,0x29,
0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#version 300 es
uniform vec4 gbuffer_billboard_vs_params[13];
layout(location = 0) in vec3 position;
out vec3 view_space_pos;
out vec3 view_space_normal;
out vec2 uv_in;
void main()
{
vec3 _53 = gbuffer_billboard_vs_params[5].xyz - gbuffer_billboard_vs_params[7].xyz;
_53.y = 0.0;
vec3 look_dir = normalize(_53);
if (gbuffer_billboard_vs_params[12].x > (-10.0))
{
look_dir = gbuffer_billboard_vs_params[12].xyz;
}
vec4 _98 = vec4((gbuffer_billboard_vs_params[5].xyz + (normalize(cross(vec3(0.0, 1.0, 0.0), look_dir)) * ((position.x - 0.5) * gbuffer_billboard_vs_params[6].x))) + (vec3(0.0, 1.0, 0.0) * (position.y * gbuffer_billboard_vs_params[6].y)), 1.0);
gl_Position = mat4(gbuffer_billboard_vs_params[0], gbuffer_billboard_vs_params[1], gbuffer_billboard_vs_params[2], gbuffer_billboard_vs_params[3]) * _98;
mat4 _106 = mat4(gbuffer_billboard_vs_params[8], gbuffer_billboard_vs_params[9], gbuffer_billboard_vs_params[10], gbuffer_billboard_vs_params[11]);
view_space_pos = (_106 * _98).xyz;
view_space_normal = mat3(_106[0].xyz, _106[1].xyz, _106[2].xyz) * vec3(0.0, 1.0, 0.0);
uv_in = vec2(gbuffer_billboard_vs_params[4].x + (position.x * gbuffer_billboard_vs_params[4].z), gbuffer_billboard_vs_params[4].y + (position.y * gbuffer_billboard_vs_params[4].w));
}
*/
vs_gbuffer_billboard_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,0x67,0x62,
0x75,0x66,0x66,0x65,0x72,0x5f,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,
0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x31,0x33,0x5d,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,0x33,0x20,0x70,0x6f,0x73,0x69,
0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x33,0x20,0x76,
0x69,0x65,0x77,0x5f,0x73,0x70,0x61,0x63,0x65,0x5f,0x70,0x6f,0x73,0x3b,0x0a,0x6f,
0x75,0x74,0x20,0x76,0x65,0x63,0x33,0x20,0x76,0x69,0x65,0x77,0x5f,0x73,0x70,0x61,
0x63,0x65,0x5f,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x3b,0x0a,0x6f,0x75,0x74,0x20,0x76,
0x65,0x63,0x32,0x20,0x75,0x76,0x5f,0x69,0x6e,0x3b,0x0a,0x0a,0x76,0x6f,0x69,0x64,
0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,
0x63,0x33,0x20,0x5f,0x35,0x33,0x20,0x3d,0x20,0x67,0x62,0x75,0x66,0x66,0x65,0x72,
0x5f,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,
0x72,0x61,0x6d,0x73,0x5b,0x35,0x5d,0x2e,0x78,0x79,0x7a,0x20,0x2d,0x20,0x67,0x62,
0x75,0x66,0x66,0x65,0x72,0x5f,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,
0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x37,0x5d,0x2e,0x78,0x79,0x7a,
0x3b,0x0a,0x20,0x20,0x20,0x20,0x5f,0x35,0x33,0x2e,0x79,0x20,0x3d,0x20,0x30,0x2e,
0x30,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x6c,0x6f,0x6f,0x6b,
0x5f,0x64,0x69,0x72,0x20,0x3d,0x20,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x69,0x7a,0x65,
0x28,0x5f,0x35,0x33,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x67,
0x62,0x75,0x66,0x66,0x65,0x72,0x5f,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,
0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x31,0x32,0x5d,0x2e,0x78,
0x20,0x3e,0x20,0x28,0x2d,0x31,0x30,0x2e,0x30,0x29,0x29,0x0a,0x20,0x20,0x20,0x20,
0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x6c,0x6f,0x6f,0x6b,0x5f,0x64,
0x69,0x72,0x20,0x3d,0x20,0x67,0x62,0x75,0x66,0x66,0x65,0x72,0x5f,0x62,0x69,0x6c,
0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,
0x5b,0x31,0x32,0x5d,0x2e,0x78,0x79,0x7a,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,
0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x34,0x20,0x5f,0x39,0x38,0x20,0x3d,0x20,0x76,
0x65,0x63,0x34,0x28,0x28,0x67,0x62,0x75,0x66,0x66,0x65,0x72,0x5f,0x62,0x69,0x6c,
0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,
0x5b,0x35,0x5d,0x2e,0x78,0x79,0x7a,0x20,0x2b,0x20,0x28,0x6e,0x6f,0x72,0x6d,0x61,
0x6c,0x69,0x7a,0x65,0x28,0x63,0x72,0x6f,0x73,0x73,0x28,0x76,0x65,0x63,0x33,0x28,
0x30,0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x29,0x2c,0x20,
0x6c,0x6f,0x6f,0x6b,0x5f,0x64,0x69,0x72,0x29,0x29,0x20,0x2a,0x20,0x28,0x28,0x70,
0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2e,0x78,0x20,0x2d,0x20,0x30,0x2e,0x35,0x29,
0x20,0x2a,0x20,0x67,0x62,0x75,0x66,0x66,0x65,0x72,0x5f,0x62,0x69,0x6c,0x6c,0x62,
0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x36,
0x5d,0x2e,0x78,0x29,0x29,0x29,0x20,0x2b,0x20,0x28,0x76,0x65,0x63,0x33,0x28,0x30,
0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x29,0x20,0x2a,0x20,
0x28,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2e,0x79,0x20,0x2a,0x20,0x67,0x62,
0x75,0x66,0x66,0x65,0x72,0x5f,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,
0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x36,0x5d,0x2e,0x79,0x29,0x29,
0x2c,0x20,0x31,0x2e,0x30,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,0x67,
0x62,0x75,0x66,0x66,0x65,0x72,0x5f,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,
0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d,0x2c,0x20,0x67,
0x62,0x75,0x66,0x66,0x65,0x72,0x5f,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,
0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x31,0x5d,0x2c,0x20,0x67,
0x62,0x75,0x66,0x66,0x65,0x72,0x5f,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,
0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x32,0x5d,0x2c,0x20,0x67,
0x62,0x75,0x66,0x66,0x65,0x72,0x5f,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,
0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x33,0x5d,0x29,0x20,0x2a,
0x20,0x5f,0x39,0x38,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6d,0x61,0x74,0x34,0x20,0x5f,
0x31,0x30,0x36,0x20,0x3d,0x20,0x6d,0x61,0x74,0x34,0x28,0x67,0x62,0x75,0x66,0x66,
0x65,0x72,0x5f,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,
0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x38,0x5d,0x2c,0x20,0x67,0x62,0x75,0x66,0x66,
0x65,0x72,0x5f,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,
0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x39,0x5d,0x2c,0x20,0x67,0x62,0x75,0x66,0x66,
0x65,0x72,0x5f,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,
0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x31,0x30,0x5d,0x2c,0x20,0x67,0x62,0x75,0x66,
0x66,0x65,0x72,0x5f,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,
0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x31,0x31,0x5d,0x29,0x3b,0x0a,0x20,0x20,
0x20,0x20,0x76,0x69,0x65,0x77,0x5f,0x73,0x70,0x61,0x63,0x65,0x5f,0x70,0x6f,0x73,
0x20,0x3d,0x20,0x28,0x5f,0x31,0x30,0x36,0x20,0x2a,0x20,0x5f,0x39,0x38,0x29,0x2e,
0x78,0x79,0x7a,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x69,0x65,0x77,0x5f,0x73,0x70,
0x61,0x63,0x65,0x5f,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x20,0x3d,0x20,0x6d,0x61,0x74,
0x33,0x28,0x5f,0x31,0x30,0x36,0x5b,0x30,0x5d,0x2e,0x78,0x79,0x7a,0x2c,0x20,0x5f,
0x31,0x30,0x36,0x5b,0x31,0x5d,0x2e,0x78,0x79,0x7a,0x2c,0x20,0x5f,0x31,0x30,0x36,
0x5b,0x32,0x5d,0x2e,0x78,0x79,0x7a,0x29,0x20,0x2a,0x20,0x76,0x65,0x63,0x33,0x28,
0x30,0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x29,0x3b,0x0a,
0x20,0x20,0x20,0x20,0x75,0x76,0x5f,0x69,0x6e,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,
0x28,0x67,0x62,0x75,0x66,0x66,0x65,0x72,0x5f,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,
0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x34,0x5d,0x2e,
0x78,0x20,0x2b,0x20,0x28,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2e,0x78,0x20,
0x2a,0x20,0x67,0x62,0x75,0x66,0x66,0x65,0x72,0x5f,0x62,0x69,0x6c,0x6c,0x62,0x6f,
0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x34,0x5d,
0x2e,0x7a,0x29,0x2c,0x20,0x67,0x62,0x75,0x66,0x66,0x65,0x72,0x5f,0x62,0x69,0x6c,
0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,
0x5b,0x34,0x5d,0x2e,0x79,0x20,0x2b,0x20,0x28,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,
0x6e,0x2e,0x79,0x20,0x2a,0x20,0x67,0x62,0x75,0x66,0x66,0x65,0x72,0x5f,0x62,0x69,
0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,
0x73,0x5b,0x34,0x5d,0x2e,0x77,0x29,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#version 300 es
precision mediump float;
precision highp int;
uniform highp sampler2D gsprite_gspritesmp;
in highp vec2 uv_in;
layout(location = 0) out highp vec4 out_position;
in highp vec3 view_space_pos;
layout(location = 1) out highp vec4 out_normal;
in highp vec3 view_space_normal;
void main()
{
highp vec2 _12 = uv_in;
_12.y = 1.0 - _12.y;
if (texture(gsprite_gspritesmp, _12).w < 0.00999999977648258209228515625)
{
discard;
}
out_position = vec4(view_space_pos, 1.0);
out_normal = vec4(normalize(view_space_normal), 1.0);
}
*/
fs_gbuffer_billboard_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,0x75,
0x6e,0x69,0x66,0x6f,0x72,0x6d,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x73,0x61,0x6d,
0x70,0x6c,0x65,0x72,0x32,0x44,0x20,0x67,0x73,0x70,0x72,0x69,0x74,0x65,0x5f,0x67,
0x73,0x70,0x72,0x69,0x74,0x65,0x73,0x6d,0x70,0x3b,0x0a,0x0a,0x69,0x6e,0x20,0x68,
0x69,0x67,0x68,0x70,0x20,0x76,0x65,0x63,0x32,0x20,0x75,0x76,0x5f,0x69,0x6e,0x3b,
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,0x6f,0x75,0x74,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,
0x6e,0x3b,0x0a,0x69,0x6e,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x76,0x65,0x63,0x33,
0x20,0x76,0x69,0x65,0x77,0x5f,0x73,0x70,0x61,0x63,0x65,0x5f,0x70,0x6f,0x73,0x3b,
0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,
0x20,0x3d,0x20,0x31,0x29,0x20,0x6f,0x75,0x74,0x20,0x68,0x69,0x67,0x68,0x70,0x20,
0x76,0x65,0x63,0x34,0x20,0x6f,0x75,0x74,0x5f,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x3b,
0x0a,0x69,0x6e,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x76,0x65,0x63,0x33,0x20,0x76,
0x69,0x65,0x77,0x5f,0x73,0x70,0x61,0x63,0x65,0x5f,0x6e,0x6f,0x72,0x6d,0x61,0x6c,
0x3b,0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,
0x0a,0x20,0x20,0x20,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x76,0x65,0x63,0x32,0x20,
0x5f,0x31,0x32,0x20,0x3d,0x20,0x75,0x76,0x5f,0x69,0x6e,0x3b,0x0a,0x20,0x20,0x20,
0x20,0x5f,0x31,0x32,0x2e,0x79,0x20,0x3d,0x20,0x31,0x2e,0x30,0x20,0x2d,0x20,0x5f,
0x31,0x32,0x2e,0x79,0x3b,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x74,0x65,
0x78,0x74,0x75,0x72,0x65,0x28,0x67,0x73,0x70,0x72,0x69,0x74,0x65,0x5f,0x67,0x73,
0x70,0x72,0x69,0x74,0x65,0x73,0x6d,0x70,0x2c,0x20,0x5f,0x31,0x32,0x29,0x2e,0x77,
0x20,0x3c,0x20,0x30,0x2e,0x30,0x30,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x37,0x37,
0x36,0x34,0x38,0x32,0x35,0x38,0x32,0x30,0x39,0x32,0x32,0x38,0x35,0x31,0x35,0x36,
0x32,0x35,0x29,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x64,0x69,0x73,0x63,0x61,0x72,0x64,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,
0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,
0x6e,0x20,0x3d,0x20,0x76,0x65,0x63,0x34,0x28,0x76,0x69,0x65,0x77,0x5f,0x73,0x70,
0x61,0x63,0x65,0x5f,0x70,0x6f,0x73,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,
0x20,0x20,0x20,0x6f,0x75,0x74,0x5f,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x20,0x3d,0x20,
0x76,0x65,0x63,0x34,0x28,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x69,0x7a,0x65,0x28,0x76,
0x69,0x65,0x77,0x5f,0x73,0x70,0x61,0x63,0x65,0x5f,0x6e,0x6f,0x72,0x6d,0x61,0x6c,
0x29,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct gbuffer_billboard_vs_params
{
float4x4 mvp;
float4 uvs;
float3 offset;
float2 size;
float3 cam;
float4x4 view_matrix;
float3 faceDir;
};
struct main0_out
{
float2 uv_in [[user(locn0)]];
float3 view_space_pos [[user(locn1)]];
float3 view_space_normal [[user(locn2)]];
float4 gl_Position [[position]];
};
struct main0_in
{
float3 position [[attribute(0)]];
};
vertex main0_out main0(main0_in in [[stage_in]], constant gbuffer_billboard_vs_params& _24 [[buffer(0)]])
{
main0_out out = {};
float3 _53 = _24.offset - _24.cam;
_53.y = 0.0;
float3 look_dir = fast::normalize(_53);
if (_24.faceDir.x > (-10.0))
{
look_dir = _24.faceDir;
}
float4 _98 = float4((_24.offset + (fast::normalize(cross(float3(0.0, 1.0, 0.0), look_dir)) * ((in.position.x - 0.5) * _24.size.x))) + (float3(0.0, 1.0, 0.0) * (in.position.y * _24.size.y)), 1.0);
out.gl_Position = _24.mvp * _98;
out.view_space_pos = (_24.view_matrix * _98).xyz;
out.view_space_normal = float3x3(_24.view_matrix[0].xyz, _24.view_matrix[1].xyz, _24.view_matrix[2].xyz) * float3(0.0, 1.0, 0.0);
out.uv_in = float2(_24.uvs.x + (in.position.x * _24.uvs.z), _24.uvs.y + (in.position.y * _24.uvs.w));
return out;
}
*/
vs_gbuffer_billboard_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,0x67,
0x62,0x75,0x66,0x66,0x65,0x72,0x5f,0x62,0x69,0x6c,0x6c,0x62,0x6f,0x61,0x72,0x64,
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,0x20,
0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x75,0x76,0x73,0x3b,0x0a,0x20,
0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x33,0x20,0x6f,0x66,0x66,0x73,0x65,0x74,
0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,0x20,0x73,0x69,0x7a,
0x65,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x33,0x20,0x63,0x61,
0x6d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x78,0x34,0x20,
0x76,0x69,0x65,0x77,0x5f,0x6d,0x61,0x74,0x72,0x69,0x78,0x3b,0x0a,0x20,0x20,0x20,
0x20,0x66,0x6c,0x6f,0x61,0x74,0x33,0x20,0x66,0x61,0x63,0x65,0x44,0x69,0x72,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,0x32,0x20,0x75,0x76,0x5f,0x69,0x6e,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,0x28,
0x6c,0x6f,0x63,0x6e,0x30,0x29,0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,
0x6f,0x61,0x74,0x33,0x20,0x76,0x69,0x65,0x77,0x5f,0x73,0x70,0x61,0x63,0x65,0x5f,
0x70,0x6f,0x73,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,0x31,
0x29,0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x33,0x20,
0x76,0x69,0x65,0x77,0x5f,0x73,0x70,0x61,0x63,0x65,0x5f,0x6e,0x6f,0x72,0x6d,0x61,
0x6c,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,0x32,0x29,0x5d,
0x5d,0x3b,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,0x33,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,0x7d,0x3b,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,0x67,0x62,0x75,0x66,0x66,0x65,0x72,0x5f,0x62,0x69,0x6c,0x6c,0x62,0x6f,
0x61,0x72,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x26,0x20,0x5f,
0x32,0x34,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,
0x66,0x6c,0x6f,0x61,0x74,0x33,0x20,0x5f,0x35,0x33,0x20,0x3d,0x20,0x5f,0x32,0x34,
0x2e,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2d,0x20,0x5f,0x32,0x34,0x2e,0x63,0x61,
0x6d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x5f,0x35,0x33,0x2e,0x79,0x20,0x3d,0x20,0x30,
0x2e,0x30,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x33,0x20,0x6c,
0x6f,0x6f,0x6b,0x5f,0x64,0x69,0x72,0x20,0x3d,0x20,0x66,0x61,0x73,0x74,0x3a,0x3a,
0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x69,0x7a,0x65,0x28,0x5f,0x35,0x33,0x29,0x3b,0x0a,
0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x5f,0x32,0x34,0x2e,0x66,0x61,0x63,0x65,
0x44,0x69,0x72,0x2e,0x78,0x20,0x3e,0x20,0x28,0x2d,0x31,0x30,0x2e,0x30,0x29,0x29,
0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x6c,
0x6f,0x6f,0x6b,0x5f,0x64,0x69,0x72,0x20,0x3d,0x20,0x5f,0x32,0x34,0x2e,0x66,0x61,
0x63,0x65,0x44,0x69,0x72,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,
0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x5f,0x39,0x38,0x20,0x3d,0x20,0x66,0x6c,
0x6f,0x61,0x74,0x34,0x28,0x28,0x5f,0x32,0x34,0x2e,0x6f,0x66,0x66,0x73,0x65,0x74,
0x20,0x2b,0x20,0x28,0x66,0x61,0x73,0x74,0x3a,0x3a,0x6e,0x6f,0x72,0x6d,0x61,0x6c,
0x69,0x7a,0x65,0x28,0x63,0x72,0x6f,0x73,0x73,0x28,0x66,0x6c,0x6f,0x61,0x74,0x33,
0x28,0x30,0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x29,0x2c,
0x20,0x6c,0x6f,0x6f,0x6b,0x5f,0x64,0x69,0x72,0x29,0x29,0x20,0x2a,0x20,0x28,0x28,
0x69,0x6e,0x2e,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2e,0x78,0x20,0x2d,0x20,
0x30,0x2e,0x35,0x29,0x20,0x2a,0x20,0x5f,0x32,0x34,0x2e,0x73,0x69,0x7a,0x65,0x2e,
0x78,0x29,0x29,0x29,0x20,0x2b,0x20,0x28,0x66,0x6c,0x6f,0x61,0x74,0x33,0x28,0x30,
0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x29,0x20,0x2a,0x20,
0x28,0x69,0x6e,0x2e,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2e,0x79,0x20,0x2a,
0x20,0x5f,0x32,0x34,0x2e,0x73,0x69,0x7a,0x65,0x2e,0x79,0x29,0x29,0x2c,0x20,0x31,
0x2e,0x30,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,0x32,0x34,0x2e,0x6d,
0x76,0x70,0x20,0x2a,0x20,0x5f,0x39,0x38,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,
0x74,0x2e,0x76,0x69,0x65,0x77,0x5f,0x73,0x70,0x61,0x63,0x65,0x5f,0x70,0x6f,0x73,
0x20,0x3d,0x20,0x28,0x5f,0x32,0x34,0x2e,0x76,0x69,0x65,0x77,0x5f,0x6d,0x61,0x74,
0x72,0x69,0x78,0x20,0x2a,0x20,0x5f,0x39,0x38,0x29,0x2e,0x78,0x79,0x7a,0x3b,0x0a,
0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,0x76,0x69,0x65,0x77,0x5f,0x73,0x70,0x61,
0x63,0x65,0x5f,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x20,0x3d,0x20,0x66,0x6c,0x6f,0x61,
0x74,0x33,0x78,0x33,0x28,0x5f,0x32,0x34,0x2e,0x76,0x69,0x65,0x77,0x5f,0x6d,0x61,
0x74,0x72,0x69,0x78,0x5b,0x30,0x5d,0x2e,0x78,0x79,0x7a,0x2c,0x20,0x5f,0x32,0x34,
0x2e,0x76,0x69,0x65,0x77,0x5f,0x6d,0x61,0x74,0x72,0x69,0x78,0x5b,0x31,0x5d,0x2e,
0x78,0x79,0x7a,0x2c,0x20,0x5f,0x32,0x34,0x2e,0x76,0x69,0x65,0x77,0x5f,0x6d,0x61,
0x74,0x72,0x69,0x78,0x5b,0x32,0x5d,0x2e,0x78,0x79,0x7a,0x29,0x20,0x2a,0x20,0x66,
0x6c,0x6f,0x61,0x74,0x33,0x28,0x30,0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30,0x2c,0x20,
0x30,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,0x75,0x76,
0x5f,0x69,0x6e,0x20,0x3d,0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,0x28,0x5f,0x32,0x34,
0x2e,0x75,0x76,0x73,0x2e,0x78,0x20,0x2b,0x20,0x28,0x69,0x6e,0x2e,0x70,0x6f,0x73,
0x69,0x74,0x69,0x6f,0x6e,0x2e,0x78,0x20,0x2a,0x20,0x5f,0x32,0x34,0x2e,0x75,0x76,
0x73,0x2e,0x7a,0x29,0x2c,0x20,0x5f,0x32,0x34,0x2e,0x75,0x76,0x73,0x2e,0x79,0x20,
0x2b,0x20,0x28,0x69,0x6e,0x2e,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2e,0x79,
0x20,0x2a,0x20,0x5f,0x32,0x34,0x2e,0x75,0x76,0x73,0x2e,0x77,0x29,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 out_position [[color(0)]];
float4 out_normal [[color(1)]];
};
struct main0_in
{
float2 uv_in [[user(locn0)]];
float3 view_space_pos [[user(locn1)]];
float3 view_space_normal [[user(locn2)]];
};
fragment main0_out main0(main0_in in [[stage_in]], texture2d<float> gsprite [[texture(0)]], sampler gspritesmp [[sampler(0)]])
{
main0_out out = {};
float2 _12 = in.uv_in;
_12.y = 1.0 - _12.y;
if (gsprite.sample(gspritesmp, _12).w < 0.00999999977648258209228515625)
{
discard_fragment();
}
out.out_position = float4(in.view_space_pos, 1.0);
out.out_normal = float4(fast::normalize(in.view_space_normal), 1.0);
return out;
}
*/
fs_gbuffer_billboard_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,0x6f,0x75,0x74,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,
0x6f,0x6e,0x20,0x5b,0x5b,0x63,0x6f,0x6c,0x6f,0x72,0x28,0x30,0x29,0x5d,0x5d,0x3b,
0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x6f,0x75,0x74,0x5f,
0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x20,0x5b,0x5b,0x63,0x6f,0x6c,0x6f,0x72,0x28,0x31,
0x29,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,0x32,0x20,0x75,0x76,0x5f,0x69,0x6e,0x20,0x5b,0x5b,0x75,0x73,
0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,0x30,0x29,0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,
0x20,0x66,0x6c,0x6f,0x61,0x74,0x33,0x20,0x76,0x69,0x65,0x77,0x5f,0x73,0x70,0x61,
0x63,0x65,0x5f,0x70,0x6f,0x73,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,
0x63,0x6e,0x31,0x29,0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,
0x74,0x33,0x20,0x76,0x69,0x65,0x77,0x5f,0x73,0x70,0x61,0x63,0x65,0x5f,0x6e,0x6f,
0x72,0x6d,0x61,0x6c,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,
0x32,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,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,0x74,0x65,0x78,
0x74,0x75,0x72,0x65,0x32,0x64,0x3c,0x66,0x6c,0x6f,0x61,0x74,0x3e,0x20,0x67,0x73,
0x70,0x72,0x69,0x74,0x65,0x20,0x5b,0x5b,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,
0x30,0x29,0x5d,0x5d,0x2c,0x20,0x73,0x61,0x6d,0x70,0x6c,0x65,0x72,0x20,0x67,0x73,
0x70,0x72,0x69,0x74,0x65,0x73,0x6d,0x70,0x20,0x5b,0x5b,0x73,0x61,0x6d,0x70,0x6c,
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,0x66,0x6c,0x6f,0x61,0x74,0x32,0x20,0x5f,0x31,
0x32,0x20,0x3d,0x20,0x69,0x6e,0x2e,0x75,0x76,0x5f,0x69,0x6e,0x3b,0x0a,0x20,0x20,
0x20,0x20,0x5f,0x31,0x32,0x2e,0x79,0x20,0x3d,0x20,0x31,0x2e,0x30,0x20,0x2d,0x20,
0x5f,0x31,0x32,0x2e,0x79,0x3b,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x67,
0x73,0x70,0x72,0x69,0x74,0x65,0x2e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x28,0x67,0x73,
0x70,0x72,0x69,0x74,0x65,0x73,0x6d,0x70,0x2c,0x20,0x5f,0x31,0x32,0x29,0x2e,0x77,
0x20,0x3c,0x20,0x30,0x2e,0x30,0x30,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x37,0x37,
0x36,0x34,0x38,0x32,0x35,0x38,0x32,0x30,0x39,0x32,0x32,0x38,0x35,0x31,0x35,0x36,
0x32,0x35,0x29,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x64,0x69,0x73,0x63,0x61,0x72,0x64,0x5f,0x66,0x72,0x61,0x67,0x6d,0x65,
0x6e,0x74,0x28,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,
0x6f,0x75,0x74,0x2e,0x6f,0x75,0x74,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,
0x20,0x3d,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x28,0x69,0x6e,0x2e,0x76,0x69,0x65,
0x77,0x5f,0x73,0x70,0x61,0x63,0x65,0x5f,0x70,0x6f,0x73,0x2c,0x20,0x31,0x2e,0x30,
0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,0x6f,0x75,0x74,0x5f,0x6e,
0x6f,0x72,0x6d,0x61,0x6c,0x20,0x3d,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x28,0x66,
0x61,0x73,0x74,0x3a,0x3a,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x69,0x7a,0x65,0x28,0x69,
0x6e,0x2e,0x76,0x69,0x65,0x77,0x5f,0x73,0x70,0x61,0x63,0x65,0x5f,0x6e,0x6f,0x72,
0x6d,0x61,0x6c,0x29,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,
];
gbuffer_billboard_shader_desc :: (backend: sg_backend) -> sg_shader_desc {
desc: sg_shader_desc;
desc.label = "gbuffer_billboard_shader";
if backend == {
case .GLCORE;
desc.vertex_func.source = xx *vs_gbuffer_billboard_source_glsl430;
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_gbuffer_billboard_source_glsl430;
desc.fragment_func.entry = "main";
desc.attrs[0].base_type = .FLOAT;
desc.attrs[0].glsl_name = "position";
desc.uniform_blocks[0].stage = .VERTEX;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 208;
desc.uniform_blocks[0].glsl_uniforms[0].type = .FLOAT4;
desc.uniform_blocks[0].glsl_uniforms[0].array_count = 13;
desc.uniform_blocks[0].glsl_uniforms[0].glsl_name = "gbuffer_billboard_vs_params";
desc.images[0].stage = .FRAGMENT;
desc.images[0].multisampled = false;
desc.images[0].image_type = ._2D;
desc.images[0].sample_type = .FLOAT;
desc.samplers[0].stage = .FRAGMENT;
desc.samplers[0].sampler_type = .FILTERING;
desc.image_sampler_pairs[0].stage = .FRAGMENT;
desc.image_sampler_pairs[0].image_slot = 0;
desc.image_sampler_pairs[0].sampler_slot = 0;
desc.image_sampler_pairs[0].glsl_name = "gsprite_gspritesmp";
case .GLES3;
desc.vertex_func.source = xx *vs_gbuffer_billboard_source_glsl300es;
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_gbuffer_billboard_source_glsl300es;
desc.fragment_func.entry = "main";
desc.attrs[0].base_type = .FLOAT;
desc.attrs[0].glsl_name = "position";
desc.uniform_blocks[0].stage = .VERTEX;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 208;
desc.uniform_blocks[0].glsl_uniforms[0].type = .FLOAT4;
desc.uniform_blocks[0].glsl_uniforms[0].array_count = 13;
desc.uniform_blocks[0].glsl_uniforms[0].glsl_name = "gbuffer_billboard_vs_params";
desc.images[0].stage = .FRAGMENT;
desc.images[0].multisampled = false;
desc.images[0].image_type = ._2D;
desc.images[0].sample_type = .FLOAT;
desc.samplers[0].stage = .FRAGMENT;
desc.samplers[0].sampler_type = .FILTERING;
desc.image_sampler_pairs[0].stage = .FRAGMENT;
desc.image_sampler_pairs[0].image_slot = 0;
desc.image_sampler_pairs[0].sampler_slot = 0;
desc.image_sampler_pairs[0].glsl_name = "gsprite_gspritesmp";
case .METAL_MACOS;
desc.vertex_func.source = xx *vs_gbuffer_billboard_source_metal_macos;
desc.vertex_func.entry = "main0";
desc.fragment_func.source = xx *fs_gbuffer_billboard_source_metal_macos;
desc.fragment_func.entry = "main0";
desc.attrs[0].base_type = .FLOAT;
desc.uniform_blocks[0].stage = .VERTEX;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 208;
desc.uniform_blocks[0].msl_buffer_n = 0;
desc.images[0].stage = .FRAGMENT;
desc.images[0].multisampled = false;
desc.images[0].image_type = ._2D;
desc.images[0].sample_type = .FLOAT;
desc.images[0].msl_texture_n = 0;
desc.samplers[0].stage = .FRAGMENT;
desc.samplers[0].sampler_type = .FILTERING;
desc.samplers[0].msl_sampler_n = 0;
desc.image_sampler_pairs[0].stage = .FRAGMENT;
desc.image_sampler_pairs[0].image_slot = 0;
desc.image_sampler_pairs[0].sampler_slot = 0;
}
return desc;
}

Some files were not shown because too many files have changed in this diff Show More