Compare commits

..

No commits in common. "0a123efc55fd5b3137c4c6fe37149b5191ff9ac2" and "0b820e19c15ec986dfafb08eeb79c503ff47d160" have entirely different histories.

17 changed files with 70 additions and 307 deletions

View File

@ -6,7 +6,7 @@ rotation : float = 0.0;
cam : Camera = .{ cam : Camera = .{
far = 2000.0, far = 2000.0,
near = 1.0, near = 1.0,
target = .{0.0, 4.0, 0.0}, target = .{0.0, 0.0, 0.0},
position = .{3.0, 5.0, 3.0} position = .{3.0, 5.0, 3.0}
}; };
@ -22,19 +22,19 @@ game_init :: () {
world.ground[501][500] = .GRASS; world.ground[501][500] = .GRASS;
} }
game_ui :: () {
}
game_tick :: () { game_tick :: () {
} }
game_draw :: () { game_draw :: () {
camtask := Rendering_Task_Set_Camera.{type = .SET_CAMERA, camera = cam}; if !is_in_reflection_pass then update_image_from_ground(*world, *gPipelines.plane.bind.images[1]);
add_rendering_task(camtask); if is_in_reflection_pass {
skytask := Rendering_Task_Sky.{type = .SKY, worldConfig = *world.conf}; cam.position.y *= -1;
add_rendering_task(skytask); cam.target.y *= -1;
groundtask := Rendering_Task_Ground.{type = .GROUND, world = *world}; }
add_rendering_task(groundtask); draw_sky(*cam);
if !is_in_reflection_pass then draw_ground_plane(*cam, *world.conf);
if is_in_reflection_pass {
cam.position.y *= -1;
cam.target.y *= -1;
}
} }

View File

