render to texture
This commit is contained in:
parent
a015143f5c
commit
acced9dfed
14
src/draw.c
14
src/draw.c
@ -20,7 +20,7 @@ struct draw_startup_receipt draw_startup(struct renderer_startup_receipt *render
|
|||||||
(UNUSED)renderer_sr;
|
(UNUSED)renderer_sr;
|
||||||
(UNUSED)font_sr;
|
(UNUSED)font_sr;
|
||||||
u32 pixel_white = 0xFFFFFFFF;
|
u32 pixel_white = 0xFFFFFFFF;
|
||||||
G.solid_white = renderer_texture_alloc((struct image_rgba) { .width = 1, .height = 1, .pixels = &pixel_white } );
|
G.solid_white = renderer_texture_image_alloc((struct image_rgba) { .width = 1, .height = 1, .pixels = &pixel_white } );
|
||||||
return (struct draw_startup_receipt) { 0 };
|
return (struct draw_startup_receipt) { 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ struct draw_startup_receipt draw_startup(struct renderer_startup_receipt *render
|
|||||||
* Texture
|
* Texture
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
void draw_quad_sprite_ex(struct renderer_canvas *canvas, struct renderer_handle texture, struct sprite_tag sprite, struct clip_rect clip, u32 tint0, u32 tint1, struct quad quad)
|
void draw_quad_texture_ex(struct renderer_canvas *canvas, struct renderer_handle texture, struct sprite_tag sprite, struct clip_rect clip, u32 tint0, u32 tint1, struct quad quad)
|
||||||
{
|
{
|
||||||
struct renderer_cmd_parameters cmd_params = ZI;
|
struct renderer_cmd_parameters cmd_params = ZI;
|
||||||
cmd_params.kind = SHADER_TEXTURE;
|
cmd_params.kind = SHADER_TEXTURE;
|
||||||
@ -76,9 +76,9 @@ void draw_quad_sprite_ex(struct renderer_canvas *canvas, struct renderer_handle
|
|||||||
indices[5] = offset + 3;
|
indices[5] = offset + 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_quad_sprite(struct renderer_canvas *canvas, struct draw_sprite_params params, struct quad quad)
|
void draw_quad_texture(struct renderer_canvas *canvas, struct draw_texture_params params, struct quad quad)
|
||||||
{
|
{
|
||||||
draw_quad_sprite_ex(canvas, renderer_handle_nil(), params.sprite, params.clip, params.tint, params.tint, quad);
|
draw_quad_texture_ex(canvas, params.texture, params.sprite, params.clip, params.tint, params.tint, quad);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -144,7 +144,7 @@ void draw_circle(struct renderer_canvas *canvas, struct v2 pos, f32 radius, u32
|
|||||||
|
|
||||||
void draw_quad(struct renderer_canvas *canvas, struct quad quad, u32 color)
|
void draw_quad(struct renderer_canvas *canvas, struct quad quad, u32 color)
|
||||||
{
|
{
|
||||||
draw_quad_sprite_ex(canvas, G.solid_white, sprite_tag_nil(), CLIP_ALL, color, color, quad);
|
draw_quad_texture_ex(canvas, G.solid_white, sprite_tag_nil(), CLIP_ALL, color, color, quad);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -154,7 +154,7 @@ void draw_quad(struct renderer_canvas *canvas, struct quad quad, u32 color)
|
|||||||
void draw_gradient_line(struct renderer_canvas *canvas, struct v2 start, struct v2 end, f32 thickness, u32 color_start, u32 color_end)
|
void draw_gradient_line(struct renderer_canvas *canvas, struct v2 start, struct v2 end, f32 thickness, u32 color_start, u32 color_end)
|
||||||
{
|
{
|
||||||
struct quad quad = quad_from_line(start, end, thickness);
|
struct quad quad = quad_from_line(start, end, thickness);
|
||||||
draw_quad_sprite_ex(canvas, G.solid_white, sprite_tag_nil(), CLIP_ALL, color_start, color_end, quad);
|
draw_quad_texture_ex(canvas, G.solid_white, sprite_tag_nil(), CLIP_ALL, color_start, color_end, quad);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_line(struct renderer_canvas *canvas, struct v2 start, struct v2 end, f32 thickness, u32 color)
|
void draw_line(struct renderer_canvas *canvas, struct v2 start, struct v2 end, f32 thickness, u32 color)
|
||||||
@ -365,7 +365,7 @@ void draw_text_ex(struct renderer_canvas *canvas, struct font *font, struct v2 p
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct quad quad = quad_from_rect(RECT(x, y, width, height));
|
struct quad quad = quad_from_rect(RECT(x, y, width, height));
|
||||||
draw_quad_sprite_ex(canvas, font->image_renderer_handle, sprite_tag_nil(), clip, 0xFFFFFFFF, 0xFFFFFFFF, quad);
|
draw_quad_texture_ex(canvas, font->image_renderer_handle, sprite_tag_nil(), clip, 0xFFFFFFFF, 0xFFFFFFFF, quad);
|
||||||
|
|
||||||
draw_pos.x += glyph->advance * scale;
|
draw_pos.x += glyph->advance * scale;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,13 +6,14 @@ struct font;
|
|||||||
struct renderer_startup_receipt;
|
struct renderer_startup_receipt;
|
||||||
struct font_startup_receipt;
|
struct font_startup_receipt;
|
||||||
|
|
||||||
#define DRAW_SPRITE_PARAMS(...) ((struct draw_sprite_params) { \
|
#define DRAW_TEXTURE_PARAMS(...) ((struct draw_texture_params) { \
|
||||||
.tint = COLOR_WHITE, \
|
.tint = COLOR_WHITE, \
|
||||||
.clip = CLIP_ALL, \
|
.clip = CLIP_ALL, \
|
||||||
__VA_ARGS__ \
|
__VA_ARGS__ \
|
||||||
})
|
})
|
||||||
|
|
||||||
struct draw_sprite_params {
|
struct draw_texture_params {
|
||||||
|
struct renderer_handle texture; /* Overrides sprite if set */
|
||||||
struct sprite_tag sprite;
|
struct sprite_tag sprite;
|
||||||
struct clip_rect clip;
|
struct clip_rect clip;
|
||||||
u32 tint;
|
u32 tint;
|
||||||
@ -22,8 +23,8 @@ struct draw_startup_receipt { i32 _; };
|
|||||||
struct draw_startup_receipt draw_startup(struct renderer_startup_receipt *renderer_sr,
|
struct draw_startup_receipt draw_startup(struct renderer_startup_receipt *renderer_sr,
|
||||||
struct font_startup_receipt *font_sr);
|
struct font_startup_receipt *font_sr);
|
||||||
|
|
||||||
void draw_quad_sprite_ex(struct renderer_canvas *canvas, struct renderer_handle texture, struct sprite_tag sprite, struct clip_rect clip, u32 tint0, u32 tint1, struct quad quad);
|
void draw_quad_texture_ex(struct renderer_canvas *canvas, struct renderer_handle texture, struct sprite_tag sprite, struct clip_rect clip, u32 tint0, u32 tint1, struct quad quad);
|
||||||
void draw_quad_sprite(struct renderer_canvas *canvas, struct draw_sprite_params params, struct quad quad);
|
void draw_quad_texture(struct renderer_canvas *canvas, struct draw_texture_params params, struct quad quad);
|
||||||
|
|
||||||
void draw_poly(struct renderer_canvas *canvas, struct v2_array array, u32 color);
|
void draw_poly(struct renderer_canvas *canvas, struct v2_array array, u32 color);
|
||||||
void draw_circle(struct renderer_canvas *canvas, struct v2 pos, f32 radius, u32 color, u32 detail);
|
void draw_circle(struct renderer_canvas *canvas, struct v2 pos, f32 radius, u32 color, u32 detail);
|
||||||
|
|||||||
@ -120,7 +120,7 @@ INTERNAL WORK_TASK_FUNC_DEF(font_load_asset_task, vparams)
|
|||||||
resource_close(res);
|
resource_close(res);
|
||||||
|
|
||||||
/* Send texture to GPU */
|
/* Send texture to GPU */
|
||||||
struct renderer_handle image_renderer_handle = renderer_texture_alloc(result.image_data);
|
struct renderer_handle image_renderer_handle = renderer_texture_image_alloc(result.image_data);
|
||||||
|
|
||||||
/* Allocate store memory */
|
/* Allocate store memory */
|
||||||
struct font *font = NULL;
|
struct font *font = NULL;
|
||||||
|
|||||||
@ -62,11 +62,6 @@ struct renderer_canvas *renderer_canvas_alloc(void);
|
|||||||
|
|
||||||
void renderer_canvas_release(struct renderer_canvas *canvas);
|
void renderer_canvas_release(struct renderer_canvas *canvas);
|
||||||
|
|
||||||
/* Set the canvas view xform to be used when presenting the canvas.
|
|
||||||
* NOTE: `view` should be in row-major order.
|
|
||||||
*/
|
|
||||||
void renderer_canvas_set_view(struct renderer_canvas *canvas, struct xform view);
|
|
||||||
|
|
||||||
/* Pushes array of vertices based on `vertices_count` & `indices_count`.
|
/* Pushes array of vertices based on `vertices_count` & `indices_count`.
|
||||||
* Sets `vertices_out` and `indices_out` to start of the pushed arrays, to be filled out by the caller.
|
* Sets `vertices_out` and `indices_out` to start of the pushed arrays, to be filled out by the caller.
|
||||||
* Returns the index of the first vertex. Each inserted index should be incremented by this.
|
* Returns the index of the first vertex. Each inserted index should be incremented by this.
|
||||||
@ -83,15 +78,25 @@ 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_canvas_present(struct renderer_canvas **canvases, u32 canvases_count, struct v2 screen_size, struct rect viewport, i32 vsync, struct sprite_scope *sprite_scope);
|
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_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_present_backbuffer(i32 vsync);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Texture
|
* Texture
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INLINE struct renderer_handle renderer_handle_nil(void) { return (struct renderer_handle) { 0 }; }
|
INLINE struct renderer_handle renderer_handle_nil(void) { return (struct renderer_handle) { 0 }; }
|
||||||
|
INLINE b32 renderer_handle_is_nil(struct renderer_handle h) { return h.v[0] == 0; }
|
||||||
|
|
||||||
|
/* Allocates a texture on the GPU filled with supplied image data */
|
||||||
|
struct renderer_handle renderer_texture_image_alloc(struct image_rgba data);
|
||||||
|
|
||||||
|
/* Allocates a texture on the GPU that can be rendered to */
|
||||||
|
struct renderer_handle renderer_texture_target_alloc(struct v2 size);
|
||||||
|
|
||||||
struct renderer_handle renderer_texture_alloc(struct image_rgba data);
|
|
||||||
void renderer_texture_release(struct renderer_handle handle);
|
void renderer_texture_release(struct renderer_handle handle);
|
||||||
b32 renderer_texture_is_nil(struct renderer_handle handle);
|
b32 renderer_texture_is_nil(struct renderer_handle handle);
|
||||||
|
|
||||||
|
|||||||
@ -20,6 +20,7 @@
|
|||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
|
||||||
#pragma comment(lib, "d3d11")
|
#pragma comment(lib, "d3d11")
|
||||||
|
#pragma comment(lib, "dxgi")
|
||||||
#pragma comment(lib, "dxguid")
|
#pragma comment(lib, "dxguid")
|
||||||
#pragma comment(lib, "d3dcompiler")
|
#pragma comment(lib, "d3dcompiler")
|
||||||
|
|
||||||
@ -84,12 +85,10 @@ struct renderer_canvas {
|
|||||||
struct cmd_store cpu_cmd_store;
|
struct cmd_store cpu_cmd_store;
|
||||||
struct cmd_store gpu_cmd_store;
|
struct cmd_store gpu_cmd_store;
|
||||||
|
|
||||||
struct xform view;
|
|
||||||
|
|
||||||
b32 valid; /* False if uninitialized (in sparse array) */
|
b32 valid; /* False if uninitialized (in sparse array) */
|
||||||
};
|
};
|
||||||
|
|
||||||
INTERNAL void renderer_capture_image_for_profiler(f32 width, f32 height);
|
INTERNAL void renderer_capture_image_for_profiler(void);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Global state
|
* Global state
|
||||||
@ -124,11 +123,9 @@ GLOBAL struct {
|
|||||||
ID3D11DeviceContext *devcon;
|
ID3D11DeviceContext *devcon;
|
||||||
|
|
||||||
IDXGISwapChain1 *swapchain;
|
IDXGISwapChain1 *swapchain;
|
||||||
ID3D11RenderTargetView *backbuffer_view;
|
|
||||||
|
|
||||||
/* Here for caching/comparison */
|
/* For caching/comparison */
|
||||||
struct v2 backbuffer_size;
|
struct v2 backbuffer_size;
|
||||||
struct rect viewport;
|
|
||||||
|
|
||||||
ID3D11BlendState *blend_state;
|
ID3D11BlendState *blend_state;
|
||||||
ID3D11RasterizerState *rasterizer_state;
|
ID3D11RasterizerState *rasterizer_state;
|
||||||
@ -433,7 +430,7 @@ struct renderer_startup_receipt renderer_startup(struct sys_window *window)
|
|||||||
/* Create D3D11 device & context */
|
/* Create D3D11 device & context */
|
||||||
{
|
{
|
||||||
#if D3D11_DEBUG
|
#if D3D11_DEBUG
|
||||||
u32 flags = D3D11_CREATE_DEVICE_DEBUG : 0;
|
u32 flags = D3D11_CREATE_DEVICE_DEBUG;
|
||||||
#else
|
#else
|
||||||
u32 flags = 0;
|
u32 flags = 0;
|
||||||
#endif
|
#endif
|
||||||
@ -648,7 +645,6 @@ struct renderer_canvas *renderer_canvas_alloc(void)
|
|||||||
MEMZERO_STRUCT(canvas);
|
MEMZERO_STRUCT(canvas);
|
||||||
canvas->cpu_cmd_store.arena = arena_alloc(GIGABYTE(8));
|
canvas->cpu_cmd_store.arena = arena_alloc(GIGABYTE(8));
|
||||||
canvas->gpu_cmd_store.arena = arena_alloc(GIGABYTE(8));
|
canvas->gpu_cmd_store.arena = arena_alloc(GIGABYTE(8));
|
||||||
canvas->view = xform_from_trs(TRS());
|
|
||||||
canvas->valid = true;
|
canvas->valid = true;
|
||||||
|
|
||||||
/* Initialize buffers */
|
/* Initialize buffers */
|
||||||
@ -679,11 +675,6 @@ void renderer_canvas_release(struct renderer_canvas *canvas)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderer_canvas_set_view(struct renderer_canvas *canvas, struct xform view)
|
|
||||||
{
|
|
||||||
canvas->view = view;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 renderer_canvas_push_vertices(struct renderer_canvas *canvas, u8 **vertices_out, vidx **indices_out, u32 vertices_count, u32 indices_count)
|
u32 renderer_canvas_push_vertices(struct renderer_canvas *canvas, u8 **vertices_out, vidx **indices_out, u32 vertices_count, u32 indices_count)
|
||||||
{
|
{
|
||||||
struct renderer_cmd *cmd = canvas->cpu_cmd_store.cmd_last;
|
struct renderer_cmd *cmd = canvas->cpu_cmd_store.cmd_last;
|
||||||
@ -835,40 +826,14 @@ void renderer_canvas_send_to_gpu(struct renderer_canvas *canvas)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Present canvas
|
* Render
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INTERNAL void resize_backbuffer(struct v2 size)
|
INTERNAL void resize_backbuffer(struct v2 size)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
/* TODO: error handling */
|
|
||||||
|
|
||||||
/* Release all outstanding references to the swap chain's buffers. */
|
|
||||||
if (G.backbuffer_view) {
|
|
||||||
ID3D11RenderTargetView_Release(G.backbuffer_view);
|
|
||||||
}
|
|
||||||
|
|
||||||
IDXGISwapChain_ResizeBuffers(G.swapchain, 0, (UINT)size.x, (UINT)size.y, DXGI_FORMAT_UNKNOWN, 0);
|
IDXGISwapChain_ResizeBuffers(G.swapchain, 0, (UINT)size.x, (UINT)size.y, DXGI_FORMAT_UNKNOWN, 0);
|
||||||
|
G.backbuffer_size = size;
|
||||||
/* Get buffer and create a render-target-view. */
|
|
||||||
ID3D11Texture2D *backbuffer_texture = NULL;
|
|
||||||
IDXGISwapChain_GetBuffer(G.swapchain, 0, &IID_ID3D11Texture2D, (LPVOID *)&backbuffer_texture);
|
|
||||||
|
|
||||||
ID3D11Device_CreateRenderTargetView(G.dev, (ID3D11Resource *)backbuffer_texture, NULL, &G.backbuffer_view);
|
|
||||||
ID3D11Texture2D_Release(backbuffer_texture);
|
|
||||||
}
|
|
||||||
|
|
||||||
INTERNAL void resize_viewport(struct rect viewport)
|
|
||||||
{
|
|
||||||
D3D11_VIEWPORT d3d11_viewport = {
|
|
||||||
.Width = viewport.width,
|
|
||||||
.Height = viewport.height,
|
|
||||||
.MinDepth = 0.0f,
|
|
||||||
.MaxDepth = 1.0f,
|
|
||||||
.TopLeftX = viewport.x,
|
|
||||||
.TopLeftY = viewport.y
|
|
||||||
};
|
|
||||||
ID3D11DeviceContext_RSSetViewports(G.devcon, 1, &d3d11_viewport);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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).
|
||||||
@ -876,42 +841,39 @@ INTERNAL void resize_viewport(struct rect viewport)
|
|||||||
* 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 */
|
||||||
void renderer_canvas_present(struct renderer_canvas **canvases, u32 canvases_count, struct v2 screen_size, struct rect viewport, i32 vsync, struct sprite_scope *sprite_scope)
|
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)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
|
ID3D11DeviceContext_OMSetRenderTargets(G.devcon, 1, &target, NULL);
|
||||||
|
|
||||||
/* Resize back buffer */
|
D3D11_VIEWPORT d3d11_viewport = ZI;
|
||||||
if (!v2_eq(G.backbuffer_size, screen_size)) {
|
d3d11_viewport.Width = viewport.width;
|
||||||
resize_backbuffer(screen_size);
|
d3d11_viewport.Height = viewport.height;
|
||||||
G.backbuffer_size = screen_size;
|
d3d11_viewport.MinDepth = 0.0f;
|
||||||
}
|
d3d11_viewport.MaxDepth = 1.0f;
|
||||||
|
d3d11_viewport.TopLeftX = viewport.x;
|
||||||
if (!rect_eq(G.viewport, viewport)) {
|
d3d11_viewport.TopLeftY = viewport.y;
|
||||||
resize_viewport(viewport);
|
ID3D11DeviceContext_RSSetViewports(G.devcon, 1, &d3d11_viewport);
|
||||||
G.viewport = viewport;
|
|
||||||
}
|
|
||||||
|
|
||||||
ID3D11DeviceContext_OMSetRenderTargets(G.devcon, 1, &G.backbuffer_view, NULL);
|
|
||||||
|
|
||||||
/* Clear back buffer */
|
|
||||||
f32 clear_color[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
|
||||||
ID3D11DeviceContext_ClearRenderTargetView(G.devcon, G.backbuffer_view, clear_color);
|
|
||||||
|
|
||||||
/* Set draw mode */
|
|
||||||
|
|
||||||
for (u32 i = 0; i < canvases_count; ++i) {
|
|
||||||
struct renderer_canvas *canvas = canvases[i];
|
|
||||||
|
|
||||||
/* Fill and set constant buffer
|
/* Fill and set constant buffer
|
||||||
* NOTE: We're only doing this once per canvas, rather than once per draw call since
|
* NOTE: We're only doing this once per render, rather than once per
|
||||||
* the only constant right now is VP. */
|
* draw call since the only constant right now is VP. */
|
||||||
struct mat4x4 vp_matrix = calculate_vp(canvas->view, viewport.width, viewport.height);
|
struct mat4x4 vp_matrix = calculate_vp(view, viewport.width, viewport.height);
|
||||||
send_constant_buffer_data(G.vs_constant_buffer, vp_matrix);
|
send_constant_buffer_data(G.vs_constant_buffer, vp_matrix);
|
||||||
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;
|
||||||
struct renderer_handle last_texture_handle = ZI;
|
if (clear_color) {
|
||||||
for (struct renderer_cmd *cmd = canvas->gpu_cmd_store.cmd_first; cmd; cmd = cmd->next) {
|
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;
|
||||||
|
for (; cmd; cmd = cmd->next) {
|
||||||
struct dx11_shader *shader = cmd->shader;
|
struct dx11_shader *shader = cmd->shader;
|
||||||
struct dx11_buffer *buffer = &canvas->buffers[shader->kind];
|
struct dx11_buffer *buffer = &canvas->buffers[shader->kind];
|
||||||
|
|
||||||
@ -938,6 +900,7 @@ void renderer_canvas_present(struct renderer_canvas **canvases, u32 canvases_cou
|
|||||||
/* Load texture if handle is set */
|
/* Load texture if handle is set */
|
||||||
texture_loaded = true;
|
texture_loaded = true;
|
||||||
texture_handle = cmd->texture_handle;
|
texture_handle = cmd->texture_handle;
|
||||||
|
/* FIXME: Texture SRV refcount needs to be increased here to prevent release mid-render */
|
||||||
} else {
|
} else {
|
||||||
/* Otherwise load sprite */
|
/* Otherwise load sprite */
|
||||||
struct sprite_texture *sprite_texture = sprite_texture_from_tag_async(sprite_scope, cmd->sprite);
|
struct sprite_texture *sprite_texture = sprite_texture_from_tag_async(sprite_scope, cmd->sprite);
|
||||||
@ -946,13 +909,9 @@ void renderer_canvas_present(struct renderer_canvas **canvases, u32 canvases_cou
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (texture_loaded) {
|
if (texture_loaded) {
|
||||||
/* FIXME: what if texture_srv is 0? will this unset it correctly? */
|
/* Bind texture */
|
||||||
/* Activate texture */
|
|
||||||
if (!handle_eq(texture_handle, last_texture_handle)) {
|
|
||||||
ID3D11ShaderResourceView *texture_srv = handle_data(texture_handle);
|
ID3D11ShaderResourceView *texture_srv = handle_data(texture_handle);
|
||||||
ID3D11DeviceContext_PSSetShaderResources(G.devcon, 0, 1, &texture_srv);
|
ID3D11DeviceContext_PSSetShaderResources(G.devcon, 0, 1, &texture_srv);
|
||||||
last_texture_handle = texture_handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
ID3D11DeviceContext_IASetPrimitiveTopology(G.devcon, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
ID3D11DeviceContext_IASetPrimitiveTopology(G.devcon, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||||
|
|
||||||
@ -967,6 +926,10 @@ void renderer_canvas_present(struct renderer_canvas **canvases, u32 canvases_cou
|
|||||||
u32 index_offset = cmd->index_offset;
|
u32 index_offset = cmd->index_offset;
|
||||||
u32 index_count = cmd->index_count;
|
u32 index_count = cmd->index_count;
|
||||||
ID3D11DeviceContext_DrawIndexed(G.devcon, index_count, index_offset, vertex_offset);
|
ID3D11DeviceContext_DrawIndexed(G.devcon, index_count, index_offset, vertex_offset);
|
||||||
|
|
||||||
|
/* Unbind */
|
||||||
|
ID3D11ShaderResourceView *null_srv[1] = { NULL };
|
||||||
|
ID3D11DeviceContext_PSSetShaderResources(G.devcon, 0, 1, null_srv);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@ -990,20 +953,76 @@ void renderer_canvas_present(struct renderer_canvas **canvases, u32 canvases_cou
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
__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);
|
||||||
|
dx11_render_to_target(target_view, canvas, clear_color, view, viewport, sprite_scope);
|
||||||
|
|
||||||
|
if (target_view) {
|
||||||
|
ID3D11RenderTargetView_Release(target_view);
|
||||||
|
}
|
||||||
|
if (target_resource) {
|
||||||
|
ID3D11Texture2D_Release((ID3D11Texture2D *)target_resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
__prof;
|
||||||
|
|
||||||
|
/* Resize back buffer */
|
||||||
|
if (!v2_eq(G.backbuffer_size, backbuffer_size)) {
|
||||||
|
resize_backbuffer(backbuffer_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
dx11_render_to_target(backbuffer_view, canvas, clear_color, view, viewport, sprite_scope);
|
||||||
|
|
||||||
|
if (backbuffer_view) {
|
||||||
|
ID3D11RenderTargetView_Release(backbuffer_view);
|
||||||
|
}
|
||||||
|
if (backbuffer_texture) {
|
||||||
|
ID3D11Texture2D_Release(backbuffer_texture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void renderer_present_backbuffer(i32 vsync)
|
||||||
|
{
|
||||||
|
__prof;
|
||||||
|
|
||||||
/* Present */
|
/* Present */
|
||||||
{
|
{
|
||||||
__profscope(IDXGISwapchain_Present);
|
__profscope(IDXGISwapchain_Present);
|
||||||
IDXGISwapChain1_Present(G.swapchain, vsync, 0);
|
IDXGISwapChain1_Present(G.swapchain, vsync, 0);
|
||||||
__profframe(0);
|
__profframe(0);
|
||||||
}
|
}
|
||||||
renderer_capture_image_for_profiler(viewport.width, viewport.height);
|
|
||||||
|
renderer_capture_image_for_profiler();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Texture
|
* Texture
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct renderer_handle renderer_texture_alloc(struct image_rgba data)
|
struct renderer_handle renderer_texture_image_alloc(struct image_rgba data)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
|
|
||||||
@ -1046,6 +1065,44 @@ struct renderer_handle renderer_texture_alloc(struct image_rgba data)
|
|||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct renderer_handle renderer_texture_target_alloc(struct v2 size)
|
||||||
|
{
|
||||||
|
__prof;
|
||||||
|
|
||||||
|
/* Create texture */
|
||||||
|
ID3D11Texture2D *texture = NULL;
|
||||||
|
D3D11_TEXTURE2D_DESC desc = {
|
||||||
|
.Width = size.x,
|
||||||
|
.Height = size.y,
|
||||||
|
.MipLevels = 1,
|
||||||
|
.ArraySize = 1,
|
||||||
|
.Format = DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||||
|
.SampleDesc.Count = 1,
|
||||||
|
.Usage = D3D11_USAGE_DEFAULT,
|
||||||
|
.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET,
|
||||||
|
.CPUAccessFlags = 0
|
||||||
|
};
|
||||||
|
ID3D11Device_CreateTexture2D(G.dev, &desc, NULL, &texture);
|
||||||
|
|
||||||
|
/* Create srv */
|
||||||
|
ID3D11ShaderResourceView *texture_srv = NULL;
|
||||||
|
if (texture) {
|
||||||
|
D3D11_SHADER_RESOURCE_VIEW_DESC shader_resource_view_desc = {
|
||||||
|
.Format = desc.Format,
|
||||||
|
.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D,
|
||||||
|
.Texture2D.MipLevels = desc.MipLevels,
|
||||||
|
.Texture2D.MostDetailedMip = 0
|
||||||
|
};
|
||||||
|
ID3D11Device_CreateShaderResourceView(G.dev, (ID3D11Resource *)texture, &shader_resource_view_desc, &texture_srv);
|
||||||
|
ID3D11Texture2D_Release(texture);
|
||||||
|
}
|
||||||
|
ASSERT(texture_srv != NULL);
|
||||||
|
|
||||||
|
struct renderer_handle handle = handle_alloc(texture_srv);
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
void renderer_texture_release(struct renderer_handle handle)
|
void renderer_texture_release(struct renderer_handle handle)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
@ -1077,7 +1134,7 @@ struct prof_cap {
|
|||||||
struct v2 size;
|
struct v2 size;
|
||||||
};
|
};
|
||||||
|
|
||||||
INTERNAL void renderer_capture_image_for_profiler(f32 width, f32 height)
|
INTERNAL void renderer_capture_image_for_profiler(void)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
|
|
||||||
@ -1096,13 +1153,14 @@ INTERNAL void renderer_capture_image_for_profiler(f32 width, f32 height)
|
|||||||
IDXGISwapChain_GetBuffer(G.swapchain, 0, &IID_ID3D11Texture2D, (LPVOID *)&backbuffer);
|
IDXGISwapChain_GetBuffer(G.swapchain, 0, &IID_ID3D11Texture2D, (LPVOID *)&backbuffer);
|
||||||
|
|
||||||
struct prof_cap *write_cap = &staging_caps[cap_index];
|
struct prof_cap *write_cap = &staging_caps[cap_index];
|
||||||
*write_cap = (struct prof_cap) { .size = V2(width, height) };
|
MEMZERO_STRUCT(write_cap);
|
||||||
{
|
{
|
||||||
D3D11_TEXTURE2D_DESC staging_desc;
|
D3D11_TEXTURE2D_DESC staging_desc;
|
||||||
ID3D11Texture2D_GetDesc(backbuffer, &staging_desc);
|
ID3D11Texture2D_GetDesc(backbuffer, &staging_desc);
|
||||||
staging_desc.Usage = D3D11_USAGE_STAGING;
|
staging_desc.Usage = D3D11_USAGE_STAGING;
|
||||||
staging_desc.BindFlags = 0;
|
staging_desc.BindFlags = 0;
|
||||||
staging_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
staging_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
||||||
|
write_cap->size = V2(staging_desc.Width, staging_desc.Height);
|
||||||
ID3D11Device_CreateTexture2D(G.dev, &staging_desc, NULL, &write_cap->texture);
|
ID3D11Device_CreateTexture2D(G.dev, &staging_desc, NULL, &write_cap->texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1153,10 +1211,8 @@ INTERNAL void renderer_capture_image_for_profiler(f32 width, f32 height)
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
||||||
INTERNAL void renderer_capture_image_for_profiler(f32 width, f32 height)
|
INTERNAL void renderer_capture_image_for_profiler(void)
|
||||||
{
|
{
|
||||||
(UNUSED)width;
|
|
||||||
(UNUSED)height;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -229,7 +229,7 @@ struct sprite_startup_receipt sprite_startup(struct renderer_startup_receipt *re
|
|||||||
{
|
{
|
||||||
struct temp_arena scratch = scratch_begin_no_conflict();
|
struct temp_arena scratch = scratch_begin_no_conflict();
|
||||||
struct image_rgba purple_black_image = generate_purple_black_image(scratch.arena, 64, 64);
|
struct image_rgba purple_black_image = generate_purple_black_image(scratch.arena, 64, 64);
|
||||||
G.nil_texture->renderer_handle = renderer_texture_alloc(purple_black_image);
|
G.nil_texture->renderer_handle = renderer_texture_image_alloc(purple_black_image);
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -365,7 +365,7 @@ INTERNAL void cache_node_load_texture(struct cache_node *n, struct sprite_tag ta
|
|||||||
n->texture = arena_push(&n->arena, struct sprite_texture);
|
n->texture = arena_push(&n->arena, struct sprite_texture);
|
||||||
n->texture->width = decoded.image.width;
|
n->texture->width = decoded.image.width;
|
||||||
n->texture->height = decoded.image.height;
|
n->texture->height = decoded.image.height;
|
||||||
n->texture->renderer_handle = renderer_texture_alloc(decoded.image);
|
n->texture->renderer_handle = renderer_texture_image_alloc(decoded.image);
|
||||||
n->texture->valid = true;
|
n->texture->valid = true;
|
||||||
n->texture->loaded = true;
|
n->texture->loaded = true;
|
||||||
/* TODO: Query renderer for more accurate texture size in VRAM */
|
/* TODO: Query renderer for more accurate texture size in VRAM */
|
||||||
|
|||||||
@ -441,6 +441,7 @@ struct string sys_get_clipboard_text(struct arena *arena);
|
|||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Util
|
* Util
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
void sys_rand(struct buffer b);
|
void sys_rand(struct buffer b);
|
||||||
u32 sys_num_logical_processors(void);
|
u32 sys_num_logical_processors(void);
|
||||||
void sys_exit(void);
|
void sys_exit(void);
|
||||||
|
|||||||
109
src/user.c
109
src/user.c
@ -40,6 +40,11 @@ GLOBAL struct {
|
|||||||
struct arena arena;
|
struct arena arena;
|
||||||
|
|
||||||
struct sys_window *window;
|
struct sys_window *window;
|
||||||
|
|
||||||
|
struct renderer_handle render_target;
|
||||||
|
struct v2 render_target_resolution;
|
||||||
|
|
||||||
|
struct renderer_canvas *backbuffer_canvas;
|
||||||
struct renderer_canvas *world_canvas;
|
struct renderer_canvas *world_canvas;
|
||||||
struct renderer_canvas *viewport_bg_canvas;
|
struct renderer_canvas *viewport_bg_canvas;
|
||||||
struct renderer_canvas *viewport_canvas;
|
struct renderer_canvas *viewport_canvas;
|
||||||
@ -142,6 +147,9 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr,
|
|||||||
G.sys_events_mutex = sys_mutex_alloc();
|
G.sys_events_mutex = sys_mutex_alloc();
|
||||||
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_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.viewport_bg_canvas = renderer_canvas_alloc();
|
||||||
@ -629,11 +637,15 @@ INTERNAL void user_update(void)
|
|||||||
enum user_bind_kind bind = g_binds[button];
|
enum user_bind_kind bind = g_binds[button];
|
||||||
if (bind) {
|
if (bind) {
|
||||||
b32 pressed = event->kind == SYS_EVENT_KIND_BUTTON_DOWN;
|
b32 pressed = event->kind == SYS_EVENT_KIND_BUTTON_DOWN;
|
||||||
|
#if 0
|
||||||
b32 out_of_bounds = button >= SYS_BTN_M1 && button <= SYS_BTN_M5 &&
|
b32 out_of_bounds = button >= SYS_BTN_M1 && button <= SYS_BTN_M5 &&
|
||||||
(G.viewport_cursor.x < 0 ||
|
(G.viewport_cursor.x < 0 ||
|
||||||
G.viewport_cursor.y < 0 ||
|
G.viewport_cursor.y < 0 ||
|
||||||
G.viewport_cursor.x > G.viewport_size.x ||
|
G.viewport_cursor.x > G.viewport_size.x ||
|
||||||
G.viewport_cursor.y > G.viewport_size.y);
|
G.viewport_cursor.y > G.viewport_size.y);
|
||||||
|
#else
|
||||||
|
b32 out_of_bounds = false;
|
||||||
|
#endif
|
||||||
G.bind_states[bind].is_held = pressed && !out_of_bounds;
|
G.bind_states[bind].is_held = pressed && !out_of_bounds;
|
||||||
if (pressed) {
|
if (pressed) {
|
||||||
if (!out_of_bounds) {
|
if (!out_of_bounds) {
|
||||||
@ -857,16 +869,6 @@ INTERNAL void user_update(void)
|
|||||||
mixer_set_listener(listener_pos, listener_dir);
|
mixer_set_listener(listener_pos, listener_dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
|
||||||
* Draw test BG
|
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
{
|
|
||||||
u32 color = RGBA_32_F(0.2f, 0.2f, 0.2f, 1.f);
|
|
||||||
struct quad quad = quad_from_rect(RECT(0, 0, G.viewport_size.x, G.viewport_size.y));
|
|
||||||
draw_quad(G.viewport_bg_canvas, quad, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Draw test grid
|
* Draw test grid
|
||||||
* ========================== */
|
* ========================== */
|
||||||
@ -875,7 +877,7 @@ INTERNAL void user_update(void)
|
|||||||
f32 thickness = 2;
|
f32 thickness = 2;
|
||||||
u32 color = RGBA_32(0x3f, 0x3f, 0x3f, 0xFF);
|
u32 color = RGBA_32(0x3f, 0x3f, 0x3f, 0xFF);
|
||||||
|
|
||||||
struct v2 offset = v2_sub(v2_neg(xform_mul_v2(G.world_view, V2(0, 0))), G.viewport_screen_offset);
|
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);
|
draw_grid(G.viewport_bg_canvas, RECT(0, 0, G.viewport_size.x, G.viewport_size.y), color, thickness, spacing, offset);
|
||||||
@ -903,7 +905,6 @@ INTERNAL void user_update(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Sort */
|
/* Sort */
|
||||||
logf_info("Sorting %F sprites", FMT_UINT(sorted_count));
|
|
||||||
{
|
{
|
||||||
__profscope(sort_sprites);
|
__profscope(sort_sprites);
|
||||||
merge_sort(sorted, sorted_count, sizeof(*sorted), entity_draw_order_cmp, NULL);
|
merge_sort(sorted, sorted_count, sizeof(*sorted), entity_draw_order_cmp, NULL);
|
||||||
@ -984,8 +985,8 @@ INTERNAL void user_update(void)
|
|||||||
if (sheet->loaded) {
|
if (sheet->loaded) {
|
||||||
struct sprite_sheet_frame frame = sprite_sheet_get_frame(sheet, ent->animation_frame);
|
struct sprite_sheet_frame frame = sprite_sheet_get_frame(sheet, ent->animation_frame);
|
||||||
struct quad quad = xform_mul_quad(sprite_xform, QUAD_UNIT_SQUARE_CENTERED);
|
struct quad quad = xform_mul_quad(sprite_xform, QUAD_UNIT_SQUARE_CENTERED);
|
||||||
struct draw_sprite_params params = DRAW_SPRITE_PARAMS(.sprite = sprite, .tint = ent->sprite_tint, .clip = frame.clip);
|
struct draw_texture_params params = DRAW_TEXTURE_PARAMS(.sprite = sprite, .tint = ent->sprite_tint, .clip = frame.clip);
|
||||||
draw_quad_sprite(G.world_canvas, params, quad);
|
draw_quad_texture(G.world_canvas, params, quad);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1399,7 +1400,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_sprite(G.viewport_canvas, DRAW_SPRITE_PARAMS(.sprite = crosshair_tag, .tint = tint), quad);
|
draw_quad_texture(G.viewport_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));
|
||||||
@ -1571,8 +1572,8 @@ INTERNAL void user_update(void)
|
|||||||
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.viewport_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 plaeyr_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)plaeyr_pos.x, 12), FMT_FLOAT_P((f64)plaeyr_pos.y, 12)));
|
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)));
|
||||||
pos.y += spacing;
|
pos.y += spacing;
|
||||||
|
|
||||||
#if COLLIDER_DEBUG
|
#if COLLIDER_DEBUG
|
||||||
@ -1589,43 +1590,65 @@ INTERNAL void user_update(void)
|
|||||||
pubilsh_game_cmds(&cmd_list);
|
pubilsh_game_cmds(&cmd_list);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Present
|
* Render
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* Allocate target texture */
|
||||||
|
struct renderer_handle target;
|
||||||
|
{
|
||||||
|
struct v2 size = ZI;
|
||||||
|
size.x = target_viewport.width + target_viewport.x;
|
||||||
|
size.y = target_viewport.height + target_viewport.y;
|
||||||
|
if (renderer_handle_is_nil(G.render_target) || !v2_eq(size, G.render_target_resolution)) {
|
||||||
|
if (!renderer_handle_is_nil(G.render_target)) {
|
||||||
|
renderer_texture_release(G.render_target);
|
||||||
|
}
|
||||||
|
G.render_target = renderer_texture_target_alloc(size);
|
||||||
|
G.render_target_resolution = size;
|
||||||
|
}
|
||||||
|
target = G.render_target;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw target texture to backbuffer */
|
||||||
|
{
|
||||||
|
struct draw_texture_params params = DRAW_TEXTURE_PARAMS(.texture = target);
|
||||||
|
struct rect rect = RECT_FROM_V2(G.viewport_screen_offset, G.viewport_size);
|
||||||
|
struct quad quad = quad_from_rect(rect);
|
||||||
|
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.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.viewport_canvas);
|
||||||
|
renderer_canvas_send_to_gpu(G.backbuffer_canvas);
|
||||||
|
|
||||||
/* Set canvas views before presenting */
|
/* Execute render cmds */
|
||||||
renderer_canvas_set_view(G.viewport_bg_canvas, XFORM_IDENT);
|
{
|
||||||
renderer_canvas_set_view(G.world_canvas, G.world_view);
|
/* Clear textures */
|
||||||
renderer_canvas_set_view(G.viewport_canvas, XFORM_IDENT);
|
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_render_to_backbuffer(G.screen_size, NULL, COLOR_BLACK, XFORM_IDENT, target_viewport, sprite_frame_scope);
|
||||||
|
|
||||||
|
/* Render to target */
|
||||||
|
renderer_render_to_texture(target, G.viewport_bg_canvas, 0, XFORM_IDENT, target_viewport, sprite_frame_scope);
|
||||||
|
if (!tick_is_first_frame) {
|
||||||
|
/* Only draw world canvas past first tick */
|
||||||
|
renderer_render_to_texture(target, G.world_canvas, 0, G.world_view, target_viewport, sprite_frame_scope);
|
||||||
|
}
|
||||||
|
renderer_render_to_texture(target, G.viewport_canvas, 0, XFORM_IDENT, target_viewport, sprite_frame_scope);
|
||||||
|
|
||||||
|
/* Render to backbuffer */
|
||||||
|
renderer_render_to_backbuffer(G.screen_size, G.backbuffer_canvas, 0, XFORM_IDENT, backbuffer_viewport, sprite_frame_scope);
|
||||||
|
}
|
||||||
|
|
||||||
/* Present */
|
/* Present */
|
||||||
i32 vsync = VSYNC_ENABLED;
|
renderer_present_backbuffer(VSYNC_ENABLED);
|
||||||
|
|
||||||
struct renderer_canvas **canvases = arena_dry_push(scratch.arena, struct renderer_canvas *);
|
|
||||||
u64 canvases_count = 0;
|
|
||||||
{
|
|
||||||
/* Viewport background canvas */
|
|
||||||
*arena_push(scratch.arena, struct renderer_canvas *) = G.viewport_bg_canvas;
|
|
||||||
++canvases_count;
|
|
||||||
|
|
||||||
/* World canvas */
|
|
||||||
if (!tick_is_first_frame) {
|
|
||||||
/* Only render world if not on first frame */
|
|
||||||
*arena_push(scratch.arena, struct renderer_canvas *) = G.world_canvas;
|
|
||||||
++canvases_count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Viewport canvas */
|
|
||||||
*arena_push(scratch.arena, struct renderer_canvas *) = G.viewport_canvas;
|
|
||||||
++canvases_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderer_canvas_present(canvases, canvases_count, G.screen_size, RECT_FROM_V2(G.viewport_screen_offset, G.viewport_size), vsync, sprite_frame_scope);
|
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* End frame cache scopes
|
* End frame cache scopes
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user