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");
#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_editor();
}
@ -276,7 +276,6 @@ frame :: () {
#if OS != .WASM { profiler_update(); }
reset_temporary_storage();
frame_end_time := get_time();
latest_frametime = frame_end_time - frame_start_time;
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/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";

View File

@ -239,7 +239,7 @@ 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 = 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.emissive_scale = lc.emissive_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");
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);
gPipelines.ssao.bind.images[0] = g_gbuf_position;
gPipelines.ssao.bind.images[1] = g_gbuf_normal;
@ -480,19 +480,6 @@ backend_process_command_buckets :: () {
sg_end_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
start_frame_profiling_group("Main pass");
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");
if !bypass_postprocess {
bloom_process();
dof_process();
}
end_frame_profiling_group("Postprocess pass");
start_frame_profiling_group("Final pass");
@ -516,8 +503,9 @@ backend_process_command_buckets :: () {
// Draw the render texture and do post processing:
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[2] = g_bloom_tex;
sg_apply_bindings(*gPipelines.postprocess.bind);
post_process_config_uniform : Post_Process_Config;
if bypass_postprocess {

View File

@ -1,27 +1,11 @@
bloom_process :: () {
sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, attachments = g_postprocess_attach_a }));
sg_apply_pipeline(gPipelines.op.pipeline);
op_uniform_bloom : Op_Fs_Params;
op_uniform_bloom.blur_size = current_post_process.bloom_size;
op_uniform_bloom.separation = current_post_process.bloom_separation;
op_uniform_bloom.bloom_treshold = current_post_process.bloom_treshold;
op_uniform_bloom.bloom_amount = current_post_process.bloom_amount;
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_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);
sg_draw(0, 6, 1);
sg_end_pass();
}

View File