@ -110,6 +110,7 @@ layer : s32 = 0;
flush_arb_commands :: () { flush_arb_commands :: () {
sfons_flush(state.fons); // All the text has been drawn, now flush it to the atlas. sfons_flush(state.fons); // All the text has been drawn, now flush it to the atlas.
layer = 0; layer = 0;
if debug_arb_flush then print(" --- !BEGIN FLUSH! ---- \n"); if debug_arb_flush then print(" --- !BEGIN FLUSH! ---- \n");
for arbTriState.command_list { for arbTriState.command_list {

View File

@ -270,9 +270,13 @@ handle_tool_click :: (x: int, y: int, z: int) {
case .TRILES; case .TRILES;
if editor_current_trile != null then add_trile(editor_current_trile.name, cast(float)x, cast(float)y, cast(float)z); if editor_current_trile != null then add_trile(editor_current_trile.name, cast(float)x, cast(float)y, cast(float)z);
case .GROUND; case .GROUND;
ray := get_mouse_ray(*get_level_editor_camera()); ray := get_mouse_ray(*get_level_editor_camera());
hit, point := ray_plane_collision_point(ray, 0, 100); hit, point := ray_plane_collision_point(ray, 0, 100);
if hit { print("ground point: %\n");
if hit {
world.ground[floor(point.y).(int) + 500][floor(point.x).(int) + 500] = groundType; world.ground[floor(point.y).(int) + 500][floor(point.x).(int) + 500] = groundType;
} }
} }
@ -379,13 +383,11 @@ draw_world_triles :: (cam: *Camera, world: *World) {
} }
draw_level_editor :: () { draw_level_editor :: () {
camtask := Rendering_Task_Set_Camera.{type = .SET_CAMERA, camera = get_level_editor_camera()}; cam := get_level_editor_camera();
add_rendering_task(camtask); if !is_in_reflection_pass then update_image_from_ground(*world, *gPipelines.plane.bind.images[1]);
skytask := Rendering_Task_Sky.{type = .SKY, worldConfig = *world.conf}; draw_sky(*get_level_editor_camera(), *world.conf);
add_rendering_task(skytask); if !is_in_reflection_pass then draw_ground_plane(*get_level_editor_camera(), *world.conf);
groundtask := Rendering_Task_Ground.{type = .GROUND, world = *world}; draw_world_triles(*cam, *world);
add_rendering_task(groundtask);
// draw_world_triles(*cam, *world);
} }
draw_level_editor_ui :: (theme: *GR.Overall_Theme) { draw_level_editor_ui :: (theme: *GR.Overall_Theme) {

View File

@ -254,12 +254,11 @@ draw_material_tab :: (theme: *GR.Overall_Theme, area: GR.Rect) {
draw_trile_editor :: () { draw_trile_editor :: () {
draw_sky(*get_trile_editor_camera());
draw_trile(); draw_trile();
} }
draw_trile :: () { draw_trile :: () {
return; // @ToDo: Implement this using the new drawing commands.
if is_in_reflection_pass then return; // We don't want to double update the buffer. if is_in_reflection_pass then return; // We don't want to double update the buffer.
if editor_current_trile == null then return; if editor_current_trile == null then return;

View File

@ -17,9 +17,12 @@ stbi :: #import "stb_image";
#load "input/hotkeys.jai"; #load "input/hotkeys.jai";
#load "ui/ui.jai"; #load "ui/ui.jai";
#load "editor/editor.jai"; #load "editor/editor.jai";
#load "pipelines.jai";
#load "time.jai"; #load "time.jai";
#load "arbtri.jai";
#load "events.jai"; #load "events.jai";
#load "load.jai"; #load "load.jai";
#load "camera.jai";
#load "ray.jai"; #load "ray.jai";
#load "world.jai"; #load "world.jai";
@ -93,6 +96,7 @@ init :: () {
} }
init_after_asset_pack :: () { init_after_asset_pack :: () {
add_font_from_pack("./resources/DroidSerif-Regular.ttf"); add_font_from_pack("./resources/DroidSerif-Regular.ttf");
ui_init_font_fields(*state.font_default); ui_init_font_fields(*state.font_default);
@ -138,16 +142,27 @@ frame :: () {
GR.getrect_handle_event(event); GR.getrect_handle_event(event);
} }
sgl_defaults();
sgl_matrix_mode_projection();
sgl_ortho(0.0, sapp_widthf(), sapp_heightf(), 0.0, -1.0, +1.0);
tick_ui(); tick_ui();
// This populates our render task queue. sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, attachments = gPipelines.plane.attachments}));
is_in_reflection_pass = true;
draw_editor();
if !in_editor_view then game_draw(); if !in_editor_view then game_draw();
is_in_reflection_pass = false;
sg_end_pass();
sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, swapchain = cast,force(sg_swapchain) sglue_swapchain() }));
draw_editor();
if !in_editor_view then game_draw();
ui_clear_mouse_occluders(); ui_clear_mouse_occluders();
ui_pass(); ui_pass();
draw_editor(); sg_end_pass();
render(); sg_commit();
input_per_frame_event_and_flag_update(); input_per_frame_event_and_flag_update();
#if MEM_DEBUG { #if MEM_DEBUG {
memory_visualizer_per_frame_update(); memory_visualizer_per_frame_update();

View File

@ -1,51 +0,0 @@
#scope_export
Render_Command_Buckets :: struct {
setup : [..]*Render_Command;
shadow : [..]*Render_Command;
reflection : [..]*Render_Command;
main : [..]*Render_Command;
ui : [..]*Render_Command;
}
render_command_buckets : Render_Command_Buckets;
Render_Command_Type :: enum {
INVALID;
DRAW_SKY;
SET_CAMERA;
DRAW_GROUND;
GENERATE_GROUND;
}
Render_Command :: struct {
type: Render_Command_Type = .INVALID;
}
Render_Command_Sky :: struct {
#as using c : Render_Command;
worldConfig : *World_Config;
}
Render_Command_Draw_Ground :: struct {
#as using c : Render_Command;
worldConfig : *World_Config;
}
Render_Command_Generate_Ground_Texture :: struct {
#as using c : Render_Command;
world : *World;
}
Render_Command_Set_Camera :: struct {
#as using c : Render_Command;
camera: Camera;
}
process_command_buckets :: () {
backend_process_command_buckets();
}
#scope_file
#load "backend_sokol.jai";

View File

@ -1,94 +0,0 @@
camera: Camera;
backend_handle_command :: (cmd: *Render_Command) {
if cmd.type == {
case .DRAW_SKY;
sky_command := cast(*Render_Command_Sky)cmd;
backend_draw_sky(sky_command.worldConfig);
case .SET_CAMERA;
camera_command := cast(*Render_Command_Set_Camera)cmd;
camera = camera_command.camera;
case .GENERATE_GROUND;
gen_command := cast(*Render_Command_Generate_Ground_Texture)cmd;
update_image_from_ground(gen_command.world, *gPipelines.plane.bind.images[1]);
case .DRAW_GROUND;
ground_command := cast(*Render_Command_Draw_Ground)cmd;
backend_draw_ground(ground_command.worldConfig);
}
}
backend_draw_sky :: (wc: *World_Config) {
mvp := create_viewproj(*camera);
vs_params : Sky_Vs_Params;
world_conf : Sky_World_Config;
world_config_to_shader_type(wc, *world_conf);
vs_params.mvp = mvp.floats;
sg_apply_pipeline(gPipelines.sky.pipeline);
sg_apply_bindings(*gPipelines.sky.bind);
sg_apply_uniforms(UB_sky_vs_params, *(sg_range.{ ptr = *vs_params, size = size_of(type_of(vs_params)) }));
sg_apply_uniforms(UB_sky_world_config, *(sg_range.{ptr = *world_conf, size = size_of(type_of(world_conf))}));
sg_draw(0, 36, 1);
}
backend_draw_ground :: (wc: *World_Config) {
mvp := create_viewproj(*camera);
vs_params : Plane_Vs_Params;
world_conf : Plane_World_Config;
plane_data : Plane_Data;
w, h := get_window_size();
plane_data.screen_w = w;
plane_data.screen_h = h;
world_config_to_shader_type(wc, *world_conf);
vs_params.mvp = mvp.floats;
sg_apply_pipeline(gPipelines.plane.pipeline);
sg_apply_bindings(*gPipelines.plane.bind);
sg_apply_uniforms(UB_plane_vs_params, *(sg_range.{ ptr = *vs_params, size = size_of(type_of(vs_params)) }));
sg_apply_uniforms(UB_plane_world_config, *(sg_range.{ptr = *world_conf, size = size_of(type_of(world_conf))}));
sg_apply_uniforms(UB_plane_data, *(sg_range.{ptr = *plane_data, size = size_of(type_of(plane_data))}));
sg_draw(0, 6, 1);
}
backend_process_command_buckets :: () {
// 1. Set up textures and buffers.
for render_command_buckets.setup {
backend_handle_command(it);
}
// 2. Reflection pass
sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, attachments = gPipelines.plane.attachments}));
for render_command_buckets.reflection {
backend_handle_command(it);
}
sg_end_pass();
// 3. Main pass
sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, swapchain = cast,force(sg_swapchain) sglue_swapchain() }));
for render_command_buckets.main {
backend_handle_command(it);
}
// 3.2 Draw the UI. @ToDo: This should probably happen after post processing once we have that.
// Also, it's kind of stupid that this has it's own command system. It should be moved to using the
// same backend commands we are using for other rendering.
sgl_defaults();
sgl_matrix_mode_projection();
sgl_ortho(0.0, sapp_widthf(), sapp_heightf(), 0.0, -1.0, +1.0);
arb_tri_flush();
// End the main pass
sg_end_pass();
sg_commit();
array_reset_keeping_memory(*render_command_buckets.setup);
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.ui);
}

