draw ui & world to separate texture

This commit is contained in:
jacob 2025-01-18 12:29:10 -06:00
parent acced9dfed
commit 511783243d
3 changed files with 233 additions and 136 deletions

View File

@ -78,9 +78,15 @@ void renderer_canvas_ensure_cmd(struct renderer_canvas *canvas, struct renderer_
void renderer_canvas_send_to_gpu(struct renderer_canvas *canvas); void renderer_canvas_send_to_gpu(struct renderer_canvas *canvas);
void renderer_render_to_texture(struct renderer_handle target_handle, struct renderer_canvas *canvas, u32 clear_color, struct xform view, struct rect viewport, struct sprite_scope *sprite_scope); void renderer_render_to_texture(struct renderer_handle target_handle, struct renderer_canvas *canvas, struct xform view, struct rect viewport, struct sprite_scope *sprite_scope);
void renderer_render_to_backbuffer(struct v2 backbuffer_size, struct renderer_canvas *canvas, u32 clear_color, struct xform view, struct rect viewport, struct sprite_scope *sprite_scope); void renderer_render_to_backbuffer(struct renderer_canvas *canvas, struct xform view, struct rect viewport, struct sprite_scope *sprite_scope);
void renderer_clear_texture(struct renderer_handle target_handle, u32 clear_color);
void renderer_clear_backbuffer(u32 clear_color);
void renderer_resize_backbuffer(struct v2 size);
void renderer_present_backbuffer(i32 vsync); void renderer_present_backbuffer(i32 vsync);

View File

@ -124,9 +124,6 @@ GLOBAL struct {
IDXGISwapChain1 *swapchain; IDXGISwapChain1 *swapchain;
/* For caching/comparison */
struct v2 backbuffer_size;
ID3D11BlendState *blend_state; ID3D11BlendState *blend_state;
ID3D11RasterizerState *rasterizer_state; ID3D11RasterizerState *rasterizer_state;
ID3D11DepthStencilState *depth_stencil_state; ID3D11DepthStencilState *depth_stencil_state;
@ -829,19 +826,12 @@ void renderer_canvas_send_to_gpu(struct renderer_canvas *canvas)
* Render * Render
* ========================== */ * ========================== */
INTERNAL void resize_backbuffer(struct v2 size)
{
__prof;
IDXGISwapChain_ResizeBuffers(G.swapchain, 0, (UINT)size.x, (UINT)size.y, DXGI_FORMAT_UNKNOWN, 0);
G.backbuffer_size = size;
}
/* TODO: Lock canvas or at least global state? (in-case multi-threaded present). /* TODO: Lock canvas or at least global state? (in-case multi-threaded present).
* Another option is to store a separate device on each canvas (need to * Another option is to store a separate device on each canvas (need to
* research if that is smart first). * research if that is smart first).
* *
* I'm thinking we may also just need to lock texture modification access while presenting */ * I'm thinking we may also just need to lock texture modification access while presenting */
INTERNAL void dx11_render_to_target(ID3D11RenderTargetView *target, struct renderer_canvas *canvas, u32 clear_color, struct xform view, struct rect viewport, struct sprite_scope *sprite_scope) INTERNAL void dx11_render_to_target(ID3D11RenderTargetView *target, struct renderer_canvas *canvas, struct xform view, struct rect viewport, struct sprite_scope *sprite_scope)
{ {
__prof; __prof;
ID3D11DeviceContext_OMSetRenderTargets(G.devcon, 1, &target, NULL); ID3D11DeviceContext_OMSetRenderTargets(G.devcon, 1, &target, NULL);
@ -863,14 +853,6 @@ INTERNAL void dx11_render_to_target(ID3D11RenderTargetView *target, struct rende
ID3D11DeviceContext_VSSetConstantBuffers(G.devcon, 0, 1, &G.vs_constant_buffer); ID3D11DeviceContext_VSSetConstantBuffers(G.devcon, 0, 1, &G.vs_constant_buffer);
struct dx11_shader *last_shader = NULL; struct dx11_shader *last_shader = NULL;
if (clear_color) {
f32 r = (f32)((clear_color >> 0) & 0xFF) / 255.0f;
f32 g = (f32)((clear_color >> 8) & 0xFF) / 255.0f;
f32 b = (f32)((clear_color >> 16) & 0xFF) / 255.0f;
f32 a = (f32)((clear_color >> 24) & 0xFF) / 255.0f;
f32 fill[4] = { r, g, b, a };
ID3D11DeviceContext_ClearRenderTargetView(G.devcon, target, fill);
}
struct renderer_cmd *cmd = canvas ? canvas->gpu_cmd_store.cmd_first : NULL; struct renderer_cmd *cmd = canvas ? canvas->gpu_cmd_store.cmd_first : NULL;
for (; cmd; cmd = cmd->next) { for (; cmd; cmd = cmd->next) {
@ -953,7 +935,7 @@ INTERNAL void dx11_render_to_target(ID3D11RenderTargetView *target, struct rende
} }
} }
void renderer_render_to_texture(struct renderer_handle target_handle, struct renderer_canvas *canvas, u32 clear_color, struct xform view, struct rect viewport, struct sprite_scope *sprite_scope) void renderer_render_to_texture(struct renderer_handle target_handle, struct renderer_canvas *canvas, struct xform view, struct rect viewport, struct sprite_scope *sprite_scope)
{ {
__prof; __prof;
@ -969,7 +951,9 @@ void renderer_render_to_texture(struct renderer_handle target_handle, struct ren
ID3D11RenderTargetView *target_view = NULL; ID3D11RenderTargetView *target_view = NULL;
ID3D11Device_CreateRenderTargetView(G.dev, target_resource, NULL, &target_view); ID3D11Device_CreateRenderTargetView(G.dev, target_resource, NULL, &target_view);
dx11_render_to_target(target_view, canvas, clear_color, view, viewport, sprite_scope); if (target_view) {
dx11_render_to_target(target_view, canvas, view, viewport, sprite_scope);
}
if (target_view) { if (target_view) {
ID3D11RenderTargetView_Release(target_view); ID3D11RenderTargetView_Release(target_view);
@ -979,22 +963,19 @@ void renderer_render_to_texture(struct renderer_handle target_handle, struct ren
} }
} }
void renderer_render_to_backbuffer(struct v2 backbuffer_size, struct renderer_canvas *canvas, u32 clear_color, struct xform view, struct rect viewport, struct sprite_scope *sprite_scope) void renderer_render_to_backbuffer(struct renderer_canvas *canvas, struct xform view, struct rect viewport, struct sprite_scope *sprite_scope)
{ {
__prof; __prof;
/* Resize back buffer */
if (!v2_eq(G.backbuffer_size, backbuffer_size)) {
resize_backbuffer(backbuffer_size);
}
ID3D11Texture2D *backbuffer_texture = NULL; ID3D11Texture2D *backbuffer_texture = NULL;
IDXGISwapChain_GetBuffer(G.swapchain, 0, &IID_ID3D11Texture2D, (LPVOID *)&backbuffer_texture); IDXGISwapChain_GetBuffer(G.swapchain, 0, &IID_ID3D11Texture2D, (LPVOID *)&backbuffer_texture);
ID3D11RenderTargetView *backbuffer_view = NULL; ID3D11RenderTargetView *backbuffer_view = NULL;
ID3D11Device_CreateRenderTargetView(G.dev, (ID3D11Resource *)backbuffer_texture, NULL, &backbuffer_view); ID3D11Device_CreateRenderTargetView(G.dev, (ID3D11Resource *)backbuffer_texture, NULL, &backbuffer_view);
dx11_render_to_target(backbuffer_view, canvas, clear_color, view, viewport, sprite_scope); if (backbuffer_view) {
dx11_render_to_target(backbuffer_view, canvas, view, viewport, sprite_scope);
}
if (backbuffer_view) { if (backbuffer_view) {
ID3D11RenderTargetView_Release(backbuffer_view); ID3D11RenderTargetView_Release(backbuffer_view);
@ -1004,6 +985,73 @@ void renderer_render_to_backbuffer(struct v2 backbuffer_size, struct renderer_ca
} }
} }
void renderer_clear_texture(struct renderer_handle target_handle, u32 clear_color)
{
__prof;
ID3D11ShaderResourceView *target_srv = handle_data(target_handle);
if (!target_srv) {
/* Invalid handle */
ASSERT(false);
return;
}
ID3D11Resource *target_resource = NULL;
ID3D11View_GetResource(target_srv, &target_resource);
ID3D11RenderTargetView *target_view = NULL;
ID3D11Device_CreateRenderTargetView(G.dev, target_resource, NULL, &target_view);
if (target_view) {
f32 r = (f32)((clear_color >> 0) & 0xFF) / 255.0f;
f32 g = (f32)((clear_color >> 8) & 0xFF) / 255.0f;
f32 b = (f32)((clear_color >> 16) & 0xFF) / 255.0f;
f32 a = (f32)((clear_color >> 24) & 0xFF) / 255.0f;
f32 fill[4] = { r, g, b, a };
ID3D11DeviceContext_ClearRenderTargetView(G.devcon, target_view, fill);
}
if (target_view) {
ID3D11RenderTargetView_Release(target_view);
}
if (target_resource) {
ID3D11Texture2D_Release((ID3D11Texture2D *)target_resource);
}
}
void renderer_clear_backbuffer(u32 clear_color)
{
__prof;
ID3D11Texture2D *backbuffer_texture = NULL;
IDXGISwapChain_GetBuffer(G.swapchain, 0, &IID_ID3D11Texture2D, (LPVOID *)&backbuffer_texture);
ID3D11RenderTargetView *backbuffer_view = NULL;
ID3D11Device_CreateRenderTargetView(G.dev, (ID3D11Resource *)backbuffer_texture, NULL, &backbuffer_view);
if (backbuffer_view) {
f32 r = (f32)((clear_color >> 0) & 0xFF) / 255.0f;
f32 g = (f32)((clear_color >> 8) & 0xFF) / 255.0f;
f32 b = (f32)((clear_color >> 16) & 0xFF) / 255.0f;
f32 a = (f32)((clear_color >> 24) & 0xFF) / 255.0f;
f32 fill[4] = { r, g, b, a };
ID3D11DeviceContext_ClearRenderTargetView(G.devcon, backbuffer_view, fill);
}
if (backbuffer_view) {
ID3D11RenderTargetView_Release(backbuffer_view);
}
if (backbuffer_texture) {
ID3D11Texture2D_Release(backbuffer_texture);
}
}
void renderer_resize_backbuffer(struct v2 size)
{
__prof;
IDXGISwapChain_ResizeBuffers(G.swapchain, 0, (UINT)size.x, (UINT)size.y, DXGI_FORMAT_UNKNOWN, 0);
}
void renderer_present_backbuffer(i32 vsync) void renderer_present_backbuffer(i32 vsync)
{ {
__prof; __prof;

View File

@ -41,13 +41,19 @@ GLOBAL struct {
struct sys_window *window; struct sys_window *window;
struct renderer_handle render_target; struct renderer_handle final_rt;
struct v2 render_target_resolution; struct renderer_handle world_rt;
struct renderer_handle ui_rt;
struct v2 final_rt_resolution;
struct v2 world_rt_resolution;
struct v2 ui_rt_resolution;
struct v2 backbuffer_size;
struct renderer_canvas *backbuffer_canvas;
struct renderer_canvas *world_canvas; struct renderer_canvas *world_canvas;
struct renderer_canvas *viewport_bg_canvas; struct renderer_canvas *ui_canvas;
struct renderer_canvas *viewport_canvas; struct renderer_canvas *final_canvas;
struct renderer_canvas *backbuffer_canvas;
struct xform world_view; struct xform world_view;
struct blend_tick *head_free_blend_tick; struct blend_tick *head_free_blend_tick;
@ -148,12 +154,12 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr,
G.sys_events_arena = arena_alloc(GIGABYTE(64)); G.sys_events_arena = arena_alloc(GIGABYTE(64));
world_alloc(&G.world); world_alloc(&G.world);
G.render_target = renderer_handle_nil();
G.backbuffer_canvas = renderer_canvas_alloc();
G.world_canvas = renderer_canvas_alloc();
G.world_view = XFORM_TRS(.t = V2(0, 0), .r = 0, .s = V2(PIXELS_PER_UNIT, PIXELS_PER_UNIT)); G.world_view = XFORM_TRS(.t = V2(0, 0), .r = 0, .s = V2(PIXELS_PER_UNIT, PIXELS_PER_UNIT));
G.viewport_bg_canvas = renderer_canvas_alloc(); G.world_canvas = renderer_canvas_alloc();
G.viewport_canvas = renderer_canvas_alloc(); G.ui_canvas = renderer_canvas_alloc();
G.final_canvas = renderer_canvas_alloc();
G.backbuffer_canvas = renderer_canvas_alloc();
G.window = window; G.window = window;
sys_window_register_event_callback(G.window, &window_event_callback); sys_window_register_event_callback(G.window, &window_event_callback);
@ -412,13 +418,13 @@ INTERNAL void debug_draw_xform(struct xform xf, u32 color_x, u32 color_y)
x_ray = v2_mul(x_ray, ray_scale); x_ray = v2_mul(x_ray, ray_scale);
y_ray = v2_mul(y_ray, ray_scale); y_ray = v2_mul(y_ray, ray_scale);
draw_arrow_ray(G.viewport_canvas, pos, x_ray, thickness, arrowhead_len, color_x); draw_arrow_ray(G.ui_canvas, pos, x_ray, thickness, arrowhead_len, color_x);
draw_arrow_ray(G.viewport_canvas, pos, y_ray, thickness, arrowhead_len, color_y); draw_arrow_ray(G.ui_canvas, pos, y_ray, thickness, arrowhead_len, color_y);
//u32 color_quad = RGBA_32_F(0, 1, 1, 0.3); //u32 color_quad = RGBA_32_F(0, 1, 1, 0.3);
//struct quad quad = quad_from_rect(RECT(0, 0, 1, -1)); //struct quad quad = quad_from_rect(RECT(0, 0, 1, -1));
//quad = xform_mul_quad(xf, quad_scale(quad, 0.075f)); //quad = xform_mul_quad(xf, quad_scale(quad, 0.075f));
//draw_quad(G.viewport_canvas, quad, color); //draw_quad(G.ui_canvas, quad, color);
} }
/* TODO: remove this (testing) */ /* TODO: remove this (testing) */
@ -435,7 +441,7 @@ INTERNAL void debug_draw_movement(struct entity *ent)
struct v2 pos = xform_mul_v2(G.world_view, xf.og); struct v2 pos = xform_mul_v2(G.world_view, xf.og);
struct v2 vel_ray = xform_basis_mul_v2(G.world_view, velocity); struct v2 vel_ray = xform_basis_mul_v2(G.world_view, velocity);
draw_arrow_ray(G.viewport_canvas, pos, vel_ray, thickness, arrow_len, color_vel); draw_arrow_ray(G.ui_canvas, pos, vel_ray, thickness, arrow_len, color_vel);
} }
/* ========================== * /* ========================== *
@ -497,7 +503,6 @@ INTERNAL void user_update(void)
* Produce interpolated tick * Produce interpolated tick
* ========================== */ * ========================== */
b32 tick_is_first_frame = false;
{ {
__profscope(produce_interpolated_tick); __profscope(produce_interpolated_tick);
@ -511,8 +516,6 @@ INTERNAL void user_update(void)
struct world *t0 = interp_ticks.from_tick; struct world *t0 = interp_ticks.from_tick;
struct world *t1 = interp_ticks.to_tick; struct world *t1 = interp_ticks.to_tick;
tick_is_first_frame = (t0->tick_id == 0 || t1->tick_id == 0);
f32 tick_blend = 0; f32 tick_blend = 0;
{ {
f64 t0_time = sys_timestamp_seconds(t0->tick_ts); f64 t0_time = sys_timestamp_seconds(t0->tick_ts);
@ -880,7 +883,9 @@ INTERNAL void user_update(void)
struct v2 offset = v2_neg(xform_mul_v2(G.world_view, V2(0, 0))); struct v2 offset = v2_neg(xform_mul_v2(G.world_view, V2(0, 0)));
f32 spacing = xform_get_scale(G.world_view).x; f32 spacing = xform_get_scale(G.world_view).x;
draw_grid(G.viewport_bg_canvas, RECT(0, 0, G.viewport_size.x, G.viewport_size.y), color, thickness, spacing, offset); struct v2 pos = xform_invert_mul_v2(G.world_view, V2(0, 0));
struct v2 size = xform_basis_invert_mul_v2(G.world_view, G.viewport_size);
draw_grid(G.world_canvas, RECT_FROM_V2(pos, size), color, thickness, spacing, offset);
} }
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
@ -1012,7 +1017,7 @@ INTERNAL void user_update(void)
start = xform_mul_v2(G.world_view, start); start = xform_mul_v2(G.world_view, start);
struct v2 end = v2_add(xf.og, ent->control.focus); struct v2 end = v2_add(xf.og, ent->control.focus);
end = xform_mul_v2(G.world_view, end); end = xform_mul_v2(G.world_view, end);
draw_arrow_line(G.viewport_canvas, start, end, 3, 10, RGBA_32_F(1, 1, 1, 0.5)); draw_arrow_line(G.ui_canvas, start, end, 3, 10, RGBA_32_F(1, 1, 1, 0.5));
} }
#if 0 #if 0
@ -1042,16 +1047,16 @@ INTERNAL void user_update(void)
struct quad quad = quad_from_rect(slice.rect); struct quad quad = quad_from_rect(slice.rect);
quad = xform_mul_quad(sprite_xform, quad); quad = xform_mul_quad(sprite_xform, quad);
quad = xform_mul_quad(G.world_view, quad); quad = xform_mul_quad(G.world_view, quad);
draw_quad_line(G.viewport_canvas, quad, 2, quad_color); draw_quad_line(G.ui_canvas, quad, 2, quad_color);
} }
draw_circle(G.viewport_canvas, center, 3, point_color, 20); draw_circle(G.ui_canvas, center, 3, point_color, 20);
if (slice.has_ray) { if (slice.has_ray) {
struct v2 ray = xform_basis_mul_v2(sprite_xform, slice.dir); struct v2 ray = xform_basis_mul_v2(sprite_xform, slice.dir);
ray = xform_basis_mul_v2(G.world_view, ray); ray = xform_basis_mul_v2(G.world_view, ray);
ray = v2_with_len(ray, 25); ray = v2_with_len(ray, 25);
draw_arrow_ray(G.viewport_canvas, center, ray, 2, 10, ray_color); draw_arrow_ray(G.ui_canvas, center, ray, 2, 10, ray_color);
} }
} }
} }
@ -1061,19 +1066,19 @@ INTERNAL void user_update(void)
/* Draw collider */ /* Draw collider */
if (entity_has_prop(ent, ENTITY_PROP_PHYSICAL_DYNAMIC)) { if (entity_has_prop(ent, ENTITY_PROP_PHYSICAL_DYNAMIC)) {
struct collider_shape collider = ent->local_collider; struct collider_shape collider = ent->local_collider;
u32 color = RGBA_32_F(1, 1, 0, 0.25); u32 color = RGBA_32_F(1, 1, 0, 0.5);
f32 thickness = 2; f32 thickness = 2;
{ {
/* Draw collider using support points */ /* Draw collider using support points */
//u32 detail = 64; //u32 detail = 64;
u32 detail = 512; u32 detail = 512;
draw_collider_line(G.viewport_canvas, G.world_view, collider, xf, thickness, color, detail); draw_collider_line(G.ui_canvas, G.world_view, collider, xf, thickness, color, detail);
} }
{ {
/* Draw collider shape points */ /* Draw collider shape points */
for (u32 i = 0; i < collider.count; ++i) { for (u32 i = 0; i < collider.count; ++i) {
struct v2 p = xform_mul_v2(xform_mul(G.world_view, xf), collider.points[i]); struct v2 p = xform_mul_v2(xform_mul(G.world_view, xf), collider.points[i]);
draw_circle(G.viewport_canvas, p, 3, COLOR_BLUE, 10); draw_circle(G.ui_canvas, p, 3, COLOR_BLUE, 10);
} }
} }
if (collider.count == 1 && collider.radius > 0) { if (collider.count == 1 && collider.radius > 0) {
@ -1082,14 +1087,14 @@ INTERNAL void user_update(void)
struct v2 end = collider_get_support_point(&collider, xf, v2_neg(xf.by)).p; struct v2 end = collider_get_support_point(&collider, xf, v2_neg(xf.by)).p;
start = xform_mul_v2(G.world_view, start); start = xform_mul_v2(G.world_view, start);
end = xform_mul_v2(G.world_view, end); end = xform_mul_v2(G.world_view, end);
draw_line(G.viewport_canvas, start, end, thickness, color); draw_line(G.ui_canvas, start, end, thickness, color);
} }
#if 0 #if 0
/* Draw support point at focus dir */ /* Draw support point at focus dir */
{ {
struct v2 p = collider_support_point(&collider, xf, ent->control.focus); struct v2 p = collider_support_point(&collider, xf, ent->control.focus);
p = xform_mul_v2(G.world_view, p); p = xform_mul_v2(G.world_view, p);
draw_circle(G.viewport_canvas, p, 3, COLOR_RED, 10); draw_circle(G.ui_canvas, p, 3, COLOR_RED, 10);
} }
#endif #endif
} }
@ -1121,7 +1126,7 @@ INTERNAL void user_update(void)
u32 color = RGBA_32_F(1, 1, 0, 0.50); u32 color = RGBA_32_F(1, 1, 0, 0.50);
//struct v2 point = xform_mul_v2(e0_xf, contact.p0_local); //struct v2 point = xform_mul_v2(e0_xf, contact.p0_local);
//struct v2 point = contact.p0_initial_world; //struct v2 point = contact.p0_initial_world;
draw_circle(G.viewport_canvas, xform_mul_v2(G.world_view, dbg_pt), radius, color, 10); draw_circle(G.ui_canvas, xform_mul_v2(G.world_view, dbg_pt), radius, color, 10);
} }
/* Draw normal */ /* Draw normal */
{ {
@ -1131,7 +1136,7 @@ INTERNAL void user_update(void)
f32 arrow_height = 5; f32 arrow_height = 5;
struct v2 start = xform_mul_v2(G.world_view, dbg_pt); struct v2 start = xform_mul_v2(G.world_view, dbg_pt);
struct v2 end = xform_mul_v2(G.world_view, v2_add(dbg_pt, v2_mul(v2_norm(data->normal), len))); struct v2 end = xform_mul_v2(G.world_view, v2_add(dbg_pt, v2_mul(v2_norm(data->normal), len)));
draw_arrow_line(G.viewport_canvas, start, end, arrow_thickness, arrow_height, color); draw_arrow_line(G.ui_canvas, start, end, arrow_thickness, arrow_height, color);
} }
#if 0 #if 0
/* Draw contact info */ /* Draw contact info */
@ -1161,7 +1166,7 @@ INTERNAL void user_update(void)
FMT_UINT(data->num_points)); FMT_UINT(data->num_points));
draw_text(G.viewport_canvas, disp_font, v2_add(v2_round(xform_mul_v2(G.world_view, dbg_pt)), V2(0, offset_px)), text); draw_text(G.ui_canvas, disp_font, v2_add(v2_round(xform_mul_v2(G.world_view, dbg_pt)), V2(0, offset_px)), text);
} }
} }
#endif #endif
@ -1188,8 +1193,8 @@ INTERNAL void user_update(void)
u32 color = RGBA_32_F(1, 1, 0, 0.5); u32 color = RGBA_32_F(1, 1, 0, 0.5);
struct v2 a = xform_mul_v2(G.world_view, data->closest0); struct v2 a = xform_mul_v2(G.world_view, data->closest0);
struct v2 b = xform_mul_v2(G.world_view, data->closest1); struct v2 b = xform_mul_v2(G.world_view, data->closest1);
draw_circle(G.viewport_canvas, a, radius, color, 10); draw_circle(G.ui_canvas, a, radius, color, 10);
draw_circle(G.viewport_canvas, b, radius, color, 10); draw_circle(G.ui_canvas, b, radius, color, 10);
} }
#endif #endif
@ -1206,28 +1211,28 @@ INTERNAL void user_update(void)
{ {
struct v2 a = xform_mul_v2(G.world_view, collider_res.a0); struct v2 a = xform_mul_v2(G.world_view, collider_res.a0);
struct v2 b = xform_mul_v2(G.world_view, collider_res.b0); struct v2 b = xform_mul_v2(G.world_view, collider_res.b0);
draw_line(G.viewport_canvas, a, b, thickness, color_line); draw_line(G.ui_canvas, a, b, thickness, color_line);
draw_circle(G.viewport_canvas, a, radius, color_a, 10); draw_circle(G.ui_canvas, a, radius, color_a, 10);
draw_circle(G.viewport_canvas, b, radius, color_b, 10); draw_circle(G.ui_canvas, b, radius, color_b, 10);
struct v2 a_clipped = xform_mul_v2(G.world_view, collider_res.a0_clipped); struct v2 a_clipped = xform_mul_v2(G.world_view, collider_res.a0_clipped);
struct v2 b_clipped = xform_mul_v2(G.world_view, collider_res.b0_clipped); struct v2 b_clipped = xform_mul_v2(G.world_view, collider_res.b0_clipped);
draw_line(G.viewport_canvas, a_clipped, b_clipped, thickness, color_line_clipped); draw_line(G.ui_canvas, a_clipped, b_clipped, thickness, color_line_clipped);
draw_circle(G.viewport_canvas, a_clipped, radius, color_a_clipped, 10); draw_circle(G.ui_canvas, a_clipped, radius, color_a_clipped, 10);
draw_circle(G.viewport_canvas, b_clipped, radius, color_b_clipped, 10); draw_circle(G.ui_canvas, b_clipped, radius, color_b_clipped, 10);
} }
{ {
struct v2 a = xform_mul_v2(G.world_view, collider_res.a1); struct v2 a = xform_mul_v2(G.world_view, collider_res.a1);
struct v2 b = xform_mul_v2(G.world_view, collider_res.b1); struct v2 b = xform_mul_v2(G.world_view, collider_res.b1);
draw_line(G.viewport_canvas, a, b, thickness, color_line); draw_line(G.ui_canvas, a, b, thickness, color_line);
draw_circle(G.viewport_canvas, a, radius, color_a, 10); draw_circle(G.ui_canvas, a, radius, color_a, 10);
draw_circle(G.viewport_canvas, b, radius, color_b, 10); draw_circle(G.ui_canvas, b, radius, color_b, 10);
struct v2 a_clipped = xform_mul_v2(G.world_view, collider_res.a1_clipped); struct v2 a_clipped = xform_mul_v2(G.world_view, collider_res.a1_clipped);
struct v2 b_clipped = xform_mul_v2(G.world_view, collider_res.b1_clipped); struct v2 b_clipped = xform_mul_v2(G.world_view, collider_res.b1_clipped);
draw_line(G.viewport_canvas, a_clipped, b_clipped, thickness, color_line_clipped); draw_line(G.ui_canvas, a_clipped, b_clipped, thickness, color_line_clipped);
draw_circle(G.viewport_canvas, a_clipped, radius, color_a_clipped, 10); draw_circle(G.ui_canvas, a_clipped, radius, color_a_clipped, 10);
draw_circle(G.viewport_canvas, b_clipped, radius, color_b_clipped, 10); draw_circle(G.ui_canvas, b_clipped, radius, color_b_clipped, 10);
} }
} }
@ -1268,7 +1273,7 @@ INTERNAL void user_update(void)
FMT_FLOAT_P(xform_get_rotation(e1_xf), 24)); FMT_FLOAT_P(xform_get_rotation(e1_xf), 24));
draw_text(G.viewport_canvas, disp_font, v2_add(v2_round(xform_mul_v2(G.world_view, V2(0, 0))), V2(0, offset_px)), text); draw_text(G.ui_canvas, disp_font, v2_add(v2_round(xform_mul_v2(G.world_view, V2(0, 0))), V2(0, offset_px)), text);
} }
} }
#endif #endif
@ -1284,8 +1289,8 @@ INTERNAL void user_update(void)
struct v2_array m = menkowski(temp.arena, &e0_collider, &e1_collider, e0_xf, e1_xf, detail); struct v2_array m = menkowski(temp.arena, &e0_collider, &e1_collider, e0_xf, e1_xf, detail);
for (u64 i = 0; i < m.count; ++i) m.points[i] = xform_mul_v2(G.world_view, m.points[i]); for (u64 i = 0; i < m.count; ++i) m.points[i] = xform_mul_v2(G.world_view, m.points[i]);
draw_poly_line(G.viewport_canvas, m, true, thickness, color); draw_poly_line(G.ui_canvas, m, true, thickness, color);
//draw_poly(G.viewport_canvas, m, color); //draw_poly(G.ui_canvas, m, color);
} }
/* Draw cloud */ /* Draw cloud */
@ -1297,7 +1302,7 @@ INTERNAL void user_update(void)
for (u64 i = 0; i < m.count; ++i) { for (u64 i = 0; i < m.count; ++i) {
struct v2 p = xform_mul_v2(G.world_view, m.points[i]); struct v2 p = xform_mul_v2(G.world_view, m.points[i]);
draw_circle(G.viewport_canvas, p, radius, color, 10); draw_circle(G.ui_canvas, p, radius, color, 10);
} }
} }
@ -1309,7 +1314,7 @@ INTERNAL void user_update(void)
f32 arrow_height = 5; f32 arrow_height = 5;
struct v2 start = xform_mul_v2(G.world_view, V2(0, 0)); struct v2 start = xform_mul_v2(G.world_view, V2(0, 0));
struct v2 end = xform_mul_v2(G.world_view, v2_mul(v2_norm(collider_res.normal), len)); struct v2 end = xform_mul_v2(G.world_view, v2_mul(v2_norm(collider_res.normal), len));
draw_arrow_line(G.viewport_canvas, start, end, arrow_thickness, arrow_height, color); draw_arrow_line(G.ui_canvas, start, end, arrow_thickness, arrow_height, color);
} }
/* Draw prototype */ /* Draw prototype */
@ -1322,8 +1327,8 @@ INTERNAL void user_update(void)
.count = collider_res.prototype.len .count = collider_res.prototype.len
}; };
for (u64 i = 0; i < m.count; ++i) m.points[i] = xform_mul_v2(G.world_view, m.points[i]); for (u64 i = 0; i < m.count; ++i) m.points[i] = xform_mul_v2(G.world_view, m.points[i]);
draw_poly_line(G.viewport_canvas, m, true, thickness, color); draw_poly_line(G.ui_canvas, m, true, thickness, color);
for (u64 i = 0; i < m.count; ++i) draw_circle(G.viewport_canvas, m.points[i], 10, color, 10); for (u64 i = 0; i < m.count; ++i) draw_circle(G.ui_canvas, m.points[i], 10, color, 10);
} }
/* Draw simplex */ /* Draw simplex */
@ -1341,18 +1346,18 @@ INTERNAL void user_update(void)
if (simplex.len >= 1) { if (simplex.len >= 1) {
u32 color = simplex.len == 1 ? color_first : (simplex.len == 2 ? color_second : color_third); u32 color = simplex.len == 1 ? color_first : (simplex.len == 2 ? color_second : color_third);
draw_circle(G.viewport_canvas, simplex_array.points[0], thickness * 3, color, 10); draw_circle(G.ui_canvas, simplex_array.points[0], thickness * 3, color, 10);
} }
if (simplex.len >= 2) { if (simplex.len >= 2) {
u32 color = simplex.len == 2 ? color_first : color_second; u32 color = simplex.len == 2 ? color_first : color_second;
draw_circle(G.viewport_canvas, simplex_array.points[1], thickness * 3, color, 10); draw_circle(G.ui_canvas, simplex_array.points[1], thickness * 3, color, 10);
} }
if (simplex.len >= 3) { if (simplex.len >= 3) {
u32 color = color_first; u32 color = color_first;
draw_circle(G.viewport_canvas, simplex_array.points[2], thickness * 3, color, 10); draw_circle(G.ui_canvas, simplex_array.points[2], thickness * 3, color, 10);
} }
if (simplex.len >= 2) { if (simplex.len >= 2) {
draw_poly_line(G.viewport_canvas, simplex_array, simplex.len > 2, thickness, line_color); draw_poly_line(G.ui_canvas, simplex_array, simplex.len > 2, thickness, line_color);
} }
} }
} }
@ -1369,7 +1374,7 @@ INTERNAL void user_update(void)
struct v2 start = xform_mul_v2(G.world_view, xf.og); struct v2 start = xform_mul_v2(G.world_view, xf.og);
struct v2 end = xform_mul_v2(G.world_view, parent_xf.og); struct v2 end = xform_mul_v2(G.world_view, parent_xf.og);
draw_arrow_line(G.viewport_canvas, start, end, thickness, arrow_height, color); draw_arrow_line(G.ui_canvas, start, end, thickness, arrow_height, color);
} }
/* Draw camera rect */ /* Draw camera rect */
@ -1381,7 +1386,7 @@ INTERNAL void user_update(void)
struct quad quad = xform_mul_quad(quad_xf, QUAD_UNIT_SQUARE_CENTERED); struct quad quad = xform_mul_quad(quad_xf, QUAD_UNIT_SQUARE_CENTERED);
quad = xform_mul_quad(G.world_view, quad); quad = xform_mul_quad(G.world_view, quad);
draw_quad_line(G.viewport_canvas, quad, thickness, color); draw_quad_line(G.ui_canvas, quad, thickness, color);
} }
arena_temp_end(temp); arena_temp_end(temp);
@ -1400,7 +1405,7 @@ INTERNAL void user_update(void)
struct v2 size = V2(t->width, t->height); struct v2 size = V2(t->width, t->height);
struct xform xf = XFORM_TRS(.t = crosshair_pos, .s = size); struct xform xf = XFORM_TRS(.t = crosshair_pos, .s = size);
struct quad quad = xform_mul_quad(xf, QUAD_UNIT_SQUARE_CENTERED); struct quad quad = xform_mul_quad(xf, QUAD_UNIT_SQUARE_CENTERED);
draw_quad_texture(G.viewport_canvas, DRAW_TEXTURE_PARAMS(.sprite = crosshair_tag, .tint = tint), quad); draw_quad_texture(G.ui_canvas, DRAW_TEXTURE_PARAMS(.sprite = crosshair_tag, .tint = tint), quad);
struct rect cursor_clip = RECT_FROM_V2(G.viewport_screen_offset, G.viewport_size); struct rect cursor_clip = RECT_FROM_V2(G.viewport_screen_offset, G.viewport_size);
cursor_clip.pos = v2_add(cursor_clip.pos, v2_mul(size, 0.5f)); cursor_clip.pos = v2_add(cursor_clip.pos, v2_mul(size, 0.5f));
@ -1519,65 +1524,65 @@ INTERNAL void user_update(void)
if (font) { if (font) {
struct temp_arena temp = arena_temp_begin(scratch.arena); struct temp_arena temp = arena_temp_begin(scratch.arena);
draw_text(G.viewport_canvas, font, pos, string_format(temp.arena, STR("time: %F"), FMT_FLOAT((f64)G.time))); draw_text(G.ui_canvas, font, pos, string_format(temp.arena, STR("time: %F"), FMT_FLOAT((f64)G.time)));
pos.y += spacing; pos.y += spacing;
draw_text(G.viewport_canvas, font, pos, string_format(temp.arena, STR("world time: %F"), FMT_FLOAT((f64)G.world.time))); draw_text(G.ui_canvas, font, pos, string_format(temp.arena, STR("world time: %F"), FMT_FLOAT((f64)G.world.time)));
pos.y += spacing; pos.y += spacing;
//draw_text(G.viewport_canvas, font, pos, string_format(temp.arena, STR("time - world time: %F"), FMT_FLOAT((f64)G.time - (f64)G.world.time))); //draw_text(G.ui_canvas, font, pos, string_format(temp.arena, STR("time - world time: %F"), FMT_FLOAT((f64)G.time - (f64)G.world.time)));
//pos.y += spacing; //pos.y += spacing;
draw_text(G.viewport_canvas, font, pos, string_format(temp.arena, STR("entities: %F/%F"), FMT_UINT(G.world.entity_store->allocated), FMT_UINT(G.world.entity_store->reserved))); draw_text(G.ui_canvas, font, pos, string_format(temp.arena, STR("entities: %F/%F"), FMT_UINT(G.world.entity_store->allocated), FMT_UINT(G.world.entity_store->reserved)));
pos.y += spacing; pos.y += spacing;
draw_text(G.viewport_canvas, font, pos, string_format(temp.arena, STR("screen_size: (%F, %F)"), FMT_FLOAT((f64)G.screen_size.x), FMT_FLOAT((f64)G.screen_size.y))); draw_text(G.ui_canvas, font, pos, string_format(temp.arena, STR("screen_size: (%F, %F)"), FMT_FLOAT((f64)G.screen_size.x), FMT_FLOAT((f64)G.screen_size.y)));
pos.y += spacing; pos.y += spacing;
draw_text(G.viewport_canvas, font, pos, string_format(temp.arena, STR("screen_cursor: (%F, %F)"), FMT_FLOAT((f64)G.screen_cursor.x), FMT_FLOAT((f64)G.screen_cursor.y))); draw_text(G.ui_canvas, font, pos, string_format(temp.arena, STR("screen_cursor: (%F, %F)"), FMT_FLOAT((f64)G.screen_cursor.x), FMT_FLOAT((f64)G.screen_cursor.y)));
pos.y += spacing; pos.y += spacing;
draw_text(G.viewport_canvas, font, pos, string_format(temp.arena, STR("viewport_screen_offset: (%F, %F)"), FMT_FLOAT((f64)G.viewport_screen_offset.x), FMT_FLOAT((f64)G.viewport_screen_offset.y))); draw_text(G.ui_canvas, font, pos, string_format(temp.arena, STR("viewport_screen_offset: (%F, %F)"), FMT_FLOAT((f64)G.viewport_screen_offset.x), FMT_FLOAT((f64)G.viewport_screen_offset.y)));
pos.y += spacing; pos.y += spacing;
draw_text(G.viewport_canvas, font, pos, string_format(temp.arena, STR("viewport_size: (%F, %F)"), FMT_FLOAT((f64)G.viewport_size.x), FMT_FLOAT((f64)G.viewport_size.y))); draw_text(G.ui_canvas, font, pos, string_format(temp.arena, STR("viewport_size: (%F, %F)"), FMT_FLOAT((f64)G.viewport_size.x), FMT_FLOAT((f64)G.viewport_size.y)));
pos.y += spacing; pos.y += spacing;
draw_text(G.viewport_canvas, font, pos, string_format(temp.arena, STR("viewport_center: (%F, %F)"), FMT_FLOAT((f64)G.viewport_center.x), FMT_FLOAT((f64)G.viewport_center.y))); draw_text(G.ui_canvas, font, pos, string_format(temp.arena, STR("viewport_center: (%F, %F)"), FMT_FLOAT((f64)G.viewport_center.x), FMT_FLOAT((f64)G.viewport_center.y)));
pos.y += spacing; pos.y += spacing;
draw_text(G.viewport_canvas, font, pos, string_format(temp.arena, STR("viewport_cursor: (%F, %F)"), FMT_FLOAT((f64)G.viewport_cursor.x), FMT_FLOAT((f64)G.viewport_cursor.y))); draw_text(G.ui_canvas, font, pos, string_format(temp.arena, STR("viewport_cursor: (%F, %F)"), FMT_FLOAT((f64)G.viewport_cursor.x), FMT_FLOAT((f64)G.viewport_cursor.y)));
pos.y += spacing; pos.y += spacing;
draw_text(G.viewport_canvas, font, pos, string_format(temp.arena, STR("world_view.og: (%F, %F)"), FMT_FLOAT((f64)G.world_view.og.x), FMT_FLOAT((f64)G.world_view.og.y))); draw_text(G.ui_canvas, font, pos, string_format(temp.arena, STR("world_view.og: (%F, %F)"), FMT_FLOAT((f64)G.world_view.og.x), FMT_FLOAT((f64)G.world_view.og.y)));
pos.y += spacing; pos.y += spacing;
draw_text(G.viewport_canvas, font, pos, string_format(temp.arena, STR("world_view rotation: %F"), FMT_FLOAT((f64)xform_get_rotation(G.world_view)))); draw_text(G.ui_canvas, font, pos, string_format(temp.arena, STR("world_view rotation: %F"), FMT_FLOAT((f64)xform_get_rotation(G.world_view))));
pos.y += spacing; pos.y += spacing;
draw_text(G.viewport_canvas, font, pos, string_format(temp.arena, STR("world_view scale: (%F, %F)"), FMT_FLOAT((f64)xform_get_scale(G.world_view).x), FMT_FLOAT((f64)xform_get_scale(G.world_view).x))); draw_text(G.ui_canvas, font, pos, string_format(temp.arena, STR("world_view scale: (%F, %F)"), FMT_FLOAT((f64)xform_get_scale(G.world_view).x), FMT_FLOAT((f64)xform_get_scale(G.world_view).x)));
pos.y += spacing; pos.y += spacing;
draw_text(G.viewport_canvas, font, pos, string_format(temp.arena, STR("world_cursor: (%F, %F)"), FMT_FLOAT((f64)G.world_cursor.x), FMT_FLOAT((f64)G.world_cursor.y))); draw_text(G.ui_canvas, font, pos, string_format(temp.arena, STR("world_cursor: (%F, %F)"), FMT_FLOAT((f64)G.world_cursor.x), FMT_FLOAT((f64)G.world_cursor.y)));
pos.y += spacing; pos.y += spacing;
draw_text(G.viewport_canvas, font, pos, string_format(temp.arena, STR("debug_camera: %F"), FMT_STR(G.debug_camera ? STR("true") : STR("false")))); draw_text(G.ui_canvas, font, pos, string_format(temp.arena, STR("debug_camera: %F"), FMT_STR(G.debug_camera ? STR("true") : STR("false"))));
pos.y += spacing; pos.y += spacing;
struct v2 player_linear_vel = entity_find_first_match_one(store, ENTITY_PROP_PLAYER_CONTROLLED)->linear_velocity; struct v2 player_linear_vel = entity_find_first_match_one(store, ENTITY_PROP_PLAYER_CONTROLLED)->linear_velocity;
draw_text(G.viewport_canvas, font, pos, string_format(temp.arena, STR("player linear velocity: (%F, %F)"), FMT_FLOAT_P((f64)player_linear_vel.x, 12), FMT_FLOAT_P((f64)player_linear_vel.y, 12))); draw_text(G.ui_canvas, font, pos, string_format(temp.arena, STR("player linear velocity: (%F, %F)"), FMT_FLOAT_P((f64)player_linear_vel.x, 12), FMT_FLOAT_P((f64)player_linear_vel.y, 12)));
pos.y += spacing; pos.y += spacing;
f32 player_angular_vel = entity_find_first_match_one(store, ENTITY_PROP_PLAYER_CONTROLLED)->angular_velocity; f32 player_angular_vel = entity_find_first_match_one(store, ENTITY_PROP_PLAYER_CONTROLLED)->angular_velocity;
draw_text(G.viewport_canvas, font, pos, string_format(temp.arena, STR("player angular velocity: %F"), FMT_FLOAT_P((f64)player_angular_vel, 12))); draw_text(G.ui_canvas, font, pos, string_format(temp.arena, STR("player angular velocity: %F"), FMT_FLOAT_P((f64)player_angular_vel, 12)));
pos.y += spacing; pos.y += spacing;
struct v2 player_pos = entity_get_xform(entity_find_first_match_one(store, ENTITY_PROP_PLAYER_CONTROLLED)).og; struct v2 player_pos = entity_get_xform(entity_find_first_match_one(store, ENTITY_PROP_PLAYER_CONTROLLED)).og;
draw_text(G.viewport_canvas, font, pos, string_format(temp.arena, STR("player pos: (%F, %F)"), FMT_FLOAT_P((f64)player_pos.x, 12), FMT_FLOAT_P((f64)player_pos.y, 12))); draw_text(G.ui_canvas, font, pos, string_format(temp.arena, STR("player pos: (%F, %F)"), FMT_FLOAT_P((f64)player_pos.x, 12), FMT_FLOAT_P((f64)player_pos.y, 12)));
pos.y += spacing; pos.y += spacing;
#if COLLIDER_DEBUG #if COLLIDER_DEBUG
draw_text(G.viewport_canvas, font, pos, string_format(temp.arena, STR("collider gjk steps: %F"), FMT_UINT(collider_debug_steps))); draw_text(G.ui_canvas, font, pos, string_format(temp.arena, STR("collider gjk steps: %F"), FMT_UINT(collider_debug_steps)));
pos.y += spacing; pos.y += spacing;
#endif #endif
@ -1594,55 +1599,93 @@ INTERNAL void user_update(void)
* ========================== */ * ========================== */
{ {
__profscope(render);
struct rect target_viewport = RECT_FROM_V2(V2(0, 0), G.viewport_size); struct rect target_viewport = RECT_FROM_V2(V2(0, 0), G.viewport_size);
struct rect backbuffer_viewport = RECT_FROM_V2(V2(0, 0), G.screen_size); struct rect backbuffer_viewport = RECT_FROM_V2(V2(0, 0), G.screen_size);
/* Allocate target texture */ /* Allocate rt textures */
struct renderer_handle target; struct v2 final_rt_resolution = G.viewport_size;
struct v2 ui_rt_resolution = final_rt_resolution;
struct v2 world_rt_resolution = V2(target_viewport.width + target_viewport.x, target_viewport.height + target_viewport.y);
{ {
struct v2 size = ZI; /* World rt */
size.x = target_viewport.width + target_viewport.x; if (renderer_handle_is_nil(G.world_rt) || !v2_eq(G.world_rt_resolution, world_rt_resolution)) {
size.y = target_viewport.height + target_viewport.y; if (!renderer_handle_is_nil(G.world_rt)) {
if (renderer_handle_is_nil(G.render_target) || !v2_eq(size, G.render_target_resolution)) { renderer_texture_release(G.world_rt);
if (!renderer_handle_is_nil(G.render_target)) {
renderer_texture_release(G.render_target);
} }
G.render_target = renderer_texture_target_alloc(size); G.world_rt_resolution = world_rt_resolution;
G.render_target_resolution = size; G.world_rt = renderer_texture_target_alloc(G.world_rt_resolution);
} }
target = G.render_target; /* Ui rt */
if (renderer_handle_is_nil(G.ui_rt) || !v2_eq(G.ui_rt_resolution, ui_rt_resolution)) {
if (!renderer_handle_is_nil(G.ui_rt)) {
renderer_texture_release(G.ui_rt);
}
G.ui_rt_resolution = ui_rt_resolution;
G.ui_rt = renderer_texture_target_alloc(G.ui_rt_resolution);
}
/* Final rt */
if (renderer_handle_is_nil(G.final_rt) || !v2_eq(G.final_rt_resolution, final_rt_resolution)) {
if (!renderer_handle_is_nil(G.final_rt)) {
renderer_texture_release(G.final_rt);
}
G.final_rt_resolution = final_rt_resolution;
G.final_rt = renderer_texture_target_alloc(G.final_rt_resolution);
}
}
if (!v2_eq(G.backbuffer_size, G.screen_size)) {
G.backbuffer_size = G.screen_size;
renderer_resize_backbuffer(G.backbuffer_size);
} }
/* Draw target texture to backbuffer */
{ {
struct draw_texture_params params = DRAW_TEXTURE_PARAMS(.texture = target); /* Draw world texture to final */
struct rect rect = RECT_FROM_V2(G.viewport_screen_offset, G.viewport_size); {
struct quad quad = quad_from_rect(rect); struct draw_texture_params params = DRAW_TEXTURE_PARAMS(.texture = G.world_rt);
struct quad quad = quad_from_rect(RECT_FROM_V2(V2(0, 0), final_rt_resolution));
draw_quad_texture(G.final_canvas, params, quad);
}
/* Draw ui texture to final */
{
struct draw_texture_params params = DRAW_TEXTURE_PARAMS(.texture = G.ui_rt);
struct quad quad = quad_from_rect(RECT_FROM_V2(V2(0, 0), final_rt_resolution));
draw_quad_texture(G.final_canvas, params, quad);
}
/* Draw final texture to backbuffer */
{
struct draw_texture_params params = DRAW_TEXTURE_PARAMS(.texture = G.final_rt);
struct quad quad = quad_from_rect(RECT_FROM_V2(G.viewport_screen_offset, G.viewport_size));
draw_quad_texture(G.backbuffer_canvas, params, quad); draw_quad_texture(G.backbuffer_canvas, params, quad);
} }
}
/* Send canvases to GPU */ /* Send canvases to GPU */
renderer_canvas_send_to_gpu(G.viewport_bg_canvas);
renderer_canvas_send_to_gpu(G.world_canvas); renderer_canvas_send_to_gpu(G.world_canvas);
renderer_canvas_send_to_gpu(G.viewport_canvas); renderer_canvas_send_to_gpu(G.ui_canvas);
renderer_canvas_send_to_gpu(G.final_canvas);
renderer_canvas_send_to_gpu(G.backbuffer_canvas); renderer_canvas_send_to_gpu(G.backbuffer_canvas);
/* Execute render cmds */ /* Execute render cmds */
{ {
/* Clear textures */ /* Clear textures */
renderer_render_to_texture(target, NULL, RGBA_32_F(0.2f, 0.2f, 0.2f, 1.f), XFORM_IDENT, target_viewport, sprite_frame_scope); renderer_clear_texture(G.world_rt, RGBA_32_F(0.2f, 0.2f, 0.2f, 1.f));
renderer_render_to_backbuffer(G.screen_size, NULL, COLOR_BLACK, XFORM_IDENT, target_viewport, sprite_frame_scope); renderer_clear_texture(G.ui_rt, RGBA_32_F(0, 0, 0, 0));
renderer_clear_texture(G.final_rt, RGBA_32_F(0, 0, 0, 0));
renderer_clear_backbuffer(RGBA_32_F(0, 0, 0, 1));
/* Render to target */ /* Render to world texture */
renderer_render_to_texture(target, G.viewport_bg_canvas, 0, XFORM_IDENT, target_viewport, sprite_frame_scope); renderer_render_to_texture(G.world_rt, G.world_canvas, G.world_view, target_viewport, sprite_frame_scope);
if (!tick_is_first_frame) {
/* Only draw world canvas past first tick */ /* Render to UI texture */
renderer_render_to_texture(target, G.world_canvas, 0, G.world_view, target_viewport, sprite_frame_scope); renderer_render_to_texture(G.ui_rt, G.ui_canvas, XFORM_IDENT, target_viewport, sprite_frame_scope);
}
renderer_render_to_texture(target, G.viewport_canvas, 0, XFORM_IDENT, target_viewport, sprite_frame_scope); /* Render to final texture */
renderer_render_to_texture(G.final_rt, G.final_canvas, XFORM_IDENT, target_viewport, sprite_frame_scope);
/* Render to backbuffer */ /* Render to backbuffer */
renderer_render_to_backbuffer(G.screen_size, G.backbuffer_canvas, 0, XFORM_IDENT, backbuffer_viewport, sprite_frame_scope); renderer_render_to_backbuffer(G.backbuffer_canvas, XFORM_IDENT, backbuffer_viewport, sprite_frame_scope);
} }
/* Present */ /* Present */