From 546067fda7e0a961ddf9598f2739a736bb402a80 Mon Sep 17 00:00:00 2001 From: katajisto Date: Sun, 19 Oct 2025 21:35:31 +0300 Subject: [PATCH] work on geometry pass for SSAO --- src/editor/textureDebugger.jai | 4 +- src/rendering/backend.jai | 1 + src/rendering/backend_sokol.jai | 54 ++- src/rendering/pipelines.jai | 86 ++++ src/rendering/tasks.jai | 1 + src/shaders/jai/shader_gbuffer.jai | 457 ++++++++++++++++++ src/shaders/shader_gbuffer.glsl | 39 ++ .../UserInterfaceState.xcuserstate | Bin 21881 -> 31788 bytes .../xcshareddata/xcschemes/trueno.xcscheme | 10 +- 9 files changed, 645 insertions(+), 7 deletions(-) create mode 100644 src/shaders/jai/shader_gbuffer.jai create mode 100644 src/shaders/shader_gbuffer.glsl diff --git a/src/editor/textureDebugger.jai b/src/editor/textureDebugger.jai index e28a7ba..795d810 100644 --- a/src/editor/textureDebugger.jai +++ b/src/editor/textureDebugger.jai @@ -7,7 +7,7 @@ theme_ptr : GR.Overall_Theme; current_pipeline : s32 = 0; current_slot : s32 = 0; -pipeline_names : []string = .["shadowmap", "reflection", "main"]; +pipeline_names : []string = .["shadowmap", "reflection", "main", "position", "normal"]; draw_subwindow_texture_debug :: (state: *GR.Subwindow_State, r: GR.Rect, data: *void) { r2 := r; @@ -27,6 +27,8 @@ draw_subwindow_texture_debug :: (state: *GR.Subwindow_State, r: GR.Rect, data: * case 0; image = g_shadowmap_img; case 1; image = gPipelines.plane.bind.images[0]; case 2; image = g_rendertex; + case 3; image = g_gbuf_position; + case 4; image = g_gbuf_normal; } uiTex.tex = image; diff --git a/src/rendering/backend.jai b/src/rendering/backend.jai index 5b7cd44..08ab13a 100644 --- a/src/rendering/backend.jai +++ b/src/rendering/backend.jai @@ -5,6 +5,7 @@ Render_Command_Buckets :: struct { shadow : [..]*Render_Command; reflection : [..]*Render_Command; main : [..]*Render_Command; + gbuffer : [..]*Render_Command; ui : [..]*Render_Command; } diff --git a/src/rendering/backend_sokol.jai b/src/rendering/backend_sokol.jai index 10cf94e..5e62cae 100644 --- a/src/rendering/backend_sokol.jai +++ b/src/rendering/backend_sokol.jai @@ -8,6 +8,7 @@ current_trile_offset_index : s32 = 0; current_world_config : *World_Config = null; in_shadowmap_pass : bool = false; in_reflection_pass : bool = false; +in_gbuffer_pass : bool = false; shadow_mvp : Matrix4; backend_handle_command :: (cmd: *Render_Command) { @@ -98,6 +99,42 @@ backend_add_trile_positions :: (positions : []Vector4) { } backend_draw_trile_positions :: (trile : string, amount : s32, worldConf: *World_Config) { + if in_gbuffer_pass { + backend_draw_trile_positions_gbuffer(trile, amount, worldConf); + } else { + backend_draw_trile_positions_main(trile, amount, worldConf); + } +} + +backend_draw_trile_positions_gbuffer :: (trile : string, amount : s32, worldConf: *World_Config) { + mvp := create_viewproj(*camera); + view := create_lookat(*camera); + vs_params : Gbuffer_Vs_Params; + vs_params.mvp = mvp.floats; + vs_params.view_matrix = view.floats; + sg_apply_pipeline(gPipelines.gbuffer.pipeline); + world_conf : Trile_World_Config; + world_config_to_shader_type(worldConf, *world_conf); + + offset := trile_offsets[current_trile_offset_index]; + current_trile_offset_index += 1; + + trilegfx := get_trile_gfx(trile); + bindings : sg_bindings; + bindings.vertex_buffers[0] = trilegfx.vertex_buffer; + bindings.vertex_buffers[1] = trilegfx.normal_buffer; + bindings.vertex_buffers[2] = trilegfx.centre_buffer; + bindings.vertex_buffers[3] = gPipelines.trile.bind.vertex_buffers[3]; + bindings.vertex_buffer_offsets[3] = offset; + bindings.samplers[0] = gPipelines.trile.bind.samplers[0]; + bindings.images[0] = trilegfx.trixel_colors; + + sg_apply_bindings(*bindings); + sg_apply_uniforms(UB_gbuffer_vs_params, *(sg_range.{ ptr = *vs_params, size = size_of(type_of(vs_params))})); + sg_draw(0, cast(s32) trilegfx.vertex_count, amount); +} + +backend_draw_trile_positions_main :: (trile : string, amount : s32, worldConf: *World_Config) { mvp : Matrix4; if !in_shadowmap_pass { mvp = create_viewproj(*camera); @@ -108,7 +145,7 @@ backend_draw_trile_positions :: (trile : string, amount : s32, worldConf: *World vs_params : Trile_Vs_Params; vs_params.mvp = mvp.floats; vs_params.camera = camera.position.component; - sg_apply_pipeline(gPipelines.trile.pipeline); + sg_apply_pipeline(gPipelines.trile.pipeline); world_conf : Trile_World_Config; world_config_to_shader_type(worldConf, *world_conf); @@ -128,15 +165,12 @@ backend_draw_trile_positions :: (trile : string, amount : s32, worldConf: *World fs_params : Trile_Fs_Params; fs_params.mvp_shadow = shadow_mvp.floats; fs_params.is_reflection = ifx in_reflection_pass then cast(s32)1 else cast(s32)0; - sg_apply_bindings(*bindings); sg_apply_uniforms(UB_trile_fs_params, *(sg_range.{ ptr = *fs_params, size = size_of(type_of(fs_params)) })); sg_apply_uniforms(UB_trile_vs_params, *(sg_range.{ ptr = *vs_params, size = size_of(type_of(vs_params))})); sg_apply_uniforms(UB_trile_world_config, *(sg_range.{ptr = *world_conf, size = size_of(type_of(world_conf))})); sg_draw(0, cast(s32) trilegfx.vertex_count, amount); - } - backend_draw_sky :: (wc: *World_Config) { mvp := create_viewproj(*camera); vs_params : Sky_Vs_Params; @@ -211,6 +245,7 @@ backend_process_command_buckets :: () { sg_end_pass(); current_trile_offset_index = 0; // This is not optimal, but it is nice and simple. + // 3. Main pass sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, attachments = g_rendertex_attachments})); for render_command_buckets.main { @@ -218,6 +253,16 @@ backend_process_command_buckets :: () { } sg_end_pass(); current_trile_offset_index = 0; // This is not optimal, but it is nice and simple. + + // 3. G-Buffer pass + in_gbuffer_pass = true; + sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, attachments = g_gbuf_attachments})); + for render_command_buckets.gbuffer { + backend_handle_command(it); + } + sg_end_pass(); + in_gbuffer_pass = false; + current_trile_offset_index = 0; // This is not optimal, but it is nice and simple. // Begin main pass sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, swapchain = cast,force(sg_swapchain) sglue_swapchain() })); @@ -246,6 +291,7 @@ backend_process_command_buckets :: () { array_reset_keeping_memory(*render_command_buckets.shadow); array_reset_keeping_memory(*render_command_buckets.reflection); array_reset_keeping_memory(*render_command_buckets.main); + array_reset_keeping_memory(*render_command_buckets.gbuffer); array_reset_keeping_memory(*render_command_buckets.ui); array_reset_keeping_memory(*trile_offsets); current_world_config = null; diff --git a/src/rendering/pipelines.jai b/src/rendering/pipelines.jai index abcedc8..b153cdc 100644 --- a/src/rendering/pipelines.jai +++ b/src/rendering/pipelines.jai @@ -18,7 +18,14 @@ g_rendertex : sg_image; g_rendertex_depth : sg_image; g_rendertex_attachments : sg_attachments; +g_gbuf_position : sg_image; +g_gbuf_normal : sg_image; +g_gbuf_depth : sg_image; +g_gbuf_attachments : sg_attachments; + gPipelines : struct { + // G-Buffer generation for SSAO and other effects + gbuffer: Pipeline_Binding; // Arbitrary triangle rendering for rendering 2D things on the screen. // Used for UI rendering. @@ -100,6 +107,8 @@ create_shadowmap_image :: () { } create_pipelines :: () { + create_gbuffer_images(); + create_gbuffer_pipeline(); create_arbtri_pipeline(); create_trixel_pipeline(); create_trile_pipeline(); @@ -111,6 +120,40 @@ create_pipelines :: () { create_final_image(); } +create_gbuffer_images :: () { + w,h := get_render_size(); + + if g_gbuf_position.id != INVALID_ID then sg_destroy_image(g_gbuf_position); + if g_gbuf_normal.id != INVALID_ID then sg_destroy_image(g_gbuf_normal); + if g_gbuf_depth.id != INVALID_ID then sg_destroy_image(g_gbuf_depth); + + img_desc := sg_image_desc.{ + width = w, + height = h, + pixel_format = .RGBA16F, + render_target = true, + }; + depth_desc := sg_image_desc.{ + width = w, + height = h, + pixel_format = .DEPTH, + render_target = true, + }; + + g_gbuf_position = sg_make_image(*img_desc); + g_gbuf_normal = sg_make_image(*img_desc); + g_gbuf_depth = sg_make_image(*depth_desc); + + attachmentsDesc : sg_attachments_desc; + attachmentsDesc = .{ + colors[0].image = g_gbuf_position, + colors[1].image = g_gbuf_normal, + depth_stencil.image = g_gbuf_depth, + }; + sg_destroy_attachments(g_gbuf_attachments); + g_gbuf_attachments = sg_make_attachments(*attachmentsDesc); +} + TRIXEL_SIZE_HALF : float : 1.0/32.0; TRIXEL_SIZE : float : 1.0/16.0; @@ -237,6 +280,49 @@ create_trixel_pipeline :: () { gPipelines.trixel.bind.vertex_buffers[2] = sg_make_buffer(*instance_buffer); } +create_gbuffer_pipeline :: () { + pipeline: sg_pipeline_desc; + shader_desc := gbuffer_shader_desc(sg_query_backend()); + pipeline.shader = sg_make_shader(*shader_desc); + pipeline.layout.buffers[0].stride = 4*3; + pipeline.layout.buffers[1].stride = 4*3; + + pipeline.layout.buffers[3].step_func = .PER_INSTANCE; + + instance_buffer := sg_buffer_desc.{ usage = .STREAM, size = 16 * 4096 * 4 * 4}; + + pipeline.layout.attrs[ATTR_trile_position] = .{ format = .FLOAT3, buffer_index = 0 }; + pipeline.layout.attrs[ATTR_trile_normal] = .{ format = .FLOAT3, buffer_index = 1 }; + pipeline.layout.attrs[ATTR_trile_centre] = .{ format = .FLOAT3, buffer_index = 2 }; + pipeline.layout.attrs[ATTR_trile_instance] = .{ format = .FLOAT4, buffer_index = 3 }; + pipeline.depth = .{ + write_enabled = true, + compare = .LESS_EQUAL, + pixel_format = .DEPTH, + }; + + color_state_pos := sg_color_target_state.{ + pixel_format = .RGBA16F, + }; + color_state_normal := sg_color_target_state.{ + pixel_format = .RGBA16F, + }; + + + pipeline.color_count = 2; + pipeline.colors[0] = color_state_pos; + pipeline.colors[1] = color_state_normal; + + gPipelines.gbuffer.pipeline = sg_make_pipeline(*pipeline); + gPipelines.gbuffer.bind.samplers[0] = sg_make_sampler(*(sg_sampler_desc.{ + wrap_u = .CLAMP_TO_EDGE, + wrap_v = .CLAMP_TO_EDGE, + min_filter = .NEAREST, + mag_filter = .NEAREST, + })); + gPipelines.gbuffer.bind.vertex_buffers[3] = sg_make_buffer(*instance_buffer); +} + create_trile_pipeline :: () { pipeline: sg_pipeline_desc; shader_desc := trile_shader_desc(sg_query_backend()); diff --git a/src/rendering/tasks.jai b/src/rendering/tasks.jai index 08058ef..93af1c3 100644 --- a/src/rendering/tasks.jai +++ b/src/rendering/tasks.jai @@ -103,6 +103,7 @@ tasks_to_commands :: () { drawPositionsCmd.conf = trileTask.worldConf; array_add(*render_command_buckets.reflection, drawPositionsCmd); array_add(*render_command_buckets.main, drawPositionsCmd); + array_add(*render_command_buckets.gbuffer, drawPositionsCmd); array_add(*render_command_buckets.shadow, drawPositionsCmd); case .SKY; command := New(Render_Command_Sky,, temp); diff --git a/src/shaders/jai/shader_gbuffer.jai b/src/shaders/jai/shader_gbuffer.jai new file mode 100644 index 0000000..d325169 --- /dev/null +++ b/src/shaders/jai/shader_gbuffer.jai @@ -0,0 +1,457 @@ +/* + #version:1# (machine generated, don't edit!) + + Generated by sokol-shdc (https://github.com/floooh/sokol-tools) + + Cmdline: + sokol-shdc -i shader_gbuffer.glsl -o ./jai/shader_gbuffer.jai -l glsl430:glsl300es:metal_macos -f sokol_jai + + Overview: + ========= + Shader program: 'gbuffer': + Get shader desc: gbuffer_shader_desc(sg_query_backend()) + Vertex Shader: vs_g + Fragment Shader: fs_g + Attributes: + ATTR_gbuffer_position => 0 + ATTR_gbuffer_normal => 1 + ATTR_gbuffer_centre => 2 + ATTR_gbuffer_instance => 3 + Bindings: + Uniform block 'gbuffer_vs_params': + Jai struct: Gbuffer_Vs_Params + Bind slot: UB_gbuffer_vs_params => 0 +*/ +ATTR_gbuffer_position :: 0; +ATTR_gbuffer_normal :: 1; +ATTR_gbuffer_centre :: 2; +ATTR_gbuffer_instance :: 3; +UB_gbuffer_vs_params :: 0; +Gbuffer_Vs_Params :: struct { + mvp: [16]float; + view_matrix: [16]float; +}; +/* + #version 430 + + uniform vec4 gbuffer_vs_params[8]; + layout(location = 0) in vec4 position; + layout(location = 3) in vec4 instance; + layout(location = 0) out vec3 view_space_pos; + layout(location = 1) out vec3 view_space_normal; + layout(location = 1) in vec4 normal; + layout(location = 2) in vec4 centre; + + void main() + { + vec4 _23 = vec4(position.xyz + instance.xyz, 1.0); + mat4 _33 = mat4(gbuffer_vs_params[4], gbuffer_vs_params[5], gbuffer_vs_params[6], gbuffer_vs_params[7]); + gl_Position = mat4(gbuffer_vs_params[0], gbuffer_vs_params[1], gbuffer_vs_params[2], gbuffer_vs_params[3]) * _23; + view_space_pos = (_33 * _23).xyz; + view_space_normal = mat3(_33[0].xyz, _33[1].xyz, _33[2].xyz) * normal.xyz; + } + +*/ +vs_g_source_glsl430 := u8.[ + 0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x34,0x33,0x30,0x0a,0x0a,0x75,0x6e, + 0x69,0x66,0x6f,0x72,0x6d,0x20,0x76,0x65,0x63,0x34,0x20,0x67,0x62,0x75,0x66,0x66, + 0x65,0x72,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x38,0x5d,0x3b, + 0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e, + 0x20,0x3d,0x20,0x30,0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x34,0x20,0x70,0x6f, + 0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c, + 0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x33,0x29,0x20,0x69,0x6e,0x20, + 0x76,0x65,0x63,0x34,0x20,0x69,0x6e,0x73,0x74,0x61,0x6e,0x63,0x65,0x3b,0x0a,0x6c, + 0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d, + 0x20,0x30,0x29,0x20,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x33,0x20,0x76,0x69,0x65, + 0x77,0x5f,0x73,0x70,0x61,0x63,0x65,0x5f,0x70,0x6f,0x73,0x3b,0x0a,0x6c,0x61,0x79, + 0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x31, + 0x29,0x20,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x33,0x20,0x76,0x69,0x65,0x77,0x5f, + 0x73,0x70,0x61,0x63,0x65,0x5f,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x3b,0x0a,0x6c,0x61, + 0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20, + 0x31,0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x34,0x20,0x6e,0x6f,0x72,0x6d,0x61, + 0x6c,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69, + 0x6f,0x6e,0x20,0x3d,0x20,0x32,0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x34,0x20, + 0x63,0x65,0x6e,0x74,0x72,0x65,0x3b,0x0a,0x0a,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,0x33,0x20,0x3d,0x20,0x76,0x65,0x63,0x34,0x28,0x70,0x6f,0x73,0x69,0x74, + 0x69,0x6f,0x6e,0x2e,0x78,0x79,0x7a,0x20,0x2b,0x20,0x69,0x6e,0x73,0x74,0x61,0x6e, + 0x63,0x65,0x2e,0x78,0x79,0x7a,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20, + 0x20,0x20,0x6d,0x61,0x74,0x34,0x20,0x5f,0x33,0x33,0x20,0x3d,0x20,0x6d,0x61,0x74, + 0x34,0x28,0x67,0x62,0x75,0x66,0x66,0x65,0x72,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72, + 0x61,0x6d,0x73,0x5b,0x34,0x5d,0x2c,0x20,0x67,0x62,0x75,0x66,0x66,0x65,0x72,0x5f, + 0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x35,0x5d,0x2c,0x20,0x67,0x62, + 0x75,0x66,0x66,0x65,0x72,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b, + 0x36,0x5d,0x2c,0x20,0x67,0x62,0x75,0x66,0x66,0x65,0x72,0x5f,0x76,0x73,0x5f,0x70, + 0x61,0x72,0x61,0x6d,0x73,0x5b,0x37,0x5d,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x67, + 0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x6d,0x61,0x74, + 0x34,0x28,0x67,0x62,0x75,0x66,0x66,0x65,0x72,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72, + 0x61,0x6d,0x73,0x5b,0x30,0x5d,0x2c,0x20,0x67,0x62,0x75,0x66,0x66,0x65,0x72,0x5f, + 0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x31,0x5d,0x2c,0x20,0x67,0x62, + 0x75,0x66,0x66,0x65,0x72,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b, + 0x32,0x5d,0x2c,0x20,0x67,0x62,0x75,0x66,0x66,0x65,0x72,0x5f,0x76,0x73,0x5f,0x70, + 0x61,0x72,0x61,0x6d,0x73,0x5b,0x33,0x5d,0x29,0x20,0x2a,0x20,0x5f,0x32,0x33,0x3b, + 0x0a,0x20,0x20,0x20,0x20,0x76,0x69,0x65,0x77,0x5f,0x73,0x70,0x61,0x63,0x65,0x5f, + 0x70,0x6f,0x73,0x20,0x3d,0x20,0x28,0x5f,0x33,0x33,0x20,0x2a,0x20,0x5f,0x32,0x33, + 0x29,0x2e,0x78,0x79,0x7a,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x69,0x65,0x77,0x5f, + 0x73,0x70,0x61,0x63,0x65,0x5f,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x20,0x3d,0x20,0x6d, + 0x61,0x74,0x33,0x28,0x5f,0x33,0x33,0x5b,0x30,0x5d,0x2e,0x78,0x79,0x7a,0x2c,0x20, + 0x5f,0x33,0x33,0x5b,0x31,0x5d,0x2e,0x78,0x79,0x7a,0x2c,0x20,0x5f,0x33,0x33,0x5b, + 0x32,0x5d,0x2e,0x78,0x79,0x7a,0x29,0x20,0x2a,0x20,0x6e,0x6f,0x72,0x6d,0x61,0x6c, + 0x2e,0x78,0x79,0x7a,0x3b,0x0a,0x7d,0x0a,0x0a,0x00, +]; +/* + #version 430 + + layout(location = 0) out vec4 out_position; + layout(location = 0) in vec3 view_space_pos; + layout(location = 1) out vec4 out_normal; + layout(location = 1) in vec3 view_space_normal; + + void main() + { + out_position = vec4(view_space_pos, 1.0); + out_normal = vec4(normalize(view_space_normal), 1.0); + } + +*/ +fs_g_source_glsl430 := u8.[ + 0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x34,0x33,0x30,0x0a,0x0a,0x6c,0x61, + 0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20, + 0x30,0x29,0x20,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x34,0x20,0x6f,0x75,0x74,0x5f, + 0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74, + 0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29,0x20,0x69, + 0x6e,0x20,0x76,0x65,0x63,0x33,0x20,0x76,0x69,0x65,0x77,0x5f,0x73,0x70,0x61,0x63, + 0x65,0x5f,0x70,0x6f,0x73,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f, + 0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x31,0x29,0x20,0x6f,0x75,0x74,0x20, + 0x76,0x65,0x63,0x34,0x20,0x6f,0x75,0x74,0x5f,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x3b, + 0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e, + 0x20,0x3d,0x20,0x31,0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x33,0x20,0x76,0x69, + 0x65,0x77,0x5f,0x73,0x70,0x61,0x63,0x65,0x5f,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x3b, + 0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a, + 0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e, + 0x20,0x3d,0x20,0x76,0x65,0x63,0x34,0x28,0x76,0x69,0x65,0x77,0x5f,0x73,0x70,0x61, + 0x63,0x65,0x5f,0x70,0x6f,0x73,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20, + 0x20,0x20,0x6f,0x75,0x74,0x5f,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x20,0x3d,0x20,0x76, + 0x65,0x63,0x34,0x28,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x69,0x7a,0x65,0x28,0x76,0x69, + 0x65,0x77,0x5f,0x73,0x70,0x61,0x63,0x65,0x5f,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x29, + 0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00, +]; +/* + #version 300 es + + uniform vec4 gbuffer_vs_params[8]; + layout(location = 0) in vec4 position; + layout(location = 3) in vec4 instance; + out vec3 view_space_pos; + out vec3 view_space_normal; + layout(location = 1) in vec4 normal; + layout(location = 2) in vec4 centre; + + void main() + { + vec4 _23 = vec4(position.xyz + instance.xyz, 1.0); + mat4 _33 = mat4(gbuffer_vs_params[4], gbuffer_vs_params[5], gbuffer_vs_params[6], gbuffer_vs_params[7]); + gl_Position = mat4(gbuffer_vs_params[0], gbuffer_vs_params[1], gbuffer_vs_params[2], gbuffer_vs_params[3]) * _23; + view_space_pos = (_33 * _23).xyz; + view_space_normal = mat3(_33[0].xyz, _33[1].xyz, _33[2].xyz) * normal.xyz; + } + +*/ +vs_g_source_glsl300es := u8.[ + 0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x33,0x30,0x30,0x20,0x65,0x73,0x0a, + 0x0a,0x75,0x6e,0x69,0x66,0x6f,0x72,0x6d,0x20,0x76,0x65,0x63,0x34,0x20,0x67,0x62, + 0x75,0x66,0x66,0x65,0x72,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b, + 0x38,0x5d,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74, + 0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x34, + 0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75, + 0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x33,0x29,0x20, + 0x69,0x6e,0x20,0x76,0x65,0x63,0x34,0x20,0x69,0x6e,0x73,0x74,0x61,0x6e,0x63,0x65, + 0x3b,0x0a,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x33,0x20,0x76,0x69,0x65,0x77,0x5f, + 0x73,0x70,0x61,0x63,0x65,0x5f,0x70,0x6f,0x73,0x3b,0x0a,0x6f,0x75,0x74,0x20,0x76, + 0x65,0x63,0x33,0x20,0x76,0x69,0x65,0x77,0x5f,0x73,0x70,0x61,0x63,0x65,0x5f,0x6e, + 0x6f,0x72,0x6d,0x61,0x6c,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f, + 0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x31,0x29,0x20,0x69,0x6e,0x20,0x76, + 0x65,0x63,0x34,0x20,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x3b,0x0a,0x6c,0x61,0x79,0x6f, + 0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x32,0x29, + 0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x34,0x20,0x63,0x65,0x6e,0x74,0x72,0x65,0x3b, + 0x0a,0x0a,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,0x33,0x20,0x3d,0x20,0x76, + 0x65,0x63,0x34,0x28,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2e,0x78,0x79,0x7a, + 0x20,0x2b,0x20,0x69,0x6e,0x73,0x74,0x61,0x6e,0x63,0x65,0x2e,0x78,0x79,0x7a,0x2c, + 0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6d,0x61,0x74,0x34,0x20, + 0x5f,0x33,0x33,0x20,0x3d,0x20,0x6d,0x61,0x74,0x34,0x28,0x67,0x62,0x75,0x66,0x66, + 0x65,0x72,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x34,0x5d,0x2c, + 0x20,0x67,0x62,0x75,0x66,0x66,0x65,0x72,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61, + 0x6d,0x73,0x5b,0x35,0x5d,0x2c,0x20,0x67,0x62,0x75,0x66,0x66,0x65,0x72,0x5f,0x76, + 0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x36,0x5d,0x2c,0x20,0x67,0x62,0x75, + 0x66,0x66,0x65,0x72,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x37, + 0x5d,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74, + 0x69,0x6f,0x6e,0x20,0x3d,0x20,0x6d,0x61,0x74,0x34,0x28,0x67,0x62,0x75,0x66,0x66, + 0x65,0x72,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d,0x2c, + 0x20,0x67,0x62,0x75,0x66,0x66,0x65,0x72,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61, + 0x6d,0x73,0x5b,0x31,0x5d,0x2c,0x20,0x67,0x62,0x75,0x66,0x66,0x65,0x72,0x5f,0x76, + 0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x32,0x5d,0x2c,0x20,0x67,0x62,0x75, + 0x66,0x66,0x65,0x72,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x33, + 0x5d,0x29,0x20,0x2a,0x20,0x5f,0x32,0x33,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x69, + 0x65,0x77,0x5f,0x73,0x70,0x61,0x63,0x65,0x5f,0x70,0x6f,0x73,0x20,0x3d,0x20,0x28, + 0x5f,0x33,0x33,0x20,0x2a,0x20,0x5f,0x32,0x33,0x29,0x2e,0x78,0x79,0x7a,0x3b,0x0a, + 0x20,0x20,0x20,0x20,0x76,0x69,0x65,0x77,0x5f,0x73,0x70,0x61,0x63,0x65,0x5f,0x6e, + 0x6f,0x72,0x6d,0x61,0x6c,0x20,0x3d,0x20,0x6d,0x61,0x74,0x33,0x28,0x5f,0x33,0x33, + 0x5b,0x30,0x5d,0x2e,0x78,0x79,0x7a,0x2c,0x20,0x5f,0x33,0x33,0x5b,0x31,0x5d,0x2e, + 0x78,0x79,0x7a,0x2c,0x20,0x5f,0x33,0x33,0x5b,0x32,0x5d,0x2e,0x78,0x79,0x7a,0x29, + 0x20,0x2a,0x20,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x2e,0x78,0x79,0x7a,0x3b,0x0a,0x7d, + 0x0a,0x0a,0x00, +]; +/* + #version 300 es + precision mediump float; + precision highp int; + + layout(location = 0) out highp vec4 out_position; + in highp vec3 view_space_pos; + layout(location = 1) out highp vec4 out_normal; + in highp vec3 view_space_normal; + + void main() + { + out_position = vec4(view_space_pos, 1.0); + out_normal = vec4(normalize(view_space_normal), 1.0); + } + +*/ +fs_g_source_glsl300es := u8.[ + 0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x33,0x30,0x30,0x20,0x65,0x73,0x0a, + 0x70,0x72,0x65,0x63,0x69,0x73,0x69,0x6f,0x6e,0x20,0x6d,0x65,0x64,0x69,0x75,0x6d, + 0x70,0x20,0x66,0x6c,0x6f,0x61,0x74,0x3b,0x0a,0x70,0x72,0x65,0x63,0x69,0x73,0x69, + 0x6f,0x6e,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x69,0x6e,0x74,0x3b,0x0a,0x0a,0x6c, + 0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d, + 0x20,0x30,0x29,0x20,0x6f,0x75,0x74,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x76,0x65, + 0x63,0x34,0x20,0x6f,0x75,0x74,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b, + 0x0a,0x69,0x6e,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x76,0x65,0x63,0x33,0x20,0x76, + 0x69,0x65,0x77,0x5f,0x73,0x70,0x61,0x63,0x65,0x5f,0x70,0x6f,0x73,0x3b,0x0a,0x6c, + 0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d, + 0x20,0x31,0x29,0x20,0x6f,0x75,0x74,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x76,0x65, + 0x63,0x34,0x20,0x6f,0x75,0x74,0x5f,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x3b,0x0a,0x69, + 0x6e,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x76,0x65,0x63,0x33,0x20,0x76,0x69,0x65, + 0x77,0x5f,0x73,0x70,0x61,0x63,0x65,0x5f,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x3b,0x0a, + 0x0a,0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20, + 0x20,0x20,0x20,0x6f,0x75,0x74,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20, + 0x3d,0x20,0x76,0x65,0x63,0x34,0x28,0x76,0x69,0x65,0x77,0x5f,0x73,0x70,0x61,0x63, + 0x65,0x5f,0x70,0x6f,0x73,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20, + 0x20,0x6f,0x75,0x74,0x5f,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x20,0x3d,0x20,0x76,0x65, + 0x63,0x34,0x28,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x69,0x7a,0x65,0x28,0x76,0x69,0x65, + 0x77,0x5f,0x73,0x70,0x61,0x63,0x65,0x5f,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x29,0x2c, + 0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00, +]; +/* + #include + #include + + using namespace metal; + + struct gbuffer_vs_params + { + float4x4 mvp; + float4x4 view_matrix; + }; + + struct main0_out + { + float3 view_space_pos [[user(locn0)]]; + float3 view_space_normal [[user(locn1)]]; + float4 gl_Position [[position]]; + }; + + struct main0_in + { + float4 position [[attribute(0)]]; + float4 normal [[attribute(1)]]; + float4 instance [[attribute(3)]]; + }; + + vertex main0_out main0(main0_in in [[stage_in]], constant gbuffer_vs_params& _28 [[buffer(0)]]) + { + main0_out out = {}; + float4 _23 = float4(in.position.xyz + in.instance.xyz, 1.0); + out.gl_Position = _28.mvp * _23; + out.view_space_pos = (_28.view_matrix * _23).xyz; + out.view_space_normal = float3x3(_28.view_matrix[0].xyz, _28.view_matrix[1].xyz, _28.view_matrix[2].xyz) * in.normal.xyz; + return out; + } + +*/ +vs_g_source_metal_macos := u8.[ + 0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x20,0x3c,0x6d,0x65,0x74,0x61,0x6c,0x5f, + 0x73,0x74,0x64,0x6c,0x69,0x62,0x3e,0x0a,0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65, + 0x20,0x3c,0x73,0x69,0x6d,0x64,0x2f,0x73,0x69,0x6d,0x64,0x2e,0x68,0x3e,0x0a,0x0a, + 0x75,0x73,0x69,0x6e,0x67,0x20,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x20, + 0x6d,0x65,0x74,0x61,0x6c,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x67, + 0x62,0x75,0x66,0x66,0x65,0x72,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73, + 0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x78,0x34,0x20, + 0x6d,0x76,0x70,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x78, + 0x34,0x20,0x76,0x69,0x65,0x77,0x5f,0x6d,0x61,0x74,0x72,0x69,0x78,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,0x33, + 0x20,0x76,0x69,0x65,0x77,0x5f,0x73,0x70,0x61,0x63,0x65,0x5f,0x70,0x6f,0x73,0x20, + 0x5b,0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,0x30,0x29,0x5d,0x5d,0x3b, + 0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x33,0x20,0x76,0x69,0x65,0x77, + 0x5f,0x73,0x70,0x61,0x63,0x65,0x5f,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x20,0x5b,0x5b, + 0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,0x31,0x29,0x5d,0x5d,0x3b,0x0a,0x20, + 0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73, + 0x69,0x74,0x69,0x6f,0x6e,0x20,0x5b,0x5b,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e, + 0x5d,0x5d,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d, + 0x61,0x69,0x6e,0x30,0x5f,0x69,0x6e,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c, + 0x6f,0x61,0x74,0x34,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x5b,0x5b, + 0x61,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x28,0x30,0x29,0x5d,0x5d,0x3b,0x0a, + 0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x6e,0x6f,0x72,0x6d,0x61, + 0x6c,0x20,0x5b,0x5b,0x61,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x28,0x31,0x29, + 0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x69, + 0x6e,0x73,0x74,0x61,0x6e,0x63,0x65,0x20,0x5b,0x5b,0x61,0x74,0x74,0x72,0x69,0x62, + 0x75,0x74,0x65,0x28,0x33,0x29,0x5d,0x5d,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x76,0x65, + 0x72,0x74,0x65,0x78,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,0x6d, + 0x61,0x69,0x6e,0x30,0x28,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x69,0x6e,0x20,0x69,0x6e, + 0x20,0x5b,0x5b,0x73,0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,0x5d,0x5d,0x2c,0x20,0x63, + 0x6f,0x6e,0x73,0x74,0x61,0x6e,0x74,0x20,0x67,0x62,0x75,0x66,0x66,0x65,0x72,0x5f, + 0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x26,0x20,0x5f,0x32,0x38,0x20,0x5b, + 0x5b,0x62,0x75,0x66,0x66,0x65,0x72,0x28,0x30,0x29,0x5d,0x5d,0x29,0x0a,0x7b,0x0a, + 0x20,0x20,0x20,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,0x6f,0x75, + 0x74,0x20,0x3d,0x20,0x7b,0x7d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61, + 0x74,0x34,0x20,0x5f,0x32,0x33,0x20,0x3d,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x28, + 0x69,0x6e,0x2e,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2e,0x78,0x79,0x7a,0x20, + 0x2b,0x20,0x69,0x6e,0x2e,0x69,0x6e,0x73,0x74,0x61,0x6e,0x63,0x65,0x2e,0x78,0x79, + 0x7a,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74, + 0x2e,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x5f, + 0x32,0x38,0x2e,0x6d,0x76,0x70,0x20,0x2a,0x20,0x5f,0x32,0x33,0x3b,0x0a,0x20,0x20, + 0x20,0x20,0x6f,0x75,0x74,0x2e,0x76,0x69,0x65,0x77,0x5f,0x73,0x70,0x61,0x63,0x65, + 0x5f,0x70,0x6f,0x73,0x20,0x3d,0x20,0x28,0x5f,0x32,0x38,0x2e,0x76,0x69,0x65,0x77, + 0x5f,0x6d,0x61,0x74,0x72,0x69,0x78,0x20,0x2a,0x20,0x5f,0x32,0x33,0x29,0x2e,0x78, + 0x79,0x7a,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,0x76,0x69,0x65,0x77, + 0x5f,0x73,0x70,0x61,0x63,0x65,0x5f,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x20,0x3d,0x20, + 0x66,0x6c,0x6f,0x61,0x74,0x33,0x78,0x33,0x28,0x5f,0x32,0x38,0x2e,0x76,0x69,0x65, + 0x77,0x5f,0x6d,0x61,0x74,0x72,0x69,0x78,0x5b,0x30,0x5d,0x2e,0x78,0x79,0x7a,0x2c, + 0x20,0x5f,0x32,0x38,0x2e,0x76,0x69,0x65,0x77,0x5f,0x6d,0x61,0x74,0x72,0x69,0x78, + 0x5b,0x31,0x5d,0x2e,0x78,0x79,0x7a,0x2c,0x20,0x5f,0x32,0x38,0x2e,0x76,0x69,0x65, + 0x77,0x5f,0x6d,0x61,0x74,0x72,0x69,0x78,0x5b,0x32,0x5d,0x2e,0x78,0x79,0x7a,0x29, + 0x20,0x2a,0x20,0x69,0x6e,0x2e,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x2e,0x78,0x79,0x7a, + 0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6f,0x75,0x74, + 0x3b,0x0a,0x7d,0x0a,0x0a,0x00, +]; +/* + #include + #include + + using namespace metal; + + struct main0_out + { + float4 out_position [[color(0)]]; + float4 out_normal [[color(1)]]; + }; + + struct main0_in + { + float3 view_space_pos [[user(locn0)]]; + float3 view_space_normal [[user(locn1)]]; + }; + + fragment main0_out main0(main0_in in [[stage_in]]) + { + main0_out out = {}; + out.out_position = float4(in.view_space_pos, 1.0); + out.out_normal = float4(fast::normalize(in.view_space_normal), 1.0); + return out; + } + +*/ +fs_g_source_metal_macos := u8.[ + 0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x20,0x3c,0x6d,0x65,0x74,0x61,0x6c,0x5f, + 0x73,0x74,0x64,0x6c,0x69,0x62,0x3e,0x0a,0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65, + 0x20,0x3c,0x73,0x69,0x6d,0x64,0x2f,0x73,0x69,0x6d,0x64,0x2e,0x68,0x3e,0x0a,0x0a, + 0x75,0x73,0x69,0x6e,0x67,0x20,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x20, + 0x6d,0x65,0x74,0x61,0x6c,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d, + 0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66, + 0x6c,0x6f,0x61,0x74,0x34,0x20,0x6f,0x75,0x74,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69, + 0x6f,0x6e,0x20,0x5b,0x5b,0x63,0x6f,0x6c,0x6f,0x72,0x28,0x30,0x29,0x5d,0x5d,0x3b, + 0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x6f,0x75,0x74,0x5f, + 0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x20,0x5b,0x5b,0x63,0x6f,0x6c,0x6f,0x72,0x28,0x31, + 0x29,0x5d,0x5d,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20, + 0x6d,0x61,0x69,0x6e,0x30,0x5f,0x69,0x6e,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66, + 0x6c,0x6f,0x61,0x74,0x33,0x20,0x76,0x69,0x65,0x77,0x5f,0x73,0x70,0x61,0x63,0x65, + 0x5f,0x70,0x6f,0x73,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e, + 0x30,0x29,0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x33, + 0x20,0x76,0x69,0x65,0x77,0x5f,0x73,0x70,0x61,0x63,0x65,0x5f,0x6e,0x6f,0x72,0x6d, + 0x61,0x6c,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,0x31,0x29, + 0x5d,0x5d,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x66,0x72,0x61,0x67,0x6d,0x65,0x6e,0x74, + 0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30, + 0x28,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x69,0x6e,0x20,0x69,0x6e,0x20,0x5b,0x5b,0x73, + 0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,0x5d,0x5d,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20, + 0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,0x6f,0x75,0x74,0x20,0x3d, + 0x20,0x7b,0x7d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,0x6f,0x75,0x74, + 0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x66,0x6c,0x6f,0x61, + 0x74,0x34,0x28,0x69,0x6e,0x2e,0x76,0x69,0x65,0x77,0x5f,0x73,0x70,0x61,0x63,0x65, + 0x5f,0x70,0x6f,0x73,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20, + 0x6f,0x75,0x74,0x2e,0x6f,0x75,0x74,0x5f,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x20,0x3d, + 0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x28,0x66,0x61,0x73,0x74,0x3a,0x3a,0x6e,0x6f, + 0x72,0x6d,0x61,0x6c,0x69,0x7a,0x65,0x28,0x69,0x6e,0x2e,0x76,0x69,0x65,0x77,0x5f, + 0x73,0x70,0x61,0x63,0x65,0x5f,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x29,0x2c,0x20,0x31, + 0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20, + 0x6f,0x75,0x74,0x3b,0x0a,0x7d,0x0a,0x0a,0x00, +]; +gbuffer_shader_desc :: (backend: sg_backend) -> sg_shader_desc { + desc: sg_shader_desc; + desc.label = "gbuffer_shader"; + if backend == { + case .GLCORE; + desc.vertex_func.source = xx *vs_g_source_glsl430; + desc.vertex_func.entry = "main"; + desc.fragment_func.source = xx *fs_g_source_glsl430; + desc.fragment_func.entry = "main"; + desc.attrs[0].base_type = .FLOAT; + desc.attrs[0].glsl_name = "position"; + desc.attrs[1].base_type = .FLOAT; + desc.attrs[1].glsl_name = "normal"; + desc.attrs[2].base_type = .FLOAT; + desc.attrs[2].glsl_name = "centre"; + desc.attrs[3].base_type = .FLOAT; + desc.attrs[3].glsl_name = "instance"; + desc.uniform_blocks[0].stage = .VERTEX; + desc.uniform_blocks[0].layout = .STD140; + desc.uniform_blocks[0].size = 128; + desc.uniform_blocks[0].glsl_uniforms[0].type = .FLOAT4; + desc.uniform_blocks[0].glsl_uniforms[0].array_count = 8; + desc.uniform_blocks[0].glsl_uniforms[0].glsl_name = "gbuffer_vs_params"; + case .GLES3; + desc.vertex_func.source = xx *vs_g_source_glsl300es; + desc.vertex_func.entry = "main"; + desc.fragment_func.source = xx *fs_g_source_glsl300es; + desc.fragment_func.entry = "main"; + desc.attrs[0].base_type = .FLOAT; + desc.attrs[0].glsl_name = "position"; + desc.attrs[1].base_type = .FLOAT; + desc.attrs[1].glsl_name = "normal"; + desc.attrs[2].base_type = .FLOAT; + desc.attrs[2].glsl_name = "centre"; + desc.attrs[3].base_type = .FLOAT; + desc.attrs[3].glsl_name = "instance"; + desc.uniform_blocks[0].stage = .VERTEX; + desc.uniform_blocks[0].layout = .STD140; + desc.uniform_blocks[0].size = 128; + desc.uniform_blocks[0].glsl_uniforms[0].type = .FLOAT4; + desc.uniform_blocks[0].glsl_uniforms[0].array_count = 8; + desc.uniform_blocks[0].glsl_uniforms[0].glsl_name = "gbuffer_vs_params"; + case .METAL_MACOS; + desc.vertex_func.source = xx *vs_g_source_metal_macos; + desc.vertex_func.entry = "main0"; + desc.fragment_func.source = xx *fs_g_source_metal_macos; + desc.fragment_func.entry = "main0"; + desc.attrs[0].base_type = .FLOAT; + desc.attrs[1].base_type = .FLOAT; + desc.attrs[2].base_type = .FLOAT; + desc.attrs[3].base_type = .FLOAT; + desc.uniform_blocks[0].stage = .VERTEX; + desc.uniform_blocks[0].layout = .STD140; + desc.uniform_blocks[0].size = 128; + desc.uniform_blocks[0].msl_buffer_n = 0; + } + return desc; +} diff --git a/src/shaders/shader_gbuffer.glsl b/src/shaders/shader_gbuffer.glsl new file mode 100644 index 0000000..de348be --- /dev/null +++ b/src/shaders/shader_gbuffer.glsl @@ -0,0 +1,39 @@ +@vs vs_g +layout(binding=0) uniform gbuffer_vs_params { + mat4 mvp; + mat4 view_matrix; +}; + +in vec4 position; +in vec4 normal; +in vec4 centre; +in vec4 instance; + +out vec3 view_space_pos; +out vec3 view_space_normal; + +void main() { + vec4 world_pos = vec4(position.xyz + instance.xyz, 1.0); + vec4 view_pos_4 = view_matrix * world_pos; + + gl_Position = mvp * world_pos; + view_space_pos = view_pos_4.xyz; + view_space_normal = mat3(view_matrix) * normal.xyz; +} +@end + +@fs fs_g + +in vec3 view_space_pos; +in vec3 view_space_normal; + +layout(location=0) out vec4 out_position; +layout(location=1) out vec4 out_normal; + +void main() { + out_position = vec4(view_space_pos, 1.0); + out_normal = vec4(normalize(view_space_normal), 1.0); +} +@end + +@program gbuffer vs_g fs_g diff --git a/trueno/trueno.xcodeproj/project.xcworkspace/xcuserdata/tuomas.katajisto.xcuserdatad/UserInterfaceState.xcuserstate b/trueno/trueno.xcodeproj/project.xcworkspace/xcuserdata/tuomas.katajisto.xcuserdatad/UserInterfaceState.xcuserstate index bc0df71a9730ca33c093a451fb67c630f06718ae..63e8759eb9846fd41f0bc232ea6069918e85e7a0 100644 GIT binary patch literal 31788 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%0Aui+VzDYL&JoS4x>L718mz@ruvo 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 ZesBAl_O&twg|YnGK`H;X|KI-j{{ut+fjIyG delta 10108 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 diff --git a/trueno/trueno.xcodeproj/xcshareddata/xcschemes/trueno.xcscheme b/trueno/trueno.xcodeproj/xcshareddata/xcschemes/trueno.xcscheme index b9d8783..394886e 100644 --- a/trueno/trueno.xcodeproj/xcshareddata/xcschemes/trueno.xcscheme +++ b/trueno/trueno.xcodeproj/xcshareddata/xcschemes/trueno.xcscheme @@ -1,7 +1,7 @@ + version = "2.3"> + +