Compare commits

..

2 Commits

Author SHA1 Message Date
a4a3c086e2 some refactoring 2026-04-05 12:59:08 +03:00
e6382913fa perf improvements 2026-04-05 11:25:23 +03:00
15 changed files with 5416 additions and 7610 deletions

View File

@ -258,7 +258,7 @@ frame :: () {
add_frame_profiling_point("After UI draw"); add_frame_profiling_point("After UI draw");
#if !FLAG_RELEASE_BUILD { #if !FLAG_RELEASE_BUILD {
prepare_text(debug_font, tprint("frametime: % ms", latest_frametime * 1000)); prepare_text(debug_font, tprint("frametime: % ms", delta_time * 1000));
draw_prepared_text(debug_font, 10, 10, .{0.0, 1.0, 0.0, 1.0}); draw_prepared_text(debug_font, 10, 10, .{0.0, 1.0, 0.0, 1.0});
draw_editor(); draw_editor();
} }
@ -276,7 +276,6 @@ frame :: () {
#if OS != .WASM { profiler_update(); } #if OS != .WASM { profiler_update(); }
reset_temporary_storage(); reset_temporary_storage();
frame_end_time := get_time(); frame_end_time := get_time();
latest_frametime = frame_end_time - frame_start_time;
input_per_frame_event_and_flag_update(); input_per_frame_event_and_flag_update();
} }

View File

@ -1,13 +1,13 @@
#import,dir "../../modules/sokol-jai/sokol/app"(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/gfx"(DEBUG = FLAG_RELEASE_BUILD);
#import,dir "../../modules/sokol-jai/sokol/gl"(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/glue"(DEBUG = FLAG_RELEASE_BUILD);
#import,dir "../../modules/sokol-jai/sokol/shape"(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/fontstash";
#import,dir "../../modules/sokol-jai/sokol/log"(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/time"(DEBUG = FLAG_RELEASE_BUILD);
#import,dir "../../modules/sokol-jai/sokol/fetch"(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/audio"(DEBUG = FLAG_RELEASE_BUILD);
#load "../main.jai"; #load "../main.jai";

View File

@ -239,7 +239,7 @@ backend_draw_trile_positions_main :: (trile : string, amount : s32, worldConf: *
fs_params.screen_w = w; fs_params.screen_w = w;
fs_params.screen_h = h; fs_params.screen_h = h;
lc := *current_lighting_config; lc := *current_lighting_config;
fs_params.rdm_enabled = lc.rdm_enabled; fs_params.rdm_enabled = ifx in_reflection_pass then 0 else lc.rdm_enabled;
fs_params.ambient_intensity = lc.ambient_intensity; fs_params.ambient_intensity = lc.ambient_intensity;
fs_params.emissive_scale = lc.emissive_scale; fs_params.emissive_scale = lc.emissive_scale;
fs_params.rdm_diff_scale = lc.rdm_diff_scale; fs_params.rdm_diff_scale = lc.rdm_diff_scale;
@ -464,7 +464,7 @@ backend_process_command_buckets :: () {
end_frame_profiling_group("G-Buffer pass"); end_frame_profiling_group("G-Buffer pass");
start_frame_profiling_group("SSAO pass"); start_frame_profiling_group("SSAO pass");
sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, attachments = g_postprocess_attach_a })); sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, attachments = g_ssao_attachments }));
sg_apply_pipeline(gPipelines.ssao.pipeline); sg_apply_pipeline(gPipelines.ssao.pipeline);
gPipelines.ssao.bind.images[0] = g_gbuf_position; gPipelines.ssao.bind.images[0] = g_gbuf_position;
gPipelines.ssao.bind.images[1] = g_gbuf_normal; gPipelines.ssao.bind.images[1] = g_gbuf_normal;
@ -480,19 +480,6 @@ backend_process_command_buckets :: () {
sg_end_pass(); sg_end_pass();
end_frame_profiling_group("SSAO pass"); end_frame_profiling_group("SSAO pass");
start_frame_profiling_group("SSAO blur pass");
sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, attachments = g_ssao_attachments }));
sg_apply_pipeline(gPipelines.op.pipeline);
op_uniform : Op_Fs_Params;
op_uniform.blur_size = current_post_process.ssao_size;
op_uniform.op = 0;
gPipelines.op.bind.images[0] = g_postprocess_a;
sg_apply_uniforms(UB_op_fs_params, *(sg_range.{ ptr = *op_uniform, size = size_of(type_of(op_uniform)) }));
sg_apply_bindings(*gPipelines.op.bind);
sg_draw(0, 6, 1);
sg_end_pass();
end_frame_profiling_group("SSAO blur pass");
// 5. Main pass // 5. Main pass
start_frame_profiling_group("Main pass"); start_frame_profiling_group("Main pass");
sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, attachments = g_rendertex_attachments})); sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, attachments = g_rendertex_attachments}));
@ -506,8 +493,8 @@ backend_process_command_buckets :: () {
start_frame_profiling_group("Postprocess pass"); start_frame_profiling_group("Postprocess pass");
if !bypass_postprocess { if !bypass_postprocess {
bloom_process(); bloom_process();
dof_process();
} }
end_frame_profiling_group("Postprocess pass"); end_frame_profiling_group("Postprocess pass");
start_frame_profiling_group("Final pass"); start_frame_profiling_group("Final pass");
@ -516,8 +503,9 @@ backend_process_command_buckets :: () {
// Draw the render texture and do post processing: // Draw the render texture and do post processing:
sg_apply_pipeline(gPipelines.postprocess.pipeline); sg_apply_pipeline(gPipelines.postprocess.pipeline);
gPipelines.postprocess.bind.images[0] = ifx bypass_postprocess then g_rendertex else g_postprocess_a; gPipelines.postprocess.bind.images[0] = g_rendertex;
gPipelines.postprocess.bind.images[1] = LUT_list[g_current_lut_texture_index].image; gPipelines.postprocess.bind.images[1] = LUT_list[g_current_lut_texture_index].image;
gPipelines.postprocess.bind.images[2] = g_bloom_tex;
sg_apply_bindings(*gPipelines.postprocess.bind); sg_apply_bindings(*gPipelines.postprocess.bind);
post_process_config_uniform : Post_Process_Config; post_process_config_uniform : Post_Process_Config;
if bypass_postprocess { if bypass_postprocess {

View File

@ -1,27 +1,11 @@
bloom_process :: () { bloom_process :: () {
sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, attachments = g_postprocess_attach_a })); sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, attachments = g_bloom_attach }));
sg_apply_pipeline(gPipelines.op.pipeline); sg_apply_pipeline(gPipelines.bloom.pipeline);
op_uniform_bloom : Op_Fs_Params; params : Bloom_Params;
op_uniform_bloom.blur_size = current_post_process.bloom_size; params.bloom_treshold = current_post_process.bloom_treshold;
op_uniform_bloom.separation = current_post_process.bloom_separation; gPipelines.bloom.bind.images[IMG_bloom_src] = g_rendertex;
op_uniform_bloom.bloom_treshold = current_post_process.bloom_treshold; sg_apply_uniforms(UB_bloom_params, *(sg_range.{ ptr = *params, size = size_of(type_of(params)) }));
op_uniform_bloom.bloom_amount = current_post_process.bloom_amount; sg_apply_bindings(*gPipelines.bloom.bind);
op_uniform_bloom.op=3;
gPipelines.op.bind.images[0] = g_rendertex;
sg_apply_uniforms(UB_op_fs_params, *(sg_range.{ ptr = *op_uniform_bloom, size = size_of(type_of(op_uniform_bloom)) }));
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_b }));
sg_apply_pipeline(gPipelines.mix.pipeline);
mix_uniform : Mix_Fs_Params;
mix_uniform.op = 1;
gPipelines.mix.bind.images[0] = g_postprocess_a;
gPipelines.mix.bind.images[1] = g_rendertex;
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_draw(0, 6, 1);
sg_end_pass(); sg_end_pass();
} }