View File

@ -1,17 +0,0 @@
#scope_export
#load "backend.jai";
// Core rendering function, runs several passes.
render :: () {
tasks_to_commands();
process_command_buckets();
// // @ToDo: Consider a depth pre-pass here? Research required.
// shadow_pass();
// reflection_pass();
// forward_pass();
// // @ToDo: Post-processing.
}
#scope_file

View File

@ -1 +1,25 @@
draw_ground_plane :: (cam: *Camera, worldConfig: *World_Config = null) {
mvp := create_viewproj(cam);
vs_params : Plane_Vs_Params;
world_conf : Plane_World_Config;
plane_data : Plane_Data;
w, h := get_window_size();
plane_data.screen_w = w;
plane_data.screen_h = h;
plane_data.is_reflection_pass = xx ifx is_in_reflection_pass then 1 else 0;
wc : *World_Config = ifx worldConfig == null then *(World_Config.{}) else worldConfig;
world_config_to_shader_type(wc, *world_conf);
vs_params.mvp = mvp.floats;
sg_apply_pipeline(gPipelines.plane.pipeline);
sg_apply_bindings(*gPipelines.plane.bind);
sg_apply_uniforms(UB_plane_vs_params, *(sg_range.{ ptr = *vs_params, size = size_of(type_of(vs_params)) }));
sg_apply_uniforms(UB_plane_world_config, *(sg_range.{ptr = *world_conf, size = size_of(type_of(world_conf))}));
sg_apply_uniforms(UB_plane_data, *(sg_range.{ptr = *plane_data, size = size_of(type_of(plane_data))}));
sg_draw(0, 6, 1);
}

View File

@ -1,20 +1,5 @@
/*
The rendering pipeline.
@ToDo: Write something smart about our rendering
architecture.
*/
#load "groundplane.jai"; #load "groundplane.jai";
#load "tasks.jai";
#load "sky.jai"; #load "sky.jai";
#load "core.jai";
#load "camera.jai";
#load "pipelines.jai";
#load "meshgen.jai";
#load "arbtri.jai";
#scope_file #scope_file

View File