@ -37,6 +37,9 @@ 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;
gPipelines : struct {
// G-Buffer generation for SSAO and other effects
@ -69,6 +72,8 @@ gPipelines : struct {
mix : Pipeline_Binding;
bloom : Pipeline_Binding;
billboard : Pipeline_Binding;
gbuffer_billboard : Pipeline_Binding;
@ -154,6 +159,7 @@ create_pipelines :: () {
create_ssao_pipeline();
create_op_pipeline();
create_mix_pipeline();
create_bloom_pipeline();
create_billboard_pipeline();
create_gbuffer_billboard_pipeline();
create_particle_pipeline();
@ -531,14 +537,14 @@ create_plane_pipeline_reflection_images :: () {
w, h := get_render_size();
img_desc := sg_image_desc.{
width = w/2,
height = h/2,
pixel_format = .RGBA32F,
width = w/3,
height = h/3,
pixel_format = .RGBA8,
render_target = true,
};
depth_desc := sg_image_desc.{
width = w/2,
height = h/2,
width = w/3,
height = h/3,
pixel_format = .DEPTH,
render_target = true,
};
@ -740,6 +746,13 @@ create_postprocess_pipeline :: () {
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.
@ -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 :: () {
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);
@ -991,7 +1050,7 @@ create_ssao_images :: () {
width = w/2,
height = h/2,
render_target = true,
pixel_format = .RGBA32F
pixel_format = .RGBA8
};
img_desc.sample_count = 1;
g_ssaobuf = sg_make_image(*img_desc);
@ -1029,6 +1088,21 @@ create_ssao_images :: () {
g_postprocess_attach_a = sg_make_attachments(*attachmentsDescA);
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);
}
create_ssao_pipeline :: () {

View File

@ -14,8 +14,6 @@ Post_Process :: struct {
dof_min : float = 1.0; @Slider,0,10,1;
dof_max : float = 3.0; @Slider,0,50,1;
dof_point : float = 5.0; @Slider,0,30,1;
bloom_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_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.colors.data, particleTask.colors.data, particleTask.count * size_of(Vector4));
array_add(*render_command_buckets.main, drawCmd);
array_add(*render_command_buckets.reflection, drawCmd);
case .SET_CAMERA;
task := (cast(*Rendering_Task_Set_Camera)it);
command := New(Render_Command_Set_Camera,, temp);

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 = 1) uniform texture2D lut;
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 {
float exposure;
@ -34,6 +36,7 @@ layout(binding=0) uniform post_process_config {
float barrel_distortion_intensity;
int lut_mode;
float dither_intensity;
float bloom_amount;
};
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;
vec3 sampled_color_hdr = vec4(r, g, b, 1.0).rgb;
vec3 color_hdr = sampled_color_hdr * exposure;
vec3 bloom_color = texture(sampler2D(bloom_tex, bloom_smp), distorted_texcoord).rgb;
vec3 color_hdr = (sampled_color_hdr + bloom_color * bloom_amount) * exposure;
vec3 color_ldr_linear;
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);
}
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 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 = 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;
}

View File

@ -13,16 +13,16 @@ layout(binding=0) uniform trile_vs_params {
out vec3 cam;
out vec3 to_center;
out vec3 vpos; // The actual position;
out vec3 ipos; // Trile space position;
out vec3 vpos;
out vec3 ipos;
out vec4 fnormal;
out vec3 orig_normal; // Unrotated object-space normal, used for trixel lookup
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_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_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;
@ -46,8 +46,8 @@ void main() {
gl_Position = mvp * vec4(rotated + instance.xyz, 1.0);
fnormal = vec4(rot * normal.xyz, 0.0);
orig_normal = normal.xyz; // unrotated, for trixel lookup
to_center = centre.xyz - position.xyz; // unrotated, for trixel lookup
orig_normal = normal.xyz;
to_center = centre.xyz - position.xyz;
vpos = rotated + instance.xyz;
ipos = position.xyz;
cam = camera;
@ -117,116 +117,68 @@ layout(binding = 4) uniform texture2D rdm_atlas;
layout(binding = 5) uniform texture2D brdf_lut;
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 cumulus = 20.0;
float hash(float n)
{
float hash(float n) {
return fract(sin(n) * 43758.5453123);
}
float noise(vec3 x)
{
float noise(vec3 x) {
vec3 f = fract(x);
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),
mix(hash(n + 157.0), hash(n + 158.0), f.x), f.y),
mix(mix(hash(n + 113.0), hash(n + 114.0), f.x),
mix(hash(n + 270.0), hash(n + 271.0), f.x), f.y), f.z);
mix(hash(n + 157.0), hash(n + 158.0), f.x), f.y),
mix(mix(hash(n + 113.0), hash(n + 114.0), f.x),
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 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
);
}
const mat3 fbm_m = mat3(0.0, 1.60, 1.20, -1.6, 0.72, -0.96, -1.2, -0.96, 1.28);
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);
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;
final += sunHalo.xyz * clamp((sDist - 0.95) * 10.0, 0.0, 0.8) * 0.2;
if (sDist > 0.9999)
result = sunDisk;
// Sun disk
if(sDist > 0.9999) {
final = sunDisk.xyz;
}
// Horizon halo
final += mix(horizonHalo.xyz, vec3(0.0,0.0,0.0), clamp(abs(npos.y) * 80.0, 0.0, 1.0)) * 0.1;
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;
result += mix(horizonHalo, vec3(0.0), clamp(abs(npos.y) * 80.0, 0.0, 1.0)) * 0.1;
return result;
}
// ---- PBR FUNCTIONS ----
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);
}
// ---- PBR ----
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 NdotH2 = NdotH*NdotH;
float num = a2;
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 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 ggx2 = GeometrySchlickGGX(NdotV, roughness);
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
float ggx1 = NdotL / (NdotL * (1.0 - k) + k);
float ggx2 = NdotV / (NdotV * (1.0 - k) + k);
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);
}
// ---- RDM FUNCTIONS ----
// ---- RDM HELPERS ----
float roughness_to_rdm_size(int roughness) {
return pow(2.0, float((7 - roughness) + 1));
}
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) {
// Hemioct encoding (Cigolle2014)
vec2 rdm_hemioct(vec3 v, int face) {
vec3 vc = v;
if(index / 2 == 0) {
vc.z = v.y;
vc.y = v.z;
}
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);
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));
vec2 res = vec2(p.x + p.y, p.x - p.y);
res.x = (res.x + 1.0) * 0.5;
res.y = (res.y + 1.0) * 0.5;
return res;
return vec2(p.x + p.y, p.x - p.y) * 0.5 + 0.5;
}
float rdm_offset_y(int index) {
return float((index / 2)) * (1.0/3.0);
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;
}
float rdm_offset_x(int index) {
return float((index % 2)) * (1.0/2.0);
}
vec4 rdm_get_atlas_rect(ivec3 local_pos, int roughness) {
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;
int tx = rdm_index % 512;
int ty = rdm_index / 512;
return texelFetch(sampler2D(rdm_lookup, trilesmp), ivec2(tx, ty), 0);
return texelFetch(sampler2D(rdm_lookup, trilesmp), ivec2(rdm_index % 512, rdm_index / 512), 0);
}
ivec2 rdm_face_pixel_offset(vec4 atlas_rect, int face, int rdmSize) {
ivec2 atlasSize = textureSize(sampler2D(rdm_atlas, rdmsmp), 0);
ivec2 rdm_face_offset(vec4 rect, int face, int rdmSize, ivec2 atlasSize) {
int col = face % 2;
int row = face / 2;
int ox = int(atlas_rect.x * float(atlasSize.x)) + col * rdmSize;
int oy = int(atlas_rect.y * float(atlasSize.y)) + row * rdmSize;
return ivec2(ox, oy);
return ivec2(int(rect.x * float(atlasSize.x)) + col * rdmSize,
int(rect.y * float(atlasSize.y)) + row * rdmSize);
}
vec3 sample_rdm(vec3 N, vec3 V, vec3 rdm_center, vec3 diff, int roughness, ivec3 local_pos) {
int face = rdm_index_from_normal(N);
vec4 atlas_rect = rdm_get_atlas_rect(local_pos, roughness);
if (atlas_rect.z <= 0.0) return vec3(1.0, 0.0, 1.0); // No data - magenta
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);
}
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));
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;
}
// ---- 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 = maxDist * float(i + 1) / float(steps);
float t = stepSize * float(i + 1);
vec3 samplePos = diff + t * reflected;
if (dot(samplePos, N) < 0.0) continue;
vec2 hemiUV = rdm_get_hemioct(normalize(samplePos), face, vec2(0.0));
vec2 atlasSize = vec2(textureSize(sampler2D(rdm_atlas, rdmsmp), 0));
vec2 texCoord = (vec2(faceOffset) + hemiUV * rdmSize) / atlasSize;
vec4 rdmSample = texture(sampler2D(rdm_atlas, rdmsmp), texCoord, 0);
float depth = rdmSample.a;
float dist = length(samplePos);
float stepSize = maxDist / float(steps);
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);
if (depth > 0.0 && depth < dist && depth + stepSize > dist) {
return rdmSample.rgb;
}
float dist = length(samplePos);
if (s.a > 0.0 && s.a < dist && s.a + stepSize > dist)
return s.rgb;
}
vec3 skyDir = reflected;
if (skyDir.y < 0.0) skyDir = reflect(skyDir, vec3(0.0, 1.0, 0.0));
return sky(skyDir, sunPosition);
return sky_reflect(reflected, sunPosition);
}
vec3 sample_rdm_diff_map(vec3 N, ivec3 local_pos, vec3 fallback) {
vec4 atlas_rect = rdm_get_atlas_rect(local_pos, 7);
if (atlas_rect.z <= 0.0) return fallback;
int face = rdm_index_from_normal(N);
int rdmSize = int(roughness_to_rdm_size(7));
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;
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;
}
int isign(float f) {
return f < 0.0 ? -1 : 1;
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 smoothT = pow(t, power) / (pow(t, power) + pow(1.0 - t, power));
return mix(a, b, smoothT);
float st = pow(t, power) / (pow(t, power) + pow(1.0 - t, power));
return mix(a, b, st);
}
vec3 sample_rdm_diff(vec3 N, vec3 diff, ivec3 local_pos) {
int face = rdm_index_from_normal(N);
vec3 ambientPlaceholder = vec3(0.3, 0.3, 0.4);
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 = vec2(0.0);
if (face == 0 || face == 1) {
delta = vec2(diff.x, diff.z);
} else if (face == 2 || face == 3) {
delta = vec2(diff.x, diff.y);
} else {
delta = vec2(diff.z, diff.y);
}
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 s0 = ivec3(0, 0, 0);
ivec3 s1, s2, s3;
if (face == 0 || face == 1) {
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 == 2 || face == 3) {
} 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);
@ -417,18 +308,18 @@ vec3 sample_rdm_diff(vec3 N, vec3 diff, ivec3 local_pos) {
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 p1 = sample_rdm_diff_map(N, ivec3(mod(vec3(local_pos + s1), 32.0)), ambientPlaceholder);
vec3 p2 = sample_rdm_diff_map(N, ivec3(mod(vec3(local_pos + s2), 32.0)), ambientPlaceholder);
vec3 p3 = sample_rdm_diff_map(N, ivec3(mod(vec3(local_pos + s3), 32.0)), ambientPlaceholder);
vec3 p0 = rdm_sample_diff_probe(N, ivec3(mod(vec3(local_pos), 32.0)), ambient);
vec3 p1 = rdm_sample_diff_probe(N, ivec3(mod(vec3(local_pos + s1), 32.0)), ambient);
vec3 p2 = rdm_sample_diff_probe(N, ivec3(mod(vec3(local_pos + s2), 32.0)), ambient);
vec3 p3 = rdm_sample_diff_probe(N, ivec3(mod(vec3(local_pos + s1 + s2),32.0)), ambient);
return smix(
smix(p0, p1, abs(delta.x)),
smix(p2, p3, abs(delta.x)),
abs(delta.y)
);
return smix(smix(p0, p1, abs(delta.x)),
smix(p2, p3, abs(delta.x)),
abs(delta.y));
}
// ---- 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));
@ -444,140 +335,146 @@ vec3 hsv2rgb(vec3 c) {
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;
}
if (vpos.y < planeHeight - 0.01 && is_reflection == 1) discard;
// Trixel material sampling
vec3 pos_after_adjust = ipos - orig_normal * 0.02;
int count = 0;
Get trixel material.
vec3 sample_pos = ipos - orig_normal * 0.02;
vec4 trixel_material;
while (count < 5) {
int xpos = int(clamp(pos_after_adjust.z, 0.0001, 0.99999) * 16.0);
int ypos = int(clamp(pos_after_adjust.y, 0.0001, 0.99999) * 16.0);
int zpos = int(clamp(pos_after_adjust.x, 0.0001, 0.99999) * 16.0);
trixel_material = texelFetch(sampler2D(triletex, trilesmp), ivec2(xpos, ypos + zpos * 16), 0);
if (length(trixel_material) > 0.01) break;
pos_after_adjust += to_center * 0.1;
count++;
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(triletex, trilesmp), texel, 0);
if (dot(trixel_material, trixel_material) > 0.0001) break;
sample_pos += to_center * 0.1;
}
vec3 albedo = trixel_material.xyz;
int packedMaterial = int(round(trixel_material.w * 255.0));
float emittance = 0.0;
int roughnessInt = 0;
float roughness = 0.05;
float metallic = 0.0;
if ((packedMaterial & 0x1) != 0) {
emittance = float((packedMaterial >> 1) & 0x7F) / 127.0;
vec3 albedo = vec3(1.0, 1.0, 1.0);
int packed = int(round(trixel_material.w * 255.0));
float emittance = 0.0;
int roughnessInt = 7;
float roughness = 1.0;
float metallic = 0.0;
if ((packed & 0x1) != 0) {
emittance = float((packed >> 1) & 0x7F) / 127.0;
} else {
roughnessInt = (packedMaterial >> 5) & 0x7;
roughnessInt = (packed >> 5) & 0x7;
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 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 (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);
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 H = normalize(V + L);
vec3 F0 = vec3(0.04);
F0 = mix(F0, albedo, metallic);
vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0);
float NDF = DistributionGGX(N, H, 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;
float NdotV = max(dot(N, V), 0.0);
float HdotV = max(dot(H, V), 0.0);
// Shadow
vec4 light_proj_pos = mvp_shadow * vec4(floor(vpos.xyz * 16.0) / 16.0, 1.0);
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);
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);
// Direct lighting
vec3 light = shadowp * (kD * albedo / PI + specular) * NdotL * sunLightColor * sunIntensity;
vec3 specular = (NDF * G * F) / (4.0 * NdotV * NdotL + 0.0001);
vec3 kD = (1.0 - F) * (1.0 - metallic);
// RDM indirect lighting
vec3 hemispherePos = trileCenter + N * 0.49;
// Shadow lookup.
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);
vec3 light = shadow * (kD * albedo / PI + specular) * NdotL * sunLightColor * sunIntensity;
// --- Indirect lighting ---
ivec3 local = ivec3(mod(floor(trileCenter), 32.0));
vec4 atlas_rect_check = rdm_get_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;
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;
// Emissive — self-lit, not shadowed.
vec3 emissive = albedo * emittance * emissive_scale;
if (rdm_enabled == 1 && atlas_rect_check.z > 0.0) {
vec3 Frough = FresnelSchlickRoughness(max(dot(N, V), 0.0), F0, roughness);
if (rdm_enabled == 100 && atlas_rect.z > 0.0) {
vec3 Frough = FresnelSchlickRoughness(NdotV, F0, roughness);
vec3 hemispherePos = trileCenter + N * 0.49;
vec3 diff = vpos - hemispherePos;
// Indirect specular
vec3 indirectSpec = sample_rdm(N, -cv,
hemispherePos, vpos - hemispherePos, roughnessInt, local) * rdm_tint;
if (roughness < ROUGHNESS_SPEC_CUTOFF) {
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
// as F0 for metals) applies the metal tint cleanly without double-tinting.
float specLum = dot(indirectSpec, vec3(0.2126, 0.7152, 0.0722));
indirectSpec = mix(indirectSpec, vec3(specLum), metallic);
vec3 indirectSpec;
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;
vec2 envBRDF = texture(sampler2D(brdf_lut, rdmsmp), vec2(max(dot(N, V), 0.0), roughness)).rg;
float NdotV_s = max(dot(N, V), 0.0);
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 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;
// Desaturate for metals to avoid double-tinting
float specLum = dot(indirectSpec, vec3(0.2126, 0.7152, 0.0722));
indirectSpec = mix(indirectSpec, vec3(specLum), metallic);
// Indirect diffuse (interpolated from neighbor probes)
vec3 indirectDiff = sample_rdm_diff(N, vpos - hemispherePos, local) * rdm_tint;
vec2 envBRDF = texture(sampler2D(brdf_lut, rdmsmp), vec2(NdotV, roughness)).rg;
float roughnessBell = 1.0 - 0.7 * sin(roughness * PI);
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);
light += indirectSpec * (Frough * envBRDF.x + envBRDF.y)
* 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));
indirectDiff = mix(vec3(diffLuma), indirectDiff, rdm_diff_saturation);
vec3 kDiff = 1.0 - Frough;
kDiff *= 1.0 - metallic;
light += (kDiff * indirectDiff / PI * albedo) * ssao_sample * rdm_diff_scale;
if (rdm_diff_scale < 0.001) {
light += ambient_color * ambient_intensity * albedo * ssao_sample;
}
if (length(light) < ambient_intensity) {
light += ambient_color * (ambient_intensity - length(light)) * albedo * ssao_sample;
}
vec3 kDiff = (1.0 - Frough) * (1.0 - metallic);
light += kDiff * indirectDiff / PI * albedo * ssao * rdm_diff_scale;
// Ambient floor
if (rdm_diff_scale < 0.001 || length(light) < ambient_intensity)
light += ambient_color * max(ambient_intensity - length(light), 0.0) * albedo * ssao;
} else {
// Fallback: ambient + sky reflection when no RDM data (or RDM disabled).
light += ambient_color * ambient_intensity * albedo * ssao_sample;
light += ambient_color * ambient_intensity * albedo * ssao;
vec3 R = reflect(-V, N);
if (R.y < 0.0) R = reflect(R, vec3(0.0, 1.0, 0.0));
light += F * sky(R, sunPosition) * 0.1;
light += F * sky_reflect(R, sunPosition) * 0.1;
}
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);
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);
}
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