Compare commits

...

2 Commits

Author SHA1 Message Date
dcad1dbe7f rendering improvements 2026-04-30 22:45:04 +03:00
5e30f3f2ab WIP 2026-04-23 11:41:44 +03:00
67 changed files with 18052 additions and 10457 deletions

16
ENGINE_TODO.md Normal file
View File

@ -0,0 +1,16 @@
# Todo for engine feature polish
## Particles
- Particle counts quite limited, increase.
## Post-processing
- DOF and bloom are both doing this thing where they draw to a small resolution buffer.
- It's performant now compared to old approach, but is bad. We need to do the blur thing
in a shader X and Y separately for both.
## Trile rendering
- Too many triangles in meshgen.
- Shadowmap should move with camera.
- Reflection trile rendering is taking forever compared to gbuffer pass even though it
shouldn't really be doing much more.
-

View File

@ -47,6 +47,46 @@ build_options_from_args :: (args: []string) -> Trueno_Build_Options {
return opts;
}
// Scans `dir` recursively and returns the size of the largest file whose
// short name ends with `ext`. Returns `floor` when no matching file exists.
max_asset_file_size :: (dir: string, ext: string, floor: s64 = 0) -> s64 {
Ctx :: struct { ext: string; max: s64; }
ctx: Ctx;
ctx.ext = ext;
visit_files(dir, true, *ctx, (info: *File_Visit_Info, c: *Ctx) {
if info.is_directory return;
if !ends_with(info.short_name, c.ext) return;
f, ok := file_open(info.full_name);
defer if ok file_close(*f);
if !ok return;
size, ok2 := file_length(f);
if ok2 && size > c.max then c.max = size;
});
return max(floor, ctx.max);
}
add_asset_buffer_sizes_to_compiler_strings :: (trueno_opts: Trueno_Build_Options, w: Workspace) {
pack_dir := ifx trueno_opts.test_exe_engine || trueno_opts.test_exe_game then "./test_packs" else "./packs";
game_resources_dir := ifx trueno_opts.test_exe_engine || trueno_opts.test_exe_game then "./test_game/resources" else "./game/resources";
sizes: [6]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);
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 {
add_build_string(tprint("% :: %;\n", names[i], sizes[i]), w);
}
}
add_trueno_opts_to_compiler_strings :: (trueno_opts : Trueno_Build_Options, w: Workspace) {
#import "String";
bool_to_string :: (b: bool) -> string {
@ -85,11 +125,11 @@ wasm_copy_assets :: () {
}
}
metaprogramming_loop :: (trueno_opts: Trueno_Build_Options, w: *Workspace) {
metaprogramming_loop :: (trueno_opts: Trueno_Build_Options, w: *Workspace, iprof_plugin: *Iprof.My_Plugin = null) {
while true {
message := compiler_wait_for_message();
// @ToDo: add iprof to this refactored metaprogram
// if trueno_opts.iprof_enabled then iprof_plugin.message(iprof_plugin, message)
// Fixed iprof integration
if iprof_plugin then iprof_plugin.message(iprof_plugin, message);
custom_message_handler(message, w);
if message.kind == .COMPLETE then break;
}
@ -112,25 +152,27 @@ native_build :: (opts: Build_Options, trueno_opts: Trueno_Build_Options) {
set_build_options(opts, w);
iprof_plugin: *Iprof.My_Plugin;
intercept_flags: Intercept_Flags;
// profile := iprof;
if trueno_opts.iprof_enabled {
iprof_plugin = cast(*Iprof.My_Plugin) Iprof.get_plugin();
iprof_plugin.workspace = w;
// Instrumenting all modules creates >65536 unique (parent,zone) hash entries,
// which trips Iprof's MAX_HASH_SIZE assert. Limit to our own files.
iprof_plugin.instrument_modules = false;
iprof_plugin.before_intercept(iprof_plugin, *intercept_flags);
}
// if profile {
// iprof_plugin = cast(*Iprof.My_Plugin) Iprof.get_plugin();
// iprof_plugin.workspace = w;
// // Set options
// iprof_plugin.instrument_modules = true;
// iprof_plugin.before_intercept(iprof_plugin, null);
// }
compiler_begin_intercept(w);
compiler_begin_intercept(w, intercept_flags);
if trueno_opts.iprof_enabled {
iprof_plugin.add_source(iprof_plugin);
}
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);
metaprogramming_loop(trueno_opts, *w, iprof_plugin);
if trueno_opts.iprof_enabled {
iprof_plugin.finish(iprof_plugin);
@ -178,7 +220,8 @@ wasm_build :: (opts: Build_Options, trueno_opts: Trueno_Build_Options) {
compiler_begin_intercept(w);
add_trueno_opts_to_compiler_strings(trueno_opts, w);
add_build_file("src/platform_specific/main_web.jai", 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);
@ -225,4 +268,6 @@ wasm_build :: (opts: Build_Options, trueno_opts: Trueno_Build_Options) {
#import "Compiler";
#import "Process";
#import "File";
#import "String";
#import "File_Utilities";

View File

@ -0,0 +1,27 @@
_______________
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: 1.8MB -> 0.6MB (1.2MB saved, 65.9% smaller)

20
perf Normal file
View File

@ -0,0 +1,20 @@
FRAME PRE OPTIMIZATION!
| Pass | Targets | Duration (µs) | What it does |
|--------------|---------|---------------|--------------|
| Colour Pass #1 | 1T+D | 257.64 | Draws all triles and billboards with the shadowmap shader into a shadowmap|
| Colour Pass #2 | 1T+D | 2226.80 | Draws triles and billboard for planar reflection, does viewport culling, uses mostly same shaders as main pass |
| Colour Pass #3 | 2T+D | 886.92 | Gbuffer pass. All triles and billboards. Special gbuffer shader. |
| Colour Pass #4 | 1T+D | 727.08 | SSAO texture draw pass. Output 4k |
| Colour Pass #5 | 1T+D | 500.60 | SSAO blur, output 1920x1066 |
| Colour Pass #6 | 1T+D | 4201.48 | Main pass, draws water (284us) draws billboards, samples previous buffers, draws particles (don't seem to be heavy, max 21us) draws triles draws billboards |
| Colour Pass #7 | 1T+D | 842.84 | Extracts bright parts and blurs? For bloom |
| Colour Pass #8 | 1T+D | 1069.52 | Applies bloom |
| Colour Pass #9 | 1T+D | 1648.36 | Blurs whole image for DOF purposes |
| Colour Pass #10 | 1T+D | 888.84 | I think this is dilution for the blurred image but not totally sure. |
| Colour Pass #11 | 1T+D | 1105.04 | Mixes blurred and original for DOF effect |
| Colour Pass #12 | 1T+D | 288.28 | Final pass, does color correction and some effects |
| **Total** | | **14643.40** | |

View File

@ -1,4 +1,4 @@
master_volume 0.475357
music_volume 0.522385
master_volume 0.364372
music_volume 1
sfx_volume 1
fullscreen 0
fullscreen 1

View File

@ -6,57 +6,60 @@ Pool :: #import "Pool";
#load "loaders.jai";
MAIN_CHUNK_BUFFER_SIZE : s64 : 256 * 1024;
RDM_CHUNK_BUFFER_SIZE : s64 : 64 * 1024 * 1024;
// 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
// by first.jai after scanning the actual asset files at compile time.
Active_Fetch :: struct {
occupied : bool;
req : Fetch_Request;
accumulated : [..]u8;
chunk_buf : []u8;
}
MAX_FETCH_SLOTS :: 16;
#scope_export
CHANNEL_MAIN : u32 : 0;
CHANNEL_RDM : u32 : 1;
// Replaces the old should_block / should_block_engine bool pair.
Load_Priority :: enum u8 {
BLOCK_ENGINE; // must finish before the first game frame
LOADING_SCREEN; // show loading screen while pending
BACKGROUND; // stream silently; game runs normally
}
Fetch_Type :: enum {
PACK;
WORLD;
WORLD_CHUNKS;
RDM_ATLAS;
RDM_LOOKUP;
RDM_MANIFEST;
SHGRID;
}
Fetch_Request :: struct {
type : Fetch_Type;
path : string;
// Pack
pack_name : string;
should_block : bool;
should_block_engine : bool;
// World / RDM
world_name : string;
chunk_key : Chunk_Key;
// Atlas GPU image held between RDM_ATLAS and its paired RDM_LOOKUP fetch.
rdm_pending_atlas : sg_image;
type : Fetch_Type;
path : string;
priority : Load_Priority;
// Copy of world.json carried between WORLD and WORLD_CHUNKS fetches.
world_json_data : []u8;
// PACK
pack_name : string;
// WORLD / RDM / SH
world_name : string;
chunk_key : Chunk_Key;
// WORLD_CHUNKS: JSON carried forward from the WORLD fetch
world_json_data : []u8;
}
// One in-flight sfetch request. `buf` is allocated when dispatched and
// freed (or handed to Loaded_Pack) when the callback fires.
Fetch_Slot :: struct {
occupied : bool;
req : Fetch_Request;
buf : []u8;
}
Asset_Manager :: struct {
active : [2]Active_Fetch;
main_queue : [..]Fetch_Request;
rdm_queue : [..]Fetch_Request;
loadedPacks : [..]Loaded_Pack;
pending_hot_reload : bool;
hot_reload_unpause_pending : bool;
slots : [MAX_FETCH_SLOTS]Fetch_Slot;
queue : [..]Fetch_Request;
loadedPacks : [..]Loaded_Pack;
pending_hot_reload : bool;
hot_reload_unpause_pending : bool;
}
g_asset_manager : Asset_Manager;
@ -66,49 +69,48 @@ g_asset_manager : Asset_Manager;
#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;
}
}
fetch_callback :: (res: *sfetch_response_t) #c_call {
push_context,defer_pop default_context;
af := *g_asset_manager.active[res.channel];
if res.fetched {
chunk_count := res.data.size.(s64);
needed := af.accumulated.count + chunk_count;
if af.accumulated.allocated < needed {
new_cap := max(needed, max(af.accumulated.allocated * 2, 1024 * 1024));
array_reserve(*af.accumulated, new_cap);
}
memcpy(af.accumulated.data + af.accumulated.count, res.data.ptr, chunk_count);
af.accumulated.count = needed;
}
// sokol copied the slot index into res.user_data when we sent the request.
slot_idx := (cast(*u32) res.user_data).*;
slot := *g_asset_manager.slots[slot_idx];
if !res.finished then return;
// Mark channel free before processing so that enqueued follow-up requests
// (WORLD -> WORLD_CHUNKS, RDM_ATLAS -> RDM_LOOKUP) are visible on the next tick.
af.occupied = false;
req := af.req;
slot.occupied = false;
req := slot.req;
if res.failed {
handle_fetch_failed(*req);
array_reset(*af.accumulated);
free(slot.buf.data);
slot.buf = .{};
return;
}
data : []u8;
data.data = af.accumulated.data;
data.count = af.accumulated.count;
data: []u8;
data.data = cast(*u8) res.data.ptr;
data.count = cast(s64) res.data.size;
process_completed_fetch(*req, data);
if req.type == .PACK {
// process_completed_fetch either stored data in Loaded_Pack.data_buffer or
// freed it on parse failure. Either way, zero af.accumulated without freeing.
af.accumulated.data = null;
af.accumulated.count = 0;
af.accumulated.allocated = 0;
// process_completed_fetch transferred ownership to Loaded_Pack.data_buffer.
slot.buf = .{};
} else {
array_reset(*af.accumulated);
free(slot.buf.data);
slot.buf = .{};
}
}
@ -120,12 +122,12 @@ handle_fetch_failed :: (req: *Fetch_Request) {
case .WORLD;
if ends_with(req.path, "world.json") {
fallback_req : Fetch_Request;
fallback_req.type = .WORLD;
fallback_req.world_name = req.world_name;
fallback_req.path = sprint("%/worlds/%/index.world", GAME_RESOURCES_DIR, req.world_name);
fallback_req.should_block = true;
array_add(*g_asset_manager.main_queue, fallback_req);
fallback: Fetch_Request;
fallback.type = .WORLD;
fallback.priority = req.priority;
fallback.world_name = req.world_name;
fallback.path = sprint("%/worlds/%/index.world", GAME_RESOURCES_DIR, req.world_name);
array_add(*g_asset_manager.queue, fallback);
return;
}
log_error("Failed to load world '%'", req.world_name);
@ -135,11 +137,10 @@ handle_fetch_failed :: (req: *Fetch_Request) {
log_error("Failed to load chunks.bin for world '%'", req.world_name);
case .RDM_ATLAS;
log_error("RDM: failed to load atlas for chunk %", req.chunk_key);
log_info("RDM: no global atlas for world '%' (ok if none baked yet)", req.world_name);
case .RDM_LOOKUP;
if req.rdm_pending_atlas.id != 0 then sg_destroy_image(req.rdm_pending_atlas);
log_error("RDM: failed to load lookup for chunk %", req.chunk_key);
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);
@ -171,13 +172,13 @@ process_completed_fetch :: (req: *Fetch_Request, data: []u8) {
if is_json {
json_copy := NewArray(data.count, u8, false);
memcpy(json_copy.data, data.data, data.count);
chunks_req : Fetch_Request;
chunks_req: Fetch_Request;
chunks_req.type = .WORLD_CHUNKS;
chunks_req.priority = req.priority;
chunks_req.world_name = req.world_name;
chunks_req.path = sprint("%/worlds/%/chunks.bin", GAME_RESOURCES_DIR, req.world_name);
chunks_req.should_block = true;
chunks_req.world_json_data = json_copy;
array_add(*g_asset_manager.main_queue, chunks_req);
array_add(*g_asset_manager.queue, chunks_req);
} else {
world, ok := load_world_from_data(data);
if ok {
@ -214,88 +215,44 @@ process_completed_fetch :: (req: *Fetch_Request, data: []u8) {
header_size := cast(s64) size_of(RDM_File_Header);
if data.count < header_size {
log_error("RDM: atlas too small for chunk %", req.chunk_key);
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 for chunk %", req.chunk_key);
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(float);
atlas_imgdata : sg_image_data;
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 = .{
atlas_desc: sg_image_desc = .{
render_target = false,
width = header.width,
height = header.height,
pixel_format = sg_pixel_format.RGBA32F,
pixel_format = sg_pixel_format.RGBA16F,
sample_count = 1,
data = atlas_imgdata,
};
chunk_ptr := table_find_pointer(*curworld.world.chunks, req.chunk_key);
lookup_path: string;
if chunk_ptr != null && chunk_ptr.rdm_lookup_path.count > 0 {
lookup_path = sprint("%/worlds/%/%", GAME_RESOURCES_DIR, req.world_name, chunk_ptr.rdm_lookup_path);
} else {
lookup_path = rdm_chunk_filename(req.world_name, req.chunk_key, "rdm_lookup");
}
lookup_req : Fetch_Request;
lookup_req.type = .RDM_LOOKUP;
lookup_req.world_name = req.world_name;
lookup_req.chunk_key = req.chunk_key;
lookup_req.path = lookup_path;
lookup_req.rdm_pending_atlas = sg_make_image(*atlas_desc);
array_add(*g_asset_manager.rdm_queue, lookup_req);
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_LOOKUP;
curworld := get_current_world();
world_ok := curworld.valid && curworld.world.name == req.world_name;
case .RDM_MANIFEST;
curworld := get_current_world();
if !curworld.valid || curworld.world.name != req.world_name then return;
if !world_ok {
if req.rdm_pending_atlas.id != 0 then sg_destroy_image(req.rdm_pending_atlas);
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;
}
header_size := cast(s64) size_of(RDM_File_Header);
if data.count < header_size {
log_error("RDM: lookup too small for chunk %", req.chunk_key);
sg_destroy_image(req.rdm_pending_atlas);
return;
}
header := cast(*RDM_File_Header) data.data;
if header.magic != RDM_FILE_MAGIC {
log_error("RDM: bad lookup magic for chunk %", req.chunk_key);
sg_destroy_image(req.rdm_pending_atlas);
return;
}
lookup_pixel_bytes := cast(u64) header.width * cast(u64) header.height * 4 * size_of(float);
lookup_imgdata : sg_image_data;
lookup_imgdata.subimage[0][0] = .{ data.data + header_size, lookup_pixel_bytes };
lookup_desc : sg_image_desc = .{
render_target = false,
width = header.width,
height = header.height,
pixel_format = sg_pixel_format.RGBA32F,
sample_count = 1,
data = lookup_imgdata,
};
chunk := table_find_pointer(*curworld.world.chunks, req.chunk_key);
if chunk != null {
chunk.rdm_atlas = req.rdm_pending_atlas;
chunk.rdm_lookup = sg_make_image(*lookup_desc);
#if !FLAG_RELEASE_BUILD {
chunk.rdm_lookup_w = header.width;
chunk.rdm_lookup_h = header.height;
num_floats := cast(s64)(header.width * header.height * 4);
cpu_copy := NewArray(num_floats, float);
memcpy(cpu_copy.data, data.data + header_size, cast(s64)lookup_pixel_bytes);
chunk.rdm_lookup_cpu = cpu_copy;
}
chunk.rdm_valid = true;
log_debug("RDM: loaded chunk %", req.chunk_key);
} else {
sg_destroy_image(req.rdm_pending_atlas);
}
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);
@ -384,15 +341,12 @@ add_resources_from_pack :: (pack: *Loaded_Pack) {
array_add(*g_palettes, pal);
log_info("Loaded % colors from hex palette(%)", pal.entries.count, v.name);
case "ttf";
// Load into a font. Add to free list.
case;
log_warn("File(%) in pack(%) has unknown format", v.name, pack.name);
}
log_debug("% -> %", v.name, extension);
}
// Properly initialize animations from the pack now that we have the images
// and the JSON files both combined.
for qsheet : sheets_to_init {
for qsheet.sheet.meta.frameTags {
anim : Animation;
@ -427,29 +381,51 @@ find_pack_by_name :: (name: string) -> (bool, Loaded_Pack) {
return false, .{};
}
dispatch_channel :: (queue: *[..]Fetch_Request, channel: u32) {
af := *g_asset_manager.active[channel];
if af.occupied || queue.count == 0 then return;
req := queue.data[0];
for i: 0..queue.count - 2 {
queue.data[i] = queue.data[i + 1];
// Removes the highest-priority item from the queue (lowest enum value = most urgent).
// Within equal priority, the earliest-queued item wins (stable).
dequeue_highest_priority :: (queue: *[..]Fetch_Request) -> (Fetch_Request, bool) {
if queue.count == 0 return .{}, false;
best := 0;
for i: 1..queue.count - 1 {
if queue.*[i].priority < queue.*[best].priority then best = i;
}
queue.count -= 1;
req := queue.*[best];
array_ordered_remove_by_index(queue, best);
return req, true;
}
af.occupied = true;
af.req = req;
af.accumulated.count = 0;
dispatch_slots :: () {
for i: 0..MAX_FETCH_SLOTS - 1 {
slot := *g_asset_manager.slots[i];
if slot.occupied continue;
if g_asset_manager.queue.count == 0 break;
path_c := to_c_string(req.path);
defer free(path_c);
sfetch_send(*(sfetch_request_t.{
channel = channel,
path = path_c,
callback = fetch_callback,
chunk_size = cast(u32) af.chunk_buf.count,
buffer = .{ ptr = af.chunk_buf.data, size = cast(u64) af.chunk_buf.count },
}));
req, found := dequeue_highest_priority(*g_asset_manager.queue);
if !found break;
slot.occupied = true;
slot.req = req;
slot.buf = NewArray(fetch_type_buffer_size(req.type), u8, false);
// sokol copies user_data bytes immediately on sfetch_send, so a
// stack-local index is safe here.
slot_idx : u32 = cast(u32) i;
// Route BACKGROUND requests to channel 1 so they don't starve
// LOADING_SCREEN / BLOCK_ENGINE work on native (two IO threads).
channel : u32 = ifx req.priority == .BACKGROUND then cast(u32)1 else cast(u32)0;
path_c := to_c_string(req.path);
defer free(path_c);
sfetch_send(*(sfetch_request_t.{
channel = channel,
path = path_c,
callback = fetch_callback,
buffer = .{ ptr = slot.buf.data, size = cast(u64) slot.buf.count },
user_data = .{ ptr = *slot_idx, size = cast(u64) size_of(u32) },
}));
}
}
#scope_export
@ -467,43 +443,35 @@ free_resources_from_pack :: (pack: *Loaded_Pack) {
}
asset_manager_init :: () {
g_asset_manager.active[CHANNEL_MAIN].chunk_buf = NewArray(MAIN_CHUNK_BUFFER_SIZE, u8, false);
g_asset_manager.active[CHANNEL_RDM].chunk_buf = NewArray(RDM_CHUNK_BUFFER_SIZE, u8, false);
// No upfront allocations; buffers are allocated per-request in dispatch_slots.
}
mandatory_loads_done :: () -> bool {
for channel: 0..1 {
af := *g_asset_manager.active[channel];
if af.occupied && af.req.should_block_engine then return false;
for g_asset_manager.slots {
if it.occupied && it.req.priority == .BLOCK_ENGINE then return false;
}
for g_asset_manager.main_queue {
if it.should_block_engine then return false;
}
for g_asset_manager.rdm_queue {
if it.should_block_engine then return false;
for g_asset_manager.queue {
if it.priority == .BLOCK_ENGINE then return false;
}
return true;
}
show_loading_screen :: () -> bool {
for channel: 0..1 {
af := *g_asset_manager.active[channel];
if af.occupied && af.req.should_block then return true;
for g_asset_manager.slots {
if it.occupied && it.req.priority != .BACKGROUND then return true;
}
for g_asset_manager.main_queue {
if it.should_block then return true;
}
for g_asset_manager.rdm_queue {
if it.should_block then return true;
for g_asset_manager.queue {
if it.priority != .BACKGROUND then return true;
}
return false;
}
asset_manager_tick :: () {
#if !FLAG_RELEASE_BUILD && OS != .WASM {
if g_asset_manager.pending_hot_reload
&& !g_asset_manager.active[CHANNEL_MAIN].occupied
&& g_asset_manager.main_queue.count == 0 {
all_idle := true;
for g_asset_manager.slots if it.occupied { all_idle = false; break; }
if g_asset_manager.pending_hot_reload && all_idle && g_asset_manager.queue.count == 0 {
g_asset_manager.pending_hot_reload = false;
hot_reload_all_packs();
}
@ -513,33 +481,30 @@ asset_manager_tick :: () {
}
}
dispatch_channel(*g_asset_manager.main_queue, CHANNEL_MAIN);
dispatch_channel(*g_asset_manager.rdm_queue, CHANNEL_RDM);
sfetch_dowork();
dispatch_slots();
}
load_world :: (name: string) {
unload_current_world();
req : Fetch_Request;
req.type = .WORLD;
req.world_name = sprint("%", name);
req.path = sprint("%/worlds/%/world.json", GAME_RESOURCES_DIR, name);
req.should_block = true;
array_add(*g_asset_manager.main_queue, req);
req: Fetch_Request;
req.type = .WORLD;
req.priority = .LOADING_SCREEN;
req.world_name = sprint("%", name);
req.path = sprint("%/worlds/%/world.json", GAME_RESOURCES_DIR, name);
array_add(*g_asset_manager.queue, req);
}
load_pack :: (name: string, shouldBlock: bool = true, shouldBlockEngine: bool = false) {
req : Fetch_Request;
req.type = .PACK;
req.pack_name = sprint("%", name);
req.path = sprint("%/%.pack", PACK_DIR, name);
req.should_block = shouldBlock;
req.should_block_engine = shouldBlockEngine;
array_add(*g_asset_manager.main_queue, req);
load_pack :: (name: string, priority: Load_Priority = .LOADING_SCREEN) {
req: Fetch_Request;
req.type = .PACK;
req.priority = priority;
req.pack_name = sprint("%", name);
req.path = sprint("%/%.pack", PACK_DIR, name);
array_add(*g_asset_manager.queue, req);
}
// Asset management:
// Asset accessors:
#scope_file
#scope_export
@ -549,7 +514,6 @@ get_texture_from_pack :: (pack: string, path: string) -> (sg_image) {
invalid_img : sg_image;
if !found {
// find_pack_by_name already logs this
return invalid_img;
}

View File

@ -1,63 +1,58 @@
// RDM streaming helpers.
// The unified fetch queue lives in asset_manager.jai; these functions
// add and remove RDM entries from that shared queue.
// enqueue and cancel the world-level global RDM atlas + manifest.
#scope_export
rdm_loader_enqueue_world :: (world: *World) {
for *chunk: world.chunks {
if chunk.rdm_valid then continue;
already_atlas := false;
already_manifest := false;
// Skip if this chunk is already in-flight on the RDM channel.
af_rdm := *g_asset_manager.active[CHANNEL_RDM];
if af_rdm.occupied {
cf := af_rdm.req;
if (cf.type == .RDM_ATLAS || cf.type == .RDM_LOOKUP) &&
cf.world_name == world.name && cf.chunk_key == chunk.coord then continue;
}
// Skip if already queued (either as atlas or its follow-up lookup).
already_queued := false;
for g_asset_manager.rdm_queue {
if (it.type == .RDM_ATLAS || it.type == .RDM_LOOKUP) &&
it.world_name == world.name && it.chunk_key == chunk.coord {
already_queued = true;
break;
}
}
if already_queued then continue;
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.chunk_key = chunk.coord;
if chunk.rdm_atlas_path.count > 0 {
req.path = sprint("%/worlds/%/%", GAME_RESOURCES_DIR, world.name, chunk.rdm_atlas_path);
} else {
req.path = rdm_chunk_filename(world.name, chunk.coord, "rdm_atlas");
}
array_add(*g_asset_manager.rdm_queue, req);
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);
}
}
// Remove all pending RDM fetches from the queue and invalidate any in-flight
// RDM fetch so its callback discards the result.
// Drain all pending RDM work.
rdm_loader_cancel_all :: () {
// Destroy any atlas images stored in queued RDM_LOOKUP requests, then drain.
for i: 0..g_asset_manager.rdm_queue.count - 1 {
item := g_asset_manager.rdm_queue[i];
if item.rdm_pending_atlas.id != 0 then sg_destroy_image(item.rdm_pending_atlas);
}
array_reset(*g_asset_manager.rdm_queue);
// Blank the world name on the in-flight RDM request so its callback discards.
af := *g_asset_manager.active[CHANNEL_RDM];
if af.occupied &&
(af.req.type == .RDM_ATLAS || af.req.type == .RDM_LOOKUP) {
if af.req.rdm_pending_atlas.id != 0 {
sg_destroy_image(af.req.rdm_pending_atlas);
af.req.rdm_pending_atlas = .{};
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;
}
af.req.world_name = "";
}
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

@ -8,26 +8,33 @@ shgrid_loader_enqueue_world :: (world: *World) {
for *chunk: world.chunks {
if chunk.sh_valid then continue;
af := *g_asset_manager.active[CHANNEL_RDM];
if af.occupied && af.req.type == .SHGRID
&& af.req.world_name == world.name && af.req.chunk_key == chunk.coord
then continue;
already_queued := false;
for g_asset_manager.rdm_queue {
if it.type == .SHGRID && it.world_name == world.name && it.chunk_key == chunk.coord {
already_queued = true;
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_queued then continue;
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.rdm_queue, req);
array_add(*g_asset_manager.queue, req);
}
}
@ -50,32 +57,44 @@ sh_loader_handle_completed :: (req: *Fetch_Request, data: []u8) {
return;
}
n := sh_header.probe_n;
expected_floats := cast(s64) n * n * n * 12;
if data.count < header_size + expected_floats * size_of(float) {
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 float[n^3 * 12] → 3-RGBA16F-texels-per-probe 2D texture layout.
// 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);
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).*);
}
}
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).*);
}
}
}

View File

@ -2,6 +2,8 @@
#load "load.jai";
#load "mixer.jai";
g_audio_sample_rate : s32 = 44100;
audio_init :: () {
// load_wav_file();
}

View File

@ -7,10 +7,13 @@ audio_thread_context : #Context;
audio_init_thread_context :: () {
audio_thread_context = default_context;
audio_thread_context.temporary_storage = *audio_thread_temp_storage;
audio_thread_temp_storage.data = audio_thread_temp_storage_data.data;
audio_thread_temp_storage.size = audio_thread_temp_storage_data.count;
audio_thread_temp_storage.original_data = audio_thread_temp_storage_data.data;
audio_thread_temp_storage.original_size = audio_thread_temp_storage_data.count;
audio_thread_temp_storage.data = audio_thread_temp_storage_data.data;
audio_thread_temp_storage.size = audio_thread_temp_storage_data.count;
// Iprof's zone stack/hash are global. The audio callback runs on a separate
// thread, so any instrumented call from inside it races with the main thread
// and corrupts those globals. Mark this context as "inside profiler runtime"
// so Automatic_Zone_Guarded skips the begin/end on this thread.
audio_thread_context.already_inside_profiler_runtime = true;
audio_thread_context_ready = true;
}

View File

@ -23,6 +23,8 @@ Mixer_Play_Task :: struct {
startTime : float64 = 0;
delay : float64 = 0;
silenceBeforeRepeat : float64 = 0;
queued_next : *Mixer_Play_Task; // if set, starts when this ONESHOT task finishes
}
Mixer_Config :: struct {
@ -71,6 +73,22 @@ mixer_add_task :: (audio: *Audio_Data, bus: Mixer_Bus, mode: Play_Mode) {
});
}
// Queue `next_task` to start as soon as the task currently playing `current_audio` finishes.
// If `current_audio` isn't playing, `next_task` starts immediately.
mixer_queue_next :: (current_audio: *Audio_Data, next_task: Mixer_Play_Task) {
mixer_lock(*g_mixer);
defer mixer_unlock(*g_mixer);
for *g_mixer.tasks {
if it.audio == current_audio {
if it.queued_next then free(it.queued_next);
it.queued_next = New(Mixer_Play_Task);
it.queued_next.* = next_task;
return;
}
}
array_add(*g_mixer.tasks, next_task);
}
mixer_get_samples :: (buffer: *float, frame_count: s32, channel_count: s32) {
mixer_lock(*g_mixer);
defer mixer_unlock(*g_mixer);
@ -101,7 +119,7 @@ mixer_get_samples :: (buffer: *float, frame_count: s32, channel_count: s32) {
source_data := task.audio.data;
source_channels := cast(s64) task.audio.channels;
src_rate := cast(s64) task.audio.sample_rate;
out_rate := cast(s64) saudio_sample_rate();
out_rate := cast(s64) g_audio_sample_rate;
num_src_frames := source_data.count / source_channels;
task_finished := false;
@ -145,7 +163,13 @@ mixer_get_samples :: (buffer: *float, frame_count: s32, channel_count: s32) {
}
if task_finished {
array_unordered_remove_by_index(*g_mixer.tasks, i);
if task.queued_next {
next := task.queued_next.*;
free(task.queued_next);
g_mixer.tasks[i] = next;
} else {
array_unordered_remove_by_index(*g_mixer.tasks, i);
}
}
}
}

View File

@ -23,12 +23,16 @@ Profiler_Mode :: enum {
profiler_mode : Profiler_Mode = .CLOSED;
draw_text :: (x: float, y: float, text: string, color: Vector4) {
_, h := get_window_size();
half_height := cast(float) iprof_font.character_height * 0.5;
prepare_text(*iprof_font, text);
draw_prepared_text(*iprof_font, xx x, xx y, color);
draw_prepared_text(*iprof_font, xx x, xx (cast(float) h - y - half_height), color);
}
draw_line :: (p0: Vector2, p1: Vector2, p2: Vector2, p3: Vector2, color: Vector4) {
immediate_quad(p0, p1, p2, p3, color);
_, h := get_window_size();
hf := cast(float) h;
immediate_quad(.{p0.x, hf - p0.y}, .{p1.x, hf - p1.y}, .{p2.x, hf - p2.y}, .{p3.x, hf - p3.y}, color);
}
text_width :: (text: string) -> float {
@ -43,7 +47,9 @@ text_width :: (text: string) -> float {
}
draw_rectangle_prof :: (x0: float, y0: float, x1: float, y1: float, color: Vector4) {
r := GR.Rect.{x0,y0,x1-x0,y1-y0};
_, h := get_window_size();
hf := cast(float) h;
r := GR.Rect.{x0, hf - y0, x1 - x0, (hf - y1) - (hf - y0)};
draw_rectangle(r, color);
}
@ -85,11 +91,17 @@ init_profiler :: () {
draw_profiler :: () {
if profiler_mode == .CLOSED then return;
// Prevent recursive profiler calls during drawing
old_value := context.already_inside_profiler_runtime;
context.already_inside_profiler_runtime = true;
defer context.already_inside_profiler_runtime = old_value;
w,h := get_window_size();
draw_rectangle(.{xx(w-700), 0, 700, xx(h) }, .{0,0,0,1});
__Iprof.draw(xx (w - 700), 20,699,xx h, *iprof_conf);
__Iprof.draw(xx (w - 700), 20, 699, xx h, *iprof_conf);
if profiler_mode == .FULL {
__Iprof.draw_graph(0,xx h,xx(w-700),200, *iprof_conf);
__Iprof.draw_graph(0, 100, xx(w-700), 100, *iprof_conf);
}
}
@ -127,6 +139,7 @@ tick_profiler :: () {
__Iprof.graph_select_sample();
}
__Iprof.set_cursor_screen_coordinates(xx input_mouse_x, xx input_mouse_y);
_, h := get_window_size();
__Iprof.set_cursor_screen_coordinates(xx input_mouse_x, xx (cast(float) h - input_mouse_y));
}
}

View File

@ -79,9 +79,7 @@ set_dist :: (dist: float) {
tacomaSamples : s32 = 100;
tacomaResolution : s32 = 500;
tacomaExposure : float = 1.0;
tacomaContrast : float = 1.0;
tacomaSaturation : float = 1.0;
tacoma_tab_scroll : float = 0;
lastInputTime : float64;
@ -237,33 +235,20 @@ tick_level_editor_camera :: () {
draw_tacoma_tab :: (theme: *GR.Overall_Theme, total_r: GR.Rect) {
curworld := get_current_world();
r := total_r;
r.h = ui_h(3,0);
#if FLAG_TACOMA_ENABLED {
region, inside := GR.begin_scrollable_region(total_r, *theme.scrollable_region_theme);
r := inside;
r.y -= tacoma_tab_scroll;
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);
}
r.y += r.h;
if GR.button(r, "Render a RDM", *theme.button_theme) {
gen_rdm(tacomaSamples, true, 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);
}
r.y += r.h;
dirty_count := 0;
if curworld.valid for chunk: curworld.world.chunks if chunk.rdm_dirty dirty_count += 1;
if GR.button(r, tprint("Bake dirty chunks (%)", dirty_count), *t_button_selectable(theme, dirty_count > 0)) {
if curworld.valid && dirty_count > 0 {
dirty_keys : [..]Chunk_Key;
dirty_keys.allocator = temp;
for chunk, key: curworld.world.chunks if chunk.rdm_dirty array_add(*dirty_keys, key);
rdm_bake_chunks(dirty_keys, curworld.world, tacomaSamples, true);
}
}
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);
}
@ -303,18 +288,6 @@ 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, "Exposure", *t_label_left(theme));
r.y += r.h;
GR.slider(r, *tacomaExposure, 0.5, 3.0, 0.1, *theme.slider_theme);
r.y += r.h;
GR.label(r, "Contrast", *t_label_left(theme));
r.y += r.h;
GR.slider(r, *tacomaContrast, 0.5, 3.0, 0.1, *theme.slider_theme);
r.y += r.h;
GR.label(r, "Saturation", *t_label_left(theme));
r.y += r.h;
GR.slider(r, *tacomaSaturation, 0.5, 3.0, 0.1, *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));
r.y += r.h;
GR.slider(r, *bake_sky_scale, 0.0, 5.0, 0.05, *theme.slider_theme);
@ -324,8 +297,10 @@ draw_tacoma_tab :: (theme: *GR.Overall_Theme, total_r: GR.Rect) {
GR.slider(r, *bake_sky_desaturation, 0.0, 1.0, 0.05, *theme.slider_theme);
r.y += r.h;
GR.end_scrollable_region(region, r.x + r.w, r.y, *tacoma_tab_scroll);
} else {
r := total_r;
r.h = ui_h(3,0);
GR.label(r, "Tacoma is not enabled in this build.", *theme.label_theme);
}
}
@ -490,17 +465,21 @@ add_trile :: (name: string, x: s32, y: s32, z: s32, orientation: u8 = 0) {
inst := Trile_Instance.{x = lx, y = ly, z = lz, orientation = orientation};
// Find existing group for this trile type, or create one.
added := false;
for *group: chunk.groups {
if group.trile_name == name {
array_add(*group.instances, inst);
return;
added = true;
break;
}
}
group: Chunk_Trile_Group;
group.trile_name = sprint("%", name);
array_add(*group.instances, inst);
array_add(*chunk.groups, group);
chunk.rdm_dirty = true;
if !added {
group: Chunk_Trile_Group;
group.trile_name = sprint("%", name);
array_add(*group.instances, inst);
array_add(*chunk.groups, group);
}
invalidate_buried_around(*curworld.world, x, y, z);
} @Command
remove_trile :: (x: s32, y: s32, z: s32) {
@ -512,15 +491,21 @@ remove_trile :: (x: s32, y: s32, z: s32) {
lx, ly, lz := world_to_local(x, y, z);
removed := false;
for *group: chunk.groups {
for inst, idx: group.instances {
if inst.x == lx && inst.y == ly && inst.z == lz {
array_unordered_remove_by_index(*group.instances, idx);
chunk.rdm_dirty = true;
return;
if group.is_buried.count > idx {
array_unordered_remove_by_index(*group.is_buried, idx);
}
removed = true;
break;
}
}
if removed break;
}
if removed invalidate_buried_around(*curworld.world, x, y, z);
} @Command
@ -540,14 +525,6 @@ tick_level_editor :: () {
tick_level_editor_camera();
tick_particles(cast(float)delta_time);
if is_action_start(Editor_Action.SAVE) then sworld();
if is_action_start(Editor_Action.LEVEL_TOOL_POINT) then current_tool_mode = .POINT;
if is_action_start(Editor_Action.LEVEL_TOOL_BRUSH) then current_tool_mode = .BRUSH;
if is_action_start(Editor_Action.LEVEL_TOOL_AREA) { current_tool_mode = .AREA; area_active = false; }
if is_action_start(Editor_Action.LEVEL_TOOL_LINE) { current_tool_mode = .LINE; line_active = false; }
if is_action_start(Editor_Action.LEVEL_TOOL_INSPECTOR) then current_tool_mode = .INSPECTOR;
if is_action_start(Editor_Action.LEVEL_TOOL_VIEWER) then current_tool_mode = .VIEWER;
if is_action_start(Editor_Action.LEVEL_TWIST_CCW) {
lastInputTime = get_time();
current_orientation_twist = (current_orientation_twist + 1) % 4;
@ -795,21 +772,35 @@ 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;
#if FLAG_TACOMA_ENABLED {
r.h = ui_h(3, 2);
GR.label(r.*, "-- Bake Config --", *t_label_left(theme));
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;
r.h = ui_h(4, 0);
size_ov, qual_ov := get_rdm_instance_override(world, inspector_x, inspector_y, inspector_z);
GR.label(r.*, tprint("Size override (0=default): %", size_ov), *t_label_left(theme));
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;
GR.slider(r.*, *size_ov, 0, 512, 1, *theme.slider_theme);
r.y += r.h;
GR.label(r.*, tprint("Samples override (0=global): %", qual_ov), *t_label_left(theme));
r.y += r.h;
GR.slider(r.*, *qual_ov, 0, 10000, 10, *theme.slider_theme);
r.y += r.h;
set_rdm_instance_override(world, inspector_x, inspector_y, inspector_z, size_ov, qual_ov);
}
} else {
GR.label(r.*, "Trile: (empty)", *t_label_left(theme));
@ -884,8 +875,9 @@ draw_inspector_panel :: (r: *GR.Rect, theme: *GR.Overall_Theme) {
if has_note {
note := *world.notes[note_idx];
r.h = ui_h(4, 0);
a, new_text, _ := GR.text_input(r.*, note.text, *theme.text_input_theme, 500, input_action = note_input_action);
if (a & .TEXT_MODIFIED) || (a & .ENTERED) note.text = copy_string(new_text);
note_id := cast(s64)inspector_x * 1000003 + cast(s64)inspector_y * 1009 + cast(s64)inspector_z;
a, _, note_state := GR.text_input(r.*, note.text, *theme.text_input_theme, note_id, input_action = note_input_action);
if (a & .TEXT_MODIFIED) || (a & .ENTERED) note.text = copy_string(note_state.text);
r.y += r.h;
if GR.button(r.*, "Remove Note", *theme.button_theme, 302) {
array_ordered_remove_by_index(*world.notes, note_idx);
@ -908,77 +900,16 @@ draw_inspector_panel :: (r: *GR.Rect, theme: *GR.Overall_Theme) {
GR.label(r.*, "-- RDM --", *t_label_left(theme));
r.y += r.h;
chunk_key := world_to_chunk_coord(inspector_x, inspector_y, inspector_z);
chunk := table_find_pointer(*world.chunks, chunk_key);
if chunk != null && chunk.rdm_valid {
GR.label(r.*, "RDM: baked", *t_label_left(theme));
r.y += r.h;
GR.label(r.*, tprint("Chunk: (%, %, %)", chunk_key.x, chunk_key.y, chunk_key.z), *t_label_left(theme));
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;
roughness_mask : u8 = 0;
if has_trile {
roughness_mask = get_trile_roughness_set(trile_name);
}
r.h = ui_h(4, 0);
GR.slider(r.*, *inspector_rdm_roughness, 0, 7, 1, *theme.slider_theme);
r.y += r.h;
r.h = ui_h(3, 2);
has_roughness := (roughness_mask & (1 << cast(u8)inspector_rdm_roughness)) != 0;
if has_roughness {
GR.label(r.*, tprint("Roughness %: present", inspector_rdm_roughness), *t_label_left(theme));
} else {
GR.label(r.*, tprint("Roughness %: not baked", inspector_rdm_roughness), *t_label_left(theme));
}
r.y += r.h;
available: String_Builder;
available.allocator = temp;
append(*available, "Available: ");
for i: 0..7 {
if roughness_mask & (1 << cast(u8)i) then print_to_builder(*available, "% ", i);
}
GR.label(r.*, builder_to_string(*available,, temp), *t_label_left(theme));
r.y += r.h;
lx, ly, lz := world_to_local(inspector_x, inspector_y, inspector_z);
lookup_idx := cast(s32)lx + cast(s32)ly * 32 + cast(s32)lz * 1024 + cast(s32)inspector_rdm_roughness * 32768;
uv0 := Vector2.{0, 0};
uv1 := Vector2.{1, 0};
uv2 := Vector2.{1, 1};
uv3 := Vector2.{0, 1};
has_rect := false;
if chunk.rdm_lookup_cpu.data != null {
tx := lookup_idx % chunk.rdm_lookup_w;
ty := lookup_idx / chunk.rdm_lookup_w;
if tx >= 0 && ty >= 0 && tx < chunk.rdm_lookup_w && ty < chunk.rdm_lookup_h {
pixel_offset := (ty * chunk.rdm_lookup_w + tx) * 4;
rect_x := chunk.rdm_lookup_cpu[pixel_offset + 0];
rect_y := chunk.rdm_lookup_cpu[pixel_offset + 1];
rect_w := chunk.rdm_lookup_cpu[pixel_offset + 2];
rect_h := chunk.rdm_lookup_cpu[pixel_offset + 3];
if rect_w > 0 && rect_h > 0 {
has_rect = true;
fy0 := 1.0 - rect_y;
fy1 := 1.0 - (rect_y + rect_h);
uv0 = .{rect_x, fy0};
uv1 = .{rect_x + rect_w, fy0};
uv2 = .{rect_x + rect_w, fy1};
uv3 = .{rect_x, fy1};
GR.label(r.*, tprint("Rect: %.2,%.2 %.2x%.2", rect_x, rect_y, rect_w, rect_h), *t_label_left(theme));
r.y += r.h;
}
}
}
if !has_rect {
GR.label(r.*, "No RDM entry for this slot/roughness", *t_label_left(theme));
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;
} else {
r.y += r.h * 0.5;
tex_size := r.w * 0.9;
tex_r : GR.Rect;
@ -987,8 +918,15 @@ draw_inspector_panel :: (r: *GR.Rect, theme: *GR.Overall_Theme) {
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 = chunk.rdm_atlas;
uiTex.tex = g_rdm_atlas;
if uiTex.tex.id != INVALID_ID {
set_shader_for_images(uiTex);
immediate_quad(
@ -1003,9 +941,12 @@ draw_inspector_panel :: (r: *GR.Rect, theme: *GR.Overall_Theme) {
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 baked", *t_label_left(theme));
GR.label(r.*, "RDM: not flagged", *t_label_left(theme));
r.y += r.h;
}
}
@ -1039,8 +980,9 @@ draw_level_editor :: () {
curworld := get_current_world();
if !curworld.valid then return;
cam := get_level_editor_camera();
create_set_cam_rendering_task(cam, effective_plane_height(*curworld.world.conf));
create_world_rendering_tasks(*curworld.world, cam);
ph := effective_plane_height(*curworld.world.conf);
create_set_cam_rendering_task(cam, ph);
create_world_rendering_tasks(*curworld.world, cam, ph);
if show_trile_preview && !trile_preview_disabled {
create_level_editor_preview_tasks();
}

View File

@ -140,7 +140,7 @@ draw_particle_editor_ui :: (theme: *GR.Overall_Theme) {
}
er.y += er.h;
pe_float(*er, tprint("Emission Rate: %", def.emission_rate), *def.emission_rate, 0, 200, 1, theme);
pe_float(*er, tprint("Emission Rate: %", def.emission_rate), *def.emission_rate, 0, 2000, 1, theme);
pe_float(*er, tprint("Lifetime Min: %", def.lifetime_min), *def.lifetime_min, 0, 10, 0.1, theme);
pe_float(*er, tprint("Lifetime Max: %", def.lifetime_max), *def.lifetime_max, 0, 10, 0.1, theme);
pe_vec3(*er, "Velocity", *def.velocity, -50, 50, theme);

View File

@ -9,15 +9,19 @@ RDM_File_Header :: struct {
RDM_FILE_MAGIC :: u32.[0x4D445254][0]; // "TRDM" as little-endian u32
rdm_chunk_filename :: (world_name: string, chunk_key: Chunk_Key, suffix: string) -> string {
return sprint("%/worlds/%/%_%_%.%", GAME_RESOURCES_DIR, world_name, chunk_key.x, chunk_key.y, chunk_key.z, suffix);
rdm_global_atlas_filename :: (world_name: string) -> string {
return sprint("%/worlds/%/rdm_atlas.rdm", GAME_RESOURCES_DIR, world_name);
}
// SH probe grid (2 probes per trile per axis = 64x64x64 per 32x32x32 chunk)
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 :: 64; // probes per axis (2 per trile in a 32-trile chunk)
SH_TEX_W :: SH_PROBE_N * 3; // 192 — 3 RGBA texels per probe along X
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;

View File

@ -14,51 +14,39 @@ Tacoma_Screenshot :: struct {
current_screenshot : Tacoma_Screenshot;
RDM_Atlas_Entry :: struct {
// Single global atlas entry: stored on the World once baked.
RDM_Atlas_Entry_Bake :: struct {
world_pos: Vector3;
roughness: s32;
x, y: s32; // position in atlas (pixels)
w, h: s32; // size of this RDM
x, y: s32; // top-left in atlas pixels
w, h: s32; // pixel size of this RDM (= 2*size, 3*size)
}
// Per-chunk atlas bake state (CPU-side, used during baking only).
RDM_Chunk_Bake :: struct {
data: *float; // CPU atlas buffer (RGBA32F)
width: s32;
height: s32;
cursor_x: s32;
cursor_y: s32;
row_height: s32;
entries: [..]RDM_Atlas_Entry;
}
RDM_ATLAS_SIZE :: 4096 * 2;
RDM_LOOKUP_SIZE :: 512; // 512x512 = 32*32*32*8 = 262144 texels
rdm_chunk_bakes : Table(Chunk_Key, RDM_Chunk_Bake, chunk_key_hash, chunk_key_compare);
RDM_ATLAS_MAX_SIZE :: 16384; // GPU 2D texture ceiling.
ctx : *Tacoma.Tacoma_Context;
// --- Chunk RDM bake queue ---
// Default RDM sizes per roughness level (0=sharpest, 7=diffuse).
// w = 2*size, h = 3*size. Tacoma accepts size directly.
g_rdm_default_sizes : [8]s32 = .[256, 128, 64, 32, 16, 8, 4, 2];
// A single RDM render job: one world_trile at one roughness level.
RDM_Bake_Job :: struct {
world_trile_index: s32;
roughness: s32;
world_pos: Vector3;
size_override: s32; // 0 = use g_rdm_default_sizes[roughness]
quality_override: s32; // 0 = use rdm_bake.quality
size: s32; // per-instance RDM side in px (tile = 2*size x 3*size).
}
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;
}
RDM_Bake_State :: struct {
active : bool = false;
quality : s32 = 100;
jobs : [..]RDM_Bake_Job;
current_job : s32 = 0;
active : bool = false;
quality : s32 = 100;
jobs : [..]RDM_Bake_Job;
current_job : s32 = 0;
atlas : RDM_Global_Bake;
}
rdm_bake : RDM_Bake_State;
@ -73,72 +61,62 @@ SH_Bake_State :: struct {
sh_bake : SH_Bake_State;
rdm_job_size :: (job: RDM_Bake_Job) -> s32 {
if job.size_override > 0 then return job.size_override;
return g_rdm_default_sizes[job.roughness];
}
rdm_job_quality :: (job: RDM_Bake_Job) -> s32 {
if job.quality_override > 0 then return job.quality_override;
return rdm_bake.quality;
}
// Pixel dimensions of a single RDM entry. w = 2*size, h = 3*size.
rdm_entry_predicted_size :: (roughness: s32) -> (w: s32, h: s32) {
size := g_rdm_default_sizes[roughness];
return 2 * size, 3 * size;
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;
}
}
// Simulate shelf-pack of jobs into a canvas of given width; return total height used.
rdm_simulate_pack_height :: (jobs: []RDM_Bake_Job, canvas_w: s32) -> s32 {
cx : s32 = 0;
cy : s32 = 0;
rh : s32 = 0;
// 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 {
s := rdm_job_size(job);
w := 2 * s;
h := 3 * s;
if cx + w > canvas_w { cy += rh; cx = 0; rh = 0; }
cx += w;
if h > rh rh = h;
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;
}
cy += rh;
return cy;
return true;
}
// Simulate shelf-packing for a chunk's sorted job list and return minimum
// power-of-2 atlas dimensions, capped at RDM_ATLAS_SIZE.
rdm_calc_chunk_atlas_size :: (jobs: []RDM_Bake_Job) -> (s32, s32) {
if jobs.count == 0 return 16, 16;
// Estimate canvas width from sqrt(total pixel area).
total_area : s64 = 0;
for job: jobs {
s := rdm_job_size(job);
total_area += cast(s64)(2 * s) * cast(s64)(3 * s);
// 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;
}
target_w : s32 = 16;
sqrt_area := cast(s32) sqrt(cast(float) total_area) + 1;
while target_w < sqrt_area target_w *= 2;
// Widen until the packed height fits within the width (roughly square).
while target_w < RDM_ATLAS_SIZE {
if rdm_simulate_pack_height(jobs, target_w) <= target_w break;
target_w *= 2;
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);
}
// Round height up to next power of 2.
final_height := rdm_simulate_pack_height(jobs, target_w);
target_h : s32 = 16;
while target_h < final_height target_h *= 2;
if target_w > RDM_ATLAS_SIZE target_w = RDM_ATLAS_SIZE;
if target_h > RDM_ATLAS_SIZE target_h = RDM_ATLAS_SIZE;
return target_w, target_h;
return RDM_ATLAS_MAX_SIZE, RDM_ATLAS_MAX_SIZE;
}
// Build the Tacoma scene from the world, and emit bake jobs for selected chunks.
// If chunk_keys is null, all chunks are queued.
// 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;
@ -150,27 +128,7 @@ rdm_bake_start :: (world: World, quality: s32, include_water: bool, chunk_keys:
trile_name_to_index: Table(string, s32);
trile_name_to_index.allocator = temp;
// Per world_trile: which roughnesses to bake.
world_trile_roughnesses : [..]u8;
world_trile_roughnesses.allocator = temp;
// Cache roughness sets per trile type.
roughness_cache: Table(string, u8);
roughness_cache.allocator = temp;
bake_all := chunk_keys.count == 0;
// Build a set of chunk keys to bake if specific ones were requested.
chunk_key_set: Table(Chunk_Key, bool, chunk_key_hash, chunk_key_compare);
chunk_key_set.allocator = temp;
if !bake_all {
for key: chunk_keys {
table_set(*chunk_key_set, key, true);
}
}
for chunk: world.chunks {
should_bake := bake_all || table_contains(*chunk_key_set, chunk.coord);
for group: chunk.groups {
success, idx := table_find(*trile_name_to_index, group.trile_name);
if !success {
@ -196,36 +154,19 @@ rdm_bake_start :: (world: World, quality: s32, include_water: bool, chunk_keys:
table_set(*trile_name_to_index, group.trile_name, idx);
}
// Get roughness set for this trile type (cached).
roughness_mask : u8;
found_r, cached_mask := table_find(*roughness_cache, group.trile_name);
if found_r {
roughness_mask = cached_mask;
} else {
roughness_mask = get_trile_roughness_set(group.trile_name);
table_set(*roughness_cache, group.trile_name, roughness_mask);
}
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});
array_add(*world_trile_roughnesses, roughness_mask);
if should_bake {
size_ov, qual_ov := get_rdm_instance_override(*world, wx, wy, wz);
for r: 0..7 {
if roughness_mask & cast(u8)(1 << r) {
array_add(*rdm_bake.jobs, .{
world_trile_index = world_trile_idx,
roughness = cast(s32) r,
world_pos = wpos,
size_override = size_ov,
quality_override = qual_ov,
});
}
}
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,
});
}
}
}
@ -237,69 +178,18 @@ rdm_bake_start :: (world: World, quality: s32, include_water: bool, chunk_keys:
ctx = Tacoma.tacoma_init("./modules/Tacoma/");
Tacoma.tacoma_load_scene(ctx, sky, blases, tlas, cast(s32) include_water);
// Sort jobs by roughness ascending (lowest roughness = biggest images first).
// Simple insertion sort, N is small.
if rdm_bake.jobs.count > 1 {
for i: 1..cast(s32)(rdm_bake.jobs.count - 1) {
key := rdm_bake.jobs[i];
j := i - 1;
while j >= 0 && rdm_bake.jobs[j].roughness > key.roughness {
rdm_bake.jobs[j + 1] = rdm_bake.jobs[j];
j -= 1;
}
rdm_bake.jobs[j + 1] = key;
}
}
// Sort jobs tallest-first for a tighter shelf pack.
rdm_sort_jobs_by_height_desc(*rdm_bake.jobs);
// Clean up any previous per-chunk bake data.
rdm_cleanup_chunk_bakes();
// Clear RDM results only for chunks that are being re-baked.
curworld := get_current_world();
for *chunk: curworld.world.chunks {
if chunk.rdm_valid && (bake_all || table_contains(*chunk_key_set, chunk.coord)) {
sg_destroy_image(chunk.rdm_atlas);
sg_destroy_image(chunk.rdm_lookup);
chunk.rdm_valid = false;
}
}
// Pre-allocate per-chunk atlas CPU buffers with optimal (minimum) sizes.
{
// Collect unique chunk keys.
unique_chunk_keys : [..]Chunk_Key;
unique_chunk_keys.allocator = temp;
for job: rdm_bake.jobs {
ck := world_to_chunk_coord(cast(s32) job.world_pos.x, cast(s32) job.world_pos.y, cast(s32) job.world_pos.z);
already := false;
for unique_chunk_keys { if it == ck { already = true; break; } }
if !already array_add(*unique_chunk_keys, ck);
}
for chunk_key: unique_chunk_keys {
// Collect this chunk's jobs (already sorted by roughness ascending).
this_jobs : [..]RDM_Bake_Job;
this_jobs.allocator = temp;
for job: rdm_bake.jobs {
ck := world_to_chunk_coord(cast(s32) job.world_pos.x, cast(s32) job.world_pos.y, cast(s32) job.world_pos.z);
if ck == chunk_key array_add(*this_jobs, job);
}
atlas_w, atlas_h := rdm_calc_chunk_atlas_size(this_jobs);
log_info("RDM atlas for chunk %: %x% (%.1f MB, was % MB)",
chunk_key, atlas_w, atlas_h,
cast(float)(cast(s64) atlas_w * atlas_h * 4 * size_of(float)) / (1024.0 * 1024.0),
RDM_ATLAS_SIZE * RDM_ATLAS_SIZE * 4 * size_of(float) / (1024 * 1024));
atlas_bytes := cast(s64) atlas_w * cast(s64) atlas_h * 4 * size_of(float);
bake : RDM_Chunk_Bake;
bake.width = atlas_w;
bake.height = atlas_h;
bake.data = cast(*float) alloc(atlas_bytes);
memset(bake.data, 0, atlas_bytes);
table_set(*rdm_chunk_bakes, chunk_key, bake);
}
}
// 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;
@ -309,17 +199,16 @@ rdm_bake_start :: (world: World, quality: s32, include_water: bool, chunk_keys:
}
}
// Queue all chunks for RDM baking.
// 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);
}
// Queue specific chunks for RDM baking.
rdm_bake_chunks :: (chunk_keys: []Chunk_Key, world: World, quality: s32, include_water: bool) {
rdm_bake_start(world, quality, include_water, chunk_keys);
}
// Called once per frame to process at most one RDM.
// 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 {
@ -329,55 +218,46 @@ rdm_bake_tick :: () {
job := rdm_bake.jobs[rdm_bake.current_job];
size := rdm_job_size(job);
size : s32 = job.size;
w := 2 * size;
h := 3 * size;
ptr := Tacoma.tacoma_render_rdm(ctx, job.world_trile_index, job.roughness, rdm_job_quality(job), size);
ptr := Tacoma.tacoma_render_rdm(ctx, job.world_trile_index, 0, rdm_job_quality(job), size);
// Find this job's per-chunk bake state.
chunk_key := world_to_chunk_coord(cast(s32) job.world_pos.x, cast(s32) job.world_pos.y, cast(s32) job.world_pos.z);
bake := table_find_pointer(*rdm_chunk_bakes, chunk_key);
bake := *rdm_bake.atlas;
if bake != null {
// Shelf-pack this RDM into the chunk's atlas.
if bake.cursor_x + w > bake.width {
bake.cursor_y += bake.row_height;
bake.cursor_x = 0;
bake.row_height = 0;
}
ax := bake.cursor_x;
ay := bake.cursor_y;
if ay + h <= bake.height {
// Copy pixels row-by-row into the chunk's atlas CPU buffer.
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;
entry.world_pos = job.world_pos;
entry.roughness = job.roughness;
entry.x = ax;
entry.y = ay;
entry.w = w;
entry.h = h;
array_add(*bake.entries, entry);
} else {
log_warn("RDM atlas overflow for chunk %, skipping (pos=%, roughness=%)", chunk_key, job.world_pos, job.roughness);
}
bake.cursor_x += w;
if h > bake.row_height then bake.row_height = h;
if bake.cursor_x + w > bake.width {
bake.cursor_y += bake.row_height;
bake.cursor_x = 0;
bake.row_height = 0;
}
// Still update the preview screenshot.
tacoma_handle_result(ptr, w, h);
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;
}
@ -385,115 +265,68 @@ rdm_bake_finish :: () {
if ctx != null then tacoma_stop();
curworld := get_current_world();
total_entries : s64 = 0;
chunk_count : s64 = 0;
bake := *rdm_bake.atlas;
// Collect unique chunk keys from jobs.
bake_chunk_keys : [..]Chunk_Key;
bake_chunk_keys.allocator = temp;
for job: rdm_bake.jobs {
ck := world_to_chunk_coord(cast(s32) job.world_pos.x, cast(s32) job.world_pos.y, cast(s32) job.world_pos.z);
already := false;
for bake_chunk_keys { if it == ck { already = true; break; } }
if !already then array_add(*bake_chunk_keys, ck);
}
if bake.entries.count > 0 {
// a) Pack atlas into RGBA16F half-floats and upload to g_rdm_atlas.
upload_global_atlas_image(bake);
lookup_texels :: RDM_LOOKUP_SIZE * RDM_LOOKUP_SIZE;
lookup_bytes :: lookup_texels * 4 * size_of(float);
for chunk_key: bake_chunk_keys {
print("Handling chunk key: %\n", chunk_key);
bake := table_find_pointer(*rdm_chunk_bakes, chunk_key);
if bake == null || bake.entries.count == 0 then continue;
// a) Upload per-chunk atlas to GPU.
atlas_imgdata : sg_image_data;
atlas_byte_size := cast(u64) bake.width * cast(u64) bake.height * 4 * size_of(float);
atlas_imgdata.subimage[0][0] = .{bake.data, atlas_byte_size};
atlas_desc : sg_image_desc = .{
render_target = false,
width = bake.width,
height = bake.height,
pixel_format = sg_pixel_format.RGBA32F,
sample_count = 1,
data = atlas_imgdata
};
atlas_image := sg_make_image(*atlas_desc);
// b) Generate lookup texture (512x512 RGBA32F).
lookup_data := cast(*float) alloc(lookup_bytes);
memset(lookup_data, 0, lookup_bytes);
atlas_w := cast(float) bake.width;
atlas_h := cast(float) bake.height;
for entry: bake.entries {
lx, ly, lz := world_to_local(cast(s32) entry.world_pos.x, cast(s32) entry.world_pos.y, cast(s32) entry.world_pos.z);
index := cast(s32) lx + cast(s32) ly * 32 + cast(s32) lz * 32 * 32 + entry.roughness * 32 * 32 * 32;
tx := index % RDM_LOOKUP_SIZE;
ty := index / RDM_LOOKUP_SIZE;
pixel_offset := (ty * RDM_LOOKUP_SIZE + tx) * 4;
lookup_data[pixel_offset + 0] = cast(float) entry.x / atlas_w;
lookup_data[pixel_offset + 1] = cast(float) entry.y / atlas_h;
lookup_data[pixel_offset + 2] = cast(float) entry.w / atlas_w;
lookup_data[pixel_offset + 3] = cast(float) entry.h / atlas_h;
}
lookup_imgdata : sg_image_data;
lookup_imgdata.subimage[0][0] = .{lookup_data, lookup_bytes};
lookup_desc : sg_image_desc = .{
render_target = false,
width = RDM_LOOKUP_SIZE,
height = RDM_LOOKUP_SIZE,
pixel_format = sg_pixel_format.RGBA32F,
sample_count = 1,
data = lookup_imgdata
};
lookup_image := sg_make_image(*lookup_desc);
free(lookup_data);
// c) Store in Chunk.
chunk := table_find_pointer(*curworld.world.chunks, chunk_key);
if chunk != null {
if chunk.rdm_valid {
sg_destroy_image(chunk.rdm_atlas);
sg_destroy_image(chunk.rdm_lookup);
// 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);
}
chunk.rdm_atlas = atlas_image;
chunk.rdm_lookup = lookup_image;
chunk.rdm_valid = true;
chunk.rdm_dirty = false;
}
total_entries += cast(s64) bake.entries.count;
chunk_count += 1;
// 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: % chunks, % total entries", chunk_count, total_entries);
// Save baked RDM data to disk.
rdm_save_all_chunks_to_disk();
// Clean up CPU bake data.
rdm_cleanup_chunk_bakes();
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 = .{};
}
rdm_cleanup_chunk_bakes :: () {
for *bake: rdm_chunk_bakes {
if bake.data != null then free(bake.data);
array_free(bake.entries);
}
deinit(*rdm_chunk_bakes);
rdm_chunk_bakes = .{};
// 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 = 0.0;
bake_sky_desaturation : float = 1.0;
world_to_sky_config :: (world: World) -> Tacoma.Sky_Config {
sky : Tacoma.Sky_Config;
@ -604,14 +437,6 @@ gen_reference :: (w: s32, h: s32, eye: Vector3, target: Vector3, quality: s32, i
tacoma_stop();
}
gen_rdm :: (quality: s32, include_water: bool, world: World) {
tacoma_init_scene(world, include_water);
size := g_rdm_default_sizes[0];
ptr := Tacoma.tacoma_render_rdm(ctx, 0, 0, quality, size);
tacoma_handle_result(ptr, 2 * size, 3 * size);
tacoma_stop();
}
sh_bake_start :: (quality: s32 = 50, include_water: bool = false) {
if sh_bake.active then return;
curworld := get_current_world();
@ -648,9 +473,11 @@ sh_bake_tick :: () {
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, cast(float) oy, cast(float) oz,
n, 0.5, sh_bake.quality);
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));
@ -708,75 +535,49 @@ shgrid_save_to_disk :: (world_name: string, chunk_key: Chunk_Key, data: *float,
builder : String_Builder;
header := SH_Grid_File_Header.{
magic = SH_FILE_MAGIC,
version = 1,
version = 2,
probe_n = probe_n,
};
write_bytes(*builder, *header, size_of(SH_Grid_File_Header));
total_floats := cast(s64) probe_n * probe_n * probe_n * 12;
write_bytes(*builder, data, total_floats * size_of(float));
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 disk persistence ---
// (RDM_File_Header, RDM_FILE_MAGIC, rdm_chunk_filename, rdm_load_from_disk
// are defined in rdm_disk.jai which is always loaded on non-WASM builds.)
rdm_save_image_to_file :: (path: string, data: *float, width: s32, height: s32) {
rdm_save_global_atlas_to_disk :: (bake: *RDM_Global_Bake) {
#if OS != .WASM {
file :: #import "File";
builder: String_Builder;
header := RDM_File_Header.{
magic = RDM_FILE_MAGIC,
width = width,
height = height,
};
write_bytes(*builder, *header, size_of(RDM_File_Header));
pixel_bytes := cast(s64) width * cast(s64) height * 4 * size_of(float);
write_bytes(*builder, data, pixel_bytes);
file.write_entire_file(path, builder_to_string(*builder));
}
}
rdm_save_all_chunks_to_disk :: () {
#if OS != .WASM {
curworld := get_current_world();
if !curworld.valid then return;
world_name := curworld.world.name;
path := rdm_global_atlas_filename(curworld.world.name);
for *bake, chunk_key: rdm_chunk_bakes {
print("Processing chunk....\n");
if bake.entries.count == 0 then continue;
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);
}
}
// Save atlas.
atlas_path := rdm_chunk_filename(world_name, chunk_key, "rdm_atlas");
rdm_save_image_to_file(atlas_path, bake.data, bake.width, bake.height);
// Regenerate and save lookup.
lookup_texels :: RDM_LOOKUP_SIZE * RDM_LOOKUP_SIZE;
lookup_floats :: lookup_texels * 4;
lookup_data : [lookup_floats]float;
memset(lookup_data.data, 0, size_of(type_of(lookup_data)));
atlas_w := cast(float) bake.width;
atlas_h := cast(float) bake.height;
for entry: bake.entries {
lx, ly, lz := world_to_local(cast(s32) entry.world_pos.x, cast(s32) entry.world_pos.y, cast(s32) entry.world_pos.z);
index := cast(s32) lx + cast(s32) ly * 32 + cast(s32) lz * 32 * 32 + entry.roughness * 32 * 32 * 32;
tx := index % RDM_LOOKUP_SIZE;
ty := index / RDM_LOOKUP_SIZE;
pixel_offset := (ty * RDM_LOOKUP_SIZE + tx) * 4;
lookup_data[pixel_offset + 0] = cast(float) entry.x / atlas_w;
lookup_data[pixel_offset + 1] = cast(float) entry.y / atlas_h;
lookup_data[pixel_offset + 2] = cast(float) entry.w / atlas_w;
lookup_data[pixel_offset + 3] = cast(float) entry.h / atlas_h;
}
lookup_path := rdm_chunk_filename(world_name, chunk_key, "rdm_lookup");
rdm_save_image_to_file(lookup_path, lookup_data.data, RDM_LOOKUP_SIZE, RDM_LOOKUP_SIZE);
log_info("Saved RDM data for chunk % to disk", chunk_key);
}
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

@ -13,7 +13,7 @@ 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 (chunk)", "rdm_lookup (chunk)"];
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;
@ -36,18 +36,9 @@ draw_subwindow_texture_debug :: (state: *GR.Subwindow_State, r: GR.Rect, data: *
case 3; image = g_gbuf_position;
case 4; image = g_gbuf_normal;
case 5; image = g_ssaobuf;
case 6; image = g_bloom_tex;
case 6; image = g_bloom_up_1;
case 7; image = g_dof_tex;
case 8; #through;
case 9;
cw := get_current_world();
for chunk: cw.world.chunks {
if chunk.rdm_valid {
if current_pipeline == 6 then image = chunk.rdm_atlas;
else image = chunk.rdm_lookup;
break;
}
}
case 8; image = g_rdm_atlas;
}
uiTex.tex = image;

View File

@ -545,20 +545,6 @@ draw_trile_editor :: () {
}
trile_editor_shortcuts :: () {
// Tool/mode buttons are only rendered in the Toolset tab — handle shortcuts here so they work from any tab.
if is_action_start(Editor_Action.TRIXEL_TOOL_PAINT) then current_tool = .PAINT;
if is_action_start(Editor_Action.TRIXEL_TOOL_ADD) then current_tool = .ADD;
if is_action_start(Editor_Action.TRIXEL_TOOL_REMOVE) then current_tool = .REMOVE;
if is_action_start(Editor_Action.TRIXEL_MODE_POINT) then current_mode = .POINT;
if is_action_start(Editor_Action.TRIXEL_MODE_AREA) then current_mode = .AREA;
if is_action_start(Editor_Action.TRIXEL_MODE_BRUSH) then current_mode = .BRUSH;
// Save is in the Toolset tab only.
if is_action_start(Editor_Action.SAVE) {
set_trile_gfx(editor_current_trile.name, generate_trile_gfx_matias(editor_current_trile));
striles();
update_trile_thumbnail(editor_current_trile.name);
}
if is_action_start(Editor_Action.TRIXEL_VIEW_TILE) then tiling_preview_active = !tiling_preview_active;
if is_action_start(Editor_Action.TRIXEL_UNDO) then do_undo();
if is_action_start(Editor_Action.TRIXEL_REDO) then do_redo();
}
@ -588,6 +574,11 @@ draw_meta_tab :: (theme: *GR.Overall_Theme, area: GR.Rect) {
}
r.y += row_h * 2;
r.h = row_h;
changed := GR.base_checkbox(r, "Opaque (occludes neighbors)", editor_current_trile.is_opaque, *theme.checkbox_theme);
if changed editor_current_trile.is_opaque = !editor_current_trile.is_opaque;
r.y += row_h * 2;
r.h = row_h;
if GR.button(r, "Delete trile", *theme.button_theme) {
name_copy := copy_string(editor_current_trile.name,, temp);

View File

@ -90,16 +90,18 @@ debug_font : *Font;
init :: () {
sg_setup(*(sg_desc.{
environment = cast,force(sg_environment) sglue_environment(),
logger = .{ func = slog_func },
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 },
}));
sfetch_setup(*(sfetch_desc_t.{
max_requests = 64,
max_requests = 128,
num_channels = 2,
num_lanes = 1,
num_lanes = 8,
logger = .{ func = slog_func },
}));
asset_manager_init();
@ -109,6 +111,7 @@ init :: () {
logger = .{ func = slog_func },
stream_cb = sokol_audio_callback,
}));
g_audio_sample_rate = saudio_sample_rate();
stm_setup();
state.dpi_scale = sapp_dpi_scale();
atlas_dim := round_pow2(1024.0 * state.dpi_scale);
@ -122,13 +125,16 @@ init :: () {
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 };
g_mixer.paused = true;
useless_mem : [1]u8;
debug_font = get_font_at_size(useless_mem, 15);
load_pack("boot", true, true);
load_pack("core", true, false);
load_pack("game_core", true, false);
load_pack("boot", .BLOCK_ENGINE);
load_pack("core");
load_pack("game_core");
#if FLAG_TEST_EXE_ENGINE {
engine_exe_tests_add();
@ -211,6 +217,10 @@ frame :: () {
init_after_core_done = true;
}
if g_mixer.paused && !in_editor_view && !show_loading_screen() {
g_mixer.paused = false;
}
fonsClearState(state.fons);
add_frame_profiling_point("After loading logic");
@ -249,7 +259,6 @@ frame :: () {
tick_ui();
add_frame_profiling_point("After UI tick");
// This populates our render task queue.
if should_tick_game then game_draw();
add_frame_profiling_point("After game draw");
@ -262,7 +271,7 @@ frame :: () {
draw_prepared_text(debug_font, 10, 10, .{0.0, 1.0, 0.0, 1.0});
draw_editor();
}
add_particle_render_tasks();
add_frame_profiling_point("After editor draw");
render();

View File

@ -51,7 +51,7 @@ hot_reload_all_packs :: () {
array_add(*pack_names, sprint("%", pack.name));
}
array_reset(*g_asset_manager.main_queue);
array_reset(*g_asset_manager.queue);
g_mixer.paused = true;
g_asset_manager.hot_reload_unpause_pending = true;
@ -76,7 +76,7 @@ hot_reload_all_packs :: () {
recreate_packs_on_disk();
for name: pack_names {
load_pack(name, true, false);
load_pack(name);
}
log_info("Hot-reload: queued % pack(s) for reload", pack_names.count);
}

View File

@ -41,9 +41,9 @@ Particle :: struct {
definition : *Particle_Emitter_Config;
}
MAX_PARTICLES : s32 : 2048;
MAX_PARTICLES :: 16384;
g_particles : [2048] Particle;
g_particles : [MAX_PARTICLES] Particle;
g_emitter_defs : [..] Particle_Emitter_Config;
clear_particles :: () {
@ -102,8 +102,11 @@ add_particle_render_tasks :: () {
anim_name : string;
blend_mode : Particle_Blend_Mode;
anim : *Animation;
task : *Rendering_Task_Particles;
sheet : sg_image;
count : s32;
pos_size : *[MAX_PARTICLES]Vector4;
uv_rects : *[MAX_PARTICLES]Vector4;
colors : *[MAX_PARTICLES]Vector4;
}
batches : [..] Batch;
@ -111,7 +114,6 @@ add_particle_render_tasks :: () {
for *p: g_particles {
if !p.alive then continue;
if p.definition == null then continue;
def := p.definition;
if def.animation_name.count == 0 then continue;
@ -127,10 +129,17 @@ add_particle_render_tasks :: () {
if batch == null {
anim := get_animation_from_string(def.animation_name);
if anim == null then continue;
array_add(*batches, .{ anim_name = def.animation_name, blend_mode = def.blend_mode, anim = anim, task = New(Rendering_Task_Particles,, temp) });
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.task.sheet = anim.sheet;
batch.task.blend_mode = def.blend_mode;
}
if batch.count >= MAX_PARTICLES then continue;
@ -140,31 +149,48 @@ add_particle_render_tasks :: () {
col := lerp_color(def.color_start, def.color_end, t);
idx := batch.count;
batch.task.pos_size[idx] = .{p.position.x, p.position.y, p.position.z, size};
batch.pos_size.*[idx] = .{p.position.x, p.position.y, p.position.z, size};
anim := batch.anim;
frame_count := anim.frames.count;
if frame_count == 0 then continue;
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);
f := anim.frames[frame];
batch.task.uv_rects[idx] = .{
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.task.colors[idx] = col;
batch.colors.*[idx] = col;
batch.count += 1;
}
buf_task := New(Rendering_Task_Particles_Buffer,, temp);
total_count : s32 = 0;
for *b: batches {
if b.count > 0 {
b.task.count = b.count;
add_rendering_task(b.task.*);
}
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.*);
}
}

View File

@ -1,13 +1,13 @@
#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/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);
#import,dir "../../modules/sokol-jai/sokol/audio"(DEBUG = FLAG_RELEASE_BUILD);
#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);
#import,dir "../../modules/sokol-jai/sokol/audio"(DEBUG = !FLAG_RELEASE_BUILD);
#load "../main.jai";
@ -22,8 +22,6 @@ sapp_init :: () {
default_context.temporary_storage = *temporary_storage;
temporary_storage.data = temporary_storage_data.data;
temporary_storage.size = temporary_storage_data.count;
temporary_storage.original_data = temporary_storage_data.data;
temporary_storage.original_size = temporary_storage_data.count;
default_allocator = default_context.allocator;
push_context default_context {

View File

@ -18,10 +18,13 @@ Render_Command_Type :: enum {
DRAW_GROUND;
ADD_TRILE_POSITIONS;
DRAW_TRILE_POSITIONS;
ADD_TRILE_RDM_POSITION;
DRAW_TRILE_RDM;
UPDATE_TRIXELS;
DRAW_TRIXELS;
SET_LIGHT;
DRAW_BILLBOARD;
UPDATE_PARTICLES;
DRAW_PARTICLES;
}
@ -54,8 +57,24 @@ Render_Command_Draw_Trile_Positions :: struct {
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
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 {
@ -86,15 +105,22 @@ Render_Command_Draw_Trixels :: struct {
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;
blend_mode : Particle_Blend_Mode;
sheet : sg_image;
pos_size : [2048]Vector4;
uv_rects : [2048]Vector4;
colors : [2048]Vector4;
#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 {

View File

@ -8,7 +8,8 @@ bypass_postprocess : bool = false;
bypass_shadows : bool = false;
bypass_reflections : bool = false;
trile_offsets : [..]s32;
trile_offsets : [..]s32;
trile_rdm_offsets : [..]s32;
current_world_config : *World_Config = null;
in_shadowmap_pass : bool = false;
@ -23,7 +24,13 @@ backend_handle_command :: (cmd: *Render_Command) {
backend_add_trile_positions(add_command.positions);
case .DRAW_TRILE_POSITIONS;
draw_command := cast(*Render_Command_Draw_Trile_Positions)cmd;
backend_draw_trile_positions(draw_command.trile, draw_command.amount, draw_command.conf, draw_command.chunk_key, draw_command.preview_mode, draw_command.offset_index);
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);
@ -53,6 +60,9 @@ backend_handle_command :: (cmd: *Render_Command) {
} 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);
@ -131,15 +141,15 @@ backend_add_trile_positions :: (positions : []Vector4) {
array_add(*trile_offsets, offset);
}
backend_draw_trile_positions :: (trile : string, amount : s32, worldConf: *World_Config, chunk_key: Chunk_Key, preview_mode: s32 = 0, offset_index: s32 = 0) {
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);
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);
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) {
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);
@ -153,10 +163,27 @@ backend_draw_trile_positions_gbuffer :: (trile : string, amount : s32, worldConf
offset := trile_offsets[offset_index];
trilegfx := get_trile_gfx(trile);
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] = trilegfx.vertex_buffer;
bindings.vertex_buffers[1] = trilegfx.normal_buffer;
bindings.vertex_buffers[2] = trilegfx.centre_buffer;
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];
@ -164,10 +191,10 @@ backend_draw_trile_positions_gbuffer :: (trile : string, amount : s32, worldConf
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) trilegfx.vertex_count, amount);
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) {
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");
@ -177,24 +204,84 @@ backend_draw_trile_positions_main :: (trile : string, amount : s32, worldConf: *
trilegfx := get_trile_gfx(trile);
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] = trilegfx.vertex_buffer;
bindings.vertex_buffers[1] = trilegfx.normal_buffer;
bindings.vertex_buffers[2] = trilegfx.centre_buffer;
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) trilegfx.vertex_count, amount);
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;
@ -205,9 +292,9 @@ backend_draw_trile_positions_main :: (trile : string, amount : s32, worldConf: *
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[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];
@ -215,27 +302,12 @@ backend_draw_trile_positions_main :: (trile : string, amount : s32, worldConf: *
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];
// Bind RDM textures for this chunk. Fall back to a 1x1 black image when
// no baked data is available so sokol doesn't drop the draw call.
// The shader gates all RDM sampling on atlas_rect.z > 0, which the
// fallback texture returns as 0, so the ambient fallback path is taken.
curworld := get_current_world();
chunk := table_find_pointer(*curworld.world.chunks, chunk_key);
if chunk != null && chunk.rdm_valid {
bindings.images[3] = chunk.rdm_lookup;
bindings.images[4] = chunk.rdm_atlas;
} else {
bindings.images[3] = g_rdm_fallback;
bindings.images[4] = g_rdm_fallback;
}
bindings.images[5] = g_brdf_lut;
if chunk != null && chunk.sh_valid {
bindings.images[6] = chunk.sh_probe_grid;
} else {
bindings.images[6] = g_sh_fallback;
}
bindings.samplers[3] = gPipelines.trile.bind.samplers[3];
fs_params : Trile_Fs_Params;
fs_params.mvp_shadow = shadow_mvp.floats;
@ -244,25 +316,92 @@ backend_draw_trile_positions_main :: (trile : string, amount : s32, worldConf: *
fs_params.screen_w = w;
fs_params.screen_h = h;
lc := *current_lighting_config;
fs_params.rdm_enabled = ifx in_reflection_pass then 0 else lc.rdm_enabled;
fs_params.ambient_intensity = lc.ambient_intensity;
fs_params.emissive_scale = lc.emissive_scale;
fs_params.rdm_diff_scale = lc.rdm_diff_scale;
fs_params.rdm_spec_scale = lc.rdm_spec_scale;
fs_params.ambient_color = lc.ambient_color.component;
fs_params.is_preview = preview_mode;
fs_params.rdm_tint = lc.rdm_tint.component;
fs_params.rdm_diff_saturation = worldConf.rdmDiffSaturation;
fs_params.sh_enabled = ifx (chunk != null && chunk.sh_valid && !in_reflection_pass) then cast(s32)1 else cast(s32)0;
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) trilegfx.vertex_count, amount);
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 := get_trile_gfx(trile);
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;
@ -370,23 +509,27 @@ backend_gbuffer_draw_billboard :: (position: Vector3, anim: *Animation, frame_id
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;
sg_update_buffer(pip.bind.vertex_buffers[1], *(sg_range.{
ptr = cmd.pos_size.data,
size = cast(u64)(cmd.count * size_of(Vector4)),
}));
sg_update_buffer(pip.bind.vertex_buffers[2], *(sg_range.{
ptr = cmd.uv_rects.data,
size = cast(u64)(cmd.count * size_of(Vector4)),
}));
sg_update_buffer(pip.bind.vertex_buffers[3], *(sg_range.{
ptr = cmd.colors.data,
size = cast(u64)(cmd.count * size_of(Vector4)),
}));
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;
@ -394,8 +537,8 @@ backend_draw_particles :: (cmd: *Render_Command_Draw_Particles) {
vs_params.cam = camera.position.component;
sg_apply_pipeline(pip.pipeline);
pip.bind.images[IMG_particle_sprite] = cmd.sheet;
sg_apply_bindings(*pip.bind);
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);
}
@ -421,6 +564,39 @@ backend_draw_ground_gbuf :: (wc: *World_Config) {
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");
@ -484,7 +660,11 @@ backend_process_command_buckets :: () {
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");
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");
@ -499,7 +679,8 @@ backend_process_command_buckets :: () {
start_frame_profiling_group("Postprocess pass");
if !bypass_postprocess {
bloom_process();
dof_process();
dof_downsample_process();
dof_bokeh_process();
}
end_frame_profiling_group("Postprocess pass");
@ -512,29 +693,23 @@ backend_process_command_buckets :: () {
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_tex;
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;
post_process_dof_config_uniform : Dof_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);
w,h := get_render_size();
post_process_dof_config_uniform.dof_tex_width = cast(float)w/2;
post_process_dof_config_uniform.dof_tex_height = cast(float)h/2;
post_process_dof_config_uniform.dof_point = current_post_process.dof_point;
post_process_dof_config_uniform.dof_min = current_post_process.dof_min;
post_process_dof_config_uniform.dof_max = current_post_process.dof_max;
}
sg_apply_uniforms(UB_post_process_config, *(sg_range.{ ptr = *post_process_config_uniform, size = size_of(type_of(post_process_config_uniform)) }));
sg_apply_uniforms(UB_dof_config, *(sg_range.{ ptr = *post_process_dof_config_uniform, size = size_of(type_of(post_process_dof_config_uniform)) }));
dof_config_uniform : Dof_Config;
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();
@ -554,5 +729,6 @@ backend_process_command_buckets :: () {
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,66 +1,81 @@
bloom_process :: () {
sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, attachments = g_bloom_attach }));
sg_apply_pipeline(gPipelines.bloom.pipeline);
params : Bloom_Params;
params.bloom_treshold = current_post_process.bloom_treshold;
gPipelines.bloom.bind.images[IMG_bloom_src] = g_rendertex;
sg_apply_uniforms(UB_bloom_params, *(sg_range.{ ptr = *params, size = size_of(type_of(params)) }));
sg_apply_bindings(*gPipelines.bloom.bind);
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_process :: () {
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.pipeline);
params : Dof_Params;
// params.dof_treshold = current_post_process.dof_treshold;
gPipelines.dof.bind.images[IMG_dof_src] = g_rendertex;
sg_apply_uniforms(UB_dof_params, *(sg_range.{ ptr = *params, size = size_of(type_of(params)) }));
sg_apply_bindings(*gPipelines.dof.bind);
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();
}
// dof_process :: () {
// sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, attachments = g_postprocess_attach_a }));
// sg_apply_pipeline(gPipelines.op.pipeline);
// op_uniform_dilate : Op_Fs_Params;
// op_uniform_dilate.blur_size = current_post_process.dof_blur_size;
// op_uniform_dilate.op=2;
// gPipelines.op.bind.images[0] = g_postprocess_b;
// sg_apply_uniforms(UB_op_fs_params, *(sg_range.{ ptr = *op_uniform_dilate, size = size_of(type_of(op_uniform_dilate)) }));
// sg_apply_bindings(*gPipelines.op.bind);
// sg_draw(0, 6, 1);
// sg_end_pass();
// sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, attachments = g_rendertex_attachments }));
// sg_apply_pipeline(gPipelines.op.pipeline);
// op_uniform_dof_blur : Op_Fs_Params;
// op_uniform_dof_blur.blur_size = current_post_process.dilate_size;
// op_uniform_dof_blur.separation = current_post_process.dilate_separation;
// op_uniform_dof_blur.dilate_min = current_post_process.dilate_min;
// op_uniform_dof_blur.dilate_max = current_post_process.dilate_max;
// op_uniform_dof_blur.op=1;
// gPipelines.op.bind.images[0] = g_postprocess_a;
// sg_apply_uniforms(UB_op_fs_params, *(sg_range.{ ptr = *op_uniform_dof_blur, size = size_of(type_of(op_uniform_dof_blur)) }));
// sg_apply_bindings(*gPipelines.op.bind);
// sg_draw(0, 6, 1);
// sg_end_pass();
// sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, attachments = g_postprocess_attach_a }));
// sg_apply_pipeline(gPipelines.mix.pipeline);
// mix_uniform : Mix_Fs_Params;
// mix_uniform.op = 0;
// mix_uniform.dof_min = current_post_process.dof_min;
// mix_uniform.dof_max = current_post_process.dof_max;
// mix_uniform.dof_point = current_post_process.dof_point;
// gPipelines.mix.bind.images[0] = g_rendertex;
// gPipelines.mix.bind.images[1] = g_postprocess_b;
// gPipelines.mix.bind.images[2] = g_gbuf_position;
// sg_apply_uniforms(UB_op_fs_params, *(sg_range.{ ptr = *mix_uniform, size = size_of(type_of(mix_uniform)) }));
// sg_apply_bindings(*gPipelines.mix.bind);
// sg_draw(0, 6, 1);
// sg_end_pass();
// }

View File

@ -18,6 +18,11 @@ Gathered_Positions :: struct {
positions: [..]Vector4;
}
Gathered_Rdm_Position :: struct {
name: string;
position: Vector4;
}
extract_frustum_planes :: (mvp: Matrix4) -> [6]Vector4 {
planes : [6]Vector4;
m := mvp;
@ -40,7 +45,19 @@ aabb_in_frustum :: (planes: [6]Vector4, bmin: Vector3, bmax: Vector3) -> bool {
return true;
}
create_world_rendering_tasks :: (world: *World, camera: Camera) {
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;
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);
@ -49,12 +66,24 @@ create_world_rendering_tasks :: (world: *World, camera: Camera) {
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);
// Gather positions for camera-visible instances (all passes) and
// shadow-only instances (chunks visible from sun but not camera).
gathered : [..]Gathered_Positions;
gathered.allocator = temp;
gathered_per_lod : [3][..]Gathered_Positions;
for i: 0..2 gathered_per_lod[i].allocator = temp;
shad_gathered : [..]Gathered_Positions;
shad_gathered.allocator = temp;
rdm_extra : [..]Gathered_Positions; // RDM-flagged instances visible to camera; shadow/gbuffer/reflection use base pipeline
rdm_extra.allocator = temp;
rdm_main : [..]Gathered_Rdm_Position; // one entry per RDM-flagged instance for the main pass
rdm_main.allocator = temp;
find_or_create :: (list: *[..]Gathered_Positions, name: string, chunk_key: Chunk_Key) -> *Gathered_Positions {
for *g: list.* {
@ -70,24 +99,47 @@ create_world_rendering_tasks :: (world: *World, camera: Camera) {
bmin := Vector3.{chunk.coord.x * 32.0, chunk.coord.y * 32.0, chunk.coord.z * 32.0};
bmax := bmin + .{32, 32, 32};
in_cam := aabb_in_frustum(cam_planes, bmin, bmax);
in_shad := aabb_in_frustum(shadow_planes, bmin, bmax);
if !in_cam && !in_shad continue;
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);
if !in_cam && !in_reflect && !in_shad continue;
for group: chunk.groups {
for inst: group.instances {
for inst, idx: group.instances {
if idx < group.is_buried.count && group.is_buried[idx] continue;
wx, wy, wz := chunk_local_to_world(chunk.coord, inst.x, inst.y, inst.z);
imin := Vector3.{cast(float)wx, cast(float)wy, cast(float)wz};
imax := imin + .{1, 1, 1};
inst_cam := in_cam && aabb_in_frustum(cam_planes, imin, imax);
inst_shad := in_shad && aabb_in_frustum(shadow_planes, imin, imax);
if !inst_cam && !inst_shad continue;
inst_cam := in_cam && aabb_in_frustum(cam_planes, imin, imax);
inst_reflect := in_reflect && aabb_in_frustum(reflect_planes, imin, imax);
inst_shad := in_shad && aabb_in_frustum(shadow_planes, imin, imax);
if !inst_cam && !inst_reflect && !inst_shad continue;
dist := length(imin + .{0.5, 0.5, 0.5} - camera.position);
lod_idx : s32 = -1;
for i: 0..2 {
if dist < LOD_DISTANCES[i] {
lod_idx = cast(s32) i;
break;
}
}
if lod_idx < 0 continue; // beyond cull distance
pos := Vector4.{cast(float)wx, cast(float)wy, cast(float)wz, cast(float)inst.orientation};
if inst_cam {
target := find_or_create(*gathered, group.trile_name, chunk.coord);
array_add(*target.positions, pos);
is_rdm := is_rdm_instance_enabled(world, wx, wy, wz);
if inst_cam || inst_reflect {
if is_rdm {
target := find_or_create(*rdm_extra, group.trile_name, chunk.coord);
array_add(*target.positions, pos);
if inst_cam {
array_add(*rdm_main, .{name = group.trile_name, position = pos});
}
} else {
target := find_or_create(*gathered_per_lod[lod_idx], group.trile_name, chunk.coord);
array_add(*target.positions, pos);
}
} else {
target := find_or_create(*shad_gathered, group.trile_name, chunk.coord);
array_add(*target.positions, pos);
@ -96,14 +148,17 @@ create_world_rendering_tasks :: (world: *World, camera: Camera) {
}
}
for g: gathered {
if g.positions.count < 1 continue;
triletask : Rendering_Task_Trile;
triletask.trile = g.name;
triletask.chunk_key = g.chunk_key;
triletask.positions = g.positions;
triletask.worldConf = *world.conf;
add_rendering_task(triletask);
for lod_idx: 0..2 {
for g: gathered_per_lod[lod_idx] {
if g.positions.count < 1 continue;
triletask : Rendering_Task_Trile;
triletask.trile = g.name;
triletask.chunk_key = g.chunk_key;
triletask.positions = g.positions;
triletask.worldConf = *world.conf;
triletask.lod_index = cast(s32) lod_idx;
add_rendering_task(triletask);
}
}
for g: shad_gathered {
if g.positions.count < 1 continue;
@ -115,6 +170,26 @@ create_world_rendering_tasks :: (world: *World, camera: Camera) {
triletask.shadow_only = true;
add_rendering_task(triletask);
}
for g: rdm_extra {
if g.positions.count < 1 continue;
triletask : Rendering_Task_Trile;
triletask.trile = g.name;
triletask.chunk_key = g.chunk_key;
triletask.positions = g.positions;
triletask.worldConf = *world.conf;
triletask.skip_main = true;
add_rendering_task(triletask);
}
for r: rdm_main {
rect, found := rdm_get_atlas_rect(world, cast(s32) r.position.x, cast(s32) r.position.y, cast(s32) r.position.z);
if !found then continue;
rdmtask : Rendering_Task_Trile_RDM;
rdmtask.trile = r.name;
rdmtask.position = r.position;
rdmtask.atlas_rect = rect;
rdmtask.worldConf = *world.conf;
add_rendering_task(rdmtask);
}
create_ground_rendering_task(world);
}

153
src/rendering/lodgen.jai Normal file
View File

@ -0,0 +1,153 @@
// 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

@ -498,6 +498,12 @@ generate_trile_gfx_matias :: (trileptr : *Trile) -> Trile_GFX {
context.allocator = old_alloc;
vecsCopy := array_copy(triangleVecs);
Pool.reset(*meshgenpool);
return .{ img, trile_vert_buffer, trile_normal_buffer, trile_centre_buffer, vecsCopy, triangleVecs.count / 3 };
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

@ -0,0 +1,34 @@
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 {
}
}

View File

@ -1,4 +1,4 @@
SHADOWMAP_SIZE :: 1000;
SHADOWMAP_SIZE :: 1500;
Pipeline_Binding :: struct {
pipeline : sg_pipeline;
@ -10,6 +10,7 @@ Pipeline_Binding :: struct {
g_specular_lut : sg_image;
g_brdf_lut : sg_image;
g_rdm_fallback : sg_image; // 1x1 black image used when a chunk has no baked RDM data
g_rdm_atlas : sg_image; // global RGBA16F atlas holding RDM hemispheres for flagged instances (populated in Steps 5-6)
g_sh_fallback : sg_image; // 1x1 black 2D image used when a chunk has no SH probe grid
g_shadowmap : sg_image;
@ -23,6 +24,7 @@ g_rendertex_attachments : sg_attachments;
g_gbuf_position : sg_image;
g_gbuf_normal : sg_image;
g_gbuf_worldpos : sg_image;
g_gbuf_depth : sg_image;
g_gbuf_attachments : sg_attachments;
@ -31,6 +33,9 @@ g_ssao_noise_buf : sg_image;
g_ssaobuf_depth : sg_image;
g_ssao_attachments : sg_attachments;
g_sh_irradiance : sg_image;
g_sh_irradiance_attach : sg_attachments;
g_postprocess_a : sg_image;
g_postprocess_b : sg_image;
g_postprocess_a_depth : sg_image;
@ -38,11 +43,18 @@ g_postprocess_b_depth : sg_image;
g_postprocess_attach_a : sg_attachments;
g_postprocess_attach_b : sg_attachments;
g_bloom_tex : sg_image;
g_bloom_attach : sg_attachments;
g_bloom_down_1 : sg_image; g_bloom_down_1_attach : sg_attachments;
g_bloom_down_2 : sg_image; g_bloom_down_2_attach : sg_attachments;
g_bloom_down_3 : sg_image; g_bloom_down_3_attach : sg_attachments;
g_bloom_down_4 : sg_image; g_bloom_down_4_attach : sg_attachments;
g_bloom_up_3 : sg_image; g_bloom_up_3_attach : sg_attachments;
g_bloom_up_2 : sg_image; g_bloom_up_2_attach : sg_attachments;
g_bloom_up_1 : sg_image; g_bloom_up_1_attach : sg_attachments;
g_dof_tex : sg_image;
g_dof_attach : sg_attachments;
g_dof_tex : sg_image;
g_dof_attach : sg_attachments;
g_dof_downsample_tex : sg_image;
g_dof_downsample_attach: sg_attachments;
gPipelines : struct {
@ -63,9 +75,15 @@ gPipelines : struct {
// Renders sets of triles
trile : Pipeline_Binding;
// Per-instance variant for triles flagged with sharp-specular RDM lookup
trile_rdm : Pipeline_Binding;
// Depth-only shadow pass for triles (no lighting/RDM)
trile_shadow : Pipeline_Binding;
// Cube-grid LOD pipeline for distant triles (vertex color, no ray-march)
trile_lod : Pipeline_Binding;
// Renders the ground plane. (just water)
plane : Pipeline_Binding;
@ -76,8 +94,12 @@ gPipelines : struct {
mix : Pipeline_Binding;
bloom : Pipeline_Binding;
dof: Pipeline_Binding;
bloom_prefilter : Pipeline_Binding;
bloom_downsample : Pipeline_Binding;
bloom_upsample : Pipeline_Binding;
dof_downsample : Pipeline_Binding;
dof_blur : Pipeline_Binding;
billboard : Pipeline_Binding;
@ -88,6 +110,8 @@ gPipelines : struct {
ssao: Pipeline_Binding;
sh_irradiance: Pipeline_Binding;
debugline : Pipeline_Binding;
}
@ -102,7 +126,7 @@ create_final_image :: () {
img_desc := sg_image_desc.{
width = w,
height = h,
pixel_format = .RGBA32F,
pixel_format = .RGBA16F,
render_target = true,
};
depth_desc := sg_image_desc.{
@ -137,7 +161,7 @@ create_shadowmap_image :: () {
img_desc := sg_image_desc.{
width = w,
height = h,
pixel_format = .RGBA32F,
pixel_format = .RGBA16F,
render_target = true,
};
g_shadowmap = sg_make_image(*depth_desc);
@ -157,15 +181,20 @@ create_pipelines :: () {
create_arbtri_pipeline();
create_trixel_pipeline();
create_trile_pipeline();
create_trile_rdm_pipeline();
create_trile_shadow_pipeline();
create_trile_lod_pipeline();
create_sky_pipeline();
create_plane_pipeline();
create_postprocess_pipeline();
create_ssao_pipeline();
create_op_pipeline();
create_mix_pipeline();
create_bloom_pipeline();
create_dof_pipeline();
create_bloom_prefilter_pipeline();
create_bloom_downsample_pipeline();
create_bloom_upsample_pipeline();
create_dof_downsample_pipeline();
create_dof_blur_pipeline();
create_billboard_pipeline();
create_gbuffer_billboard_pipeline();
create_particle_pipeline();
@ -174,6 +203,8 @@ create_pipelines :: () {
create_shadowmap_image();
create_final_image();
create_ssao_images();
create_sh_irradiance_pipeline();
create_sh_irradiance_image();
create_gbuffer_impostors();
}
@ -182,6 +213,7 @@ create_gbuffer_images :: () {
if g_gbuf_position.id != INVALID_ID then sg_destroy_image(g_gbuf_position);
if g_gbuf_normal.id != INVALID_ID then sg_destroy_image(g_gbuf_normal);
if g_gbuf_worldpos.id != INVALID_ID then sg_destroy_image(g_gbuf_worldpos);
if g_gbuf_depth.id != INVALID_ID then sg_destroy_image(g_gbuf_depth);
img_desc := sg_image_desc.{
@ -198,15 +230,17 @@ create_gbuffer_images :: () {
};
g_gbuf_position = sg_make_image(*img_desc);
g_gbuf_normal = sg_make_image(*img_desc);
g_gbuf_depth = sg_make_image(*depth_desc);
g_gbuf_normal = sg_make_image(*img_desc);
g_gbuf_worldpos = sg_make_image(*img_desc);
g_gbuf_depth = sg_make_image(*depth_desc);
attachmentsDesc : sg_attachments_desc;
attachmentsDesc = .{
colors[0].image = g_gbuf_position,
colors[1].image = g_gbuf_normal,
depth_stencil.image = g_gbuf_depth,
};
attachmentsDesc = .{
colors[0].image = g_gbuf_position,
colors[1].image = g_gbuf_normal,
colors[2].image = g_gbuf_worldpos,
depth_stencil.image = g_gbuf_depth,
};
sg_destroy_attachments(g_gbuf_attachments);
g_gbuf_attachments = sg_make_attachments(*attachmentsDesc);
}
@ -241,7 +275,7 @@ create_trixel_pipeline :: () {
};
color_state := sg_color_target_state.{
pixel_format = .RGBA32F,
pixel_format = .RGBA16F,
blend = .{
enabled = true,
src_factor_rgb = .SRC_ALPHA,
@ -369,9 +403,10 @@ create_gbuffer_pipeline :: () {
};
pipeline.color_count = 2;
pipeline.color_count = 3;
pipeline.colors[0] = color_state_pos;
pipeline.colors[1] = color_state_normal;
pipeline.colors[2] = .{ pixel_format = .RGBA16F };
gPipelines.gbuffer.pipeline = sg_make_pipeline(*pipeline);
gPipelines.gbuffer.bind.samplers[0] = sg_make_sampler(*(sg_sampler_desc.{
@ -405,7 +440,7 @@ create_trile_pipeline :: () {
};
color_state := sg_color_target_state.{
pixel_format = .RGBA32F,
pixel_format = .RGBA16F,
blend = .{
enabled = true,
src_factor_rgb = .SRC_ALPHA,
@ -433,6 +468,52 @@ create_trile_pipeline :: () {
}));
}
create_trile_rdm_pipeline :: () {
pipeline: sg_pipeline_desc;
shader_desc := trile_rdm_shader_desc(sg_query_backend());
pipeline.shader = sg_make_shader(*shader_desc);
pipeline.layout.buffers[0].stride = 4*3;
pipeline.layout.buffers[1].stride = 4*3;
pipeline.layout.buffers[3].step_func = .PER_INSTANCE;
instance_buffer := sg_buffer_desc.{ usage = .STREAM, size = 16 * 64 };
pipeline.layout.attrs[ATTR_trile_rdm_position] = .{ format = .FLOAT3, buffer_index = 0 };
pipeline.layout.attrs[ATTR_trile_rdm_normal] = .{ format = .FLOAT3, buffer_index = 1 };
pipeline.layout.attrs[ATTR_trile_rdm_centre] = .{ format = .FLOAT3, buffer_index = 2 };
pipeline.layout.attrs[ATTR_trile_rdm_instance] = .{ format = .FLOAT4, buffer_index = 3 };
pipeline.depth = .{
write_enabled = true,
compare = .LESS_EQUAL,
pixel_format = .DEPTH,
};
pipeline.color_count = 1;
pipeline.colors[0] = sg_color_target_state.{
pixel_format = .RGBA16F,
blend = .{
enabled = true,
src_factor_rgb = .SRC_ALPHA,
dst_factor_rgb = .ONE_MINUS_SRC_ALPHA,
},
};
gPipelines.trile_rdm.pipeline = sg_make_pipeline(*pipeline);
gPipelines.trile_rdm.bind.samplers[0] = sg_make_sampler(*(sg_sampler_desc.{
wrap_u = .CLAMP_TO_EDGE,
wrap_v = .CLAMP_TO_EDGE,
min_filter = .NEAREST,
mag_filter = .NEAREST,
}));
gPipelines.trile_rdm.bind.vertex_buffers[3] = sg_make_buffer(*instance_buffer);
gPipelines.trile_rdm.bind.samplers[3] = sg_make_sampler(*(sg_sampler_desc.{
wrap_u = .CLAMP_TO_EDGE,
wrap_v = .CLAMP_TO_EDGE,
min_filter = .LINEAR,
mag_filter = .LINEAR,
}));
}
create_trile_shadow_pipeline :: () {
pipeline: sg_pipeline_desc;
shader_desc := trile_shadow_shader_desc(sg_query_backend());
@ -451,10 +532,43 @@ create_trile_shadow_pipeline :: () {
pixel_format = .DEPTH,
};
pipeline.color_count = 1;
pipeline.colors[0].pixel_format = .RGBA32F;
pipeline.colors[0].pixel_format = .RGBA16F;
gPipelines.trile_shadow.pipeline = sg_make_pipeline(*pipeline);
}
create_trile_lod_pipeline :: () {
pipeline: sg_pipeline_desc;
shader_desc := trile_lod_shader_desc(sg_query_backend());
pipeline.shader = sg_make_shader(*shader_desc);
pipeline.layout.buffers[0].stride = 4*3;
pipeline.layout.buffers[1].stride = 4*3;
pipeline.layout.buffers[2].stride = 4*3;
pipeline.layout.buffers[3].step_func = .PER_INSTANCE;
pipeline.layout.attrs[ATTR_trile_lod_position] = .{ format = .FLOAT3, buffer_index = 0 };
pipeline.layout.attrs[ATTR_trile_lod_normal] = .{ format = .FLOAT3, buffer_index = 1 };
pipeline.layout.attrs[ATTR_trile_lod_color] = .{ format = .FLOAT3, buffer_index = 2 };
pipeline.layout.attrs[ATTR_trile_lod_instance] = .{ format = .FLOAT4, buffer_index = 3 };
pipeline.depth = .{
write_enabled = true,
compare = .LESS_EQUAL,
pixel_format = .DEPTH,
};
pipeline.color_count = 1;
pipeline.colors[0] = sg_color_target_state.{
pixel_format = .RGBA16F,
blend = .{
enabled = true,
src_factor_rgb = .SRC_ALPHA,
dst_factor_rgb = .ONE_MINUS_SRC_ALPHA,
},
};
gPipelines.trile_lod.pipeline = sg_make_pipeline(*pipeline);
}
create_sky_pipeline :: () {
pipeline: sg_pipeline_desc;
shader_desc := sky_shader_desc(sg_query_backend());
@ -470,7 +584,7 @@ create_sky_pipeline :: () {
};
color_state := sg_color_target_state.{
pixel_format = .RGBA32F,
pixel_format = .RGBA16F,
blend = .{
enabled = true,
src_factor_rgb = .SRC_ALPHA,
@ -545,7 +659,7 @@ create_plane_pipeline_reflection_images :: () {
img_desc := sg_image_desc.{
width = w/3,
height = h/3,
pixel_format = .RGBA8,
pixel_format = .RGBA16F,
render_target = true,
};
depth_desc := sg_image_desc.{
@ -585,7 +699,7 @@ create_plane_pipeline :: () {
};
color_state := sg_color_target_state.{
pixel_format = .RGBA32F,
pixel_format = .RGBA16F,
blend = .{
enabled = true,
src_factor_rgb = .SRC_ALPHA,
@ -766,6 +880,13 @@ create_postprocess_pipeline :: () {
mag_filter = .LINEAR,
}));
gPipelines.postprocess.bind.samplers[4] = sg_make_sampler(*(sg_sampler_desc.{
wrap_u = .CLAMP_TO_EDGE,
wrap_v = .CLAMP_TO_EDGE,
min_filter = .NEAREST,
mag_filter = .NEAREST,
}));
}
// Takes in a texture, manipulates it and outputs it.
@ -785,7 +906,7 @@ create_op_pipeline :: () {
src_factor_rgb = .SRC_ALPHA,
dst_factor_rgb = .ONE_MINUS_SRC_ALPHA
},
pixel_format = .RGBA32F,
pixel_format = .RGBA16F,
};
pipeline.depth = .{
write_enabled = true,
@ -845,7 +966,7 @@ create_billboard_pipeline :: () {
};
color_state := sg_color_target_state.{
pixel_format = .RGBA32F,
pixel_format = .RGBA16F,
blend = .{
enabled = true,
src_factor_rgb = .SRC_ALPHA,
@ -907,9 +1028,10 @@ create_gbuffer_billboard_pipeline :: () {
};
pipeline.color_count = 2;
pipeline.color_count = 3;
pipeline.colors[0] = color_state_pos;
pipeline.colors[1] = color_state_normal;
pipeline.colors[2] = .{ pixel_format = .RGBA16F };
vertices: [4]Vector3 = .[
.{ 0.0, 0.0, 0.0},
@ -923,10 +1045,6 @@ create_gbuffer_billboard_pipeline :: () {
0, 2, 3,
];
pipeline.color_count = 2;
pipeline.colors[0] = color_state_pos;
pipeline.colors[1] = color_state_normal;
gPipelines.gbuffer_billboard.pipeline = sg_make_pipeline(*pipeline);
ibuffer := sg_buffer_desc.{ type = .INDEXBUFFER, data = .{ ptr = indices.data, size = 6 * 2 } };
@ -960,7 +1078,7 @@ create_mix_pipeline :: () {
src_factor_rgb = .SRC_ALPHA,
dst_factor_rgb = .ONE_MINUS_SRC_ALPHA
},
pixel_format = .RGBA32F,
pixel_format = .RGBA16F,
};
pipeline.depth = .{
write_enabled = true,
@ -1005,66 +1123,92 @@ create_mix_pipeline :: () {
}
create_bloom_pipeline :: () {
platconf := get_plat_conf();
pipeline: sg_pipeline_desc;
shader_desc := bloom_shader_desc(sg_query_backend());
pipeline.shader = sg_make_shader(*shader_desc);
pipeline.layout.attrs[ATTR_bloom_position] = .{ format = .FLOAT2 };
pipeline.layout.attrs[ATTR_bloom_uv] = .{ format = .FLOAT2 };
pipeline.index_type = .UINT16;
pipeline.color_count = 1;
pipeline.colors[0] = .{ pixel_format = .RGBA32F };
gPipelines.bloom.pipeline = sg_make_pipeline(*pipeline);
bloom_quad_vbuffer : sg_buffer;
bloom_quad_ibuffer : sg_buffer;
create_bloom_quad_buffers :: () {
quad_vertices : [16]float = .[
-1.0, 1.0, 0.0, flip_if_plat(1.0),
-1.0, -1.0, 0.0, flip_if_plat(0.0),
1.0, -1.0, 1.0, flip_if_plat(0.0),
1.0, 1.0, 1.0, flip_if_plat(1.0),
];
quad_indices : [6]u16 = .[
0, 1, 2, 0, 2, 3
];
quad_indices : [6]u16 = .[ 0, 1, 2, 0, 2, 3 ];
bloom_quad_vbuffer = sg_make_buffer(*(sg_buffer_desc.{ size = size_of(float) * 16, data = .{ ptr = quad_vertices.data, size = 16 * 4 }}));
bloom_quad_ibuffer = sg_make_buffer(*(sg_buffer_desc.{ size = size_of(u16) * 6, data = .{ ptr = quad_indices.data, size = 6 * 2 }, type = .INDEXBUFFER }));
}
vbuffer := sg_buffer_desc.{ size = size_of(float) * 16, data = .{
ptr = quad_vertices.data,
size = 16 * 4
}};
ibuffer := sg_buffer_desc.{ size = size_of(u16) * 6, data = .{
ptr = quad_indices.data,
size = 6 * 2
},
type = .INDEXBUFFER,
};
gPipelines.bloom.bind.vertex_buffers[0] = sg_make_buffer(*vbuffer);
gPipelines.bloom.bind.index_buffer = sg_make_buffer(*ibuffer);
gPipelines.bloom.bind.samplers[0] = sg_make_sampler(*(sg_sampler_desc.{
linear_clamp_sampler :: () -> sg_sampler {
return sg_make_sampler(*(sg_sampler_desc.{
wrap_u = .CLAMP_TO_EDGE,
wrap_v = .CLAMP_TO_EDGE,
min_filter = .NEAREST,
mag_filter = .NEAREST,
min_filter = .LINEAR,
mag_filter = .LINEAR,
}));
}
create_dof_pipeline :: () {
create_bloom_prefilter_pipeline :: () {
create_bloom_quad_buffers();
pipeline: sg_pipeline_desc;
pipeline.shader = sg_make_shader(*bloom_prefilter_shader_desc(sg_query_backend()));
pipeline.layout.attrs[ATTR_bloom_prefilter_position] = .{ format = .FLOAT2 };
pipeline.layout.attrs[ATTR_bloom_prefilter_uv] = .{ format = .FLOAT2 };
pipeline.index_type = .UINT16;
pipeline.depth.pixel_format = .NONE;
pipeline.color_count = 1;
pipeline.colors[0] = .{ pixel_format = .RGBA16F };
gPipelines.bloom_prefilter.pipeline = sg_make_pipeline(*pipeline);
gPipelines.bloom_prefilter.bind.vertex_buffers[0] = bloom_quad_vbuffer;
gPipelines.bloom_prefilter.bind.index_buffer = bloom_quad_ibuffer;
gPipelines.bloom_prefilter.bind.samplers[SMP_bloom_prefilter_src_smp] = linear_clamp_sampler();
}
create_bloom_downsample_pipeline :: () {
pipeline: sg_pipeline_desc;
pipeline.shader = sg_make_shader(*bloom_downsample_shader_desc(sg_query_backend()));
pipeline.layout.attrs[ATTR_bloom_downsample_position] = .{ format = .FLOAT2 };
pipeline.layout.attrs[ATTR_bloom_downsample_uv] = .{ format = .FLOAT2 };
pipeline.index_type = .UINT16;
pipeline.depth.pixel_format = .NONE;
pipeline.color_count = 1;
pipeline.colors[0] = .{ pixel_format = .RGBA16F };
gPipelines.bloom_downsample.pipeline = sg_make_pipeline(*pipeline);
gPipelines.bloom_downsample.bind.vertex_buffers[0] = bloom_quad_vbuffer;
gPipelines.bloom_downsample.bind.index_buffer = bloom_quad_ibuffer;
gPipelines.bloom_downsample.bind.samplers[SMP_bloom_downsample_src_smp] = linear_clamp_sampler();
}
create_bloom_upsample_pipeline :: () {
pipeline: sg_pipeline_desc;
pipeline.shader = sg_make_shader(*bloom_upsample_shader_desc(sg_query_backend()));
pipeline.layout.attrs[ATTR_bloom_upsample_position] = .{ format = .FLOAT2 };
pipeline.layout.attrs[ATTR_bloom_upsample_uv] = .{ format = .FLOAT2 };
pipeline.index_type = .UINT16;
pipeline.depth.pixel_format = .NONE;
pipeline.color_count = 1;
pipeline.colors[0] = .{ pixel_format = .RGBA16F };
gPipelines.bloom_upsample.pipeline = sg_make_pipeline(*pipeline);
gPipelines.bloom_upsample.bind.vertex_buffers[0] = bloom_quad_vbuffer;
gPipelines.bloom_upsample.bind.index_buffer = bloom_quad_ibuffer;
gPipelines.bloom_upsample.bind.samplers[SMP_bloom_upsample_small_smp] = linear_clamp_sampler();
gPipelines.bloom_upsample.bind.samplers[SMP_bloom_upsample_large_smp] = linear_clamp_sampler();
}
create_dof_downsample_pipeline :: () {
platconf := get_plat_conf();
pipeline: sg_pipeline_desc;
shader_desc := dof_shader_desc(sg_query_backend());
shader_desc := dof_downsample_shader_desc(sg_query_backend());
pipeline.shader = sg_make_shader(*shader_desc);
pipeline.layout.attrs[ATTR_dof_position] = .{ format = .FLOAT2 };
pipeline.layout.attrs[ATTR_dof_uv] = .{ format = .FLOAT2 };
pipeline.layout.attrs[ATTR_dof_downsample_position] = .{ format = .FLOAT2 };
pipeline.layout.attrs[ATTR_dof_downsample_uv] = .{ format = .FLOAT2 };
pipeline.index_type = .UINT16;
pipeline.depth.pixel_format = .NONE;
pipeline.color_count = 1;
pipeline.colors[0] = .{ pixel_format = .RGBA32F };
pipeline.colors[0] = .{ pixel_format = .RGBA16F };
gPipelines.dof.pipeline = sg_make_pipeline(*pipeline);
gPipelines.dof_downsample.pipeline = sg_make_pipeline(*pipeline);
quad_vertices : [16]float = .[
-1.0, 1.0, 0.0, flip_if_plat(1.0),
@ -1087,9 +1231,103 @@ create_dof_pipeline :: () {
type = .INDEXBUFFER,
};
gPipelines.dof.bind.vertex_buffers[0] = sg_make_buffer(*vbuffer);
gPipelines.dof.bind.index_buffer = sg_make_buffer(*ibuffer);
gPipelines.dof.bind.samplers[0] = sg_make_sampler(*(sg_sampler_desc.{
gPipelines.dof_downsample.bind.vertex_buffers[0] = sg_make_buffer(*vbuffer);
gPipelines.dof_downsample.bind.index_buffer = sg_make_buffer(*ibuffer);
gPipelines.dof_downsample.bind.samplers[SMP_dof_downsample_src_smp] = sg_make_sampler(*(sg_sampler_desc.{
wrap_u = .CLAMP_TO_EDGE,
wrap_v = .CLAMP_TO_EDGE,
min_filter = .LINEAR,
mag_filter = .LINEAR,
}));
}
create_dof_blur_pipeline :: () {
platconf := get_plat_conf();
pipeline: sg_pipeline_desc;
shader_desc := dof_blur_shader_desc(sg_query_backend());
pipeline.shader = sg_make_shader(*shader_desc);
pipeline.layout.attrs[ATTR_dof_blur_position] = .{ format = .FLOAT2 };
pipeline.layout.attrs[ATTR_dof_blur_uv] = .{ format = .FLOAT2 };
pipeline.index_type = .UINT16;
pipeline.depth.pixel_format = .NONE;
pipeline.color_count = 1;
pipeline.colors[0] = .{ pixel_format = .RGBA16F };
gPipelines.dof_blur.pipeline = sg_make_pipeline(*pipeline);
quad_vertices : [16]float = .[
-1.0, 1.0, 0.0, flip_if_plat(1.0),
-1.0, -1.0, 0.0, flip_if_plat(0.0),
1.0, -1.0, 1.0, flip_if_plat(0.0),
1.0, 1.0, 1.0, flip_if_plat(1.0),
];
quad_indices : [6]u16 = .[
0, 1, 2, 0, 2, 3
];
vbuffer := sg_buffer_desc.{ size = size_of(float) * 16, data = .{
ptr = quad_vertices.data,
size = 16 * 4
}};
ibuffer := sg_buffer_desc.{ size = size_of(u16) * 6, data = .{
ptr = quad_indices.data,
size = 6 * 2
},
type = .INDEXBUFFER,
};
gPipelines.dof_blur.bind.vertex_buffers[0] = sg_make_buffer(*vbuffer);
gPipelines.dof_blur.bind.index_buffer = sg_make_buffer(*ibuffer);
gPipelines.dof_blur.bind.samplers[SMP_dof_blur_src_smp] = sg_make_sampler(*(sg_sampler_desc.{
wrap_u = .CLAMP_TO_EDGE,
wrap_v = .CLAMP_TO_EDGE,
min_filter = .LINEAR,
mag_filter = .LINEAR,
}));
}
create_sh_irradiance_image :: () {
w, h := get_render_size();
if g_sh_irradiance.id != INVALID_ID then sg_destroy_image(g_sh_irradiance);
g_sh_irradiance = sg_make_image(*(sg_image_desc.{
width = w / 2,
height = h / 2,
pixel_format = .RGBA16F,
render_target = true,
sample_count = 1,
}));
sg_destroy_attachments(g_sh_irradiance_attach);
g_sh_irradiance_attach = sg_make_attachments(*(sg_attachments_desc.{
colors[0].image = g_sh_irradiance,
}));
}
create_sh_irradiance_pipeline :: () {
pipeline: sg_pipeline_desc;
shader_desc := sh_deferred_shader_desc(sg_query_backend());
pipeline.shader = sg_make_shader(*shader_desc);
pipeline.layout.attrs[ATTR_sh_deferred_position] = .{ format = .FLOAT2 };
pipeline.layout.attrs[ATTR_sh_deferred_uv] = .{ format = .FLOAT2 };
pipeline.index_type = .UINT16;
pipeline.depth.pixel_format = .NONE;
pipeline.color_count = 1;
pipeline.colors[0] = .{ pixel_format = .RGBA16F };
gPipelines.sh_irradiance.pipeline = sg_make_pipeline(*pipeline);
quad_vertices : [16]float = .[
-1.0, 1.0, 0.0, flip_if_plat(1.0),
-1.0, -1.0, 0.0, flip_if_plat(0.0),
1.0, -1.0, 1.0, flip_if_plat(0.0),
1.0, 1.0, 1.0, flip_if_plat(1.0),
];
quad_indices : [6]u16 = .[ 0, 1, 2, 0, 2, 3 ];
vbuffer := sg_buffer_desc.{ size = size_of(float) * 16, data = .{ ptr = quad_vertices.data, size = 16 * 4 }};
ibuffer := sg_buffer_desc.{ size = size_of(u16) * 6, data = .{ ptr = quad_indices.data, size = 6 * 2 }, type = .INDEXBUFFER };
gPipelines.sh_irradiance.bind.vertex_buffers[0] = sg_make_buffer(*vbuffer);
gPipelines.sh_irradiance.bind.index_buffer = sg_make_buffer(*ibuffer);
gPipelines.sh_irradiance.bind.samplers[0] = sg_make_sampler(*(sg_sampler_desc.{
wrap_u = .CLAMP_TO_EDGE,
wrap_v = .CLAMP_TO_EDGE,
min_filter = .NEAREST,
@ -1109,7 +1347,7 @@ create_ssao_images :: () {
width = w/2,
height = h/2,
render_target = true,
pixel_format = .RGBA8
pixel_format = .RGBA16F
};
img_desc.sample_count = 1;
g_ssaobuf = sg_make_image(*img_desc);
@ -1148,35 +1386,44 @@ create_ssao_images :: () {
sg_destroy_attachments(g_postprocess_attach_b);
g_postprocess_attach_b = sg_make_attachments(*attachmentsDescB);
if g_bloom_tex.id != INVALID_ID then sg_destroy_image(g_bloom_tex);
bloom_img_desc := sg_image_desc.{
width = w/8,
height = h/8,
pixel_format = .RGBA32F,
render_target = true,
sample_count = 1,
};
g_bloom_tex = sg_make_image(*bloom_img_desc);
bloom_attach_desc := sg_attachments_desc.{
colors[0].image = g_bloom_tex,
};
sg_destroy_attachments(g_bloom_attach);
g_bloom_attach = sg_make_attachments(*bloom_attach_desc);
bloom_levels := sg_image.[g_bloom_down_1, g_bloom_down_2, g_bloom_down_3, g_bloom_down_4, g_bloom_up_3, g_bloom_up_2, g_bloom_up_1];
for * bloom_levels { if it.id != INVALID_ID then sg_destroy_image(<<it); }
make_bloom_level :: (img: *sg_image, attach: *sg_attachments, width: s32, height: s32) {
<<img = sg_make_image(*(sg_image_desc.{ width=width, height=height, pixel_format=.RGBA16F, render_target=true, sample_count=1 }));
sg_destroy_attachments(<<attach);
<<attach = sg_make_attachments(*(sg_attachments_desc.{ colors[0].image = <<img }));
}
make_bloom_level(*g_bloom_down_1, *g_bloom_down_1_attach, w/2, h/2);
make_bloom_level(*g_bloom_down_2, *g_bloom_down_2_attach, w/4, h/4);
make_bloom_level(*g_bloom_down_3, *g_bloom_down_3_attach, w/8, h/8);
make_bloom_level(*g_bloom_down_4, *g_bloom_down_4_attach, w/16, h/16);
make_bloom_level(*g_bloom_up_3, *g_bloom_up_3_attach, w/8, h/8);
make_bloom_level(*g_bloom_up_2, *g_bloom_up_2_attach, w/4, h/4);
make_bloom_level(*g_bloom_up_1, *g_bloom_up_1_attach, w/2, h/2);
if g_dof_tex.id != INVALID_ID then sg_destroy_image(g_dof_tex);
if g_dof_tex.id != INVALID_ID then sg_destroy_image(g_dof_tex);
if g_dof_downsample_tex.id != INVALID_ID then sg_destroy_image(g_dof_downsample_tex);
dof_img_desc := sg_image_desc.{
width = cast(s32)((cast(float)w)/1.5),
height = cast(s32)((cast(float)h)/1.5),
pixel_format = .RGBA32F,
width = w/2,
height = h/2,
pixel_format = .RGBA16F,
render_target = true,
sample_count = 1,
};
g_dof_tex = sg_make_image(*dof_img_desc);
dof_attach_desc := sg_attachments_desc.{
colors[0].image = g_dof_tex,
};
g_dof_tex = sg_make_image(*dof_img_desc);
g_dof_downsample_tex = sg_make_image(*dof_img_desc);
sg_destroy_attachments(g_dof_attach);
g_dof_attach = sg_make_attachments(*dof_attach_desc);
g_dof_attach = sg_make_attachments(*(sg_attachments_desc.{
colors[0].image = g_dof_tex,
}));
sg_destroy_attachments(g_dof_downsample_attach);
g_dof_downsample_attach = sg_make_attachments(*(sg_attachments_desc.{
colors[0].image = g_dof_downsample_tex,
}));
}
create_ssao_pipeline :: () {
@ -1196,7 +1443,7 @@ create_ssao_pipeline :: () {
src_factor_rgb = .SRC_ALPHA,
dst_factor_rgb = .ONE_MINUS_SRC_ALPHA
},
pixel_format = .RGBA32F,
pixel_format = .RGBA16F,
};
pipeline.color_count = 1;
@ -1273,9 +1520,6 @@ init_brdf_lut :: () {
g_brdf_lut = sg_make_image(*desc);
}
// 1x1 black image for RDM slots when no baked data is present.
// The lookup texture returning all zeros makes atlas_rect.z == 0,
// so the shader's fallback ambient path is taken.
{
pixels : [4]u8 = .[0, 0, 0, 0];
imgdata : sg_image_data;
@ -1288,7 +1532,6 @@ init_brdf_lut :: () {
};
g_rdm_fallback = sg_make_image(*desc);
// 1x1 RGBA16F 2D texture — fallback when a chunk has no SH probe grid.
zero_sh : [4]u16 = .[0, 0, 0, 0];
sh_imgdata : sg_image_data;
sh_imgdata.subimage[0][0] = .{ zero_sh.data, size_of(type_of(zero_sh)) };
@ -1299,6 +1542,17 @@ init_brdf_lut :: () {
data = sh_imgdata,
};
g_sh_fallback = sg_make_image(*sh_desc);
zero_atlas : [4]u16 = .[0, 0, 0, 0];
atlas_imgdata : sg_image_data;
atlas_imgdata.subimage[0][0] = .{ zero_atlas.data, size_of(type_of(zero_atlas)) };
atlas_desc := sg_image_desc.{
width = 1,
height = 1,
pixel_format = .RGBA16F,
data = atlas_imgdata,
};
g_rdm_atlas = sg_make_image(*atlas_desc);
}
}
@ -1383,7 +1637,7 @@ create_particle_pipeline :: () {
pipeline.color_count = 1;
pipeline.colors[0] = .{
pixel_format = .RGBA32F,
pixel_format = .RGBA16F,
blend = .{
enabled = true,
src_factor_rgb = .SRC_ALPHA,
@ -1460,7 +1714,7 @@ create_debugline_pipeline :: () {
pixel_format = .DEPTH,
};
color_state := sg_color_target_state.{
pixel_format = .RGBA32F,
pixel_format = .RGBA16F,
};
pipeline.color_count = 1;
pipeline.colors[0] = color_state;

View File

@ -1,7 +1,7 @@
Post_Process :: struct {
exposure : float = 1.0; @Slider,0,3,0.1;
contrast : float = 1.0; @Slider,0,6,0.1;
saturation : float = 1.0; @Slider,0.0,2.0,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;
@ -10,7 +10,7 @@ Post_Process :: struct {
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 : s32 = 0; @Slider,0,10,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;
@ -32,13 +32,12 @@ Post_Process :: struct {
current_post_process : Post_Process;
Lighting_Config :: struct {
rdm_enabled : s32 = 1; @Slider,0,1,1
ambient_intensity : float = 0.35; @Slider,0,2,0.05
emissive_scale : float = 5.0; @Slider,0,20,0.5
rdm_diff_scale : float = 1.0; @Slider,0,3,0.1
rdm_spec_scale : float = 1.0; @Slider,0,3,0.1
ambient_color : Vector3 = .{0.3,0.3,0.4}; @Color
rdm_tint : Vector3 = .{1.05,1.0,0.9}; @Color
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;

View File

@ -15,6 +15,7 @@
#load "arbtri.jai";
#load "debug_draw.jai";
#load "meshgen.jai";
#load "lodgen.jai";
#load "helpers.jai";
#load "animation.jai";
#load "pipelines.jai";
@ -32,6 +33,7 @@ on_window_resize :: () {
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);

View File

@ -58,7 +58,7 @@ create_shadow_viewproj :: (cam: *Camera, conf: *World_Config) -> Matrix4 {
B.z, C.z, A.z, 0,
-dot(B, sunCameraPosition), -dot(C, sunCameraPosition), -dot(A, sunCameraPosition), 1
};
proj := matrix_ortho(-60, 60, -60, 60, 0, 100);
proj := matrix_ortho(-30, 30, -30, 30, 0, 100);
return view*proj;
}

View File

@ -7,9 +7,11 @@ Rendering_Task_Type :: enum {
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_RDM;
TRIXELS;
BILLBOARD;
BILLBOARD;
PARTICLES;
PARTICLES_BUFFER;
};
Rendering_Task :: struct {
@ -59,6 +61,17 @@ Rendering_Task_Trile :: struct {
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
}
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 {
@ -73,14 +86,21 @@ Rendering_Task_Trixels :: struct {
}
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;
count : s32;
blend_mode : Particle_Blend_Mode;
sheet : sg_image;
pos_size : [2048]Vector4;
uv_rects : [2048]Vector4;
colors : [2048]Vector4;
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 {
@ -103,6 +123,7 @@ 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;
@ -139,17 +160,34 @@ tasks_to_commands :: () {
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_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;
@ -173,15 +211,21 @@ tasks_to_commands :: () {
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);
particleTask := cast(*Rendering_Task_Particles)it;
drawCmd := New(Render_Command_Draw_Particles,, temp);
drawCmd.count = particleTask.count;
drawCmd.blend_mode = particleTask.blend_mode;
drawCmd.sheet = particleTask.sheet;
memcpy(drawCmd.pos_size.data, particleTask.pos_size.data, particleTask.count * size_of(Vector4));
memcpy(drawCmd.uv_rects.data, particleTask.uv_rects.data, particleTask.count * size_of(Vector4));
memcpy(drawCmd.colors.data, particleTask.colors.data, particleTask.count * size_of(Vector4));
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;

View File

@ -45,10 +45,18 @@ Blob :: struct {
g_settings : Settings_State;
g_settings_config : Settings_Menu_Config;
MAIN_ITEMS :: string.["Resume", "Settings", "Exit"];
#if OS == .WASM {
MAIN_ITEMS :: string.["Resume", "Settings"];
} else {
MAIN_ITEMS :: string.["Resume", "Settings", "Exit"];
}
SETTINGS_ITEMS :: string.["Audio", "Graphics"];
AUDIO_LABELS :: string.["Master Volume", "Music Volume", "Sound Effects"];
GRAPHICS_ITEMS :: string.["Fullscreen"];
#if OS == .WASM {
GRAPHICS_ITEMS :: string.[];
} else {
GRAPHICS_ITEMS :: string.["Fullscreen"];
}
page_items :: () -> []string {
if g_settings.page == .MAIN return MAIN_ITEMS;
@ -223,7 +231,7 @@ handle_enter :: (index: s32 = -1) {
if i == 0 then navigate_to(.AUDIO);
if i == 1 then navigate_to(.GRAPHICS);
case .GRAPHICS;
if i == 0 then sapp_toggle_fullscreen();
#if OS != .WASM { if i == 0 then sapp_toggle_fullscreen(); }
}
}
@ -422,8 +430,10 @@ draw_settings_menu :: () {
bt.label_theme.alignment = GR.Text_Alignment.Center;
label := items[i];
if g_settings.page == .GRAPHICS && i == 0
label = tprint("Fullscreen: %", ifx sapp_is_fullscreen() then "On" else "Off");
#if OS != .WASM {
if g_settings.page == .GRAPHICS && i == 0
label = tprint("Fullscreen: %", ifx sapp_is_fullscreen() then "On" else "Off");
}
pressed, _, _ := GR.button(r, label, *bt, identifier = cast(s64)i);
if pressed then handle_enter(cast(s32)i);

View File

@ -1,423 +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.glsl -o ./jai/shader_bloom.jai -l glsl430:glsl300es:metal_macos -f sokol_jai
Overview:
=========
Shader program: 'bloom':
Get shader desc: bloom_shader_desc(sg_query_backend())
Vertex Shader: vs_bloom
Fragment Shader: fs_bloom
Attributes:
ATTR_bloom_position => 0
ATTR_bloom_uv => 1
Bindings:
Uniform block 'bloom_params':
Jai struct: Bloom_Params
Bind slot: UB_bloom_params => 0
Image 'bloom_src':
Image type: ._2D
Sample type: .FLOAT
Multisampled: false
Bind slot: IMG_bloom_src => 0
Sampler 'bloom_src_smp':
Type: .FILTERING
Bind slot: SMP_bloom_src_smp => 0
*/
ATTR_bloom_position :: 0;
ATTR_bloom_uv :: 1;
UB_bloom_params :: 0;
IMG_bloom_src :: 0;
SMP_bloom_src_smp :: 0;
Bloom_Params :: struct {
bloom_treshold: float;
_: [12]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_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_params[1];
layout(binding = 16) uniform sampler2D bloom_src_bloom_src_smp;
layout(location = 0) in vec2 texcoord;
layout(location = 0) out vec4 frag_color;
void main()
{
vec4 _24 = texture(bloom_src_bloom_src_smp, texcoord);
vec4 color = _24;
if (max(_24.x, max(_24.y, _24.z)) < bloom_params[0].x)
{
color = vec4(0.0, 0.0, 0.0, 1.0);
}
frag_color = vec4(color.xyz, 1.0);
}
*/
fs_bloom_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,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,0x73,0x72,0x63,0x5f,0x62,0x6c,0x6f,
0x6f,0x6d,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,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x73,0x72,0x63,0x5f,0x62,0x6c,
0x6f,0x6f,0x6d,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,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x5f,0x32,0x34,0x3b,0x0a,0x20,0x20,
0x20,0x20,0x69,0x66,0x20,0x28,0x6d,0x61,0x78,0x28,0x5f,0x32,0x34,0x2e,0x78,0x2c,
0x20,0x6d,0x61,0x78,0x28,0x5f,0x32,0x34,0x2e,0x79,0x2c,0x20,0x5f,0x32,0x34,0x2e,
0x7a,0x29,0x29,0x20,0x3c,0x20,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x70,0x61,0x72,0x61,
0x6d,0x73,0x5b,0x30,0x5d,0x2e,0x78,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,0x34,0x28,0x30,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x30,0x2e,
0x30,0x2c,0x20,0x31,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,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_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_params[1];
uniform highp sampler2D bloom_src_bloom_src_smp;
in highp vec2 texcoord;
layout(location = 0) out highp vec4 frag_color;
void main()
{
highp vec4 _24 = texture(bloom_src_bloom_src_smp, texcoord);
highp vec4 color = _24;
if (max(_24.x, max(_24.y, _24.z)) < bloom_params[0].x)
{
color = vec4(0.0, 0.0, 0.0, 1.0);
}
frag_color = vec4(color.xyz, 1.0);
}
*/
fs_bloom_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,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,0x73,0x72,0x63,0x5f,0x62,0x6c,0x6f,0x6f,0x6d,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,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x73,
0x72,0x63,0x5f,0x62,0x6c,0x6f,0x6f,0x6d,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,0x63,0x6f,0x6c,0x6f,
0x72,0x20,0x3d,0x20,0x5f,0x32,0x34,0x3b,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,
0x28,0x6d,0x61,0x78,0x28,0x5f,0x32,0x34,0x2e,0x78,0x2c,0x20,0x6d,0x61,0x78,0x28,
0x5f,0x32,0x34,0x2e,0x79,0x2c,0x20,0x5f,0x32,0x34,0x2e,0x7a,0x29,0x29,0x20,0x3c,
0x20,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d,
0x2e,0x78,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,0x34,0x28,0x30,
0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x31,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,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_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_params
{
float bloom_treshold;
};
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_params& _42 [[buffer(0)]], texture2d<float> bloom_src [[texture(0)]], sampler bloom_src_smp [[sampler(0)]])
{
main0_out out = {};
float4 _24 = bloom_src.sample(bloom_src_smp, in.texcoord);
float4 color = _24;
if (fast::max(_24.x, fast::max(_24.y, _24.z)) < _42.bloom_treshold)
{
color = float4(0.0, 0.0, 0.0, 1.0);
}
out.frag_color = float4(color.xyz, 1.0);
return out;
}
*/
fs_bloom_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,0x61,0x72,0x61,0x6d,0x73,0x0a,0x7b,0x0a,0x20,0x20,
0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x74,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,0x61,0x72,0x61,0x6d,0x73,0x26,0x20,0x5f,0x34,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,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,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,0x62,0x6c,0x6f,0x6f,0x6d,
0x5f,0x73,0x72,0x63,0x2e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x28,0x62,0x6c,0x6f,0x6f,
0x6d,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,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x5f,0x32,0x34,0x3b,
0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x66,0x61,0x73,0x74,0x3a,0x3a,0x6d,
0x61,0x78,0x28,0x5f,0x32,0x34,0x2e,0x78,0x2c,0x20,0x66,0x61,0x73,0x74,0x3a,0x3a,
0x6d,0x61,0x78,0x28,0x5f,0x32,0x34,0x2e,0x79,0x2c,0x20,0x5f,0x32,0x34,0x2e,0x7a,
0x29,0x29,0x20,0x3c,0x20,0x5f,0x34,0x32,0x2e,0x62,0x6c,0x6f,0x6f,0x6d,0x5f,0x74,
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,0x34,0x28,0x30,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,
0x30,0x2e,0x30,0x2c,0x20,0x31,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,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_shader_desc :: (backend: sg_backend) -> sg_shader_desc {
desc: sg_shader_desc;
desc.label = "bloom_shader";
if backend == {
case .GLCORE;
desc.vertex_func.source = xx *vs_bloom_source_glsl430;
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_bloom_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_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_src_bloom_src_smp";
case .GLES3;
desc.vertex_func.source = xx *vs_bloom_source_glsl300es;
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_bloom_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_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_src_bloom_src_smp";
case .METAL_MACOS;
desc.vertex_func.source = xx *vs_bloom_source_metal_macos;
desc.vertex_func.entry = "main0";
desc.fragment_func.source = xx *fs_bloom_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

@ -0,0 +1,491 @@
/*
#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

@ -0,0 +1,552 @@
/*
#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

@ -0,0 +1,563 @@
/*
#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

@ -0,0 +1,566 @@
/*
#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

@ -4,39 +4,31 @@
Generated by sokol-shdc (https://github.com/floooh/sokol-tools)
Cmdline:
sokol-shdc -i shader_dof.glsl -o ./jai/shader_dof.jai -l glsl430:glsl300es:metal_macos -f sokol_jai
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':
Get shader desc: dof_shader_desc(sg_query_backend())
Vertex Shader: vs_dof
Fragment Shader: fs_dof
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_position => 0
ATTR_dof_uv => 1
ATTR_dof_downsample_position => 0
ATTR_dof_downsample_uv => 1
Bindings:
Uniform block 'dof_params':
Jai struct: Dof_Params
Bind slot: UB_dof_params => 0
Image 'dof_src':
Image 'dof_downsample_src':
Image type: ._2D
Sample type: .FLOAT
Multisampled: false
Bind slot: IMG_dof_src => 0
Sampler 'dof_src_smp':
Bind slot: IMG_dof_downsample_src => 0
Sampler 'dof_downsample_src_smp':
Type: .FILTERING
Bind slot: SMP_dof_src_smp => 0
Bind slot: SMP_dof_downsample_src_smp => 0
*/
ATTR_dof_position :: 0;
ATTR_dof_uv :: 1;
UB_dof_params :: 0;
IMG_dof_src :: 0;
SMP_dof_src_smp :: 0;
Dof_Params :: struct {
dof_treshold: float;
_: [12]u8;
};
ATTR_dof_downsample_position :: 0;
ATTR_dof_downsample_uv :: 1;
IMG_dof_downsample_src :: 0;
SMP_dof_downsample_src_smp :: 0;
/*
#version 430
@ -51,7 +43,7 @@ Dof_Params :: struct {
}
*/
vs_dof_source_glsl430 := u8.[
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,
@ -70,52 +62,37 @@ vs_dof_source_glsl430 := u8.[
/*
#version 430
uniform vec4 dof_params[1];
layout(binding = 16) uniform sampler2D dof_src_dof_src_smp;
layout(binding = 16) uniform sampler2D dof_downsample_src_dof_downsample_src_smp;
layout(location = 0) in vec2 texcoord;
layout(location = 0) out vec4 frag_color;
layout(location = 0) in vec2 texcoord;
void main()
{
vec4 _24 = texture(dof_src_dof_src_smp, texcoord);
vec4 color = _24;
if (max(_24.x, max(_24.y, _24.z)) < dof_params[0].x)
{
color = vec4(0.0, 0.0, 0.0, 1.0);
}
frag_color = vec4(color.xyz, 1.0);
frag_color = vec4(texture(dof_downsample_src_dof_downsample_src_smp, texcoord).xyz, 1.0);
}
*/
fs_dof_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,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,0x73,0x72,0x63,0x5f,0x64,0x6f,0x66,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,0x73,0x72,0x63,0x5f,0x64,0x6f,0x66,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,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x5f,
0x32,0x34,0x3b,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x6d,0x61,0x78,0x28,
0x5f,0x32,0x34,0x2e,0x78,0x2c,0x20,0x6d,0x61,0x78,0x28,0x5f,0x32,0x34,0x2e,0x79,
0x2c,0x20,0x5f,0x32,0x34,0x2e,0x7a,0x29,0x29,0x20,0x3c,0x20,0x64,0x6f,0x66,0x5f,
0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d,0x2e,0x78,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,0x34,0x28,0x30,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,
0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x31,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,0x2e,0x78,
0x79,0x7a,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
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
@ -131,7 +108,7 @@ fs_dof_source_glsl430 := u8.[
}
*/
vs_dof_source_glsl300es := u8.[
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,
@ -150,55 +127,38 @@ vs_dof_source_glsl300es := u8.[
precision mediump float;
precision highp int;
uniform highp vec4 dof_params[1];
uniform highp sampler2D dof_src_dof_src_smp;
uniform highp sampler2D dof_downsample_src_dof_downsample_src_smp;
in highp vec2 texcoord;
layout(location = 0) out highp vec4 frag_color;
in highp vec2 texcoord;
void main()
{
highp vec4 _24 = texture(dof_src_dof_src_smp, texcoord);
highp vec4 color = _24;
if (max(_24.x, max(_24.y, _24.z)) < dof_params[0].x)
{
color = vec4(0.0, 0.0, 0.0, 1.0);
}
frag_color = vec4(color.xyz, 1.0);
frag_color = vec4(texture(dof_downsample_src_dof_downsample_src_smp, texcoord).xyz, 1.0);
}
*/
fs_dof_source_glsl300es := u8.[
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,0x76,0x65,0x63,
0x34,0x20,0x64,0x6f,0x66,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,0x73,0x72,0x63,
0x5f,0x64,0x6f,0x66,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,0x73,0x72,0x63,0x5f,0x64,0x6f,0x66,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,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x5f,0x32,0x34,0x3b,0x0a,0x20,
0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x6d,0x61,0x78,0x28,0x5f,0x32,0x34,0x2e,0x78,
0x2c,0x20,0x6d,0x61,0x78,0x28,0x5f,0x32,0x34,0x2e,0x79,0x2c,0x20,0x5f,0x32,0x34,
0x2e,0x7a,0x29,0x29,0x20,0x3c,0x20,0x64,0x6f,0x66,0x5f,0x70,0x61,0x72,0x61,0x6d,
0x73,0x5b,0x30,0x5d,0x2e,0x78,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,0x34,0x28,0x30,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,
0x2c,0x20,0x31,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,0x2e,0x78,0x79,0x7a,0x2c,0x20,0x31,
0x2e,0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
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>
@ -227,7 +187,7 @@ fs_dof_source_glsl300es := u8.[
}
*/
vs_dof_source_metal_macos := u8.[
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,
@ -263,11 +223,6 @@ vs_dof_source_metal_macos := u8.[
using namespace metal;
struct dof_params
{
float dof_treshold;
};
struct main0_out
{
float4 frag_color [[color(0)]];
@ -278,29 +233,20 @@ vs_dof_source_metal_macos := u8.[
float2 texcoord [[user(locn0)]];
};
fragment main0_out main0(main0_in in [[stage_in]], constant dof_params& _42 [[buffer(0)]], texture2d<float> dof_src [[texture(0)]], sampler dof_src_smp [[sampler(0)]])
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 = {};
float4 _24 = dof_src.sample(dof_src_smp, in.texcoord);
float4 color = _24;
if (fast::max(_24.x, fast::max(_24.y, _24.z)) < _42.dof_treshold)
{
color = float4(0.0, 0.0, 0.0, 1.0);
}
out.frag_color = float4(color.xyz, 1.0);
out.frag_color = float4(dof_downsample_src.sample(dof_downsample_src_smp, in.texcoord).xyz, 1.0);
return out;
}
*/
fs_dof_source_metal_macos := u8.[
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,0x64,
0x6f,0x66,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,
0x66,0x6c,0x6f,0x61,0x74,0x20,0x64,0x6f,0x66,0x5f,0x74,0x72,0x65,0x73,0x68,0x6f,
0x6c,0x64,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,
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,
@ -311,53 +257,36 @@ fs_dof_source_metal_macos := u8.[
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,0x70,0x61,
0x72,0x61,0x6d,0x73,0x26,0x20,0x5f,0x34,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,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,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,0x73,0x72,0x63,0x2e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x28,
0x64,0x6f,0x66,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,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x5f,0x32,
0x34,0x3b,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x66,0x61,0x73,0x74,0x3a,
0x3a,0x6d,0x61,0x78,0x28,0x5f,0x32,0x34,0x2e,0x78,0x2c,0x20,0x66,0x61,0x73,0x74,
0x3a,0x3a,0x6d,0x61,0x78,0x28,0x5f,0x32,0x34,0x2e,0x79,0x2c,0x20,0x5f,0x32,0x34,
0x2e,0x7a,0x29,0x29,0x20,0x3c,0x20,0x5f,0x34,0x32,0x2e,0x64,0x6f,0x66,0x5f,0x74,
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,0x34,0x28,0x30,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,
0x30,0x2e,0x30,0x2c,0x20,0x31,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,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,
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_shader_desc :: (backend: sg_backend) -> sg_shader_desc {
dof_downsample_shader_desc :: (backend: sg_backend) -> sg_shader_desc {
desc: sg_shader_desc;
desc.label = "dof_shader";
desc.label = "dof_downsample_shader";
if backend == {
case .GLCORE;
desc.vertex_func.source = xx *vs_dof_source_glsl430;
desc.vertex_func.source = xx *vs_dof_downsample_source_glsl430;
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_dof_source_glsl430;
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.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_params";
desc.images[0].stage = .FRAGMENT;
desc.images[0].multisampled = false;
desc.images[0].image_type = ._2D;
@ -367,22 +296,16 @@ dof_shader_desc :: (backend: sg_backend) -> sg_shader_desc {
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_src_dof_src_smp";
desc.image_sampler_pairs[0].glsl_name = "dof_downsample_src_dof_downsample_src_smp";
case .GLES3;
desc.vertex_func.source = xx *vs_dof_source_glsl300es;
desc.vertex_func.source = xx *vs_dof_downsample_source_glsl300es;
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_dof_source_glsl300es;
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.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_params";
desc.images[0].stage = .FRAGMENT;
desc.images[0].multisampled = false;
desc.images[0].image_type = ._2D;
@ -392,18 +315,14 @@ dof_shader_desc :: (backend: sg_backend) -> sg_shader_desc {
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_src_dof_src_smp";
desc.image_sampler_pairs[0].glsl_name = "dof_downsample_src_dof_downsample_src_smp";
case .METAL_MACOS;
desc.vertex_func.source = xx *vs_dof_source_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_source_metal_macos;
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.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;

File diff suppressed because it is too large Load Diff

View File

@ -58,7 +58,7 @@ Gbuffer_Billboard_Vs_Params :: struct {
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))
if (gbuffer_billboard_vs_params[12].x > (-10.0))
{
look_dir = gbuffer_billboard_vs_params[12].xyz;
}
@ -98,7 +98,7 @@ vs_gbuffer_billboard_source_glsl430 := u8.[
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,0x3c,0x20,0x28,
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,
@ -236,7 +236,7 @@ fs_gbuffer_billboard_source_glsl430 := u8.[
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))
if (gbuffer_billboard_vs_params[12].x > (-10.0))
{
look_dir = gbuffer_billboard_vs_params[12].xyz;
}
@ -273,7 +273,7 @@ vs_gbuffer_billboard_source_glsl300es := u8.[
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,0x3c,0x20,0x28,0x2d,0x31,0x30,0x2e,0x30,0x29,0x29,0x0a,0x20,0x20,0x20,0x20,
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,
@ -434,7 +434,7 @@ fs_gbuffer_billboard_source_glsl300es := u8.[
float3 _53 = _24.offset - _24.cam;
_53.y = 0.0;
float3 look_dir = fast::normalize(_53);
if (_24.faceDir.x < (-10.0))
if (_24.faceDir.x > (-10.0))
{
look_dir = _24.faceDir;
}
@ -494,7 +494,7 @@ vs_gbuffer_billboard_source_metal_macos := u8.[
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,0x3c,0x20,0x28,0x2d,0x31,0x30,0x2e,0x30,0x29,0x29,
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,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,32 +0,0 @@
@vs vs_bloom
in vec2 position;
in vec2 uv;
out vec2 texcoord;
void main() {
gl_Position = vec4(position, 0.5, 1.0);
texcoord = uv;
}
@end
@fs fs_bloom
in vec2 texcoord;
out vec4 frag_color;
layout(binding=0) uniform bloom_params {
float bloom_treshold;
};
layout(binding = 0) uniform texture2D bloom_src;
layout(binding = 0) uniform sampler bloom_src_smp;
void main() {
vec4 color = texture(sampler2D(bloom_src, bloom_src_smp), texcoord);
float value = max(color.r, max(color.g, color.b));
if(value < bloom_treshold) { color = vec4(0.0, 0.0, 0.0, 1.0); }
frag_color = vec4(color.rgb, 1.0);
}
@end
@program bloom vs_bloom fs_bloom

View File

@ -0,0 +1,35 @@
@vs vs_bloom_downsample
in vec2 position;
in vec2 uv;
out vec2 texcoord;
void main() {
gl_Position = vec4(position, 0.5, 1.0);
texcoord = uv;
}
@end
@fs fs_bloom_downsample
in vec2 texcoord;
out vec4 frag_color;
layout(binding=0) uniform bloom_downsample_params {
float src_texel_x;
float src_texel_y;
};
layout(binding = 0) uniform texture2D bloom_downsample_src;
layout(binding = 0) uniform sampler bloom_downsample_src_smp;
void main() {
vec2 ts = vec2(src_texel_x, src_texel_y) * 0.5;
vec3 a = texture(sampler2D(bloom_downsample_src, bloom_downsample_src_smp), texcoord + vec2(-ts.x, -ts.y)).rgb;
vec3 b = texture(sampler2D(bloom_downsample_src, bloom_downsample_src_smp), texcoord + vec2( ts.x, -ts.y)).rgb;
vec3 c = texture(sampler2D(bloom_downsample_src, bloom_downsample_src_smp), texcoord + vec2(-ts.x, ts.y)).rgb;
vec3 d = texture(sampler2D(bloom_downsample_src, bloom_downsample_src_smp), texcoord + vec2( ts.x, ts.y)).rgb;
frag_color = vec4((a + b + c + d) * 0.25, 1.0);
}
@end
@program bloom_downsample vs_bloom_downsample fs_bloom_downsample

View File

@ -0,0 +1,39 @@
@vs vs_bloom_prefilter
in vec2 position;
in vec2 uv;
out vec2 texcoord;
void main() {
gl_Position = vec4(position, 0.5, 1.0);
texcoord = uv;
}
@end
@fs fs_bloom_prefilter
in vec2 texcoord;
out vec4 frag_color;
layout(binding=0) uniform bloom_prefilter_params {
float src_texel_x;
float src_texel_y;
float threshold;
};
layout(binding = 0) uniform texture2D bloom_prefilter_src;
layout(binding = 0) uniform sampler bloom_prefilter_src_smp;
void main() {
vec2 ts = vec2(src_texel_x, src_texel_y) * 0.5;
vec3 a = texture(sampler2D(bloom_prefilter_src, bloom_prefilter_src_smp), texcoord + vec2(-ts.x, -ts.y)).rgb;
vec3 b = texture(sampler2D(bloom_prefilter_src, bloom_prefilter_src_smp), texcoord + vec2( ts.x, -ts.y)).rgb;
vec3 c = texture(sampler2D(bloom_prefilter_src, bloom_prefilter_src_smp), texcoord + vec2(-ts.x, ts.y)).rgb;
vec3 d = texture(sampler2D(bloom_prefilter_src, bloom_prefilter_src_smp), texcoord + vec2( ts.x, ts.y)).rgb;
vec3 color = (a + b + c + d) * 0.25;
float lum = dot(color, vec3(0.2126, 0.7152, 0.0722));
if (lum < threshold) color = vec3(0.0);
frag_color = vec4(color, 1.0);
}
@end
@program bloom_prefilter vs_bloom_prefilter fs_bloom_prefilter

View File

@ -0,0 +1,39 @@
@vs vs_bloom_upsample
in vec2 position;
in vec2 uv;
out vec2 texcoord;
void main() {
gl_Position = vec4(position, 0.5, 1.0);
texcoord = uv;
}
@end
@fs fs_bloom_upsample
in vec2 texcoord;
out vec4 frag_color;
layout(binding=0) uniform bloom_upsample_params {
float src_texel_x;
float src_texel_y;
};
layout(binding = 0) uniform texture2D bloom_upsample_small;
layout(binding = 0) uniform sampler bloom_upsample_small_smp;
layout(binding = 1) uniform texture2D bloom_upsample_large;
layout(binding = 1) uniform sampler bloom_upsample_large_smp;
void main() {
vec2 ts = vec2(src_texel_x, src_texel_y) * 0.5;
vec3 tent =
texture(sampler2D(bloom_upsample_small, bloom_upsample_small_smp), texcoord + vec2(-ts.x, -ts.y)).rgb +
texture(sampler2D(bloom_upsample_small, bloom_upsample_small_smp), texcoord + vec2( ts.x, -ts.y)).rgb +
texture(sampler2D(bloom_upsample_small, bloom_upsample_small_smp), texcoord + vec2(-ts.x, ts.y)).rgb +
texture(sampler2D(bloom_upsample_small, bloom_upsample_small_smp), texcoord + vec2( ts.x, ts.y)).rgb;
vec3 large = texture(sampler2D(bloom_upsample_large, bloom_upsample_large_smp), texcoord).rgb;
frag_color = vec4(tent * 0.25 + large, 1.0);
}
@end
@program bloom_upsample vs_bloom_upsample fs_bloom_upsample

View File

@ -1,32 +0,0 @@
@vs vs_dof
in vec2 position;
in vec2 uv;
out vec2 texcoord;
void main() {
gl_Position = vec4(position, 0.5, 1.0);
texcoord = uv;
}
@end
@fs fs_dof
in vec2 texcoord;
out vec4 frag_color;
layout(binding=0) uniform dof_params {
float dof_treshold;
};
layout(binding = 0) uniform texture2D dof_src;
layout(binding = 0) uniform sampler dof_src_smp;
void main() {
vec4 color = texture(sampler2D(dof_src, dof_src_smp), texcoord);
float value = max(color.r, max(color.g, color.b));
if(value < dof_treshold) { color = vec4(0.0, 0.0, 0.0, 1.0); }
frag_color = vec4(color.rgb, 1.0);
}
@end
@program dof vs_dof fs_dof

View File

@ -0,0 +1,48 @@
@vs vs_dof_blur
in vec2 position;
in vec2 uv;
out vec2 texcoord;
void main() {
gl_Position = vec4(position, 0.5, 1.0);
texcoord = uv;
}
@end
@fs fs_dof_blur
in vec2 texcoord;
out vec4 frag_color;
layout(binding=0) uniform dof_blur_params {
float bokeh_radius_x;
float bokeh_radius_y;
};
layout(binding = 0) uniform texture2D dof_blur_src;
layout(binding = 0) uniform sampler dof_blur_src_smp;
void main() {
const int NUM_SAMPLES = 32;
const float GOLDEN_ANGLE = 2.39996323;
vec4 best = texture(sampler2D(dof_blur_src, dof_blur_src_smp), texcoord);
float best_lum = dot(best.rgb, vec3(0.2126, 0.7152, 0.0722));
for (int i = 0; i < NUM_SAMPLES; i++) {
float theta = float(i) * GOLDEN_ANGLE;
float r = sqrt(float(i) / float(NUM_SAMPLES - 1) + 0.001);
vec2 offset = vec2(cos(theta), sin(theta)) * r * vec2(bokeh_radius_x, bokeh_radius_y);
vec4 s = texture(sampler2D(dof_blur_src, dof_blur_src_smp), texcoord + offset);
float lum = dot(s.rgb, vec3(0.2126, 0.7152, 0.0722));
if (lum > best_lum) {
best = s;
best_lum = lum;
}
}
frag_color = best;
}
@end
@program dof_blur vs_dof_blur fs_dof_blur

View File

@ -0,0 +1,25 @@
@vs vs_dof_downsample
in vec2 position;
in vec2 uv;
out vec2 texcoord;
void main() {
gl_Position = vec4(position, 0.5, 1.0);
texcoord = uv;
}
@end
@fs fs_dof_downsample
in vec2 texcoord;
out vec4 frag_color;
layout(binding = 0) uniform texture2D dof_downsample_src;
layout(binding = 0) uniform sampler dof_downsample_src_smp;
void main() {
frag_color = vec4(texture(sampler2D(dof_downsample_src, dof_downsample_src_smp), texcoord).rgb, 1.0);
}
@end
@program dof_downsample vs_dof_downsample fs_dof_downsample

View File

@ -13,6 +13,7 @@ in vec4 instance;
out vec3 view_space_pos;
out vec3 view_space_normal;
out vec3 v_world_pos;
mat3 gbuf_rot_x(float a) { float c=cos(a),s=sin(a); return mat3(1,0,0, 0,c,-s, 0,s,c); }
mat3 gbuf_rot_z(float a) { float c=cos(a),s=sin(a); return mat3(c,-s,0, s,c,0, 0,0,1); }
@ -39,6 +40,7 @@ void main() {
gl_Position = mvp * world_pos;
view_space_pos = view_pos_4.xyz;
view_space_normal = mat3(view_matrix) * normal.xyz;
v_world_pos = world_pos.xyz;
} else {
int ori = int(round(instance.w));
mat3 rot = gbuf_get_orientation_matrix(ori);
@ -49,6 +51,7 @@ void main() {
gl_Position = mvp * world_pos;
view_space_pos = view_pos_4.xyz;
view_space_normal = mat3(view_matrix) * (rot * normal.xyz);
v_world_pos = world_pos.xyz;
}
}
@end
@ -57,13 +60,16 @@ void main() {
in vec3 view_space_pos;
in vec3 view_space_normal;
in vec3 v_world_pos;
layout(location=0) out vec4 out_position;
layout(location=1) out vec4 out_normal;
layout(location=2) out vec4 out_worldpos;
void main() {
out_position = vec4(view_space_pos, 1.0);
out_normal = vec4(normalize(view_space_normal), 1.0);
out_worldpos = vec4(v_world_pos, 1.0);
}
@end

View File

@ -22,7 +22,7 @@ void main() {
vec3 look_dir = offset - cam;
look_dir.y = 0.0;
look_dir = normalize(look_dir);
if(faceDir.x < -10) look_dir = faceDir;
if(faceDir.x > -10) look_dir = faceDir;
vec3 world_right = normalize(cross(world_up, look_dir));
vec3 world_pos = offset + (world_right * local_pos.x) + (world_up * local_pos.y);
gl_Position = mvp * vec4(world_pos, 1.0);

View File

@ -25,6 +25,11 @@ layout(binding = 3) uniform sampler dof_smp;
layout(binding = 4) uniform texture2D pos_buf;
layout(binding = 4) uniform sampler pos_smp;
layout(binding=1) uniform dof_config {
float dof_max;
float dof_point;
};
layout(binding=0) uniform post_process_config {
float exposure;
float contrast;
@ -43,14 +48,6 @@ layout(binding=0) uniform post_process_config {
float bloom_amount;
};
layout(binding=1) uniform dof_config {
float dof_min;
float dof_max;
float dof_point;
float dof_tex_width;
float dof_tex_height;
};
vec3 aces(vec3 x) {
const float a = 2.51;
const float b = 0.03;
@ -129,11 +126,16 @@ void main() {
float r = texture(sampler2D(pptex, ppsmp), distorted_texcoord + vec2(chromatic_aberration_intensity, 0.0)).r;
float g = texture(sampler2D(pptex, ppsmp), distorted_texcoord).g;
float b = texture(sampler2D(pptex, ppsmp), distorted_texcoord - vec2(chromatic_aberration_intensity, 0.0)).b;
sampled_color_hdr = vec3(r,g,b + dof_min * 0.00000000000001);
sampled_color_hdr = vec3(r,g,b);
} else {
sampled_color_hdr = texture(sampler2D(pptex, ppsmp), distorted_texcoord).rgb;
}
float view_z = texture(sampler2D(pos_buf, pos_smp), distorted_texcoord).z;
float depth = abs(view_z);
float coc = smoothstep(0.0, 1.0, abs(depth - dof_point) / max(dof_max, 0.0001));
vec3 dof_blurred = texture(sampler2D(dof_tex, dof_smp), distorted_texcoord).rgb;
sampled_color_hdr = mix(sampled_color_hdr, dof_blurred, coc);
vec3 bloom_color = texture(sampler2D(bloom_tex, bloom_smp), distorted_texcoord).rgb;
vec3 color_hdr = (sampled_color_hdr + bloom_color * bloom_amount) * exposure;

View File

@ -0,0 +1,102 @@
@vs vs_sh_deferred
in vec2 position;
in vec2 uv;
out vec2 quad_uv;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
quad_uv = uv;
}
@end
@fs fs_sh_deferred
layout(binding=0) uniform texture2D gbuf_worldpos;
layout(binding=1) uniform texture2D gbuf_norm;
layout(binding=2) uniform texture2D sh_chunk;
layout(binding=0) uniform sampler sh_smp;
layout(binding=0) uniform sh_deferred_params {
mat4 inv_view;
vec4 chunk_origin;
vec4 ambient; // rgb = ambient color, a = ambient intensity
};
in vec2 quad_uv;
out vec4 frag_color;
const float PI = 3.14159265359;
vec3 sh_eval(ivec3 probe, vec3 N) {
int base = probe.x * 3;
int row = probe.z * 32 + probe.y;
vec4 t0 = texelFetch(sampler2D(sh_chunk, sh_smp), ivec2(base, row), 0);
vec4 t1 = texelFetch(sampler2D(sh_chunk, sh_smp), ivec2(base+1, row), 0);
vec4 t2 = texelFetch(sampler2D(sh_chunk, sh_smp), ivec2(base+2, row), 0);
float x = N.x, y = N.y, z = N.z;
float r = 0.886227*t0.x + 1.023327*(t0.w*x + t0.y*y + t0.z*z);
float g = 0.886227*t1.x + 1.023327*(t1.w*x + t1.y*y + t1.z*z);
float b = 0.886227*t2.x + 1.023327*(t2.w*x + t2.y*y + t2.z*z);
return max(vec3(r, g, b) / PI, vec3(0.0));
}
float sh_probe_energy(ivec3 probe) {
int base = probe.x * 3;
int row = probe.z * 32 + probe.y;
vec4 t0 = texelFetch(sampler2D(sh_chunk, sh_smp), ivec2(base, row), 0);
vec4 t1 = texelFetch(sampler2D(sh_chunk, sh_smp), ivec2(base+1, row), 0);
vec4 t2 = texelFetch(sampler2D(sh_chunk, sh_smp), ivec2(base+2, row), 0);
return max(0.886227 * (t0.x + t1.x + t2.x), 0.0);
}
vec3 sh_eval_trilinear(ivec3 p0, ivec3 p1, vec3 t, vec3 N) {
float wx[2] = float[2](1.0 - t.x, t.x);
float wy[2] = float[2](1.0 - t.y, t.y);
float wz[2] = float[2](1.0 - t.z, t.z);
vec3 result = vec3(0.0);
vec3 unweighted = vec3(0.0);
float total_w = 0.0;
for (int iz = 0; iz < 2; iz++) {
for (int iy = 0; iy < 2; iy++) {
for (int ix = 0; ix < 2; ix++) {
ivec3 probe = ivec3(
ix == 0 ? p0.x : p1.x,
iy == 0 ? p0.y : p1.y,
iz == 0 ? p0.z : p1.z
);
vec3 sh = sh_eval(probe, N);
float triw = wx[ix] * wy[iy] * wz[iz];
float w = triw * sh_probe_energy(probe);
result += sh * w;
unweighted += sh * triw;
total_w += w;
}
}
}
vec3 amb = ambient.rgb * ambient.a;
return total_w > 0.001 ? result / total_w : max(unweighted, amb);
}
void main() {
vec4 wp_sample = texture(sampler2D(gbuf_worldpos, sh_smp), quad_uv);
if (wp_sample.a < 0.5) discard;
vec3 world_pos = wp_sample.xyz;
vec3 cmin = chunk_origin.xyz;
vec3 cmax = cmin + vec3(32.0);
if (any(lessThan(world_pos, cmin)) || any(greaterThanEqual(world_pos, cmax))) discard;
vec3 view_norm = normalize(texture(sampler2D(gbuf_norm, sh_smp), quad_uv).xyz);
vec3 world_norm = normalize(mat3(inv_view) * view_norm);
const float SH_PAD = 2.0;
const float SH_SPACING = (32.0 + 2.0 * SH_PAD) / 32.0;
vec3 probe_f = clamp((world_pos - (cmin - vec3(SH_PAD))) / SH_SPACING, vec3(0.0), vec3(31.0));
ivec3 p0 = ivec3(floor(probe_f));
ivec3 p1 = min(p0 + ivec3(1), ivec3(31));
frag_color = vec4(sh_eval_trilinear(p0, p1, fract(probe_f), world_norm), 1.0);
}
@end
@program sh_deferred vs_sh_deferred fs_sh_deferred

View File

@ -17,7 +17,6 @@ out vec3 vpos;
out vec3 ipos;
out vec4 fnormal;
out vec3 orig_normal;
out vec3 trileCenter;
out vec3 cv;
mat3 rot_x(float a) { float c=cos(a),s=sin(a); return mat3(1,0,0, 0,c,-s, 0,s,c); }
@ -52,7 +51,6 @@ void main() {
ipos = position.xyz;
cam = camera;
cv = normalize(camera - vpos);
trileCenter = instance.xyz + vec3(0.5);
}
@end
@ -86,7 +84,6 @@ in vec3 vpos;
in vec3 ipos;
in vec4 fnormal;
in vec3 orig_normal;
in vec3 trileCenter;
in vec3 cv;
out vec4 frag_color;
@ -95,36 +92,29 @@ layout(binding=3) uniform trile_fs_params {
int is_reflection;
int screen_h;
int screen_w;
int rdm_enabled;
float ambient_intensity;
float emissive_scale;
float rdm_diff_scale;
float rdm_spec_scale;
float indirect_diff_scale;
float indirect_spec_scale;
vec3 ambient_color;
int is_preview;
vec3 rdm_tint;
float rdm_diff_saturation;
vec3 indirect_tint;
int sh_enabled;
float fog_start;
float fog_end;
};
layout(binding = 0) uniform texture2D triletex;
layout(binding = 0) uniform sampler trilesmp;
layout(binding = 1) uniform texture2D ssaotex;
layout(binding = 1) uniform sampler ssaosmp;
layout(binding = 2) uniform texture2D shadowtex;
layout(binding = 2) uniform sampler shadowsmp;
layout(binding = 3) uniform texture2D rdm_lookup;
layout(binding = 4) uniform texture2D rdm_atlas;
layout(binding = 5) uniform texture2D brdf_lut;
layout(binding = 6) uniform texture2D sh_chunk;
layout(binding = 3) uniform sampler rdmsmp;
layout(binding = 3) uniform texture2D brdf_lut;
layout(binding = 4) uniform texture2D sh_irradiance;
layout(binding = 3) uniform sampler linsmp;
const float PI = 3.1415927;
const float ROUGHNESS_RAYMARCH_MAX = 0.2; // Below this roughness, actually try to get sharp reflection from RDM.
const float ROUGHNESS_SPEC_CUTOFF = 0.7; // Above this roughness, disregard RDM specular lighting entirely.
// ---- SKY ----
const float ROUGHNESS_SPEC_CUTOFF = 0.7;
const float cirrus = 0.5;
@ -164,8 +154,6 @@ vec3 sky_reflect(vec3 R, vec3 sunpos) {
return sky(R, sunpos);
}
// ---- PBR ----
float DistributionGGX(vec3 N, vec3 H, float roughness) {
float a = roughness * roughness;
float a2 = a * a;
@ -192,222 +180,9 @@ vec3 FresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness) {
return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);
}
// ---- RDM HELPERS ----
// Hemioct encoding (Cigolle2014)
vec2 rdm_hemioct(vec3 v, int face) {
vec3 vc = v;
if (face / 2 == 0) { vc.z = v.y; vc.y = v.z; }
if (face / 2 == 2) { vc.z = v.x; vc.x = v.z; }
if (face % 2 == 1) { vc.z *= -1.0; }
vec2 p = vc.xy * (1.0 / (abs(vc.x) + abs(vc.y) + vc.z));
return vec2(p.x + p.y, p.x - p.y) * 0.5 + 0.5;
}
int rdm_face_from_normal(vec3 N) {
vec3 a = abs(N);
if (a.y >= a.x && a.y >= a.z) return N.y >= 0.0 ? 0 : 1;
if (a.z >= a.x && a.z >= a.y) return N.z >= 0.0 ? 2 : 3;
return N.x >= 0.0 ? 4 : 5;
}
vec4 rdm_atlas_rect(ivec3 local_pos, int roughness) {
int rdm_index = local_pos.x + local_pos.y * 32 + local_pos.z * 1024 + roughness * 32768;
return texelFetch(sampler2D(rdm_lookup, trilesmp), ivec2(rdm_index % 512, rdm_index / 512), 0);
}
ivec2 rdm_face_offset(vec4 rect, int face, int rdmSize, ivec2 atlasSize) {
int col = face % 2;
int row = face / 2;
return ivec2(int(rect.x * float(atlasSize.x)) + col * rdmSize,
int(rect.y * float(atlasSize.y)) + row * rdmSize);
}
vec2 rdm_face_uv(int face) {
if (face <= 1) return vec2(ipos.x, ipos.z);
if (face <= 3) return vec2(ipos.x, ipos.y);
return vec2(ipos.z, ipos.y);
}
// ---- RDM SPECULAR ----
vec3 rdm_spec_raymarch(vec3 N, vec3 V, vec3 diff, int face, ivec2 faceOffset, int rdmSize, vec2 atlasInvSize) {
vec3 reflected = reflect(V, N);
float maxDist = 20.0;
int steps = 40;
float stepSize = maxDist / float(steps);
for (int i = 0; i < steps; i++) {
float t = stepSize * float(i + 1);
vec3 samplePos = diff + t * reflected;
if (dot(samplePos, N) < 0.0) continue;
vec3 dir = normalize(samplePos);
vec2 hemiUV = rdm_hemioct(dir, face);
vec2 texCoord = (vec2(faceOffset) + hemiUV * float(rdmSize)) * atlasInvSize;
vec4 s = texture(sampler2D(rdm_atlas, rdmsmp), texCoord, 0);
float dist = length(samplePos);
if (s.a > 0.0 && s.a < dist && s.a + stepSize > dist)
return s.rgb;
}
return sky_reflect(reflected, sunPosition);
}
vec3 rdm_spec_single(vec3 N, vec3 V, vec3 diff, int face, ivec2 faceOffset, int rdmSize, vec2 atlasInvSize) {
vec3 reflected = reflect(V, N);
vec3 sampleDir = normalize(diff + 2.0 * reflected);
vec2 hemiUV = rdm_hemioct(sampleDir, face);
vec2 texCoord = (vec2(faceOffset) + hemiUV * float(rdmSize)) * atlasInvSize;
return texture(sampler2D(rdm_atlas, rdmsmp), texCoord).rgb;
}
vec3 rdm_sample_diff_probe(vec3 N, ivec3 local_pos, vec3 fallback) {
vec4 rect = rdm_atlas_rect(local_pos, 7);
if (rect.z <= 0.0) return fallback;
int face = rdm_face_from_normal(N);
int rdmSize = int(pow(2.0, float((7 - 7) + 1)));
ivec2 atlasSize = textureSize(sampler2D(rdm_atlas, rdmsmp), 0);
ivec2 fOff = rdm_face_offset(rect, face, rdmSize, atlasSize);
vec2 pos = rdm_hemioct(N, face);
return texelFetch(sampler2D(rdm_atlas, rdmsmp),
ivec2(fOff.x + int(pos.x * float(rdmSize)),
fOff.y + int(pos.y * float(rdmSize))), 0).rgb;
}
int isign(float f) { return f < 0.0 ? -1 : 1; }
vec3 smix(vec3 a, vec3 b, float t) {
float power = 1.6;
float st = pow(t, power) / (pow(t, power) + pow(1.0 - t, power));
return mix(a, b, st);
}
vec3 rdm_indirect_diffuse(vec3 N, vec3 diff, ivec3 local_pos) {
int face = rdm_face_from_normal(N);
vec3 ambient = vec3(0.3, 0.3, 0.4);
vec2 delta;
if (face <= 1) delta = vec2(diff.x, diff.z);
else if (face <= 3) delta = vec2(diff.x, diff.y);
else delta = vec2(diff.z, diff.y);
ivec3 s1, s2, s3;
if (face <= 1) {
s1 = ivec3(isign(delta.x), 0, 0);
s2 = ivec3(0, 0, isign(delta.y));
s3 = ivec3(isign(delta.x), 0, isign(delta.y));
} else if (face <= 3) {
s1 = ivec3(isign(delta.x), 0, 0);
s2 = ivec3(0, isign(delta.y), 0);
s3 = ivec3(isign(delta.x), isign(delta.y), 0);
} else {
s1 = ivec3(0, 0, isign(delta.x));
s2 = ivec3(0, isign(delta.y), 0);
s3 = ivec3(0, isign(delta.y), isign(delta.x));
}
vec3 p0 = rdm_sample_diff_probe(N, clamp(local_pos, ivec3(0), ivec3(31)), ambient);
vec3 p1 = rdm_sample_diff_probe(N, clamp(local_pos + s1, ivec3(0), ivec3(31)), ambient);
vec3 p2 = rdm_sample_diff_probe(N, clamp(local_pos + s2, ivec3(0), ivec3(31)), ambient);
vec3 p3 = rdm_sample_diff_probe(N, clamp(local_pos + s1 + s2,ivec3(0), ivec3(31)), ambient);
return smix(smix(p0, p1, abs(delta.x)),
smix(p2, p3, abs(delta.x)),
abs(delta.y));
}
// ---- SH PROBE GRID ----
// Each probe stores 27 L2 SH coefficients (9 per RGB channel), packed into
// 3 RGBA16F texels per probe along the X axis of a 192x4096 2D texture.
// Row = probe.z * 64 + probe.y, col = probe.x * 3 + k.
// Texel layout per probe (px,py,pz):
// t0: R.c0-3 t1: G.c0-3 t2: B.c0-3
// Probe index from chunk-local world position p (0..32 range):
// ivec3(floor(p * 2.0)) clamped to [0,63]
// SH evaluation: Lambertian irradiance (L1 only), A0=PI, A1=2PI/3.
vec3 sh_eval(ivec3 probe, vec3 N) {
int base = probe.x * 3;
int row = probe.z * 64 + probe.y;
vec4 t0 = texelFetch(sampler2D(sh_chunk, rdmsmp), ivec2(base, row), 0);
vec4 t1 = texelFetch(sampler2D(sh_chunk, rdmsmp), ivec2(base+1, row), 0);
vec4 t2 = texelFetch(sampler2D(sh_chunk, rdmsmp), ivec2(base+2, row), 0);
float x = N.x, y = N.y, z = N.z;
float r = 0.886227*t0.x + 1.023327*(t0.w*x + t0.y*y + t0.z*z);
float g = 0.886227*t1.x + 1.023327*(t1.w*x + t1.y*y + t1.z*z);
float b = 0.886227*t2.x + 1.023327*(t2.w*x + t2.y*y + t2.z*z);
return max(vec3(r, g, b) / PI, vec3(0.0));
}
// Sum of L0 irradiance across RGB — proxy for total incoming energy.
// Near-zero means the probe is buried inside solid geometry.
float sh_probe_energy(ivec3 probe) {
int base = probe.x * 3;
int row = probe.z * 64 + probe.y;
vec4 t0 = texelFetch(sampler2D(sh_chunk, rdmsmp), ivec2(base, row), 0);
vec4 t1 = texelFetch(sampler2D(sh_chunk, rdmsmp), ivec2(base+1, row), 0);
vec4 t2 = texelFetch(sampler2D(sh_chunk, rdmsmp), ivec2(base+2, row), 0);
return max(0.886227 * (t0.x + t1.x + t2.x), 0.0);
}
// Trilinear SH evaluation with confidence weighting.
// Probes with near-zero energy (buried in geometry) are downweighted
// so they don't pull the result toward black.
vec3 sh_eval_trilinear(ivec3 p0, ivec3 p1, vec3 t, vec3 N) {
float wx[2] = float[2](1.0 - t.x, t.x);
float wy[2] = float[2](1.0 - t.y, t.y);
float wz[2] = float[2](1.0 - t.z, t.z);
vec3 result = vec3(0.0);
float total_w = 0.0;
for (int iz = 0; iz < 2; iz++) {
for (int iy = 0; iy < 2; iy++) {
for (int ix = 0; ix < 2; ix++) {
ivec3 probe = ivec3(
ix == 0 ? p0.x : p1.x,
iy == 0 ? p0.y : p1.y,
iz == 0 ? p0.z : p1.z
);
float w = wx[ix] * wy[iy] * wz[iz] * sh_probe_energy(probe);
result += sh_eval(probe, N) * w;
total_w += w;
}
}
}
return total_w > 0.001 ? result / total_w : vec3(0.0);
}
// ---- HSV ----
vec3 rgb2hsv(vec3 c) {
vec4 K = vec4(0.0, -1.0/3.0, 2.0/3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
vec3 hsv2rgb(vec3 c) {
vec4 K = vec4(1.0, 2.0/3.0, 1.0/3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
// ---- MAIN ----
void main() {
if (vpos.y < planeHeight - 0.01 && is_reflection == 1) discard;
// Get trixel material.
vec3 sample_pos = ipos - orig_normal * 0.02;
vec4 trixel_material;
int maxSteps = is_reflection == 1 ? 1 : 3;
@ -438,14 +213,12 @@ void main() {
metallic = float((packed >> 3) & 0x3) / 3.0;
}
// Avoid noise in normals which appears for some reason.
vec3 absN = abs(fnormal.xyz);
vec3 N;
if (absN.x >= absN.y && absN.x >= absN.z) N = vec3(sign(fnormal.x), 0.0, 0.0);
else if (absN.y >= absN.x && absN.y >= absN.z) N = vec3(0.0, sign(fnormal.y), 0.0);
else N = vec3(0.0, 0.0, sign(fnormal.z));
// Simplified lighting evaluation for planar reflection.
if (is_reflection == 1) {
vec3 L = normalize(sunPosition);
float NdotL = max(dot(N, L), 0.0);
@ -453,7 +226,6 @@ void main() {
return;
}
// ---- 1. VIEW / LIGHT VECTORS ----
vec3 V = normalize(cam - vpos);
vec3 L = normalize(sunPosition);
vec3 H = normalize(V + L);
@ -461,14 +233,12 @@ void main() {
float NdotV = max(dot(N, V), 0.0);
float HdotV = max(dot(H, V), 0.0);
// ---- 2. PBR TERMS ----
vec3 F0 = mix(vec3(0.04), albedo, metallic);
vec3 F = fresnelSchlick(HdotV, F0);
float NDF = DistributionGGX(N, H, roughness);
float G = GeometrySmith(N, V, L, roughness);
vec3 kD = (1.0 - F) * (1.0 - metallic);
// ---- 3. DIRECT LIGHT (sun + shadow) ----
vec4 light_proj = mvp_shadow * vec4(floor(vpos * 16.0) / 16.0, 1.0);
vec3 light_ndc = light_proj.xyz / light_proj.w * 0.5 + 0.5;
light_ndc.z -= 0.001;
@ -477,84 +247,38 @@ void main() {
vec3 direct_specular = (NDF * G * F) / (4.0 * NdotV * NdotL + 0.0001);
vec3 light = shadow * (kD * albedo / PI + direct_specular) * NdotL * sunLightColor * sunIntensity;
// ---- 4. INDIRECT LIGHT (RDM / SH / ambient fallback) ----
ivec3 local = ivec3(mod(floor(trileCenter), 32.0));
vec4 atlas_rect = rdm_atlas_rect(local, roughnessInt);
float ssao = texture(sampler2D(ssaotex, rdmsmp),
gl_FragCoord.xy / vec2(float(screen_w), float(screen_h))).r;
vec3 emissive = albedo * emittance * emissive_scale;
float ssao = texture(sampler2D(ssaotex, linsmp),
gl_FragCoord.xy / vec2(float(screen_w), float(screen_h))).r;
vec3 emissive = albedo * emittance * emissive_scale;
if (rdm_enabled == 1) {
vec3 Frough = FresnelSchlickRoughness(NdotV, F0, roughness);
vec3 hemispherePos = trileCenter + N * 0.49;
vec3 diff = vpos - hemispherePos;
vec3 Frough = FresnelSchlickRoughness(NdotV, F0, roughness);
// 4a. Indirect specular.
// roughnessInt 0-1 with a baked RDM: ray-march or single-sample into the atlas.
// roughnessInt 2+ without RDM data: sky reflection.
// roughnessInt > ROUGHNESS_SPEC_CUTOFF: skip specular entirely.
if (roughnessInt <= 1 && atlas_rect.z > 0.0) {
int face = rdm_face_from_normal(N);
ivec2 atlasSize = textureSize(sampler2D(rdm_atlas, rdmsmp), 0);
vec2 atlasInvSz = 1.0 / vec2(atlasSize);
int rdmSize = int(atlas_rect.z * float(atlasSize.x)) / 2;
ivec2 fOff = rdm_face_offset(atlas_rect, face, rdmSize, atlasSize);
vec3 indirectSpec = roughness < ROUGHNESS_RAYMARCH_MAX
? rdm_spec_raymarch(N, -cv, diff, face, fOff, rdmSize, atlasInvSz)
: rdm_spec_single (N, -cv, diff, face, fOff, rdmSize, atlasInvSz);
indirectSpec *= rdm_tint;
float specLum = dot(indirectSpec, vec3(0.2126, 0.7152, 0.0722));
indirectSpec = mix(indirectSpec, vec3(specLum), metallic);
vec2 envBRDF = texture(sampler2D(brdf_lut, rdmsmp), vec2(NdotV, roughness)).rg;
float roughnessBell = 1.0 - 0.7 * sin(roughness * PI);
float grazingSuppr = 1.0 - 0.9 * roughness * sin(roughness * PI) * pow(1.0 - NdotV, 2.0);
float specRoughFade = 1.0 - clamp((roughness - 0.5) / 0.3, 0.0, 1.0);
light += indirectSpec * (Frough * envBRDF.x + envBRDF.y)
* rdm_spec_scale * roughnessBell * grazingSuppr * specRoughFade;
} else if (roughness < ROUGHNESS_SPEC_CUTOFF) {
vec3 R = reflect(-V, N);
vec2 envBRDF = texture(sampler2D(brdf_lut, rdmsmp), vec2(NdotV, roughness)).rg;
float specRoughFd = 1.0 - clamp((roughness - 0.5) / 0.3, 0.0, 1.0);
light += sky_reflect(R, sunPosition) * (Frough * envBRDF.x + envBRDF.y)
* rdm_spec_scale * specRoughFd;
}
// 4b. Indirect diffuse.
// SH probe grid when available (trilinear, confidence-weighted).
// Falls back to RDM level-7 diffuse probes.
vec3 indirectDiff;
if (sh_enabled == 1) {
vec3 trile_origin = floor(trileCenter);
vec3 local_frag = vec3(local) + (vpos - trile_origin);
vec3 probe_f = clamp(local_frag * 2.0, vec3(0.0), vec3(63.0));
ivec3 p0 = ivec3(floor(probe_f));
ivec3 p1 = min(p0 + ivec3(1), ivec3(63));
indirectDiff = sh_eval_trilinear(p0, p1, fract(probe_f), N) * rdm_tint;
} else {
indirectDiff = rdm_indirect_diffuse(N, diff, local) * rdm_tint;
}
float diffLuma = dot(indirectDiff, vec3(0.2126, 0.7152, 0.0722));
indirectDiff = mix(vec3(diffLuma), indirectDiff, rdm_diff_saturation);
light += (1.0 - Frough) * (1.0 - metallic) * indirectDiff / PI * albedo * ssao * rdm_diff_scale;
// 4c. Ambient floor — kicks in when indirect light is below the configured minimum.
if (rdm_diff_scale < 0.001 || length(light) < ambient_intensity)
light += ambient_color * max(ambient_intensity - length(light), 0.0) * albedo * ssao;
} else {
// No baked data: flat ambient + sky specular.
light += ambient_color * ambient_intensity * albedo * ssao;
light += F * sky_reflect(reflect(-V, N), sunPosition) * 0.1;
if (roughness < ROUGHNESS_SPEC_CUTOFF) {
vec3 R = reflect(-V, N);
vec2 envBRDF = texture(sampler2D(brdf_lut, linsmp), vec2(NdotV, roughness)).rg;
float specRoughFd = 1.0 - clamp((roughness - 0.5) / 0.3, 0.0, 1.0);
light += sky_reflect(R, sunPosition) * (Frough * envBRDF.x + envBRDF.y)
* indirect_spec_scale * specRoughFd;
}
// ---- 5. FINAL COMPOSITE ----
vec3 indirectDiff;
if (sh_enabled == 1) {
vec2 sh_uv = gl_FragCoord.xy / vec2(float(screen_w), float(screen_h));
indirectDiff = texture(sampler2D(sh_irradiance, linsmp), sh_uv).rgb * indirect_tint;
} else {
indirectDiff = ambient_color * ambient_intensity;
}
light += (1.0 - Frough) * (1.0 - metallic) * indirectDiff / PI * albedo * ssao * indirect_diff_scale;
vec3 final_color = light + emissive;
frag_color = vec4(mix(deepColor, final_color, smoothstep(0.0, planeHeight, vpos.y)), 1.0);
final_color = mix(deepColor, final_color, smoothstep(0.0, planeHeight, vpos.y));
float fog_dist = length(vpos - cam);
float fog_factor = smoothstep(fog_start, fog_end, fog_dist);
final_color = mix(final_color, skyBase, fog_factor);
frag_color = vec4(final_color, 1.0);
if (is_preview == 1) frag_color.rgb = mix(frag_color.rgb, vec3(0.3, 0.7, 1.0), 0.5);
else if (is_preview == 2) frag_color.rgb = mix(frag_color.rgb, vec3(1.0, 0.3, 0.2), 0.5);

View File

@ -0,0 +1,97 @@
@vs vs_trile_lod
in vec4 position;
in vec4 normal;
in vec4 color;
in vec4 instance;
layout(binding=0) uniform trile_lod_vs_params {
mat4 mvp;
vec3 camera;
};
out vec3 vpos;
out vec3 cam;
out vec3 vcolor;
out vec3 vnorm;
mat3 rot_x(float a) { float c=cos(a),s=sin(a); return mat3(1,0,0, 0,c,-s, 0,s,c); }
mat3 rot_y(float a) { float c=cos(a),s=sin(a); return mat3(c,0,s, 0,1,0, -s,0,c); }
mat3 rot_z(float a) { float c=cos(a),s=sin(a); return mat3(c,-s,0, s,c,0, 0,0,1); }
mat3 get_orientation_matrix(int ori) {
int face = ori / 4;
int twist = ori % 4;
float PI = 3.1415927;
mat3 base;
if (face == 0) base = mat3(1.0);
else if (face == 1) base = rot_x(PI);
else if (face == 2) base = rot_z(-PI*0.5);
else if (face == 3) base = rot_z( PI*0.5);
else if (face == 4) base = rot_x( PI*0.5);
else base = rot_x(-PI*0.5);
return base * rot_y(float(twist) * PI * 0.5);
}
void main() {
int ori = int(round(instance.w));
mat3 rot = get_orientation_matrix(ori);
vec3 local = position.xyz - 0.5;
vec3 rotated = rot * local + 0.5;
gl_Position = mvp * vec4(rotated + instance.xyz, 1.0);
vpos = rotated + instance.xyz;
cam = camera;
vcolor = color.xyz;
vnorm = rot * normal.xyz;
}
@end
@fs fs_trile_lod
layout(binding=1) uniform trile_lod_fs_params {
vec3 skyBase;
vec3 sunPosition;
vec3 sunLightColor;
float sunIntensity;
vec3 ambient_color;
float ambient_intensity;
float planeHeight;
vec3 deepColor;
int is_reflection;
float fog_start;
float fog_end;
};
in vec3 vpos;
in vec3 cam;
in vec3 vcolor;
in vec3 vnorm;
out vec4 frag_color;
void main() {
if (vpos.y < planeHeight - 0.01 && is_reflection == 1) discard;
const float PI = 3.1415927;
vec3 N = normalize(vnorm);
vec3 L = normalize(sunPosition);
float NdotL = max(dot(N, L), 0.0);
vec3 lit;
if (is_reflection == 1) {
lit = vcolor * (NdotL * sunLightColor * sunIntensity + 0.1) / PI;
} else {
lit = vcolor * (NdotL * sunLightColor * sunIntensity + ambient_color * ambient_intensity) / PI;
}
vec3 final_color = mix(deepColor, lit, smoothstep(0.0, planeHeight, vpos.y));
float fog_dist = length(vpos - cam);
float fog_factor = smoothstep(fog_start, fog_end, fog_dist);
final_color = mix(final_color, skyBase, fog_factor);
frag_color = vec4(final_color, 1.0);
}
@end
@program trile_lod vs_trile_lod fs_trile_lod

View File

@ -0,0 +1,346 @@
@vs vs_trile_rdm
in vec4 position;
in vec4 normal;
in vec4 centre;
in vec4 instance;
layout(binding=0) uniform trile_rdm_vs_params {
mat4 mvp;
mat4 mvp_shadow;
vec3 camera;
};
out vec3 cam;
out vec3 to_center;
out vec3 vpos;
out vec3 ipos;
out vec4 fnormal;
out vec3 orig_normal;
out vec3 trileCenter;
out vec3 cv;
mat3 rot_x(float a) { float c=cos(a),s=sin(a); return mat3(1,0,0, 0,c,-s, 0,s,c); }
mat3 rot_y(float a) { float c=cos(a),s=sin(a); return mat3(c,0,s, 0,1,0, -s,0,c); }
mat3 rot_z(float a) { float c=cos(a),s=sin(a); return mat3(c,-s,0, s,c,0, 0,0,1); }
mat3 get_orientation_matrix(int ori) {
int face = ori / 4;
int twist = ori % 4;
float PI = 3.1415927;
mat3 base;
if (face == 0) base = mat3(1.0);
else if (face == 1) base = rot_x(PI);
else if (face == 2) base = rot_z(-PI*0.5);
else if (face == 3) base = rot_z( PI*0.5);
else if (face == 4) base = rot_x( PI*0.5);
else base = rot_x(-PI*0.5);
return base * rot_y(float(twist) * PI * 0.5);
}
void main() {
int ori = int(round(instance.w));
mat3 rot = get_orientation_matrix(ori);
vec3 local = position.xyz - 0.5;
vec3 rotated = rot * local + 0.5;
gl_Position = mvp * vec4(rotated + instance.xyz, 1.0);
fnormal = vec4(rot * normal.xyz, 0.0);
orig_normal = normal.xyz;
to_center = centre.xyz - position.xyz;
vpos = rotated + instance.xyz;
ipos = position.xyz;
cam = camera;
cv = normalize(camera - vpos);
trileCenter = instance.xyz + vec3(0.5);
}
@end
@fs fs_trile_rdm
layout(binding=1) uniform trile_rdm_world_config {
vec3 skyBase;
vec3 skyTop;
vec3 sunDisk;
vec3 horizonHalo;
vec3 sunHalo;
vec3 sunLightColor;
vec3 sunPosition;
float sunIntensity;
float skyIntensity;
int hasClouds;
float planeHeight;
int animatePlaneHeight;
vec3 waterColor;
vec3 deepColor;
float time;
int hsv_lighting;
};
in vec3 cam;
in vec3 to_center;
in vec3 vpos;
in vec3 ipos;
in vec4 fnormal;
in vec3 orig_normal;
in vec3 trileCenter;
in vec3 cv;
out vec4 frag_color;
layout(binding=3) uniform trile_rdm_fs_params {
mat4 mvp_shadow;
int is_reflection;
int screen_h;
int screen_w;
float ambient_intensity;
float emissive_scale;
float indirect_diff_scale;
float indirect_spec_scale;
vec3 ambient_color;
int is_preview;
vec3 indirect_tint;
int sh_enabled;
vec4 atlas_rect;
};
layout(binding = 0) uniform texture2D rdm_triletex;
layout(binding = 0) uniform sampler rdm_trilesmp;
layout(binding = 1) uniform texture2D rdm_ssaotex;
layout(binding = 2) uniform texture2D rdm_shadowtex;
layout(binding = 2) uniform sampler rdm_shadowsmp;
layout(binding = 3) uniform texture2D rdm_brdflut;
layout(binding = 4) uniform texture2D rdm_shirradiance;
layout(binding = 5) uniform texture2D rdm_atlas;
layout(binding = 3) uniform sampler rdm_linsmp;
const float PI = 3.1415927;
const float ROUGHNESS_SPEC_CUTOFF = 0.7;
const float ROUGHNESS_RAYMARCH_MAX = 0.2;
vec3 sky(vec3 skypos, vec3 sunpos) {
vec3 npos = normalize(skypos);
float sDist = dot(npos, normalize(sunpos));
vec3 skyGradient = mix(skyBase, skyTop, clamp(npos.y * 2.0, 0.0, 0.7));
vec3 result = skyGradient;
result += sunHalo * clamp((sDist - 0.95) * 10.0, 0.0, 0.8) * 0.2;
if (sDist > 0.9999)
result = sunDisk;
result += mix(horizonHalo, vec3(0.0), clamp(abs(npos.y) * 80.0, 0.0, 1.0)) * 0.1;
return result;
}
vec3 sky_reflect(vec3 R, vec3 sunpos) {
if (R.y < 0.0) R = reflect(R, vec3(0.0, 1.0, 0.0));
return sky(R, sunpos);
}
float DistributionGGX(vec3 N, vec3 H, float roughness) {
float a = roughness * roughness;
float a2 = a * a;
float NdotH = max(dot(N, H), 0.0);
float denom = NdotH * NdotH * (a2 - 1.0) + 1.0;
return a2 / (PI * denom * denom);
}
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) {
float r = roughness + 1.0;
float k = (r * r) / 8.0;
float NdotV = max(dot(N, V), 0.0);
float NdotL = max(dot(N, L), 0.0);
float ggx1 = NdotL / (NdotL * (1.0 - k) + k);
float ggx2 = NdotV / (NdotV * (1.0 - k) + k);
return ggx1 * ggx2;
}
vec3 fresnelSchlick(float cosTheta, vec3 F0) {
return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);
}
vec3 FresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness) {
return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);
}
vec2 rdm_hemioct(vec3 v, int face) {
vec3 vc = v;
if (face / 2 == 0) { vc.z = v.y; vc.y = v.z; }
if (face / 2 == 2) { vc.z = v.x; vc.x = v.z; }
if (face % 2 == 1) { vc.z *= -1.0; }
vec2 p = vc.xy * (1.0 / (abs(vc.x) + abs(vc.y) + vc.z));
return vec2(p.x + p.y, p.x - p.y) * 0.5 + 0.5;
}
int rdm_face_from_normal(vec3 N) {
vec3 a = abs(N);
if (a.y >= a.x && a.y >= a.z) return N.y >= 0.0 ? 0 : 1;
if (a.z >= a.x && a.z >= a.y) return N.z >= 0.0 ? 2 : 3;
return N.x >= 0.0 ? 4 : 5;
}
ivec2 rdm_face_offset(vec4 rect, int face, int rdmSize, ivec2 atlasSize) {
int col = face % 2;
int row = face / 2;
return ivec2(int(rect.x * float(atlasSize.x)) + col * rdmSize,
int(rect.y * float(atlasSize.y)) + row * rdmSize);
}
vec3 rdm_spec_raymarch(vec3 N, vec3 V, vec3 diff, int face, ivec2 faceOffset, int rdmSize, vec2 atlasInvSize) {
vec3 reflected = reflect(V, N);
float maxDist = 20.0;
int steps = 40;
float stepSize = maxDist / float(steps);
for (int i = 0; i < steps; i++) {
float t = stepSize * float(i + 1);
vec3 samplePos = diff + t * reflected;
if (dot(samplePos, N) < 0.0) continue;
vec3 dir = normalize(samplePos);
vec2 hemiUV = rdm_hemioct(dir, face);
vec2 texCoord = (vec2(faceOffset) + hemiUV * float(rdmSize)) * atlasInvSize;
vec4 s = texture(sampler2D(rdm_atlas, rdm_linsmp), texCoord, 0);
float dist = length(samplePos);
if (s.a > 0.0 && s.a < dist && s.a + stepSize > dist)
return s.rgb;
}
return sky_reflect(reflected, sunPosition);
}
vec3 rdm_spec_single(vec3 N, vec3 V, vec3 diff, int face, ivec2 faceOffset, int rdmSize, vec2 atlasInvSize) {
vec3 reflected = reflect(V, N);
vec3 sampleDir = normalize(diff + 2.0 * reflected);
vec2 hemiUV = rdm_hemioct(sampleDir, face);
vec2 texCoord = (vec2(faceOffset) + hemiUV * float(rdmSize)) * atlasInvSize;
return texture(sampler2D(rdm_atlas, rdm_linsmp), texCoord).rgb;
}
void main() {
if (vpos.y < planeHeight - 0.01 && is_reflection == 1) discard;
vec3 sample_pos = ipos - orig_normal * 0.02;
vec4 trixel_material;
int maxSteps = is_reflection == 1 ? 1 : 3;
for (int i = 0; i < maxSteps; i++) {
ivec2 texel = ivec2(
int(clamp(sample_pos.z, 0.0001, 0.99999) * 16.0),
int(clamp(sample_pos.y, 0.0001, 0.99999) * 16.0) +
int(clamp(sample_pos.x, 0.0001, 0.99999) * 16.0) * 16
);
trixel_material = texelFetch(sampler2D(rdm_triletex, rdm_trilesmp), texel, 0);
if (dot(trixel_material, trixel_material) > 0.0001) break;
sample_pos += to_center * 0.1;
}
vec3 albedo = trixel_material.xyz;
int packed = int(round(trixel_material.w * 255.0));
float emittance = 0.0;
int roughnessInt = 0;
float roughness = 0.0;
float metallic = 0.0;
if ((packed & 0x1) != 0) {
emittance = float((packed >> 1) & 0x7F) / 127.0;
} else {
roughnessInt = (packed >> 5) & 0x7;
roughness = max(float(roughnessInt) / 7.0, 0.05);
metallic = float((packed >> 3) & 0x3) / 3.0;
}
vec3 absN = abs(fnormal.xyz);
vec3 N;
if (absN.x >= absN.y && absN.x >= absN.z) N = vec3(sign(fnormal.x), 0.0, 0.0);
else if (absN.y >= absN.x && absN.y >= absN.z) N = vec3(0.0, sign(fnormal.y), 0.0);
else N = vec3(0.0, 0.0, sign(fnormal.z));
if (is_reflection == 1) {
vec3 L = normalize(sunPosition);
float NdotL = max(dot(N, L), 0.0);
frag_color = vec4(albedo * (NdotL * sunLightColor * sunIntensity + 0.1), 1.0);
return;
}
vec3 V = normalize(cam - vpos);
vec3 L = normalize(sunPosition);
vec3 H = normalize(V + L);
float NdotL = max(dot(N, L), 0.0);
float NdotV = max(dot(N, V), 0.0);
float HdotV = max(dot(H, V), 0.0);
vec3 F0 = mix(vec3(0.04), albedo, metallic);
vec3 F = fresnelSchlick(HdotV, F0);
float NDF = DistributionGGX(N, H, roughness);
float G = GeometrySmith(N, V, L, roughness);
vec3 kD = (1.0 - F) * (1.0 - metallic);
vec4 light_proj = mvp_shadow * vec4(floor(vpos * 16.0) / 16.0, 1.0);
vec3 light_ndc = light_proj.xyz / light_proj.w * 0.5 + 0.5;
light_ndc.z -= 0.001;
float shadow = texture(sampler2DShadow(rdm_shadowtex, rdm_shadowsmp), light_ndc);
vec3 direct_specular = (NDF * G * F) / (4.0 * NdotV * NdotL + 0.0001);
vec3 light = shadow * (kD * albedo / PI + direct_specular) * NdotL * sunLightColor * sunIntensity;
float ssao = texture(sampler2D(rdm_ssaotex, rdm_linsmp),
gl_FragCoord.xy / vec2(float(screen_w), float(screen_h))).r;
vec3 emissive = albedo * emittance * emissive_scale;
vec3 Frough = FresnelSchlickRoughness(NdotV, F0, roughness);
vec3 hemispherePos = trileCenter + N * 0.49;
vec3 diff = vpos - hemispherePos;
if (roughnessInt <= 1) {
int face = rdm_face_from_normal(N);
ivec2 atlasSize = textureSize(sampler2D(rdm_atlas, rdm_linsmp), 0);
vec2 atlasInvSz = 1.0 / vec2(atlasSize);
int rdmSize = int(atlas_rect.z * float(atlasSize.x)) / 2;
ivec2 fOff = rdm_face_offset(atlas_rect, face, rdmSize, atlasSize);
vec3 indirectSpec = roughness < ROUGHNESS_RAYMARCH_MAX
? rdm_spec_raymarch(N, -cv, diff, face, fOff, rdmSize, atlasInvSz)
: rdm_spec_single (N, -cv, diff, face, fOff, rdmSize, atlasInvSz);
vec2 envBRDF = texture(sampler2D(rdm_brdflut, rdm_linsmp), vec2(NdotV, roughness)).rg;
float roughnessBell = 1.0 - 0.7 * sin(roughness * PI);
float grazingSuppr = 1.0 - 0.9 * roughness * sin(roughness * PI) * pow(1.0 - NdotV, 2.0);
float specRoughFade = 1.0 - clamp((roughness - 0.5) / 0.3, 0.0, 1.0);
light += indirectSpec * (Frough * envBRDF.x + envBRDF.y)
* indirect_spec_scale * roughnessBell * grazingSuppr * specRoughFade;
} else if (roughness < ROUGHNESS_SPEC_CUTOFF) {
vec3 R = reflect(-V, N);
vec2 envBRDF = texture(sampler2D(rdm_brdflut, rdm_linsmp), vec2(NdotV, roughness)).rg;
float specRoughFd = 1.0 - clamp((roughness - 0.5) / 0.3, 0.0, 1.0);
light += sky_reflect(R, sunPosition) * (Frough * envBRDF.x + envBRDF.y)
* indirect_spec_scale * specRoughFd;
}
vec3 indirectDiff;
if (sh_enabled == 1) {
vec2 sh_uv = gl_FragCoord.xy / vec2(float(screen_w), float(screen_h));
indirectDiff = texture(sampler2D(rdm_shirradiance, rdm_linsmp), sh_uv).rgb * indirect_tint;
} else {
indirectDiff = ambient_color * ambient_intensity;
}
light += (1.0 - Frough) * (1.0 - metallic) * indirectDiff / PI * albedo * ssao * indirect_diff_scale;
vec3 final_color = light + emissive;
frag_color = vec4(mix(deepColor, final_color, smoothstep(0.0, planeHeight, vpos.y)), 1.0);
if (is_preview == 1) frag_color.rgb = mix(frag_color.rgb, vec3(0.3, 0.7, 1.0), 0.5);
else if (is_preview == 2) frag_color.rgb = mix(frag_color.rgb, vec3(1.0, 0.3, 0.2), 0.5);
}
@end
@program trile_rdm vs_trile_rdm fs_trile_rdm

View File

@ -7,6 +7,13 @@ trile_table : Table(string, Trile);
editor_current_trile : *Trile = null;
Trile_GFX_LOD :: struct {
vertex_buffer : sg_buffer;
normal_buffer : sg_buffer;
color_buffer : sg_buffer;
vertex_count : s64;
}
Trile_GFX :: struct {
trixel_colors : sg_image;
vertex_buffer : sg_buffer;
@ -14,6 +21,9 @@ Trile_GFX :: struct {
centre_buffer : sg_buffer;
vertices : []float;
vertex_count : s64;
lod_4 : Trile_GFX_LOD; // 4^3 cube grid
lod_2 : Trile_GFX_LOD; // 2^3 cube grid
};
get_trile_table_ptr :: () -> *Table(string, Trile) {
@ -49,6 +59,8 @@ set_trile_gfx :: (name: string, gfx: Trile_GFX, skip_preexist_check: bool = fals
sg_destroy_buffer(old_gfx.normal_buffer);
sg_destroy_buffer(old_gfx.centre_buffer);
sg_destroy_image(old_gfx.trixel_colors);
destroy_trile_gfx_lod(*old_gfx.lod_4);
destroy_trile_gfx_lod(*old_gfx.lod_2);
array_reset(*old_gfx.vertices);
log_debug("Destroyed old GFX buffers for trile: %", name);
}
@ -65,6 +77,8 @@ set_trile :: (name: string, trile: Trile) {
sg_destroy_buffer(old_gfx.normal_buffer);
sg_destroy_buffer(old_gfx.centre_buffer);
sg_destroy_image(old_gfx.trixel_colors);
destroy_trile_gfx_lod(*old_gfx.lod_4);
destroy_trile_gfx_lod(*old_gfx.lod_2);
array_reset(*old_gfx.vertices);
table_remove(*trile_gfx_table, name);
}
@ -95,6 +109,8 @@ rename_trile :: (old_name: string, new_name: string) {
sg_destroy_buffer(old_gfx.normal_buffer);
sg_destroy_buffer(old_gfx.centre_buffer);
sg_destroy_image(old_gfx.trixel_colors);
destroy_trile_gfx_lod(*old_gfx.lod_4);
destroy_trile_gfx_lod(*old_gfx.lod_2);
array_reset(*old_gfx.vertices);
table_remove(*trile_gfx_table, old_name);
}
@ -112,6 +128,8 @@ delete_trile :: (name: string) {
sg_destroy_buffer(old_gfx.normal_buffer);
sg_destroy_buffer(old_gfx.centre_buffer);
sg_destroy_image(old_gfx.trixel_colors);
destroy_trile_gfx_lod(*old_gfx.lod_4);
destroy_trile_gfx_lod(*old_gfx.lod_2);
array_reset(*old_gfx.vertices);
table_remove(*trile_gfx_table, name);
}
@ -121,23 +139,6 @@ delete_trile :: (name: string) {
}
}
get_trile_roughness_set :: (trile_name: string) -> u8 {
trile, ok := get_trile(trile_name);
if !ok then return 1 << 7;
mask : u8 = 1 << 7;
for x: 0..15 {
for y: 0..15 {
for z: 0..15 {
if !trile.trixels[x][y][z].empty {
mask |= cast(u8)(1 << trile.trixels[x][y][z].material.roughness);
}
}
}
}
return mask;
}
lstrile :: () -> string {
count := 0;
for v : trile_table {
@ -202,22 +203,25 @@ Trixel :: struct {
};
Trile :: struct {
name : string = "test";
trixels : [16][16][16] Trixel;
name : string = "test";
is_opaque : bool = true;
trixels : [16][16][16] Trixel;
};
TrixelSerialize :: [5]u8;
TrileSerialize :: struct {
name : string = "test";
version : int = 0;
trixels : [16][16][16] TrixelSerialize;
name : string = "test";
version : int = 0;
is_opaque : u8 = 1;
trixels : [16][16][16] TrixelSerialize;
};
trile_to_serialize_form :: (t: Trile) -> TrileSerialize {
ts := TrileSerialize.{
name = t.name,
version = 1,
name = t.name,
version = 2,
is_opaque = ifx t.is_opaque then cast(u8)1 else cast(u8)0,
};
for i: 0..15 {
for j: 0..15 {
@ -232,6 +236,8 @@ trile_to_serialize_form :: (t: Trile) -> TrileSerialize {
trile_from_serialize_form :: (ts: TrileSerialize) -> Trile {
t := Trile.{ name = sprint("%", ts.name) };
if ts.version >= 2 t.is_opaque = ts.is_opaque != 0;
else t.is_opaque = true;
for i: 0..15 {
for j: 0..15 {
for k: 0..15 {

View File

@ -17,15 +17,15 @@ demo_toggle_float :: (val: *float, saved: *float, default: float) {
draw_demo_ui :: (theme: *GR.Overall_Theme) {
r := GR.get_rect(ui_w(86,0), ui_h(1,0), ui_w(13,0), ui_h(3,0));
rdm_diff_on := current_lighting_config.rdm_diff_scale > 0;
if GR.button(r, ifx rdm_diff_on then "RDM Diffuse: ON" else "RDM Diffuse: OFF") {
demo_toggle_float(*current_lighting_config.rdm_diff_scale, *demo_saved_rdm_diff, 1.0);
diff_on := current_lighting_config.indirect_diff_scale > 0;
if GR.button(r, ifx diff_on then "Indirect Diffuse: ON" else "Indirect Diffuse: OFF") {
demo_toggle_float(*current_lighting_config.indirect_diff_scale, *demo_saved_rdm_diff, 1.0);
}
r.y += r.h * 1.3;
rdm_spec_on := current_lighting_config.rdm_spec_scale > 0;
if GR.button(r, ifx rdm_spec_on then "RDM Specular: ON" else "RDM Specular: OFF") {
demo_toggle_float(*current_lighting_config.rdm_spec_scale, *demo_saved_rdm_spec, 1.0);
spec_on := current_lighting_config.indirect_spec_scale > 0;
if GR.button(r, ifx spec_on then "Indirect Specular: ON" else "Indirect Specular: OFF") {
demo_toggle_float(*current_lighting_config.indirect_spec_scale, *demo_saved_rdm_spec, 1.0);
}
r.y += r.h * 1.3;

View File

@ -429,14 +429,15 @@ font_boundary :: () {
render_ui :: () {
voxel_theme := get_voxel_theme();
GR.set_default_theme(voxel_theme);
loading := show_loading_screen();
#if !FLAG_RELEASE_BUILD {
draw_editor_ui(*voxel_theme);
if !in_editor_view then game_ui(*voxel_theme);
if !in_editor_view && !loading then game_ui(*voxel_theme);
draw_console(*voxel_theme);
} else {
game_ui(*voxel_theme);
if !loading then game_ui(*voxel_theme);
}
#if FLAG_DEMO_BUILD { if !in_editor_view then draw_demo_ui(*voxel_theme); }
#if FLAG_DEMO_BUILD { if !in_editor_view && !loading then draw_demo_ui(*voxel_theme); }
draw_settings_menu();
}

View File

@ -92,6 +92,8 @@ get_voxel_theme :: () -> GR.Overall_Theme {
t.slider_theme.background.frame_color = cfg.frame_color;
t.slider_theme.background.frame_color_over = cfg.frame_color;
t.slider_theme.foreground.label_theme.text_color = .{1, 1, 1, 1};
apply_voxel_btn(*t.slider_theme.spinbox_theme, cfg, true);
t.slider_theme.surface_style = .EXTEND_FROM_LEFT;

View File

@ -46,27 +46,16 @@ Trile_Instance :: struct {
Chunk_Trile_Group :: struct {
trile_name: string;
instances: [..]Trile_Instance;
is_buried: [..]bool; // Runtime-only, parallel to instances. Not serialized.
}
Chunk :: struct {
coord: Chunk_Key;
groups: [..]Chunk_Trile_Group;
rdm_atlas: sg_image;
rdm_lookup: sg_image;
rdm_valid: bool;
rdm_dirty: bool;
rdm_atlas_path: string;
rdm_lookup_path: string;
sh_probe_grid: sg_image; // 192x4096 RGBA16F 2D texture (2 probes/trile/axis)
sh_valid: bool;
sh_dirty: bool;
#if !FLAG_RELEASE_BUILD {
rdm_lookup_cpu: []float;
rdm_lookup_w: s32;
rdm_lookup_h: s32;
}
}
Editor_Note :: struct {
@ -74,12 +63,20 @@ Editor_Note :: struct {
text : string;
}
RDM_DEFAULT_SIZE :: 128;
Rdm_Instance_Override :: struct {
x : s32;
y : s32;
z : s32;
size_override : s32;
quality_override : s32;
x : s32;
y : s32;
z : s32;
rdm_enabled : bool;
rdm_size : s32; // side in px; 0 means legacy — treat as RDM_DEFAULT_SIZE.
}
// Per-world entry of the global RDM atlas. atlas_rect is normalized UV (x, y, w, h).
Rdm_Atlas_Entry :: struct {
x, y, z : s32;
atlas_rect : Vector4;
}
World :: struct {
@ -89,32 +86,72 @@ World :: struct {
emitter_instances : [..]Particle_Emitter_Instance;
notes : [..]Editor_Note;
rdm_overrides : [..]Rdm_Instance_Override;
rdm_lookup : [..]Rdm_Atlas_Entry; // populated by bake (Step 5) and by loader (Step 6)
}
get_rdm_instance_override :: (world: *World, x: s32, y: s32, z: s32) -> (size_override: s32, quality_override: s32) {
for world.rdm_overrides {
if it.x == x && it.y == y && it.z == z then return it.size_override, it.quality_override;
rdm_get_atlas_rect :: (world: *World, x: s32, y: s32, z: s32) -> (Vector4, bool) {
for world.rdm_lookup {
if it.x == x && it.y == y && it.z == z then return it.atlas_rect, true;
}
return 0, 0;
return .{}, false;
}
set_rdm_instance_override :: (world: *World, x: s32, y: s32, z: s32, size_override: s32, quality_override: s32) {
is_rdm_instance_enabled :: (world: *World, x: s32, y: s32, z: s32) -> bool {
for world.rdm_overrides {
if it.x == x && it.y == y && it.z == z then return it.rdm_enabled;
}
return false;
}
set_rdm_instance_enabled :: (world: *World, x: s32, y: s32, z: s32, enabled: bool) {
for *world.rdm_overrides {
if it.x == x && it.y == y && it.z == z {
if size_override == 0 && quality_override == 0 {
if !enabled {
array_ordered_remove_by_index(*world.rdm_overrides, it_index);
} else {
it.size_override = size_override;
it.quality_override = quality_override;
it.rdm_enabled = true;
if it.rdm_size == 0 then it.rdm_size = RDM_DEFAULT_SIZE;
}
return;
}
}
if size_override != 0 || quality_override != 0 {
array_add(*world.rdm_overrides, .{x=x, y=y, z=z, size_override=size_override, quality_override=quality_override});
if enabled {
array_add(*world.rdm_overrides, .{x=x, y=y, z=z, rdm_enabled=true, rdm_size=RDM_DEFAULT_SIZE});
}
}
get_rdm_instance_size :: (world: *World, x: s32, y: s32, z: s32) -> s32 {
for world.rdm_overrides {
if it.x == x && it.y == y && it.z == z {
if !it.rdm_enabled then return 0;
return ifx it.rdm_size > 0 then it.rdm_size else RDM_DEFAULT_SIZE;
}
}
return 0;
}
set_rdm_instance_size :: (world: *World, x: s32, y: s32, z: s32, size: s32) {
for *world.rdm_overrides {
if it.x == x && it.y == y && it.z == z {
it.rdm_size = size;
return;
}
}
}
RDM_SIZE_LADDER :: s32.[32, 64, 128, 256, 512, 1024, 2048, 4096];
rdm_cycle_size :: (cur: s32, dir: s32) -> s32 {
idx : s32 = 2;
for RDM_SIZE_LADDER {
if it == cur { idx = cast(s32) it_index; break; }
}
idx += dir;
if idx < 0 then idx = 0;
if idx >= cast(s32) RDM_SIZE_LADDER.count then idx = cast(s32) RDM_SIZE_LADDER.count - 1;
return RDM_SIZE_LADDER[idx];
}
// Convert a world-space integer position to chunk coordinate.
world_to_chunk_coord :: (wx: s32, wy: s32, wz: s32) -> Chunk_Key {
return .{
@ -172,23 +209,14 @@ unload_current_world :: () {
if !current_world.valid then return;
rdm_loader_cancel_all();
for *chunk: current_world.world.chunks {
if chunk.rdm_valid {
sg_destroy_image(chunk.rdm_atlas);
sg_destroy_image(chunk.rdm_lookup);
#if !FLAG_RELEASE_BUILD {
if chunk.rdm_lookup_cpu.data then free(chunk.rdm_lookup_cpu.data);
chunk.rdm_lookup_cpu = .{};
}
chunk.rdm_atlas = .{};
chunk.rdm_lookup = .{};
chunk.rdm_valid = false;
}
for *group: chunk.groups {
array_free(group.instances);
array_free(group.is_buried);
}
array_free(chunk.groups);
}
deinit(*current_world.world.chunks);
array_free(current_world.world.rdm_lookup);
Pool.reset(*current_world.pool);
current_world.valid = false;
}
@ -198,6 +226,108 @@ set_loaded_world :: (world: World) {
current_world.world = world;
current_world.valid = true;
resolve_emitter_definitions(*current_world.world);
for *chunk: current_world.world.chunks {
recompute_buried_for_chunk(*current_world.world, chunk);
}
}
is_cell_opaque :: (name: string) -> bool {
if name.count == 0 return false;
t, ok := get_trile(name);
if !ok return false;
return t.is_opaque;
}
trile_at_world :: (world: *World, wx: s32, wy: s32, wz: s32) -> string {
key := world_to_chunk_coord(wx, wy, wz);
chunk := table_find_pointer(*world.chunks, key);
if !chunk return "";
lx, ly, lz := world_to_local(wx, wy, wz);
for *group: chunk.groups {
for inst: group.instances {
if inst.x == lx && inst.y == ly && inst.z == lz {
return group.trile_name;
}
}
}
return "";
}
BURIED_DIRS :: s32.[ 1,0,0, -1,0,0, 0,1,0, 0,-1,0, 0,0,1, 0,0,-1 ];
compute_buried_at_world :: (world: *World, wx: s32, wy: s32, wz: s32) -> bool {
for axis: 0..5 {
nwx := wx + BURIED_DIRS[axis*3+0];
nwy := wy + BURIED_DIRS[axis*3+1];
nwz := wz + BURIED_DIRS[axis*3+2];
if !is_cell_opaque(trile_at_world(world, nwx, nwy, nwz)) return false;
}
return true;
}
recompute_buried_for_chunk :: (world: *World, chunk: *Chunk) {
// Build an O(1) local lookup grid (32^3 trile names) for this chunk so the
// common in-chunk neighbor case is a single index lookup. Cross-chunk
// neighbors fall back to trile_at_world.
GRID :: CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE;
grid: [GRID] string;
grid_data := grid;
for *group: chunk.groups {
for inst: group.instances {
idx := cast(int)inst.x + CHUNK_SIZE * (cast(int)inst.y + CHUNK_SIZE * cast(int)inst.z);
grid_data[idx] = group.trile_name;
}
}
for *group: chunk.groups {
array_resize(*group.is_buried, group.instances.count);
for inst, i: group.instances {
wx, wy, wz := chunk_local_to_world(chunk.coord, inst.x, inst.y, inst.z);
buried := true;
for axis: 0..5 {
nwx := wx + BURIED_DIRS[axis*3+0];
nwy := wy + BURIED_DIRS[axis*3+1];
nwz := wz + BURIED_DIRS[axis*3+2];
neighbor_name: string;
nkey := world_to_chunk_coord(nwx, nwy, nwz);
if nkey == chunk.coord {
nlx, nly, nlz := world_to_local(nwx, nwy, nwz);
nidx := cast(int)nlx + CHUNK_SIZE * (cast(int)nly + CHUNK_SIZE * cast(int)nlz);
neighbor_name = grid_data[nidx];
} else {
neighbor_name = trile_at_world(world, nwx, nwy, nwz);
}
if !is_cell_opaque(neighbor_name) {
buried = false;
break;
}
}
group.is_buried[i] = buried;
}
}
}
recompute_buried_at_cell :: (world: *World, wx: s32, wy: s32, wz: s32) {
key := world_to_chunk_coord(wx, wy, wz);
chunk := table_find_pointer(*world.chunks, key);
if !chunk return;
lx, ly, lz := world_to_local(wx, wy, wz);
for *group: chunk.groups {
for inst, i: group.instances {
if inst.x == lx && inst.y == ly && inst.z == lz {
if group.is_buried.count != group.instances.count array_resize(*group.is_buried, group.instances.count);
group.is_buried[i] = compute_buried_at_world(world, wx, wy, wz);
return;
}
}
}
}
invalidate_buried_around :: (world: *World, wx: s32, wy: s32, wz: s32) {
recompute_buried_at_cell(world, wx, wy, wz);
for axis: 0..5 {
recompute_buried_at_cell(world, wx + BURIED_DIRS[axis*3+0], wy + BURIED_DIRS[axis*3+1], wz + BURIED_DIRS[axis*3+2]);
}
}
resolve_emitter_definitions :: (world: *World) {
@ -211,6 +341,7 @@ clear_world :: () {
for *chunk: current_world.world.chunks {
for *group: chunk.groups {
array_free(group.instances);
array_free(group.is_buried);
}
array_free(chunk.groups);
}
@ -253,7 +384,6 @@ World_Json_Config :: struct {
waterColor : [3]float;
deepColor : [3]float;
waterShininess : float;
rdmDiffSaturation : float;
}
World_Json_Chunk :: struct {
@ -262,8 +392,6 @@ World_Json_Chunk :: struct {
z : s32;
offset : s32;
size : s32;
rdm_atlas : string;
rdm_lookup : string;
}
World_Json_Emitter :: struct {
@ -278,11 +406,11 @@ World_Json_Note :: struct {
}
World_Json_Rdm_Override :: struct {
x : s32;
y : s32;
z : s32;
size_override : s32;
quality_override : s32;
x : s32;
y : s32;
z : s32;
rdm_enabled : bool;
rdm_size : s32;
}
// World_Config serialized as a fixed-size binary blob.
@ -303,7 +431,6 @@ World_Config_Binary :: struct {
water_color: [3]float;
deep_color: [3]float;
water_shininess: float;
rdm_diff_saturation: float;
}
world_config_to_binary :: (conf: *World_Config) -> World_Config_Binary {
@ -323,7 +450,6 @@ world_config_to_binary :: (conf: *World_Config) -> World_Config_Binary {
b.water_color = conf.waterColor.component;
b.deep_color = conf.deepColor.component;
b.water_shininess = conf.waterShininess;
b.rdm_diff_saturation = conf.rdmDiffSaturation;
return b;
}
@ -344,7 +470,6 @@ world_config_from_binary :: (b: *World_Config_Binary) -> World_Config {
conf.waterColor.component = b.water_color;
conf.deepColor.component = b.deep_color;
conf.waterShininess = b.water_shininess;
conf.rdmDiffSaturation = b.rdm_diff_saturation;
return conf;
}
@ -409,7 +534,6 @@ world_config_to_json :: (conf: *World_Config) -> World_Json_Config {
jc.waterColor = conf.waterColor.component;
jc.deepColor = conf.deepColor.component;
jc.waterShininess = conf.waterShininess;
jc.rdmDiffSaturation = conf.rdmDiffSaturation;
return jc;
}
@ -430,7 +554,6 @@ world_config_from_json :: (jc: *World_Json_Config) -> World_Config {
conf.waterColor.component = jc.waterColor;
conf.deepColor.component = jc.deepColor;
conf.waterShininess = ifx jc.waterShininess > 0 then jc.waterShininess else 64.0;
conf.rdmDiffSaturation = ifx jc.rdmDiffSaturation > 0 then jc.rdmDiffSaturation else 1.0;
return conf;
}
@ -441,8 +564,6 @@ save_world :: (world: *World) -> (json: string, chunks_bin: string) {
coord: Chunk_Key;
offset: s32;
size: s32;
rdm_atlas_path: string;
rdm_lookup_path: string;
}
chunk_entries: [..]Chunk_Save_Entry;
chunk_entries.allocator = temp;
@ -469,19 +590,10 @@ save_world :: (world: *World) -> (json: string, chunks_bin: string) {
chunk_data := builder_to_string(*chunk_builder,, temp);
data_size := cast(s32) chunk_data.count;
atlas_path := chunk.rdm_atlas_path;
lookup_path := chunk.rdm_lookup_path;
if !atlas_path.count {
atlas_path = tprint("%_%_%.rdm_atlas", chunk.coord.x, chunk.coord.y, chunk.coord.z);
lookup_path = tprint("%_%_%.rdm_lookup", chunk.coord.x, chunk.coord.y, chunk.coord.z);
}
array_add(*chunk_entries, .{
coord = chunk.coord,
offset = running_offset,
size = data_size,
rdm_atlas_path = atlas_path,
rdm_lookup_path = lookup_path,
});
append(*bin_builder, chunk_data);
running_offset += data_size;
@ -499,8 +611,6 @@ save_world :: (world: *World) -> (json: string, chunks_bin: string) {
jc.z = entry.coord.z;
jc.offset = entry.offset;
jc.size = entry.size;
jc.rdm_atlas = entry.rdm_atlas_path;
jc.rdm_lookup = entry.rdm_lookup_path;
array_add(*wj.chunks, jc);
}
@ -520,7 +630,8 @@ save_world :: (world: *World) -> (json: string, chunks_bin: string) {
}
for ov: world.rdm_overrides {
array_add(*wj.rdm_overrides, .{x=ov.x, y=ov.y, z=ov.z, size_override=ov.size_override, quality_override=ov.quality_override});
size := ifx ov.rdm_size > 0 then ov.rdm_size else RDM_DEFAULT_SIZE;
array_add(*wj.rdm_overrides, .{x=ov.x, y=ov.y, z=ov.z, rdm_enabled=ov.rdm_enabled, rdm_size=size});
}
json_str := Jaison.json_write_string(wj, " ");
@ -542,8 +653,6 @@ load_world_from_json :: (json_str: string, chunk_bin: []u8) -> (World, bool) {
for jc: wj.chunks {
chunk: Chunk;
chunk.coord = .{x = jc.x, y = jc.y, z = jc.z};
chunk.rdm_atlas_path = sprint("%", jc.rdm_atlas);
chunk.rdm_lookup_path = sprint("%", jc.rdm_lookup);
offset := cast(s64) jc.offset;
size := cast(s64) jc.size;
@ -589,7 +698,8 @@ load_world_from_json :: (json_str: string, chunk_bin: []u8) -> (World, bool) {
}
for jov: wj.rdm_overrides {
array_add(*world.rdm_overrides, .{x=jov.x, y=jov.y, z=jov.z, size_override=jov.size_override, quality_override=jov.quality_override});
size := ifx jov.rdm_size > 0 then jov.rdm_size else RDM_DEFAULT_SIZE;
array_add(*world.rdm_overrides, .{x=jov.x, y=jov.y, z=jov.z, rdm_enabled=jov.rdm_enabled, rdm_size=size});
}
return world, true;
@ -721,7 +831,6 @@ World_Config :: struct {
waterColor : Vector3 = .{1.0, 1.0, 1.0}; @Color // @ToDo: sensible default values.
deepColor : Vector3 = .{1.0, 1.0, 1.0}; @Color // @ToDo: sensible default values.
waterShininess : float = 64.0; @Slider,1,512,8
rdmDiffSaturation : float = 1.0; @Slider,0,2,0.05
hsv_lighting : s32 = 1; @Slider,0,1,1
// ambientColor : Vector3 = .{1.0, 1.0, 1.0}; @Color