View File

@ -37,6 +37,9 @@ g_postprocess_b_depth : sg_image;
g_postprocess_attach_a : sg_attachments; g_postprocess_attach_a : sg_attachments;
g_postprocess_attach_b : sg_attachments; g_postprocess_attach_b : sg_attachments;
g_bloom_tex : sg_image;
g_bloom_attach : sg_attachments;
gPipelines : struct { gPipelines : struct {
// G-Buffer generation for SSAO and other effects // G-Buffer generation for SSAO and other effects
@ -69,6 +72,8 @@ gPipelines : struct {
mix : Pipeline_Binding; mix : Pipeline_Binding;
bloom : Pipeline_Binding;
billboard : Pipeline_Binding; billboard : Pipeline_Binding;
gbuffer_billboard : Pipeline_Binding; gbuffer_billboard : Pipeline_Binding;
@ -154,6 +159,7 @@ create_pipelines :: () {
create_ssao_pipeline(); create_ssao_pipeline();
create_op_pipeline(); create_op_pipeline();
create_mix_pipeline(); create_mix_pipeline();
create_bloom_pipeline();
create_billboard_pipeline(); create_billboard_pipeline();
create_gbuffer_billboard_pipeline(); create_gbuffer_billboard_pipeline();
create_particle_pipeline(); create_particle_pipeline();
@ -531,14 +537,14 @@ create_plane_pipeline_reflection_images :: () {
w, h := get_render_size(); w, h := get_render_size();
img_desc := sg_image_desc.{ img_desc := sg_image_desc.{
width = w/2, width = w/3,
height = h/2, height = h/3,
pixel_format = .RGBA32F, pixel_format = .RGBA8,
render_target = true, render_target = true,
}; };
depth_desc := sg_image_desc.{ depth_desc := sg_image_desc.{
width = w/2, width = w/3,
height = h/2, height = h/3,
pixel_format = .DEPTH, pixel_format = .DEPTH,
render_target = true, render_target = true,
}; };
@ -740,6 +746,13 @@ create_postprocess_pipeline :: () {
mag_filter = .LINEAR, mag_filter = .LINEAR,
})); }));
gPipelines.postprocess.bind.samplers[2] = sg_make_sampler(*(sg_sampler_desc.{
wrap_u = .CLAMP_TO_EDGE,
wrap_v = .CLAMP_TO_EDGE,
min_filter = .LINEAR,
mag_filter = .LINEAR,
}));
} }
// Takes in a texture, manipulates it and outputs it. // Takes in a texture, manipulates it and outputs it.
@ -979,6 +992,52 @@ 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);
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.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.{
wrap_u = .CLAMP_TO_EDGE,
wrap_v = .CLAMP_TO_EDGE,
min_filter = .NEAREST,
mag_filter = .NEAREST,
}));
}
create_ssao_images :: () { create_ssao_images :: () {
if g_ssaobuf.id != INVALID_ID then sg_destroy_image(g_ssaobuf); if g_ssaobuf.id != INVALID_ID then sg_destroy_image(g_ssaobuf);
if g_ssaobuf_depth.id != INVALID_ID then sg_destroy_image(g_ssaobuf_depth); if g_ssaobuf_depth.id != INVALID_ID then sg_destroy_image(g_ssaobuf_depth);
@ -991,7 +1050,7 @@ create_ssao_images :: () {
width = w/2, width = w/2,
height = h/2, height = h/2,
render_target = true, render_target = true,
pixel_format = .RGBA32F pixel_format = .RGBA8
}; };
img_desc.sample_count = 1; img_desc.sample_count = 1;
g_ssaobuf = sg_make_image(*img_desc); g_ssaobuf = sg_make_image(*img_desc);
@ -1029,6 +1088,21 @@ create_ssao_images :: () {
g_postprocess_attach_a = sg_make_attachments(*attachmentsDescA); g_postprocess_attach_a = sg_make_attachments(*attachmentsDescA);
sg_destroy_attachments(g_postprocess_attach_b); sg_destroy_attachments(g_postprocess_attach_b);
g_postprocess_attach_b = sg_make_attachments(*attachmentsDescB); 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);
} }
create_ssao_pipeline :: () { create_ssao_pipeline :: () {

View File

@ -14,8 +14,6 @@ Post_Process :: struct {
dof_min : float = 1.0; @Slider,0,10,1; dof_min : float = 1.0; @Slider,0,10,1;
dof_max : float = 3.0; @Slider,0,50,1; dof_max : float = 3.0; @Slider,0,50,1;
dof_point : float = 5.0; @Slider,0,30,1; dof_point : float = 5.0; @Slider,0,30,1;
bloom_size : s32 = 5; @Slider,0,10,1;
bloom_separation : float = 3.0; @Slider,0,10,1;
bloom_treshold : float = 0.4; @Slider,0,1,0.1; bloom_treshold : float = 0.4; @Slider,0,1,0.1;
bloom_amount : float = 0.0; @Slider,0,5,0.1; bloom_amount : float = 0.0; @Slider,0,5,0.1;

View File

@ -183,6 +183,7 @@ tasks_to_commands :: () {
memcpy(drawCmd.uv_rects.data, particleTask.uv_rects.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)); memcpy(drawCmd.colors.data, particleTask.colors.data, particleTask.count * size_of(Vector4));
array_add(*render_command_buckets.main, drawCmd); array_add(*render_command_buckets.main, drawCmd);
array_add(*render_command_buckets.reflection, drawCmd);
case .SET_CAMERA; case .SET_CAMERA;
task := (cast(*Rendering_Task_Set_Camera)it); task := (cast(*Rendering_Task_Set_Camera)it);
command := New(Render_Command_Set_Camera,, temp); command := New(Render_Command_Set_Camera,, temp);

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

@ -18,6 +18,8 @@ layout(binding = 0) uniform texture2D pptex;
layout(binding = 0) uniform sampler ppsmp; layout(binding = 0) uniform sampler ppsmp;
layout(binding = 1) uniform texture2D lut; layout(binding = 1) uniform texture2D lut;
layout(binding = 1) uniform sampler lut_linear; layout(binding = 1) uniform sampler lut_linear;
layout(binding = 2) uniform texture2D bloom_tex;
layout(binding = 2) uniform sampler bloom_smp;
layout(binding=0) uniform post_process_config { layout(binding=0) uniform post_process_config {
float exposure; float exposure;
@ -34,6 +36,7 @@ layout(binding=0) uniform post_process_config {
float barrel_distortion_intensity; float barrel_distortion_intensity;
int lut_mode; int lut_mode;
float dither_intensity; float dither_intensity;
float bloom_amount;
}; };
vec3 aces(vec3 x) { vec3 aces(vec3 x) {
@ -85,8 +88,8 @@ void main() {
float b = texture(sampler2D(pptex, ppsmp), distorted_texcoord - vec2(chromatic_aberration_intensity, 0.0)).b; float b = texture(sampler2D(pptex, ppsmp), distorted_texcoord - vec2(chromatic_aberration_intensity, 0.0)).b;
vec3 sampled_color_hdr = vec4(r, g, b, 1.0).rgb; vec3 sampled_color_hdr = vec4(r, g, b, 1.0).rgb;
vec3 bloom_color = texture(sampler2D(bloom_tex, bloom_smp), distorted_texcoord).rgb;
vec3 color_hdr = sampled_color_hdr * exposure; vec3 color_hdr = (sampled_color_hdr + bloom_color * bloom_amount) * exposure;
vec3 color_ldr_linear; vec3 color_ldr_linear;
if(tonemap > 0.5) { if(tonemap > 0.5) {

View File

@ -62,18 +62,6 @@ float noise(vec3 x)
mix(hash(n + 270.0), hash(n + 271.0), f.x), f.y), f.z); mix(hash(n + 270.0), hash(n + 271.0), f.x), f.y), f.z);
} }
const mat3 m = mat3(0.0, 1.60, 1.20, -1.6, 0.72, -0.96, -1.2, -0.96, 1.28);
float fbm(vec3 p)
{
float f = 0.0;
f += noise(p) / 2.0; p = m * p * 1.1;
f += noise(p) / 4.0; p = m * p * 1.2;
f += noise(p) / 6.0; p = m * p * 1.3;
f += noise(p) / 12.0; p = m * p * 1.4;
f += noise(p) / 24.0;
return f;
}
vec3 sky(vec3 skypos, vec3 sunpos) { vec3 sky(vec3 skypos, vec3 sunpos) {
vec3 sunCol = sunDisk.xyz; vec3 sunCol = sunDisk.xyz;
@ -111,13 +99,6 @@ vec3 sky(vec3 skypos, vec3 sunpos) {
final += mix(horizonHalo.xyz, vec3(0.0,0.0,0.0), clamp(abs(npos.y) * 20.0, 0.0, 1.0)) * 0.8; final += mix(horizonHalo.xyz, vec3(0.0,0.0,0.0), clamp(abs(npos.y) * 20.0, 0.0, 1.0)) * 0.8;
final = vec3(final); final = vec3(final);
// Cirrus Clouds
if(hasClouds == 1) {
float density = smoothstep(1.0 - cirrus, 1.0, fbm(npos.xyz / npos.y * 2.0 + time * 0.05)) * 0.3;
final.rgb = mix(final.rgb, vec3(1.0, 1.0, 1.0), max(0.0, npos.y) * density * 2.0);
}
return final; return final;
} }

View File

@ -13,16 +13,16 @@ layout(binding=0) uniform trile_vs_params {
out vec3 cam; out vec3 cam;
out vec3 to_center; out vec3 to_center;
out vec3 vpos; // The actual position; out vec3 vpos;
out vec3 ipos; // Trile space position; out vec3 ipos;
out vec4 fnormal; out vec4 fnormal;
out vec3 orig_normal; // Unrotated object-space normal, used for trixel lookup out vec3 orig_normal;
out vec3 trileCenter; out vec3 trileCenter;
out vec3 cv; 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_x(float a) { float c=cos(a),s=sin(a); return mat3(1,0,0, 0,c,-s, 0,s,c); }
mat3 rot_z(float a) { float c=cos(a),s=sin(a); return mat3(c,-s,0, s,c,0, 0,0,1); }
mat3 rot_y(float a) { float c=cos(a),s=sin(a); return mat3(c,0,s, 0,1,0, -s,0,c); } mat3 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) { mat3 get_orientation_matrix(int ori) {
int face = ori / 4; int face = ori / 4;
@ -46,8 +46,8 @@ void main() {
gl_Position = mvp * vec4(rotated + instance.xyz, 1.0); gl_Position = mvp * vec4(rotated + instance.xyz, 1.0);
fnormal = vec4(rot * normal.xyz, 0.0); fnormal = vec4(rot * normal.xyz, 0.0);
orig_normal = normal.xyz; // unrotated, for trixel lookup orig_normal = normal.xyz;
to_center = centre.xyz - position.xyz; // unrotated, for trixel lookup to_center = centre.xyz - position.xyz;
vpos = rotated + instance.xyz; vpos = rotated + instance.xyz;
ipos = position.xyz; ipos = position.xyz;
cam = camera; cam = camera;
@ -117,20 +117,20 @@ layout(binding = 4) uniform texture2D rdm_atlas;
layout(binding = 5) uniform texture2D brdf_lut; layout(binding = 5) uniform texture2D brdf_lut;
layout(binding = 3) uniform sampler rdmsmp; layout(binding = 3) uniform sampler rdmsmp;
const float PI = 3.1412854; const float PI = 3.1415927;
// --- SKY START --- 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 cirrus = 0.5; const float cirrus = 0.5;
const float cumulus = 20.0;
float hash(float n) float hash(float n) {
{
return fract(sin(n) * 43758.5453123); return fract(sin(n) * 43758.5453123);
} }
float noise(vec3 x) float noise(vec3 x) {
{
vec3 f = fract(x); vec3 f = fract(x);
float n = dot(floor(x), vec3(1.0, 157.0, 113.0)); float n = dot(floor(x), vec3(1.0, 157.0, 113.0));
return mix(mix(mix(hash(n + 0.0), hash(n + 1.0), f.x), return mix(mix(mix(hash(n + 0.0), hash(n + 1.0), f.x),
@ -139,94 +139,46 @@ float noise(vec3 x)
mix(hash(n + 270.0), hash(n + 271.0), f.x), f.y), f.z); mix(hash(n + 270.0), hash(n + 271.0), f.x), f.y), f.z);
} }
const mat3 m = mat3(0.0, 1.60, 1.20, -1.6, 0.72, -0.96, -1.2, -0.96, 1.28); const mat3 fbm_m = mat3(0.0, 1.60, 1.20, -1.6, 0.72, -0.96, -1.2, -0.96, 1.28);
float fbm(vec3 p)
{
float f = 0.0;
f += noise(p) / 2.0; p = m * p * 1.1;
f += noise(p) / 4.0; p = m * p * 1.2;
f += noise(p) / 6.0; p = m * p * 1.3;
f += noise(p) / 12.0; p = m * p * 1.4;
f += noise(p) / 24.0;
return f;
}
vec3 filmic_aces(vec3 v)
{
v = v * mat3(
0.59719f, 0.35458f, 0.04823f,
0.07600f, 0.90834f, 0.01566f,
0.02840f, 0.13383f, 0.83777f
);
return (v * (v + 0.0245786f) - 9.0537e-5f) /
(v * (0.983729f * v + 0.4329510f) + 0.238081f) * mat3(
1.60475f, -0.53108f, -0.07367f,
-0.10208f, 1.10813f, -0.00605f,
-0.00327f, -0.07276f, 1.07602f
);
}
vec3 sky(vec3 skypos, vec3 sunpos) { vec3 sky(vec3 skypos, vec3 sunpos) {
vec3 sunCol = sunDisk.xyz;
vec3 baseSky = skyBase.xyz;
vec3 topSky = skyTop.xyz;
float sDist = dot(normalize(skypos), normalize(sunpos));
vec3 npos = normalize(skypos); 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;
vec3 skyGradient = mix(baseSky, topSky, clamp(skypos.y * 2.0, 0.0, 0.7)); result += sunHalo * clamp((sDist - 0.95) * 10.0, 0.0, 0.8) * 0.2;
vec3 final = skyGradient; if (sDist > 0.9999)
final += sunHalo.xyz * clamp((sDist - 0.95) * 10.0, 0.0, 0.8) * 0.2; result = sunDisk;
// Sun disk result += mix(horizonHalo, vec3(0.0), clamp(abs(npos.y) * 80.0, 0.0, 1.0)) * 0.1;
if(sDist > 0.9999) { return result;
final = sunDisk.xyz;
} }
// Horizon halo vec3 sky_reflect(vec3 R, vec3 sunpos) {
final += mix(horizonHalo.xyz, vec3(0.0,0.0,0.0), clamp(abs(npos.y) * 80.0, 0.0, 1.0)) * 0.1; if (R.y < 0.0) R = reflect(R, vec3(0.0, 1.0, 0.0));
return sky(R, sunpos);
final = vec3(final);
// Cirrus Clouds
if(hasClouds == 1) {
float density = smoothstep(1.0 - cirrus, 1.0, fbm(npos.xyz / npos.y * 2.0 + time * 0.05)) * 0.3;
final.rgb = mix(final.rgb, vec3(1.0, 1.0, 1.0), max(0.0, npos.y) * density * 2.0);
} }
return final; // ---- PBR ----
}
// ---- PBR FUNCTIONS ----
float DistributionGGX(vec3 N, vec3 H, float roughness) { float DistributionGGX(vec3 N, vec3 H, float roughness) {
float a = roughness * roughness; float a = roughness * roughness;
float a2 = a * a; float a2 = a * a;
float NdotH = max(dot(N, H), 0.0); float NdotH = max(dot(N, H), 0.0);
float NdotH2 = NdotH*NdotH; float denom = NdotH * NdotH * (a2 - 1.0) + 1.0;
float num = a2; return a2 / (PI * denom * denom);
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
denom = PI * denom * denom;
return num / denom;
}
float GeometrySchlickGGX(float NdotV, float roughness) {
float r = (roughness + 1.0);
float k = (r*r) / 8.0;
float num = NdotV;
float denom = NdotV * (1.0 - k) + k;
return num / denom;
} }
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) { 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 NdotV = max(dot(N, V), 0.0);
float NdotL = max(dot(N, L), 0.0); float NdotL = max(dot(N, L), 0.0);
float ggx2 = GeometrySchlickGGX(NdotV, roughness); float ggx1 = NdotL / (NdotL * (1.0 - k) + k);
float ggx1 = GeometrySchlickGGX(NdotL, roughness); float ggx2 = NdotV / (NdotV * (1.0 - k) + k);
return ggx1 * ggx2; return ggx1 * ggx2;
} }
@ -238,176 +190,115 @@ 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); return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);
} }
// ---- RDM FUNCTIONS ---- // ---- RDM HELPERS ----
float roughness_to_rdm_size(int roughness) { // Hemioct encoding (Cigolle2014)
return pow(2.0, float((7 - roughness) + 1)); vec2 rdm_hemioct(vec3 v, int face) {
}
int rdm_index_from_normal(vec3 N) {
vec3 n_leftright = vec3(0.0, 0.0, 1.0);
vec3 n_updown = vec3(0.0, 1.0, 0.0);
vec3 n_frontback = vec3(1.0, 0.0, 0.0);
int res = 0;
res += int(dot(-n_updown, N) >= 0.98) * 1;
res += int(dot(n_leftright, N) >= 0.98) * 2;
res += int(dot(-n_leftright, N) >= 0.98) * 3;
res += int(dot(n_frontback, N) >= 0.98) * 4;
res += int(dot(-n_frontback, N) >= 0.98) * 5;
return res;
}
// Taken from Cigolle2014Vector.pdf
vec2 rdm_get_hemioct(vec3 v, int index, vec2 off) {
vec3 vc = v; vec3 vc = v;
if(index / 2 == 0) { if (face / 2 == 0) { vc.z = v.y; vc.y = v.z; }
vc.z = v.y; if (face / 2 == 2) { vc.z = v.x; vc.x = v.z; }
vc.y = v.z; if (face % 2 == 1) { vc.z *= -1.0; }
}
if(index / 2 == 2) {
vc.z = v.x;
vc.x = v.z;
}
if(index % 2 == 1) {
vc.z *= -1.0;
}
vc.x += off.x;
vc.y += off.y;
normalize(vc);
vec2 p = vc.xy * (1.0 / (abs(vc.x) + abs(vc.y) + vc.z)); vec2 p = vc.xy * (1.0 / (abs(vc.x) + abs(vc.y) + vc.z));
vec2 res = vec2(p.x + p.y, p.x - p.y); return vec2(p.x + p.y, p.x - p.y) * 0.5 + 0.5;
res.x = (res.x + 1.0) * 0.5;
res.y = (res.y + 1.0) * 0.5;
return res;
} }
float rdm_offset_y(int index) { int rdm_face_from_normal(vec3 N) {
return float((index / 2)) * (1.0/3.0); 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;
} }
float rdm_offset_x(int index) { vec4 rdm_atlas_rect(ivec3 local_pos, int roughness) {
return float((index % 2)) * (1.0/2.0);
}
vec4 rdm_get_atlas_rect(ivec3 local_pos, int roughness) {
int rdm_index = local_pos.x + local_pos.y * 32 + local_pos.z * 1024 + roughness * 32768; int rdm_index = local_pos.x + local_pos.y * 32 + local_pos.z * 1024 + roughness * 32768;
int tx = rdm_index % 512; return texelFetch(sampler2D(rdm_lookup, trilesmp), ivec2(rdm_index % 512, rdm_index / 512), 0);
int ty = rdm_index / 512;
return texelFetch(sampler2D(rdm_lookup, trilesmp), ivec2(tx, ty), 0);
} }
ivec2 rdm_face_pixel_offset(vec4 atlas_rect, int face, int rdmSize) { ivec2 rdm_face_offset(vec4 rect, int face, int rdmSize, ivec2 atlasSize) {
ivec2 atlasSize = textureSize(sampler2D(rdm_atlas, rdmsmp), 0);
int col = face % 2; int col = face % 2;
int row = face / 2; int row = face / 2;
int ox = int(atlas_rect.x * float(atlasSize.x)) + col * rdmSize; return ivec2(int(rect.x * float(atlasSize.x)) + col * rdmSize,
int oy = int(atlas_rect.y * float(atlasSize.y)) + row * rdmSize; int(rect.y * float(atlasSize.y)) + row * rdmSize);
return ivec2(ox, oy);
} }
vec3 sample_rdm(vec3 N, vec3 V, vec3 rdm_center, vec3 diff, int roughness, ivec3 local_pos) { vec2 rdm_face_uv(int face) {
int face = rdm_index_from_normal(N); if (face <= 1) return vec2(ipos.x, ipos.z);
vec4 atlas_rect = rdm_get_atlas_rect(local_pos, roughness); if (face <= 3) return vec2(ipos.x, ipos.y);
if (atlas_rect.z <= 0.0) return vec3(1.0, 0.0, 1.0); // No data - magenta return vec2(ipos.z, ipos.y);
ivec2 atlasTexSize = textureSize(sampler2D(rdm_atlas, rdmsmp), 0);
int rdmSizeInt = int(atlas_rect.z * float(atlasTexSize.x)) / 2;
float rdmSize = float(rdmSizeInt);
ivec2 faceOffset = rdm_face_pixel_offset(atlas_rect, face, rdmSizeInt);
vec2 uv;
if (face == 0 || face == 1) { // +Y / -Y
uv = vec2(ipos.x, ipos.z);
} else if (face == 2 || face == 3) { // +Z / -Z
uv = vec2(ipos.x, ipos.y);
} else { // +X / -X
uv = vec2(ipos.z, ipos.y);
} }
vec3 reflected = normalize(reflect(V, N)); // ---- RDM SPECULAR ----
if (roughness > 1) {
vec3 samplePos = normalize(diff + 2.0 * reflected);
vec2 hemiUV = rdm_get_hemioct(samplePos, face, vec2(0.0));
vec2 atlasSize = vec2(textureSize(sampler2D(rdm_atlas, rdmsmp), 0));
vec2 texUV = (vec2(faceOffset) + hemiUV * rdmSize) / atlasSize;
return texture(sampler2D(rdm_atlas, rdmsmp), texUV).rgb;
}
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; float maxDist = 20.0;
int steps = 40; int steps = 40;
float stepSize = maxDist / float(steps);
for (int i = 0; i < steps; i++) { for (int i = 0; i < steps; i++) {
float t = maxDist * float(i + 1) / float(steps); float t = stepSize * float(i + 1);
vec3 samplePos = diff + t * reflected; vec3 samplePos = diff + t * reflected;
if (dot(samplePos, N) < 0.0) continue; if (dot(samplePos, N) < 0.0) continue;
vec2 hemiUV = rdm_get_hemioct(normalize(samplePos), face, vec2(0.0)); vec3 dir = normalize(samplePos);
vec2 atlasSize = vec2(textureSize(sampler2D(rdm_atlas, rdmsmp), 0)); vec2 hemiUV = rdm_hemioct(dir, face);
vec2 texCoord = (vec2(faceOffset) + hemiUV * rdmSize) / atlasSize; vec2 texCoord = (vec2(faceOffset) + hemiUV * float(rdmSize)) * atlasInvSize;
vec4 rdmSample = texture(sampler2D(rdm_atlas, rdmsmp), texCoord, 0); vec4 s = texture(sampler2D(rdm_atlas, rdmsmp), texCoord, 0);
float depth = rdmSample.a;
float dist = length(samplePos); float dist = length(samplePos);
float stepSize = maxDist / float(steps); if (s.a > 0.0 && s.a < dist && s.a + stepSize > dist)
return s.rgb;
if (depth > 0.0 && depth < dist && depth + stepSize > dist) {
return rdmSample.rgb;
}
} }
vec3 skyDir = reflected; return sky_reflect(reflected, sunPosition);
if (skyDir.y < 0.0) skyDir = reflect(skyDir, vec3(0.0, 1.0, 0.0));
return sky(skyDir, sunPosition);
} }
vec3 sample_rdm_diff_map(vec3 N, ivec3 local_pos, vec3 fallback) { vec3 rdm_spec_single(vec3 N, vec3 V, vec3 diff, int face, ivec2 faceOffset, int rdmSize, vec2 atlasInvSize) {
vec4 atlas_rect = rdm_get_atlas_rect(local_pos, 7); vec3 reflected = reflect(V, N);
if (atlas_rect.z <= 0.0) return fallback; vec3 sampleDir = normalize(diff + 2.0 * reflected);
vec2 hemiUV = rdm_hemioct(sampleDir, face);
int face = rdm_index_from_normal(N); vec2 texCoord = (vec2(faceOffset) + hemiUV * float(rdmSize)) * atlasInvSize;
int rdmSize = int(roughness_to_rdm_size(7)); return texture(sampler2D(rdm_atlas, rdmsmp), texCoord).rgb;
ivec2 faceOffset = rdm_face_pixel_offset(atlas_rect, face, rdmSize);
vec2 pos = rdm_get_hemioct(N, face, vec2(0.0));
ivec2 texCoord = ivec2(faceOffset.x + int(pos.x * float(rdmSize)),
faceOffset.y + int(pos.y * float(rdmSize)));
return texelFetch(sampler2D(rdm_atlas, rdmsmp), texCoord, 0).rgb;
} }
int isign(float f) { vec3 rdm_sample_diff_probe(vec3 N, ivec3 local_pos, vec3 fallback) {
return f < 0.0 ? -1 : 1; 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) { vec3 smix(vec3 a, vec3 b, float t) {
float power = 1.6; float power = 1.6;
float smoothT = pow(t, power) / (pow(t, power) + pow(1.0 - t, power)); float st = pow(t, power) / (pow(t, power) + pow(1.0 - t, power));
return mix(a, b, smoothT); return mix(a, b, st);
} }
vec3 sample_rdm_diff(vec3 N, vec3 diff, ivec3 local_pos) { vec3 rdm_indirect_diffuse(vec3 N, vec3 diff, ivec3 local_pos) {
int face = rdm_index_from_normal(N); int face = rdm_face_from_normal(N);
vec3 ambientPlaceholder = vec3(0.3, 0.3, 0.4); vec3 ambient = vec3(0.3, 0.3, 0.4);
vec2 delta = vec2(0.0); vec2 delta;
if (face == 0 || face == 1) { if (face <= 1) delta = vec2(diff.x, diff.z);
delta = vec2(diff.x, diff.z); else if (face <= 3) delta = vec2(diff.x, diff.y);
} else if (face == 2 || face == 3) { else delta = vec2(diff.z, diff.y);
delta = vec2(diff.x, diff.y);
} else {
delta = vec2(diff.z, diff.y);
}
ivec3 s0 = ivec3(0, 0, 0);
ivec3 s1, s2, s3; ivec3 s1, s2, s3;
if (face == 0 || face == 1) { if (face <= 1) {
s1 = ivec3(isign(delta.x), 0, 0); s1 = ivec3(isign(delta.x), 0, 0);
s2 = ivec3(0, 0, isign(delta.y)); s2 = ivec3(0, 0, isign(delta.y));
s3 = ivec3(isign(delta.x), 0, isign(delta.y)); s3 = ivec3(isign(delta.x), 0, isign(delta.y));
} else if (face == 2 || face == 3) { } else if (face <= 3) {
s1 = ivec3(isign(delta.x), 0, 0); s1 = ivec3(isign(delta.x), 0, 0);
s2 = ivec3(0, isign(delta.y), 0); s2 = ivec3(0, isign(delta.y), 0);
s3 = ivec3(isign(delta.x), isign(delta.y), 0); s3 = ivec3(isign(delta.x), isign(delta.y), 0);
@ -417,18 +308,18 @@ vec3 sample_rdm_diff(vec3 N, vec3 diff, ivec3 local_pos) {
s3 = ivec3(0, isign(delta.y), isign(delta.x)); s3 = ivec3(0, isign(delta.y), isign(delta.x));
} }
vec3 p0 = sample_rdm_diff_map(N, ivec3(mod(vec3(local_pos + s0), 32.0)), ambientPlaceholder); vec3 p0 = rdm_sample_diff_probe(N, ivec3(mod(vec3(local_pos), 32.0)), ambient);
vec3 p1 = sample_rdm_diff_map(N, ivec3(mod(vec3(local_pos + s1), 32.0)), ambientPlaceholder); vec3 p1 = rdm_sample_diff_probe(N, ivec3(mod(vec3(local_pos + s1), 32.0)), ambient);
vec3 p2 = sample_rdm_diff_map(N, ivec3(mod(vec3(local_pos + s2), 32.0)), ambientPlaceholder); vec3 p2 = rdm_sample_diff_probe(N, ivec3(mod(vec3(local_pos + s2), 32.0)), ambient);
vec3 p3 = sample_rdm_diff_map(N, ivec3(mod(vec3(local_pos + s3), 32.0)), ambientPlaceholder); vec3 p3 = rdm_sample_diff_probe(N, ivec3(mod(vec3(local_pos + s1 + s2),32.0)), ambient);
return smix( return smix(smix(p0, p1, abs(delta.x)),
smix(p0, p1, abs(delta.x)),
smix(p2, p3, abs(delta.x)), smix(p2, p3, abs(delta.x)),
abs(delta.y) abs(delta.y));
);
} }
// ---- HSV ----
vec3 rgb2hsv(vec3 c) { vec3 rgb2hsv(vec3 c) {
vec4 K = vec4(0.0, -1.0/3.0, 2.0/3.0, -1.0); 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 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
@ -444,140 +335,146 @@ vec3 hsv2rgb(vec3 c) {
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
} }
// ---- MAIN ----
void main() { void main() {
if (vpos.y < planeHeight - 0.01 && is_reflection == 1) { if (vpos.y < planeHeight - 0.01 && is_reflection == 1) discard;
discard;
}
// Trixel material sampling Get trixel material.
vec3 pos_after_adjust = ipos - orig_normal * 0.02; vec3 sample_pos = ipos - orig_normal * 0.02;
int count = 0;
vec4 trixel_material; vec4 trixel_material;
while (count < 5) { int maxSteps = is_reflection == 1 ? 1 : 3;
int xpos = int(clamp(pos_after_adjust.z, 0.0001, 0.99999) * 16.0); for (int i = 0; i < maxSteps; i++) {
int ypos = int(clamp(pos_after_adjust.y, 0.0001, 0.99999) * 16.0); ivec2 texel = ivec2(
int zpos = int(clamp(pos_after_adjust.x, 0.0001, 0.99999) * 16.0); int(clamp(sample_pos.z, 0.0001, 0.99999) * 16.0),
int(clamp(sample_pos.y, 0.0001, 0.99999) * 16.0) +
trixel_material = texelFetch(sampler2D(triletex, trilesmp), ivec2(xpos, ypos + zpos * 16), 0); int(clamp(sample_pos.x, 0.0001, 0.99999) * 16.0) * 16
if (length(trixel_material) > 0.01) break; );
pos_after_adjust += to_center * 0.1; trixel_material = texelFetch(sampler2D(triletex, trilesmp), texel, 0);
count++; if (dot(trixel_material, trixel_material) > 0.0001) break;
sample_pos += to_center * 0.1;
} }
vec3 albedo = trixel_material.xyz; vec3 albedo = vec3(1.0, 1.0, 1.0);
int packedMaterial = int(round(trixel_material.w * 255.0));
int packed = int(round(trixel_material.w * 255.0));
float emittance = 0.0; float emittance = 0.0;
int roughnessInt = 0; int roughnessInt = 7;
float roughness = 0.05; float roughness = 1.0;
float metallic = 0.0; float metallic = 0.0;
if ((packedMaterial & 0x1) != 0) {
emittance = float((packedMaterial >> 1) & 0x7F) / 127.0; if ((packed & 0x1) != 0) {
emittance = float((packed >> 1) & 0x7F) / 127.0;
} else { } else {
roughnessInt = (packedMaterial >> 5) & 0x7; roughnessInt = (packed >> 5) & 0x7;
roughness = max(float(roughnessInt) / 7.0, 0.05); roughness = max(float(roughnessInt) / 7.0, 0.05);
metallic = float((packedMaterial >> 3) & 0x3) / 3.0; metallic = float((packed >> 3) & 0x3) / 3.0;
} }
// Snap normal to nearest axis to avoid interpolation noise // Avoid noise in normals which appears for some reason.
vec3 absN = abs(fnormal.xyz); vec3 absN = abs(fnormal.xyz);
vec3 N; vec3 N;
if (absN.x >= absN.y && absN.x >= absN.z) { if (absN.x >= absN.y && absN.x >= absN.z) N = vec3(sign(fnormal.x), 0.0, 0.0);
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 if (absN.y >= absN.x && absN.y >= absN.z) { else N = vec3(0.0, 0.0, sign(fnormal.z));
N = vec3(0.0, sign(fnormal.y), 0.0);
} else { // Simplified lighting evaluation for planar reflection.
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.xyz); // Evaluate direct light.
vec3 V = normalize(cam - vpos);
vec3 L = normalize(sunPosition); vec3 L = normalize(sunPosition);
vec3 H = normalize(V + L); 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 = vec3(0.04); vec3 F0 = mix(vec3(0.04), albedo, metallic);
F0 = mix(F0, albedo, metallic); vec3 F = fresnelSchlick(HdotV, F0);
vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0);
float NDF = DistributionGGX(N, H, roughness); float NDF = DistributionGGX(N, H, roughness);
float G = GeometrySmith(N, V, L, roughness); float G = GeometrySmith(N, V, L, roughness);
vec3 numerator = NDF * G * F;
float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001;
vec3 specular = numerator / denominator;
float NdotL = max(dot(N, L), 0.0);
vec3 kD = vec3(1.0) - F;
kD *= 1.0 - metallic;
// Shadow vec3 specular = (NDF * G * F) / (4.0 * NdotV * NdotL + 0.0001);
vec4 light_proj_pos = mvp_shadow * vec4(floor(vpos.xyz * 16.0) / 16.0, 1.0); vec3 kD = (1.0 - F) * (1.0 - metallic);
vec3 light_pos = light_proj_pos.xyz / light_proj_pos.w;
light_pos = light_pos * 0.5 + 0.5;
light_pos.z -= 0.001;
float shadowp = texture(sampler2DShadow(shadowtex, shadowsmp), light_pos);
// Direct lighting // Shadow lookup.
vec3 light = shadowp * (kD * albedo / PI + specular) * NdotL * sunLightColor * sunIntensity; 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(shadowtex, shadowsmp), light_ndc);
// RDM indirect lighting vec3 light = shadow * (kD * albedo / PI + specular) * NdotL * sunLightColor * sunIntensity;
vec3 hemispherePos = trileCenter + N * 0.49;
// --- Indirect lighting ---
ivec3 local = ivec3(mod(floor(trileCenter), 32.0)); ivec3 local = ivec3(mod(floor(trileCenter), 32.0));
vec4 atlas_rect_check = rdm_get_atlas_rect(local, roughnessInt); vec4 atlas_rect = rdm_atlas_rect(local, roughnessInt);
float ssao_sample = texture(sampler2D(ssaotex, trilesmp), vec2(gl_FragCoord.x / float(screen_w), gl_FragCoord.y / float(screen_h)), 0).r; float ssao = texture(sampler2D(ssaotex, rdmsmp),
gl_FragCoord.xy / vec2(float(screen_w), float(screen_h))).r;
// Emissive — self-lit, not shadowed.
vec3 emissive = albedo * emittance * emissive_scale; vec3 emissive = albedo * emittance * emissive_scale;
if (rdm_enabled == 1 && atlas_rect_check.z > 0.0) { if (rdm_enabled == 100 && atlas_rect.z > 0.0) {
vec3 Frough = FresnelSchlickRoughness(max(dot(N, V), 0.0), F0, roughness); vec3 Frough = FresnelSchlickRoughness(NdotV, F0, roughness);
vec3 hemispherePos = trileCenter + N * 0.49;
vec3 diff = vpos - hemispherePos;
// Indirect specular // Indirect specular
vec3 indirectSpec = sample_rdm(N, -cv, if (roughness < ROUGHNESS_SPEC_CUTOFF) {
hemispherePos, vpos - hemispherePos, roughnessInt, local) * rdm_tint; int face = rdm_face_from_normal(N);
ivec2 atlasSize = textureSize(sampler2D(rdm_atlas, rdmsmp), 0);
vec2 atlasInvSize = 1.0 / vec2(atlasSize);
int rdmSize = int(atlas_rect.z * float(atlasSize.x)) / 2;
ivec2 fOff = rdm_face_offset(atlas_rect, face, rdmSize, atlasSize);
// For metallic surfaces: desaturate the reflection so Frough (which uses albedo vec3 indirectSpec;
// as F0 for metals) applies the metal tint cleanly without double-tinting. if (roughness < ROUGHNESS_RAYMARCH_MAX) {
indirectSpec = rdm_spec_raymarch(N, -cv, diff, face, fOff, rdmSize, atlasInvSize);
} else {
indirectSpec = rdm_spec_single(N, -cv, diff, face, fOff, rdmSize, atlasInvSize);
}
indirectSpec *= rdm_tint;
// Desaturate for metals to avoid double-tinting
float specLum = dot(indirectSpec, vec3(0.2126, 0.7152, 0.0722)); float specLum = dot(indirectSpec, vec3(0.2126, 0.7152, 0.0722));
indirectSpec = mix(indirectSpec, vec3(specLum), metallic); indirectSpec = mix(indirectSpec, vec3(specLum), metallic);
vec2 envBRDF = texture(sampler2D(brdf_lut, rdmsmp), vec2(max(dot(N, V), 0.0), roughness)).rg; vec2 envBRDF = texture(sampler2D(brdf_lut, rdmsmp), vec2(NdotV, roughness)).rg;
float NdotV_s = max(dot(N, V), 0.0);
float roughnessBell = 1.0 - 0.7 * sin(roughness * PI); float roughnessBell = 1.0 - 0.7 * sin(roughness * PI);
float grazingSuppress = 1.0 - 0.9 * roughness * sin(roughness * PI) * pow(1.0 - NdotV_s, 2.0); float grazingSuppress = 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); 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 * grazingSuppress * specRoughFade;
// Indirect diffuse (interpolated from neighbor probes) light += indirectSpec * (Frough * envBRDF.x + envBRDF.y)
vec3 indirectDiff = sample_rdm_diff(N, vpos - hemispherePos, local) * rdm_tint; * rdm_spec_scale * roughnessBell * grazingSuppress * specRoughFade;
}
// Indirect diffuse
vec3 indirectDiff = rdm_indirect_diffuse(N, diff, local) * rdm_tint;
float diffLuma = dot(indirectDiff, vec3(0.2126, 0.7152, 0.0722)); float diffLuma = dot(indirectDiff, vec3(0.2126, 0.7152, 0.0722));
indirectDiff = mix(vec3(diffLuma), indirectDiff, rdm_diff_saturation); indirectDiff = mix(vec3(diffLuma), indirectDiff, rdm_diff_saturation);
vec3 kDiff = 1.0 - Frough; vec3 kDiff = (1.0 - Frough) * (1.0 - metallic);
kDiff *= 1.0 - metallic;
light += (kDiff * indirectDiff / PI * albedo) * ssao_sample * rdm_diff_scale; light += kDiff * indirectDiff / PI * albedo * ssao * rdm_diff_scale;
if (rdm_diff_scale < 0.001) {
light += ambient_color * ambient_intensity * albedo * ssao_sample; // Ambient floor
} if (rdm_diff_scale < 0.001 || length(light) < ambient_intensity)
if (length(light) < ambient_intensity) { light += ambient_color * max(ambient_intensity - length(light), 0.0) * albedo * ssao;
light += ambient_color * (ambient_intensity - length(light)) * albedo * ssao_sample;
}
} else { } else {
// Fallback: ambient + sky reflection when no RDM data (or RDM disabled). light += ambient_color * ambient_intensity * albedo * ssao;
light += ambient_color * ambient_intensity * albedo * ssao_sample;
vec3 R = reflect(-V, N); vec3 R = reflect(-V, N);
if (R.y < 0.0) R = reflect(R, vec3(0.0, 1.0, 0.0)); light += F * sky_reflect(R, sunPosition) * 0.1;
light += F * sky(R, sunPosition) * 0.1;
} }
vec3 final_color = light + emissive; vec3 final_color = light + emissive;
if (hsv_lighting == 1) {
float albedo_lum = dot(albedo, vec3(0.2126, 0.7152, 0.0722)) + 0.001;
float light_lum = dot(final_color, vec3(0.2126, 0.7152, 0.0722));
vec3 hsv = rgb2hsv(albedo);
hsv.z = clamp(hsv.z * (light_lum / albedo_lum), 0.0, 1.0);
final_color = hsv2rgb(hsv);
}
frag_color = vec4(mix(deepColor, final_color, smoothstep(0.0, planeHeight, vpos.y)), 1.0); 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); 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) { else if (is_preview == 2) frag_color.rgb = mix(frag_color.rgb, vec3(1.0, 0.3, 0.2), 0.5);
frag_color.rgb = mix(frag_color.rgb, vec3(1.0, 0.3, 0.2), 0.5);
}
} }
@end @end