@ -13,26 +13,5 @@ draw_sky :: (cam: *Camera, worldConfig: *World_Config = null) {
sg_apply_bindings(*gPipelines.sky.bind); sg_apply_bindings(*gPipelines.sky.bind);
sg_apply_uniforms(UB_sky_vs_params, *(sg_range.{ ptr = *vs_params, size = size_of(type_of(vs_params)) })); sg_apply_uniforms(UB_sky_vs_params, *(sg_range.{ ptr = *vs_params, size = size_of(type_of(vs_params)) }));
sg_apply_uniforms(UB_sky_world_config, *(sg_range.{ptr = *world_conf, size = size_of(type_of(world_conf))})); sg_apply_uniforms(UB_sky_world_config, *(sg_range.{ptr = *world_conf, size = size_of(type_of(world_conf))}));
sg_draw(0, 36, 1); sg_draw(0, 36, 1);
}
sun_shadowmap_viewproj :: (cam: *Camera, conf: *World_Config) -> Matrix4 {
up: Vector3 = .{0, 1, 0};
targetToPos := conf.sunPosition;
A := normalize(targetToPos);
B := normalize(cross(up, A));
C := cross(A, B);
sunCameraPosition := cam.target + 20*A;
view := Matrix4.{
B.x, C.x, A.x, 0,
B.y, C.y, A.y, 0,
B.z, C.z, A.z, 0,
-dot(B, sunCameraPosition), -dot(C, sunCameraPosition), -dot(A, sunCameraPosition), 1
};
top := 10.0; right := 10.0;
proj := orthographic_projection_matrix(-right, right, -top, top, 5, 100, true);
return view * proj;
} }

View File

@ -1,83 +0,0 @@
#scope_export
Rendering_Task_Type :: enum {
INVALID;
GROUND;
SKY;
SET_CAMERA;
TRILE; // not implemented yet
SPRITE; // not implemented yet
PARTICLES; // not implemented yet
};
Rendering_Task :: struct {
type : Rendering_Task_Type = .INVALID;
};
Rendering_Task_World :: struct {
#as using t : Rendering_Task;
world : *World;
}
Rendering_Task_Sky :: struct {
#as using t : Rendering_Task;
t.type = .SKY;
worldConfig : *World_Config;
}
Rendering_Task_Ground :: struct {
#as using t : Rendering_Task;
t.type = .GROUND;
world : *World;
}
Rendering_Task_Set_Camera :: struct {
#as using t : Rendering_Task;
camera : Camera;
}
rendering_tasklist_clear :: () {
array_reset_keeping_memory(*rendering_tasklist);
}
add_rendering_task :: (task: $T) {
task_ptr := New(T,, temp);
task_ptr.* = task;
array_add(*rendering_tasklist, task_ptr);
}
rendering_tasklist : [..]*Rendering_Task;
tasks_to_commands :: () {
for rendering_tasklist {
if it.type == {
case .SKY;
command := New(Render_Command_Sky,, temp);
command.type = .DRAW_SKY;
command.worldConfig = (cast(*Rendering_Task_Sky)it).worldConfig;
array_add(*render_command_buckets.reflection, command);
array_add(*render_command_buckets.main, command);
case .GROUND;
commandDrawGround := New(Render_Command_Draw_Ground,, temp);
commandDrawGround.type = .DRAW_GROUND;
commandDrawGround.worldConfig = *(cast(*Rendering_Task_Ground)it).world.conf;
commandGenGround := New(Render_Command_Generate_Ground_Texture,, temp);
commandGenGround.type = .GENERATE_GROUND;
commandGenGround.world = (cast(*Rendering_Task_Ground)it).world;
array_add(*render_command_buckets.setup, commandGenGround);
array_add(*render_command_buckets.main, commandDrawGround);
case .SET_CAMERA;
command := New(Render_Command_Set_Camera,, temp);
command.type = .SET_CAMERA;
command.camera = (cast(*Rendering_Task_Set_Camera)it).camera;
array_add(*render_command_buckets.main, command);
commandReflected := New(Render_Command_Set_Camera,, temp);
commandReflected.type = .SET_CAMERA;
commandReflected.camera = (cast(*Rendering_Task_Set_Camera)it).camera;
commandReflected.camera.target *= Vector3.{1, -1, 1};
commandReflected.camera.position *= Vector3.{1, -1, 1};
array_add(*render_command_buckets.reflection, commandReflected);
}
}
rendering_tasklist_clear();
}

View File

@ -1,3 +1,5 @@
#load "meshgen.jai";
#scope_file #scope_file
trile_gfx_table : Table(string, Trile_GFX); trile_gfx_table : Table(string, Trile_GFX);

View File

@ -405,4 +405,5 @@ render_ui :: () {
ui_pass :: () { ui_pass :: () {
render_ui(); // Generates commands that are handled in arb_tri_flush render_ui(); // Generates commands that are handled in arb_tri_flush
arb_tri_flush();
} }