work on audio mixer implementation
This commit is contained in:
parent
b8b1aaaac5
commit
81b1a407ae
@ -5,7 +5,7 @@ hash :: #import "Hash";
|
||||
|
||||
#load "loaders.jai";
|
||||
|
||||
MAX_FILE_SIZE :: 2_000_000_000;
|
||||
MAX_FILE_SIZE :: 200_000_000;
|
||||
buf : [MAX_FILE_SIZE]u8;
|
||||
|
||||
Pack_Request :: struct {
|
||||
|
||||
@ -46,5 +46,6 @@ load_wav_from_memory :: (data: []u8) -> Audio_Data {
|
||||
array_add(*audio.data, cast(float)sample / 32768.0);
|
||||
}
|
||||
}
|
||||
audio.channels = format.nChannels;
|
||||
return audio;
|
||||
}
|
||||
|
||||
@ -1,17 +1,4 @@
|
||||
sokol_audio_callback :: (buffer: *float, num_frames: s32, num_channels: s32) #c_call {
|
||||
push_context,defer_pop default_context;
|
||||
audio := get_audio_from_pack("game_core", "sound/music/monoco");
|
||||
if !audio {
|
||||
print("Audio was null!!\n");
|
||||
return;
|
||||
}
|
||||
if audio.data.count < 1 then return;
|
||||
|
||||
for i : 0..num_frames-1 {
|
||||
if cur_sample >= audio.data.count {
|
||||
cur_sample = 0;
|
||||
}
|
||||
buffer[i] = audio.data[cur_sample] * 0.5;
|
||||
cur_sample += 1;
|
||||
}
|
||||
mixer_get_samples(buffer, num_frames, num_channels);
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Audio_Data :: struct {
|
||||
channels: u16;
|
||||
channels: s16;
|
||||
data: [..]float;
|
||||
}
|
||||
|
||||
@ -50,25 +50,83 @@ Mixer :: struct {
|
||||
tasks : [..]Mixer_Play_Task;
|
||||
}
|
||||
|
||||
// Removes tasks from the mixer's task list that
|
||||
// no longer have a reason to be on the task list.
|
||||
// Eg. a sound that is .ONESHOT but has already been played.
|
||||
mixer_clean_tasks :: () {
|
||||
mixer_lock(*g_mixer);
|
||||
defer mixer_unlock(*g_mixer);
|
||||
|
||||
}
|
||||
|
||||
mixer_add_task :: (task: Mixer_Play_Task) {
|
||||
mixer_lock(*g_mixer);
|
||||
defer mixer_unlock(*g_mixer);
|
||||
|
||||
array_add(*g_mixer.tasks, task);
|
||||
}
|
||||
|
||||
mixer_get_samples :: (samples: *float, sampleCount: s32, channelCount: s32) {
|
||||
mixer_add_task :: (audio: *Audio_Data, bus: Mixer_Bus, mode: Play_Mode) {
|
||||
mixer_add_task(.{
|
||||
audio = audio,
|
||||
bus = bus,
|
||||
mode = mode
|
||||
});
|
||||
}
|
||||
|
||||
mixer_get_samples :: (buffer: *float, frame_count: s32, channel_count: s32) {
|
||||
mixer_lock(*g_mixer);
|
||||
defer mixer_unlock(*g_mixer);
|
||||
|
||||
total_samples := frame_count * channel_count;
|
||||
memset(buffer, 0, total_samples * size_of(float));
|
||||
|
||||
if g_mixer.tasks.count < 1 then return;
|
||||
|
||||
for < i : 0..g_mixer.tasks.count-1 {
|
||||
task := *g_mixer.tasks[i];
|
||||
|
||||
if !task.audio {
|
||||
array_unordered_remove_by_index(*g_mixer.tasks, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
bus_vol := 1.0;
|
||||
if task.bus == {
|
||||
case .MUSIC; bus_vol = g_mixer.config.musicVolume;
|
||||
case .SOUND_EFFECT; bus_vol = g_mixer.config.soundEffectVolume;
|
||||
case .DIALOGUE; bus_vol = g_mixer.config.dialogueVolume;
|
||||
}
|
||||
|
||||
vol := bus_vol * g_mixer.config.masterVolume;
|
||||
|
||||
source_data := task.audio.data;
|
||||
source_channels := task.audio.channels;
|
||||
|
||||
task_finished := false;
|
||||
|
||||
for f : 0..frame_count-1 {
|
||||
if task.curSample >= source_data.count {
|
||||
if task.mode == .ONESHOT {
|
||||
task_finished = true;
|
||||
break;
|
||||
} else {
|
||||
task.curSample = 0;
|
||||
}
|
||||
}
|
||||
|
||||
cursor := task.curSample;
|
||||
|
||||
for ch : 0..channel_count-1 {
|
||||
out_index := (f * channel_count) + ch;
|
||||
offset := ifx source_channels == 1 then 0 else ch;
|
||||
|
||||
sample : float = 0;
|
||||
|
||||
if cursor + offset < source_data.count {
|
||||
sample = source_data[cursor + offset];
|
||||
}
|
||||
|
||||
buffer[out_index] += sample * vol;
|
||||
}
|
||||
|
||||
task.curSample += source_channels;
|
||||
}
|
||||
|
||||
if task_finished {
|
||||
array_unordered_remove_by_index(*g_mixer.tasks, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mixer_lock :: (mixer: *Mixer) {
|
||||
|
||||
14
src/main.jai
14
src/main.jai
@ -25,6 +25,7 @@ stbi :: #import "stb_image";
|
||||
#load "events.jai";
|
||||
#load "load.jai";
|
||||
#load "ray.jai";
|
||||
#load "profiling.jai";
|
||||
#load "world.jai";
|
||||
#load "utils.jai";
|
||||
#load "audio/audio.jai";
|
||||
@ -155,12 +156,15 @@ is_in_reflection_pass : bool = false;
|
||||
delta_time_accumulator : float64 = 0;
|
||||
|
||||
frame :: () {
|
||||
clear_frame_profiling();
|
||||
check_and_handle_window_resize();
|
||||
delta_time = get_time() - last_frame_time;
|
||||
last_frame_time = get_time();
|
||||
|
||||
asset_manager_tick();
|
||||
|
||||
add_frame_profiling_point("After asset manager tick");
|
||||
|
||||
if !mandatory_loads_done() then return;
|
||||
|
||||
if !init_after_mandatory_done {
|
||||
@ -180,6 +184,8 @@ frame :: () {
|
||||
|
||||
fonsClearState(state.fons);
|
||||
|
||||
add_frame_profiling_point("After loading logic");
|
||||
|
||||
frame_start_time := get_time();
|
||||
|
||||
dpis := state.dpi_scale;
|
||||
@ -200,17 +206,25 @@ frame :: () {
|
||||
}
|
||||
|
||||
|
||||
add_frame_profiling_point("After game ticks");
|
||||
tick_ui();
|
||||
add_frame_profiling_point("After UI tick");
|
||||
|
||||
// This populates our render task queue.
|
||||
if !in_editor_view then game_draw();
|
||||
add_frame_profiling_point("After game draw");
|
||||
|
||||
ui_clear_mouse_occluders();
|
||||
ui_pass();
|
||||
add_frame_profiling_point("After UI draw");
|
||||
prepare_text(debug_font, tprint("frametime: % ms", latest_frametime * 1000));
|
||||
draw_prepared_text(debug_font, 10, 10, .{0.0, 1.0, 0.0, 1.0});
|
||||
draw_editor();
|
||||
add_frame_profiling_point("After editor draw");
|
||||
render();
|
||||
add_frame_profiling_point("After rendering");
|
||||
|
||||
end_frame_profiling();
|
||||
#if MEM_DEBUG {
|
||||
memory_visualizer_per_frame_update();
|
||||
}
|
||||
|
||||
93
src/profiling.jai
Normal file
93
src/profiling.jai
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
Profiling functions for profiling the performance of a single frame.
|
||||
*/
|
||||
|
||||
#scope_file
|
||||
|
||||
DO_FRAME_PROFILING :: false;
|
||||
|
||||
Frame_Point :: struct {
|
||||
name : string;
|
||||
time : Apollo_Time;
|
||||
depth : s32;
|
||||
type : Frame_Point_Type;
|
||||
}
|
||||
|
||||
Frame_Point_Type :: enum {
|
||||
POINT;
|
||||
GROUP_START;
|
||||
GROUP_END;
|
||||
}
|
||||
|
||||
add_frame_profiling_point_with_type :: (pointName: string, pointType: Frame_Point_Type) {
|
||||
array_add(*current_frame_points, .{pointName, get_apollo_time(), current_depth, pointType});
|
||||
}
|
||||
|
||||
|
||||
print_point :: (name: string, us: s64, depth: s32, type: Frame_Point_Type) {
|
||||
for 0..depth print(" ");
|
||||
if type == {
|
||||
case .POINT;
|
||||
print("(%): %µs\n", name, us);
|
||||
case .GROUP_START;
|
||||
print("GROUP_START(%): %µs\n", name, us);
|
||||
case .GROUP_END;
|
||||
print("GROUP_END(%): %µs\n", name, us);
|
||||
}
|
||||
}
|
||||
|
||||
current_frame_points : [..]Frame_Point;
|
||||
current_depth : s32;
|
||||
#scope_export
|
||||
|
||||
clear_frame_profiling :: () {
|
||||
#if DO_FRAME_PROFILING {
|
||||
array_reset_keeping_memory(*current_frame_points);
|
||||
add_frame_profiling_point("frame_start");
|
||||
}
|
||||
}
|
||||
|
||||
add_frame_profiling_point :: (pointName: string) {
|
||||
#if DO_FRAME_PROFILING {
|
||||
add_frame_profiling_point_with_type(pointName, .POINT);
|
||||
}
|
||||
}
|
||||
|
||||
start_frame_profiling_group :: (groupName: string) {
|
||||
#if DO_FRAME_PROFILING {
|
||||
add_frame_profiling_point_with_type(groupName, .GROUP_START);
|
||||
current_depth += 1;
|
||||
}
|
||||
}
|
||||
|
||||
end_frame_profiling_group :: (groupName: string) {
|
||||
#if DO_FRAME_PROFILING {
|
||||
current_depth -= 1;
|
||||
add_frame_profiling_point_with_type(groupName, .GROUP_END);
|
||||
}
|
||||
}
|
||||
|
||||
end_frame_profiling :: () {
|
||||
#if DO_FRAME_PROFILING {
|
||||
endTime := get_apollo_time();
|
||||
startPoint : Apollo_Time;
|
||||
startPointSet := false;
|
||||
|
||||
print("\n\n-----Frame profiling report ----\n");
|
||||
|
||||
add_frame_profiling_point("frame_end");
|
||||
|
||||
for current_frame_points {
|
||||
if !startPointSet {
|
||||
startPoint = it.time;
|
||||
startPointSet = true;
|
||||
print_point(it.name, 0, it.depth, it.type);
|
||||
} else {
|
||||
startUs := to_microseconds(startPoint);
|
||||
curUs := to_microseconds(it.time);
|
||||
print_point(it.name, curUs - startUs, it.depth, it.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,7 +143,8 @@ backend_draw_trile_positions_gbuffer :: (trile : string, amount : s32, worldConf
|
||||
}
|
||||
|
||||
backend_draw_trile_positions_main :: (trile : string, amount : s32, worldConf: *World_Config) {
|
||||
mvp : Matrix4;
|
||||
start_frame_profiling_group("Draw trile positions");
|
||||
mvp : Matrix4;
|
||||
if !in_shadowmap_pass {
|
||||
mvp = create_viewproj(*camera);
|
||||
} else {
|
||||
@ -191,7 +192,9 @@ backend_draw_trile_positions_main :: (trile : string, amount : s32, worldConf: *
|
||||
sg_apply_uniforms(UB_trile_fs_params, *(sg_range.{ ptr = *fs_params, size = size_of(type_of(fs_params)) }));
|
||||
sg_apply_uniforms(UB_trile_vs_params, *(sg_range.{ ptr = *vs_params, size = size_of(type_of(vs_params))}));
|
||||
sg_apply_uniforms(UB_trile_world_config, *(sg_range.{ptr = *world_conf, size = size_of(type_of(world_conf))}));
|
||||
add_frame_profiling_point("After drawing setup");
|
||||
sg_draw(0, cast(s32) trilegfx.vertex_count, amount);
|
||||
end_frame_profiling_group("Draw trile positions");
|
||||
}
|
||||
backend_draw_sky :: (wc: *World_Config) {
|
||||
mvp := create_viewproj(*camera);
|
||||
@ -324,10 +327,13 @@ backend_draw_ground_gbuf :: (wc: *World_Config) {
|
||||
|
||||
backend_process_command_buckets :: () {
|
||||
// 1. Set up textures and buffers.
|
||||
start_frame_profiling_group("Setup");
|
||||
for render_command_buckets.setup {
|
||||
backend_handle_command(it);
|
||||
}
|
||||
end_frame_profiling_group("Setup");
|
||||
|
||||
start_frame_profiling_group("Shadow pass");
|
||||
// 2. Shadow pass
|
||||
if current_world_config != null {
|
||||
shadow_mvp = create_shadow_viewproj(*camera, current_world_config);
|
||||
@ -340,7 +346,9 @@ backend_process_command_buckets :: () {
|
||||
in_shadowmap_pass = false;
|
||||
}
|
||||
current_trile_offset_index = 0; // This is not optimal, but it is nice and simple.
|
||||
end_frame_profiling_group("Shadow pass");
|
||||
|
||||
start_frame_profiling_group("Reflection pass");
|
||||
// 3. Reflection pass
|
||||
sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, attachments = gPipelines.plane.attachments}));
|
||||
in_reflection_pass = true;
|
||||
@ -350,8 +358,10 @@ backend_process_command_buckets :: () {
|
||||
in_reflection_pass = false;
|
||||
sg_end_pass();
|
||||
current_trile_offset_index = 0; // This is not optimal, but it is nice and simple.
|
||||
end_frame_profiling_group("Reflection pass");
|
||||
|
||||
// 4. G-Buffer pass
|
||||
start_frame_profiling_group("G-Buffer pass");
|
||||
in_gbuffer_pass = true;
|
||||
sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear_gbuf, attachments = g_gbuf_attachments}));
|
||||
for render_command_buckets.gbuffer {
|
||||
@ -360,7 +370,9 @@ backend_process_command_buckets :: () {
|
||||
sg_end_pass();
|
||||
in_gbuffer_pass = false;
|
||||
current_trile_offset_index = 0; // This is not optimal, but it is nice and simple.
|
||||
|
||||
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_apply_pipeline(gPipelines.ssao.pipeline);
|
||||
gPipelines.ssao.bind.images[0] = g_gbuf_position;
|
||||
@ -375,9 +387,9 @@ backend_process_command_buckets :: () {
|
||||
sg_apply_uniforms(UB_ssao_fs_params, *(sg_range.{ ptr = *ssao_fs_uniform, size = size_of(type_of(ssao_fs_uniform)) }));
|
||||
sg_draw(0, 6, 1);
|
||||
sg_end_pass();
|
||||
end_frame_profiling_group("SSAO pass");
|
||||
|
||||
|
||||
|
||||
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;
|
||||
@ -388,18 +400,24 @@ backend_process_command_buckets :: () {
|
||||
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}));
|
||||
for render_command_buckets.main {
|
||||
backend_handle_command(it);
|
||||
}
|
||||
sg_end_pass();
|
||||
current_trile_offset_index = 0; // This is not optimal, but it is nice and simple.
|
||||
end_frame_profiling_group("Main pass");
|
||||
|
||||
start_frame_profiling_group("Postprocess pass");
|
||||
bloom_process();
|
||||
dof_process();
|
||||
|
||||
end_frame_profiling_group("Postprocess pass");
|
||||
|
||||
start_frame_profiling_group("Final pass");
|
||||
// Begin drawing to swapchain
|
||||
sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, swapchain = cast,force(sg_swapchain) sglue_swapchain() }));
|
||||
|
||||
@ -419,6 +437,7 @@ backend_process_command_buckets :: () {
|
||||
arb_tri_flush();
|
||||
|
||||
sg_end_pass();
|
||||
end_frame_profiling_group("Final pass");
|
||||
|
||||
sg_commit();
|
||||
|
||||
|
||||
@ -9,7 +9,10 @@ init_rendering :: () {
|
||||
// Core rendering function, runs several passes.
|
||||
render :: () {
|
||||
tasks_to_commands();
|
||||
add_frame_profiling_point("After task->command conversion");
|
||||
start_frame_profiling_group("Rendering command bucket processing");
|
||||
process_command_buckets();
|
||||
end_frame_profiling_group("Rendering command bucket processing");
|
||||
}
|
||||
|
||||
#scope_file
|
||||
|
||||
@ -101,7 +101,7 @@ vs_ssao_source_glsl430 := u8.[
|
||||
vec3 _60 = normalize(_51 - (_35 * dot(_51, _35)));
|
||||
mat3 _85 = mat3(_60, cross(_35, _60), _35);
|
||||
float occlusion = 0.0;
|
||||
for (int i = 0; i < 64; i++)
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
vec3 _121 = _26 + ((_85 * ssao_fs_params[i * 1 + 4].xyz) * 0.5);
|
||||
vec4 _133 = mat4(ssao_fs_params[0], ssao_fs_params[1], ssao_fs_params[2], ssao_fs_params[3]) * vec4(_121, 1.0);
|
||||
@ -176,7 +176,7 @@ fs_ssao_source_glsl430 := u8.[
|
||||
0x2c,0x20,0x5f,0x33,0x35,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,
|
||||
0x74,0x20,0x6f,0x63,0x63,0x6c,0x75,0x73,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x2e,
|
||||
0x30,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,
|
||||
0x69,0x20,0x3d,0x20,0x30,0x3b,0x20,0x69,0x20,0x3c,0x20,0x36,0x34,0x3b,0x20,0x69,
|
||||
0x69,0x20,0x3d,0x20,0x30,0x3b,0x20,0x69,0x20,0x3c,0x20,0x31,0x36,0x3b,0x20,0x69,
|
||||
0x2b,0x2b,0x29,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
|
||||
0x20,0x20,0x76,0x65,0x63,0x33,0x20,0x5f,0x31,0x32,0x31,0x20,0x3d,0x20,0x5f,0x32,
|
||||
0x36,0x20,0x2b,0x20,0x28,0x28,0x5f,0x38,0x35,0x20,0x2a,0x20,0x73,0x73,0x61,0x6f,
|
||||
@ -286,7 +286,7 @@ vs_ssao_source_glsl300es := u8.[
|
||||
highp vec3 _60 = normalize(_51 - (_35 * dot(_51, _35)));
|
||||
highp mat3 _85 = mat3(_60, cross(_35, _60), _35);
|
||||
highp float occlusion = 0.0;
|
||||
for (int i = 0; i < 64; i++)
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
highp vec3 _121 = _26 + ((_85 * ssao_fs_params[i * 1 + 4].xyz) * 0.5);
|
||||
highp vec4 _133 = mat4(ssao_fs_params[0], ssao_fs_params[1], ssao_fs_params[2], ssao_fs_params[3]) * vec4(_121, 1.0);
|
||||
@ -364,7 +364,7 @@ fs_ssao_source_glsl300es := u8.[
|
||||
0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x6f,0x63,0x63,0x6c,0x75,0x73,0x69,0x6f,0x6e,
|
||||
0x20,0x3d,0x20,0x30,0x2e,0x30,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6f,0x72,0x20,
|
||||
0x28,0x69,0x6e,0x74,0x20,0x69,0x20,0x3d,0x20,0x30,0x3b,0x20,0x69,0x20,0x3c,0x20,
|
||||
0x36,0x34,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,
|
||||
0x31,0x36,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,
|
||||
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x76,0x65,0x63,
|
||||
0x33,0x20,0x5f,0x31,0x32,0x31,0x20,0x3d,0x20,0x5f,0x32,0x36,0x20,0x2b,0x20,0x28,
|
||||
0x28,0x5f,0x38,0x35,0x20,0x2a,0x20,0x73,0x73,0x61,0x6f,0x5f,0x66,0x73,0x5f,0x70,
|
||||
@ -517,7 +517,7 @@ vs_ssao_source_metal_macos := u8.[
|
||||
float3 _60 = fast::normalize(_51 - (_35 * dot(_51, _35)));
|
||||
float3x3 _85 = float3x3(_60, cross(_35, _60), _35);
|
||||
float occlusion = 0.0;
|
||||
for (int i = 0; i < 64; i++)
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
float3 _121 = _26 + ((_85 * _109.samples[i].xyz) * 0.5);
|
||||
float4 _133 = _109.projection * float4(_121, 1.0);
|
||||
@ -613,7 +613,7 @@ fs_ssao_source_metal_macos := u8.[
|
||||
0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x6f,0x63,0x63,0x6c,0x75,0x73,
|
||||
0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x2e,0x30,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,
|
||||
0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x20,0x3d,0x20,0x30,0x3b,0x20,0x69,
|
||||
0x20,0x3c,0x20,0x36,0x34,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x20,0x20,0x20,0x20,
|
||||
0x20,0x3c,0x20,0x31,0x36,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x20,0x20,0x20,0x20,
|
||||
0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x33,
|
||||
0x20,0x5f,0x31,0x32,0x31,0x20,0x3d,0x20,0x5f,0x32,0x36,0x20,0x2b,0x20,0x28,0x28,
|
||||
0x5f,0x38,0x35,0x20,0x2a,0x20,0x5f,0x31,0x30,0x39,0x2e,0x73,0x61,0x6d,0x70,0x6c,
|
||||
|
||||
@ -38,7 +38,7 @@ void main() {
|
||||
mat3 tbn = mat3(tangent, bitangent, normal);
|
||||
|
||||
float occlusion = 0.0;
|
||||
for(int i = 0; i < 64; i++) {
|
||||
for(int i = 0; i < 16; i++) {
|
||||
vec3 sample_pos = tbn * samples[i].xyz;
|
||||
sample_pos = frag_pos + sample_pos * 0.5;
|
||||
|
||||
|
||||
13
src/time.jai
13
src/time.jai
@ -1,3 +1,16 @@
|
||||
get_apollo_time :: () -> Apollo_Time {
|
||||
#if OS != .WASM {
|
||||
// Since we are making a game engine, we want the monotonic time.
|
||||
// This means that we won't take corrections to the time into account
|
||||
// since this could make a delta time negative and that would be bad.
|
||||
return current_time_monotonic();
|
||||
} else {
|
||||
// Implement a WASM Apollo_Time backend here.
|
||||
#assert false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
get_time :: () -> float64 {
|
||||
return stm_sec(stm_now());
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user