gpu layer refactoring progress

This commit is contained in:
jacob 2025-05-27 01:57:47 -05:00
parent 721151f04a
commit 91f89ac65b
12 changed files with 1204 additions and 972 deletions

View File

@ -1,8 +1,31 @@
#define DECL(t, n) t n : n
#define DESV(t, n, s) t n : s
/* Linear color form sRGB color */
struct xform {
float2 bx;
float2 by;
float2 og;
};
/* Linear color from normalized sRGB */
float4 linear_from_srgb(float4 srgb)
{
return float4(pow(srgb.rgb, 2.2), srgb.a);
}
/* Linear color from R8G8B8A8 sRGB */
float4 linear_from_srgb32(uint srgb32)
{
float4 res;
res.r = ((srgb32 >> 0) & 0xFF) / 255.0;
res.g = ((srgb32 >> 8) & 0xFF) / 255.0;
res.b = ((srgb32 >> 16) & 0xFF) / 255.0;
res.a = ((srgb32 >> 24) & 0xFF) / 255.0;
return linear_from_srgb(res);
}
float2 xform_mul(struct xform xf, float2 v)
{
// return xf.bx * v.x + xf.by * v.y + xf.og;
return float2(xf.bx.x * v.x + xf.by.x * v.y, xf.bx.y * v.x + xf.by.y * v.y) + xf.og;
}

View File

@ -1,10 +1,5 @@
#include "shaders/common.hlsl"
cbuffer constants : register(b0)
{
float4x4 G_projection;
};
struct vs_input {
DECL(float4, pos);
DECL(float, line_thickness);
@ -29,6 +24,15 @@ struct ps_input {
DECL(float4, y_lin);
};
/* ========================== *
* Globals
* ========================== */
cbuffer constants : register(b0)
{
float4x4 G_projection;
};
/* ========================== *
* Vertex shader
* ========================== */

91
res/shaders/texture.hlsl Normal file
View File

@ -0,0 +1,91 @@
#include "shaders/common.hlsl"
struct vs_instance {
struct xform xf;
float2 uv0;
float2 uv1;
uint tint_srgb;
};
struct ps_input {
DESV(float4, screen_pos, SV_POSITION);
DECL(float2, uv);
DECL(float4, tint_lin);
};
/* ========================== *
* Globals
* ========================== */
SamplerState G_sampler : register(s0);
Texture2D G_Texture : register(t0);
StructuredBuffer<vs_instance> G_instance_buffer : register(t1);
cbuffer constants : register(b0)
{
float4x4 G_projection;
uint G_instance_offset;
};
/* ========================== *
* Vertex shader
* ========================== */
ps_input vs_main(uint instance_id : SV_InstanceID, uint vertex_id : SV_VertexID)
{
// static float2 quad[4] = {
// float2(-0.5f, -0.5f),
// float2( 0.5f, -0.5f),
// float2( 0.5f, 0.5f),
// float2(-0.5f, 0.5f)
// };
static const uint indices[6] = { 0, 1, 2, 2, 3, 0 };
static const float2 vertices[4] = {
float2(-0.5f, -0.5f),
float2( 0.5f, -0.5f),
float2( 0.5f, 0.5f),
float2(-0.5f, 0.5f)
};
vs_instance instance = G_instance_buffer[instance_id + G_instance_offset];
int index = indices[vertex_id];
int top = index == 0 || index == 1;
int right = index == 1 || index == 2;
int bottom = index == 2 || index == 3;
int left = index == 3 || index == 0;
//int top = vertex_id == 0 || vertex_id == 2;
//int left = vertex_id == 0 || vertex_id == 1;
//int bottom = vertex_id == 1 || vertex_id == 3;
//int right = vertex_id == 2 || vertex_id == 3;
float2 vert = vertices[index];
float2 world_pos = xform_mul(instance.xf, vert);
float4 screen_pos = mul(G_projection, float4(world_pos, 0, 1));
float uv_x = instance.uv0.x * left;
uv_x += instance.uv1.x * right;
float uv_y = instance.uv0.y * top;
uv_y += instance.uv1.y * bottom;
ps_input output;
output.screen_pos = screen_pos;
output.uv = float2(uv_x, uv_y);
output.tint_lin = linear_from_srgb32(instance.tint_srgb);
return output;
}
/* ========================== *
* Pixel shader
* ========================== */
float4 ps_main(ps_input input) : SV_TARGET
{
float4 color = G_Texture.Sample(G_sampler, input.uv) * input.tint_lin;
return color;
}

View File

@ -1,13 +1,5 @@
#include "shaders/common.hlsl"
SamplerState G_sampler0;
Texture2D G_texture0;
cbuffer constants : register(b0)
{
float4x4 G_projection;
};
struct vs_input {
DECL(float4, pos);
DECL(float2, uv);
@ -20,6 +12,19 @@ struct ps_input {
DECL(float4, tint_lin);
};
/* ========================== *
* Globals
* ========================== */
SamplerState G_sampler : register(s0);
Texture2D G_texture : register(t0);
cbuffer constants : register(b0)
{
float4x4 G_projection;
};
/* ========================== *
* Vertex shader
* ========================== */
@ -41,6 +46,6 @@ ps_input vs_main(vs_input input)
float4 ps_main(ps_input input) : SV_TARGET
{
float4 color = G_texture0.Sample(G_sampler0, input.uv) * input.tint_lin;
float4 color = G_texture.Sample(G_sampler, input.uv) * input.tint_lin;
return color;
}

View File

@ -705,14 +705,6 @@ struct ase_decode_image_result ase_decode_image(struct arena *arena, struct stri
}
} break;
case CHUNK_TYPE_COLOR_PROFILE: {
u16 type = br_read_ubits(&br, 16);
if (type == 1) {
res.srgb = true;
}
br_seek_to_byte(&br, chunk_end_pos);
} break;
default: {
br_seek_to_byte(&br, chunk_end_pos);
} break;

View File

@ -48,7 +48,6 @@ struct ase_frame {
struct ase_decode_image_result {
struct image_rgba image;
struct ase_error_list errors;
b32 srgb;
b32 success;
};

View File

@ -28,94 +28,60 @@ struct draw_startup_receipt draw_startup(struct gpu_startup_receipt *gpu_sr,
* Texture
* ========================== */
void draw_quad_texture(struct gpu_cmd_buffer *cmdbuff, struct draw_texture_params params)
void draw_texture(struct gpu_cmd_store store, struct draw_texture_params params)
{
struct gpu_cmd_parameters cmd_params = ZI;
cmd_params.kind = SHADER_TRIANGLE;
cmd_params.texture_params.texture = params.texture;
cmd_params.texture_params.sprite = params.sprite;
gpu_cmd_buffer_ensure_cmd(cmdbuff, &cmd_params);
struct triangle_shader_vertex *vertices = NULL;
vidx *indices = NULL;
u32 offset = gpu_cmd_buffer_push_vertices(cmdbuff, (u8 **)&vertices, &indices, 4, 6);
/* Top left */
vertices[0] = (struct triangle_shader_vertex) {
.pos = params.quad.p0,
.uv = { params.clip.p0.x, params.clip.p0.y },
.tint_srgb = params.tint0_srgb
};
/* Top right */
vertices[1] = (struct triangle_shader_vertex) {
.pos = params.quad.p1,
.uv = { params.clip.p1.x, params.clip.p0.y },
.tint_srgb = params.tint0_srgb
};
/* Bottom right */
vertices[2] = (struct triangle_shader_vertex) {
.pos = params.quad.p2,
.uv = { params.clip.p1.x, params.clip.p1.y },
.tint_srgb = params.tint1_srgb
};
/* Bottom left */
vertices[3] = (struct triangle_shader_vertex) {
.pos = params.quad.p3,
.uv = { params.clip.p0.x, params.clip.p1.y },
.tint_srgb = params.tint1_srgb
};
/* Top / right triangle */
indices[0] = offset + 0;
indices[1] = offset + 1;
indices[2] = offset + 2;
/* Bottom / left triangle */
indices[3] = offset + 0;
indices[4] = offset + 2;
indices[5] = offset + 3;
struct gpu_cmd_params cmd = ZI;
cmd.kind = GPU_CMD_KIND_DRAW_TEXTURE;
cmd.texture.xf = params.xf;
cmd.texture.sprite = params.sprite;
cmd.texture.texture = params.texture;
cmd.texture.clip = params.clip;
cmd.texture.tint = params.tint;
gpu_push_cmd(store, cmd);
}
/* ========================== *
* Solid fill shapes
* Fill shapes
* ========================== */
void draw_poly(struct gpu_cmd_buffer *cmdbuff, struct v2_array array, u32 srgb)
void draw_poly_ex(struct gpu_cmd_store store, struct v2_array vertices, struct gpu_indices indices, u32 color)
{
if (array.count < 3) {
return;
}
struct gpu_cmd_params cmd = ZI;
cmd.kind = GPU_CMD_KIND_DRAW_TRIANGLES;
cmd.triangles.vertices = vertices;
cmd.triangles.indices = indices;
cmd.triangles.color = color;
gpu_push_cmd(store, cmd);
}
struct gpu_cmd_parameters cmd_params = ZI;
cmd_params.kind = SHADER_TRIANGLE;
cmd_params.texture_params.texture = G.solid_white;
gpu_cmd_buffer_ensure_cmd(cmdbuff, &cmd_params);
/* Draws a filled polygon using triangles in a fan pattern */
void draw_poly(struct gpu_cmd_store store, struct v2_array vertices, u32 color)
{
if (vertices.count >= 3) {
struct temp_arena scratch = scratch_begin_no_conflict();
u32 num_tris = array.count - 2;
u32 num_indices = num_tris * 3;
u32 num_tris = vertices.count - 2;
u32 num_indices = num_tris * 3;
struct triangle_shader_vertex *vertices = NULL;
vidx *indices = NULL;
u32 idx_offset = gpu_cmd_buffer_push_vertices(cmdbuff, (u8 **)&vertices, &indices, array.count, num_indices);
/* Fill vertices */
for (u32 i = 0; i < array.count; ++i) {
vertices[i] = (struct triangle_shader_vertex) {
.pos = array.points[i],
.tint_srgb = srgb
/* Generate indices in a fan pattern */
struct gpu_indices indices = {
.count = num_indices,
.indices = arena_push_array_no_zero(scratch.arena, u16, num_indices)
};
}
for (u32 i = 0; i < num_tris; ++i) {
u32 tri_offset = i * 3;
indices.indices[tri_offset + 0] = 0;
indices.indices[tri_offset + 1] = (i + 1);
indices.indices[tri_offset + 2] = (i + 2);
}
/* Fill indices */
for (u32 i = 0; i < num_tris; ++i) {
u32 tri_offset = i * 3;
indices[tri_offset + 0] = idx_offset + 0;
indices[tri_offset + 1] = idx_offset + (i + 1);
indices[tri_offset + 2] = idx_offset + (i + 2);
draw_poly_ex(store, vertices, indices, color);
scratch_end(scratch);
}
}
void draw_circle(struct gpu_cmd_buffer *cmdbuff, struct v2 pos, f32 radius, u32 srgb, u32 detail)
void draw_circle(struct gpu_cmd_store store, struct v2 pos, f32 radius, u32 color, u32 detail)
{
struct temp_arena scratch = scratch_begin_no_conflict();
@ -128,63 +94,74 @@ void draw_circle(struct gpu_cmd_buffer *cmdbuff, struct v2 pos, f32 radius, u32
points[i] = v2_add(pos, p);
}
struct v2_array a = {
struct v2_array vertices = {
.points = points,
.count = detail
};
draw_poly(cmdbuff, a, srgb);
draw_poly(store, vertices, color);
scratch_end(scratch);
}
void draw_quad(struct gpu_cmd_buffer *cmdbuff, struct quad quad, u32 srgb)
void draw_quad(struct gpu_cmd_store store, struct quad quad, u32 color)
{
draw_quad_texture(cmdbuff, DRAW_TEXTURE_PARAMS(.texture = G.solid_white, .tint0_srgb = srgb, .tint1_srgb = srgb, .quad = quad));
LOCAL_PERSIST u16 indices_array[6] = {
0, 1, 2,
0, 2, 3
};
struct v2_array vertices = { .count = 4, .points = quad.e };
struct gpu_indices indices = { .count = 6, .indices = indices_array };
draw_poly_ex(store, vertices, indices, color);
}
/* ========================== *
* Solid line shapes
* Line shapes
* ========================== */
void draw_gradient_line(struct gpu_cmd_buffer *cmdbuff, struct v2 start, struct v2 end, f32 thickness, u32 start_srgb, u32 end_srgb)
void draw_gradient_line(struct gpu_cmd_store store, struct v2 start, struct v2 end, f32 thickness, u32 start_color, u32 end_color)
{
#if 0
struct quad quad = quad_from_line(start, end, thickness);
draw_quad_texture(cmdbuff, DRAW_TEXTURE_PARAMS(.texture = G.solid_white, .tint0_srgb = start_srgb, .tint1_srgb = end_srgb, .quad = quad));
draw_texture(store, DRAW_TEXTURE_PARAMS(.texture = G.solid_white, .tint0 = start_color, .tint1 = end_color, .quad = quad));
#else
/* Placeholder */
(UNUSED)end_color;
struct quad quad = quad_from_line(start, end, thickness);
draw_quad(store, quad, start_color);
#endif
}
void draw_line(struct gpu_cmd_buffer *cmdbuff, struct v2 start, struct v2 end, f32 thickness, u32 srgb)
void draw_line(struct gpu_cmd_store store, struct v2 start, struct v2 end, f32 thickness, u32 color)
{
struct quad quad = quad_from_line(start, end, thickness);
draw_quad(cmdbuff, quad, srgb);
draw_quad(store, quad, color);
}
void draw_ray(struct gpu_cmd_buffer *cmdbuff, struct v2 pos, struct v2 rel, f32 thickness, u32 srgb)
void draw_ray(struct gpu_cmd_store store, struct v2 pos, struct v2 rel, f32 thickness, u32 color)
{
struct quad quad = quad_from_ray(pos, rel, thickness);
draw_quad(cmdbuff, quad, srgb);
draw_quad(store, quad, color);
}
void draw_poly_line(struct gpu_cmd_buffer *cmdbuff, struct v2_array array, b32 loop, f32 thickness, u32 srgb)
void draw_poly_line(struct gpu_cmd_store store, struct v2_array points, b32 loop, f32 thickness, u32 color)
{
if (array.count < 2) {
return;
}
for (u64 i = 1; i < array.count; ++i) {
struct v2 p1 = array.points[i - 1];
struct v2 p2 = array.points[i];
struct quad q = quad_from_line(p1, p2, thickness);
draw_quad(cmdbuff, q, srgb);
}
if (loop && array.count > 2) {
struct v2 p1 = array.points[array.count - 1];
struct v2 p2 = array.points[0];
struct quad q = quad_from_line(p1, p2, thickness);
draw_quad(cmdbuff, q, srgb);
if (points.count >= 2) {
for (u64 i = 1; i < points.count; ++i) {
struct v2 p1 = points.points[i - 1];
struct v2 p2 = points.points[i];
struct quad q = quad_from_line(p1, p2, thickness);
draw_quad(store, q, color);
}
if (loop && points.count > 2) {
struct v2 p1 = points.points[points.count - 1];
struct v2 p2 = points.points[0];
struct quad q = quad_from_line(p1, p2, thickness);
draw_quad(store, q, color);
}
}
}
void draw_circle_line(struct gpu_cmd_buffer *cmdbuff, struct v2 pos, f32 radius, f32 thickness, u32 srgb, u32 detail)
void draw_circle_line(struct gpu_cmd_store store, struct v2 pos, f32 radius, f32 thickness, u32 color, u32 detail)
{
struct temp_arena scratch = scratch_begin_no_conflict();
@ -201,19 +178,19 @@ void draw_circle_line(struct gpu_cmd_buffer *cmdbuff, struct v2 pos, f32 radius,
.points = points,
.count = detail
};
draw_poly_line(cmdbuff, a, true, thickness, srgb);
draw_poly_line(store, a, true, thickness, color);
scratch_end(scratch);
}
void draw_quad_line(struct gpu_cmd_buffer *cmdbuff, struct quad quad, f32 thickness, u32 srgb)
void draw_quad_line(struct gpu_cmd_store store, struct quad quad, f32 thickness, u32 color)
{
struct v2 points[] = { quad.p0, quad.p1, quad.p2, quad.p3 };
struct v2_array a = { .points = points, .count = ARRAY_COUNT(points) };
draw_poly_line(cmdbuff, a, true, thickness, srgb);
draw_poly_line(store, a, true, thickness, color);
}
void draw_arrow_line(struct gpu_cmd_buffer *cmdbuff, struct v2 start, struct v2 end, f32 thickness, f32 arrowhead_height, u32 srgb)
void draw_arrow_line(struct gpu_cmd_store store, struct v2 start, struct v2 end, f32 thickness, f32 arrowhead_height, u32 color)
{
const f32 head_width_ratio = 0.5f; /* Width of arrowhead relative to its length */
@ -237,19 +214,19 @@ void draw_arrow_line(struct gpu_cmd_buffer *cmdbuff, struct v2 start, struct v2
.points = head_points,
.count = ARRAY_COUNT(head_points)
};
draw_poly(cmdbuff, head_points_v2_array, srgb);
draw_poly(store, head_points_v2_array, color);
struct quad line_quad = quad_from_line(start, head_start, thickness);
draw_quad(cmdbuff, line_quad, srgb);
draw_quad(store, line_quad, color);
}
void draw_arrow_ray(struct gpu_cmd_buffer *cmdbuff, struct v2 pos, struct v2 rel, f32 thickness, f32 arrowhead_height, u32 srgb)
void draw_arrow_ray(struct gpu_cmd_store store, struct v2 pos, struct v2 rel, f32 thickness, f32 arrowhead_height, u32 color)
{
struct v2 end = v2_add(pos, rel);
draw_arrow_line(cmdbuff, pos, end, thickness, arrowhead_height, srgb);
draw_arrow_line(store, pos, end, thickness, arrowhead_height, color);
}
void draw_collider_line(struct gpu_cmd_buffer *cmdbuff, struct xform draw_xf, struct collider_shape shape, struct xform shape_xf, f32 thickness, u32 srgb, u32 detail)
void draw_collider_line(struct gpu_cmd_store store, struct xform draw_xf, struct collider_shape shape, struct xform shape_xf, f32 thickness, u32 color, u32 detail)
{
struct temp_arena scratch = scratch_begin_no_conflict();
@ -262,16 +239,8 @@ void draw_collider_line(struct gpu_cmd_buffer *cmdbuff, struct xform draw_xf, st
points[i] = p;
}
#if 1
struct v2_array poly = { .points = points, .count = detail };
draw_poly_line(cmdbuff, poly, true, thickness, srgb);
#else
for (u64 i = 0; i < detail; ++i) {
struct v2 point = points[i];
(UNUSED)thickness;
draw_circle(cmdbuff, point, 3, srgb, 10);
}
#endif
draw_poly_line(store, poly, true, thickness, color);
scratch_end(scratch);
}
@ -280,57 +249,28 @@ void draw_collider_line(struct gpu_cmd_buffer *cmdbuff, struct xform draw_xf, st
* Grid
* ========================== */
void draw_grid(struct gpu_cmd_buffer *cmdbuff, struct rect rect, u32 bg0_srgb, u32 bg1_srgb, u32 line_srgb, u32 x_srgb, u32 y_srgb, f32 thickness, f32 spacing, struct v2 offset)
void draw_grid(struct gpu_cmd_store store, struct xform xf, u32 bg0_color, u32 bg1_color, u32 line_color, u32 x_color, u32 y_color, f32 thickness, f32 spacing, struct v2 offset)
{
struct gpu_cmd_parameters cmd_params = ZI;
cmd_params.kind = SHADER_GRID;
gpu_cmd_buffer_ensure_cmd(cmdbuff, &cmd_params);
struct grid_shader_vertex *vertices = NULL;
vidx *indices = NULL;
u32 index_offset = gpu_cmd_buffer_push_vertices(cmdbuff, (u8 **)&vertices, &indices, 4, 6);
struct quad quad = quad_from_rect(rect);
struct grid_shader_vertex attributes = ZI;
attributes.bg0_srgb = bg0_srgb;
attributes.bg1_srgb = bg1_srgb;
attributes.line_srgb = line_srgb;
attributes.x_srgb = x_srgb;
attributes.y_srgb = y_srgb;
attributes.line_thickness = thickness;
attributes.line_spacing = spacing;
attributes.offset = offset;
/* Top left */
vertices[0] = attributes;
vertices[0].pos = quad.p0;
/* Top right */
vertices[1] = attributes;
vertices[1].pos = quad.p1;
/* Bottom right */
vertices[2] = attributes;
vertices[2].pos = quad.p2;
/* Bottom left */
vertices[3] = attributes;
vertices[3].pos = quad.p3;
/* Top / right triangle */
indices[0] = index_offset + 0;
indices[1] = index_offset + 1;
indices[2] = index_offset + 2;
/* Bottom / left triangle */
indices[3] = index_offset + 0;
indices[4] = index_offset + 2;
indices[5] = index_offset + 3;
struct gpu_cmd_params cmd = ZI;
cmd.kind = GPU_CMD_KIND_DRAW_GRID;
cmd.grid.xf = xf;
cmd.grid.bg0_color = bg0_color;
cmd.grid.bg1_color = bg1_color;
cmd.grid.line_color = line_color;
cmd.grid.x_color = x_color;
cmd.grid.y_color = y_color;
cmd.grid.line_thickness = thickness;
cmd.grid.line_spacing = spacing;
cmd.grid.offset = offset;
gpu_push_cmd(store, cmd);
}
/* ========================== *
* Text
* ========================== */
/* Returns the rect that the drawn text spans */
struct rect draw_text(struct gpu_cmd_buffer *cmdbuff, struct draw_text_params params)
/* Returns the rect of the text area */
struct rect draw_text(struct gpu_cmd_store store, struct draw_text_params params)
{
struct temp_arena scratch = scratch_begin_no_conflict();
@ -338,6 +278,10 @@ struct rect draw_text(struct gpu_cmd_buffer *cmdbuff, struct draw_text_params pa
f32 inv_font_image_height = 1.0 / (f32)params.font->image_height;
f32 line_spacing = params.font->point_size * 1.5f * params.scale;
/* ========================== *
* Build line glyphs
* ========================== */
struct drawable_glyph {
f32 off_x;
f32 off_y;
@ -428,6 +372,10 @@ struct rect draw_text(struct gpu_cmd_buffer *cmdbuff, struct draw_text_params pa
string_codepoint_iter_end(&iter);
}
/* ========================== *
* Determine text bounds
* ========================== */
struct rect bounds = ZI;
bounds.x = params.pos.x;
bounds.y = params.pos.y;
@ -462,6 +410,9 @@ struct rect draw_text(struct gpu_cmd_buffer *cmdbuff, struct draw_text_params pa
} break;
}
/* ========================== *
* Draw lines
* ========================== */
u64 line_number = 0;
for (struct drawable_line *line = first_line; line; line = line->next) {
@ -484,10 +435,11 @@ struct rect draw_text(struct gpu_cmd_buffer *cmdbuff, struct draw_text_params pa
/* Draw glyphs */
for (u64 i = 0; i < line->num_glyphs; ++i) {
struct drawable_glyph *tg = &line->glyphs[i];
f32 x = draw_pos.x + tg->off_x;
f32 y = draw_pos.y + tg->off_y;
struct quad quad = quad_from_rect(RECT(x, y, tg->width, tg->height));
draw_quad_texture(cmdbuff, DRAW_TEXTURE_PARAMS(.texture = params.font->texture, .tint0_srgb = params.color, .tint1_srgb = params.color, .clip = tg->clip, .quad = quad));
struct v2 pos = V2(draw_pos.x + tg->off_x, draw_pos.y + tg->off_y);
struct v2 size = V2(tg->width, tg->height);
struct v2 pos_center = v2_add(pos, v2_mul(size, 0.5));
struct xform xf = XFORM_TRS(.t = pos_center, size);
draw_texture(store, DRAW_TEXTURE_PARAMS(.xf = xf, .texture = params.font->texture, .tint = params.color, .clip = tg->clip));
draw_pos.x += tg->advance;
}

View File

@ -3,27 +3,86 @@
#include "gpu.h"
struct gpu_cmd_buffer;
struct font;
struct gpu_startup_receipt;
struct font_startup_receipt;
struct draw_startup_receipt { i32 _; };
struct draw_startup_receipt draw_startup(struct gpu_startup_receipt *gpu_sr,
struct font_startup_receipt *font_sr);
/* ========================== *
* Texture
* ========================== */
#define DRAW_TEXTURE_PARAMS(...) ((struct draw_texture_params) { \
.tint0_srgb = COLOR_WHITE, \
.tint1_srgb = COLOR_WHITE, \
.tint = COLOR_WHITE, \
.clip = CLIP_ALL, \
__VA_ARGS__ \
})
struct draw_texture_params {
struct xform xf;
struct gpu_texture texture; /* Overrides sprite if set */
struct sprite_tag sprite;
struct clip_rect clip;
struct quad quad;
u32 tint0_srgb;
u32 tint1_srgb;
u32 tint;
};
void draw_texture(struct gpu_cmd_store store, struct draw_texture_params params);
/* ========================== *
* Fill shapes
* ========================== */
void draw_poly_ex(struct gpu_cmd_store store, struct v2_array vertices, struct gpu_indices indices, u32 color);
void draw_poly(struct gpu_cmd_store store, struct v2_array points, u32 color);
void draw_circle(struct gpu_cmd_store store, struct v2 pos, f32 radius, u32 color, u32 detail);
void draw_quad(struct gpu_cmd_store store, struct quad quad, u32 color);
/* ========================== *
* Line shapes
* ========================== */
void draw_gradient_line(struct gpu_cmd_store store, struct v2 start, struct v2 end, f32 thickness, u32 start_color, u32 end_color);
void draw_line(struct gpu_cmd_store store, struct v2 start, struct v2 end, f32 thickness, u32 color);
void draw_ray(struct gpu_cmd_store store, struct v2 pos, struct v2 rel, f32 thickness, u32 color);
void draw_poly_line(struct gpu_cmd_store store, struct v2_array points, b32 loop, f32 thickness, u32 color);
void draw_circle_line(struct gpu_cmd_store store, struct v2 pos, f32 radius, f32 thickness, u32 color, u32 detail);
void draw_quad_line(struct gpu_cmd_store store, struct quad quad, f32 thickness, u32 color);
void draw_arrow_line(struct gpu_cmd_store store, struct v2 start, struct v2 end, f32 thickness, f32 arrowhead_height, u32 color);
void draw_arrow_ray(struct gpu_cmd_store store, struct v2 pos, struct v2 rel, f32 thickness, f32 arrowhead_height, u32 color);
void draw_collider_line(struct gpu_cmd_store store, struct xform draw_xf, struct collider_shape shape, struct xform shape_xf, f32 thickness, u32 color, u32 detail);
/* ========================== *
* Grid
* ========================== */
void draw_grid(struct gpu_cmd_store store, struct xform xf, u32 bg0_color, u32 bg1_color, u32 line_color, u32 x_color, u32 y_color, f32 thickness, f32 spacing, struct v2 offset);
/* ========================== *
* Text
* ========================== */
#define DRAW_TEXT_PARAMS(...) ((struct draw_text_params) { \
.scale = 1.0, \
.alignment = DRAW_TEXT_ALIGNMENT_LEFT, \
.offset_x = DRAW_TEXT_OFFSET_X_LEFT, \
.offset_y = DRAW_TEXT_OFFSET_Y_TOP, \
.color = COLOR_WHITE, \
__VA_ARGS__ \
})
/* How is text aligned within its area */
enum draw_text_alignment {
DRAW_TEXT_ALIGNMENT_LEFT, /* Default */
@ -39,55 +98,13 @@ enum draw_text_offset_x {
DRAW_TEXT_OFFSET_X_CENTER,
DRAW_TEXT_OFFSET_X_RIGHT
};
enum draw_text_offset_y {
DRAW_TEXT_OFFSET_Y_TOP, /* Default */
DRAW_TEXT_OFFSET_Y_CENTER,
DRAW_TEXT_OFFSET_Y_BOTTOM
};
struct draw_startup_receipt { i32 _; };
struct draw_startup_receipt draw_startup(struct gpu_startup_receipt *gpu_sr,
struct font_startup_receipt *font_sr);
/* ========================== *
* Textures
* ========================== */
void draw_quad_texture(struct gpu_cmd_buffer *cmdbuff, struct draw_texture_params params);
/* ========================== *
* Shapes
* ========================== */
void draw_poly(struct gpu_cmd_buffer *cmdbuff, struct v2_array array, u32 srgb);
void draw_circle(struct gpu_cmd_buffer *cmdbuff, struct v2 pos, f32 radius, u32 srgb, u32 detail);
void draw_quad(struct gpu_cmd_buffer *cmdbuff, struct quad quad, u32 srgb);
void draw_gradient_line(struct gpu_cmd_buffer *cmdbuff, struct v2 start, struct v2 end, f32 thickness, u32 start_srgb, u32 end_srgb);
void draw_line(struct gpu_cmd_buffer *cmdbuff, struct v2 start, struct v2 end, f32 thickness, u32 srgb);
void draw_ray(struct gpu_cmd_buffer *cmdbuff, struct v2 start, struct v2 ray, f32 thickness, u32 srgb);
void draw_poly_line(struct gpu_cmd_buffer *cmdbuff, struct v2_array array, b32 loop, f32 thickness, u32 srgb);
void draw_circle_line(struct gpu_cmd_buffer *cmdbuff, struct v2 pos, f32 radius, f32 thickness, u32 srgb, u32 detail);
void draw_quad_line(struct gpu_cmd_buffer *cmdbuff, struct quad quad, f32 thickness, u32 srgb);
void draw_arrow_line(struct gpu_cmd_buffer *cmdbuff, struct v2 start, struct v2 end, f32 thickness, f32 arrowhead_height, u32 srgb);
void draw_arrow_ray(struct gpu_cmd_buffer *cmdbuff, struct v2 pos, struct v2 rel, f32 thickness, f32 arrowhead_height, u32 srgb);
void draw_collider_line(struct gpu_cmd_buffer *cmdbuff, struct xform draw_xf, struct collider_shape shape, struct xform shape_xf, f32 thickness, u32 srgb, u32 detail);
void draw_grid(struct gpu_cmd_buffer *cmdbuff, struct rect rect, u32 bg0_srgb, u32 bg1_srgb, u32 line_srgb, u32 x_srgb, u32 y_srgb, f32 thickness, f32 spacing, struct v2 offset);
/* ========================== *
* Text
* ========================== */
#define DRAW_TEXT_PARAMS(...) ((struct draw_text_params) { \
.scale = 1.0, \
.alignment = DRAW_TEXT_ALIGNMENT_LEFT, \
.offset_x = DRAW_TEXT_OFFSET_X_LEFT, \
.offset_y = DRAW_TEXT_OFFSET_Y_TOP, \
.color = COLOR_WHITE, \
__VA_ARGS__ \
})
struct draw_text_params {
struct font *font;
struct v2 pos;
@ -99,6 +116,6 @@ struct draw_text_params {
struct string str;
};
struct rect draw_text(struct gpu_cmd_buffer *cmdbuff, struct draw_text_params params);
struct rect draw_text(struct gpu_cmd_store store, struct draw_text_params params);
#endif

133
src/gpu.h
View File

@ -6,54 +6,6 @@ struct sys_window;
#define GPU_TEXTURE_MAX_WIDTH 16384
#define GPU_TEXTURE_MAX_HEIGHT 16384
typedef u32 vidx;
struct gpu_cmd_buffer;
struct gpu_texture {
u64 handle;
};
/* ========================== *
* Shaders
* ========================== */
enum shader_kind {
SHADER_NONE,
SHADER_TRIANGLE,
SHADER_GRID,
NUM_SHADERS
};
struct gpu_cmd_parameters {
enum shader_kind kind;
union {
struct {
struct gpu_texture texture; /* Overrides sprite if set */
struct sprite_tag sprite;
} texture_params;
};
};
PACK(struct triangle_shader_vertex {
struct v2 pos;
struct v2 uv;
u32 tint_srgb;
});
PACK(struct grid_shader_vertex {
struct v2 pos;
f32 line_thickness;
f32 line_spacing;
struct v2 offset;
u32 bg0_srgb;
u32 bg1_srgb;
u32 line_srgb;
u32 x_srgb;
u32 y_srgb;
});
/* ========================== *
* Startup
* ========================== */
@ -67,55 +19,98 @@ struct gpu_startup_receipt gpu_startup(struct sys_window *window);
enum gpu_texture_format {
GPU_TEXTURE_FORMAT_NONE,
GPU_TEXTURE_FORMAT_R8G8B8A8_UNORM,
GPU_TEXTURE_FORMAT_R8G8B8A8_UNORM_SRGB,
NUM_GPU_TEXTURE_FORMATS
};
#define GPU_TEXTURE_FLAG_NONE (0)
#define GPU_TEXTURE_FLAG_TARGET (1<<0)
enum gpu_texture_flag {
GPU_TEXTURE_FLAG_NONE = (0),
GPU_TEXTURE_FLAG_TARGETABLE = (1 << 0)
};
struct gpu_texture {
u64 handle;
};
struct gpu_texture gpu_texture_alloc(enum gpu_texture_format format, u32 flags, struct v2i32 size, void *initial_data);
void gpu_texture_release(struct gpu_texture t);
void gpu_texture_clear(struct gpu_texture target_texture, u32 clear_color);
void gpu_texture_render(struct gpu_texture texture, struct gpu_cmd_buffer *cmdbuff, struct xform view, struct rect viewport);
struct v2i32 gpu_texture_get_size(struct gpu_texture texture);
/* ========================== *
* Backbuffer
* ========================== */
/* Returns a texture linking to the internal backbuffer. Lifetime is managed by gpu layer. */
/* Returns a texture representing the internal backbuffer. Lifetime is managed by gpu layer. */
struct gpu_texture gpu_recreate_backbuffer(struct v2i32 size);
void gpu_present_backbuffer(i32 vsync);
/* Presents the backbuffer to the screen */
void gpu_swap_backbuffer(i32 vsync);
/* ========================== *
* Cmd buffer
* ========================== */
struct gpu_cmd_buffer *gpu_cmd_buffer_alloc(void);
struct gpu_indices {
u16 count;
u16 *indices;
};
void gpu_cmd_buffer_release(struct gpu_cmd_buffer *cmdbuff);
enum gpu_cmd_kind {
GPU_CMD_KIND_NONE,
GPU_CMD_KIND_DRAW_TRIANGLES,
GPU_CMD_KIND_DRAW_TEXTURE,
GPU_CMD_KIND_DRAW_GRID,
/* 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.
* Returns the index of the first vertex. Each inserted index should be incremented by this.
*
* NOTE: This should be preceded by an `ensure_cmd` call to ensure that the correct vertex types
* are being pushed.
*/
u32 gpu_cmd_buffer_push_vertices(struct gpu_cmd_buffer *cmdbuff, u8 **vertices_out, vidx **indices_out, u32 vertices_count, u32 indices_count);
NU
};
/* Checks the currently active draw command. Ensures a new command is created
* if it doesn't match the expected parameters (otherwise the existing command
* can be re-used for batching). */
void gpu_cmd_buffer_ensure_cmd(struct gpu_cmd_buffer *cmdbuff, struct gpu_cmd_parameters *params);
struct gpu_cmd_params {
enum gpu_cmd_kind kind;
union {
struct {
struct v2_array vertices;
struct gpu_indices indices;
u32 color;
} triangles;
struct {
struct xform xf;
struct sprite_tag sprite;
struct gpu_texture texture;
struct clip_rect clip;
u32 tint;
} texture;
struct {
struct xform xf;
f32 line_thickness;
f32 line_spacing;
struct v2 offset;
u32 bg0_color;
u32 bg1_color;
u32 line_color;
u32 x_color;
u32 y_color;
} grid;
};
};
void gpu_cmd_buffer_flush_to_gpu(struct gpu_cmd_buffer *cmdbuff);
struct gpu_cmd_store {
u64 handle;
};
struct gpu_cmd_store gpu_cmd_store_alloc(void);
void gpu_cmd_store_release(struct gpu_cmd_store gpu_cmd_store);
void gpu_push_cmd(struct gpu_cmd_store gpu_cmd_store, struct gpu_cmd_params params);
void gpu_submit_cmds(struct gpu_cmd_store gpu_cmd_store);
void gpu_run_cmds(struct gpu_cmd_store gpu_cmd_store, struct gpu_texture target, struct xform view, struct rect viewport);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -375,16 +375,11 @@ INTERNAL void cache_entry_load_texture(struct cache_ref ref, struct sprite_tag t
}
if (decoded.success) {
enum gpu_texture_format format = GPU_TEXTURE_FORMAT_R8G8B8A8_UNORM;
if (decoded.srgb) {
format = GPU_TEXTURE_FORMAT_R8G8B8A8_UNORM_SRGB;
}
/* Initialize */
e->texture = arena_push(&e->arena, struct sprite_texture);
e->texture->width = decoded.image.width;
e->texture->height = decoded.image.height;
e->texture->texture = gpu_texture_alloc(format, 0, V2I32(decoded.image.width, decoded.image.height), decoded.image.pixels);
e->texture->texture = gpu_texture_alloc(GPU_TEXTURE_FORMAT_R8G8B8A8_UNORM_SRGB, 0, V2I32(decoded.image.width, decoded.image.height), decoded.image.pixels);
e->texture->valid = true;
e->texture->loaded = true;
/* TODO: Query gpu for more accurate texture size in VRAM */

View File

@ -71,17 +71,14 @@ GLOBAL struct {
struct second_stat net_bytes_sent;
/* Render targets */
struct gpu_texture final_texture;
struct gpu_texture world_texture;
struct gpu_texture ui_texture;
struct gpu_texture user_texture;
struct gpu_texture backbuffer_texture;
struct gpu_cmd_buffer *world_cmd_buffer;
struct gpu_cmd_buffer *ui_cmd_buffer;
struct gpu_cmd_buffer *final_cmd_buffer;
struct gpu_cmd_buffer *backbuffer_cmd_buffer;
struct gpu_cmd_store world_gpu_cmd_store;
struct gpu_cmd_store user_gpu_cmd_store;
struct gpu_cmd_store backbuffer_gpu_cmd_store;
struct xform world_to_ui_xf;
struct xform world_to_user_xf;
struct bind_state bind_states[USER_BIND_KIND_COUNT];
@ -139,10 +136,10 @@ GLOBAL struct {
/* Per-frame */
struct v2 screen_size;
struct v2 screen_cursor;
struct v2 ui_screen_offset;
struct v2 ui_size;
struct v2 ui_center;
struct v2 ui_cursor;
struct v2 user_screen_offset;
struct v2 user_size;
struct v2 user_center;
struct v2 user_cursor;
struct v2 world_cursor;
struct v2 focus_send;
} G = ZI, DEBUG_ALIAS(G, G_user);
@ -255,11 +252,10 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr,
/* User sim control */
G.user_sim_cmd_mutex = sys_mutex_alloc();
G.world_to_ui_xf = XFORM_IDENT;
G.world_cmd_buffer = gpu_cmd_buffer_alloc();
G.ui_cmd_buffer = gpu_cmd_buffer_alloc();
G.final_cmd_buffer = gpu_cmd_buffer_alloc();
G.backbuffer_cmd_buffer = gpu_cmd_buffer_alloc();
G.world_to_user_xf = XFORM_IDENT;
G.world_gpu_cmd_store = gpu_cmd_store_alloc();
G.user_gpu_cmd_store = gpu_cmd_store_alloc();
G.backbuffer_gpu_cmd_store = gpu_cmd_store_alloc();
//log_register_callback(debug_console_log_callback, LOG_LEVEL_SUCCESS);
log_register_callback(debug_console_log_callback, LOG_LEVEL_DEBUG);
@ -338,21 +334,21 @@ INTERNAL void debug_draw_xform(struct xform xf, u32 color_x, u32 color_y)
f32 thickness = 2.f;
f32 arrowhead_len = 15.f;
struct v2 pos = xform_mul_v2(G.world_to_ui_xf, xf.og);
struct v2 x_ray = xform_basis_mul_v2(G.world_to_ui_xf, xform_get_right(xf));
struct v2 y_ray = xform_basis_mul_v2(G.world_to_ui_xf, xform_get_up(xf));
struct v2 pos = xform_mul_v2(G.world_to_user_xf, xf.og);
struct v2 x_ray = xform_basis_mul_v2(G.world_to_user_xf, xform_get_right(xf));
struct v2 y_ray = xform_basis_mul_v2(G.world_to_user_xf, xform_get_up(xf));
f32 ray_scale = 1;
x_ray = v2_mul(x_ray, ray_scale);
y_ray = v2_mul(y_ray, ray_scale);
draw_arrow_ray(G.ui_cmd_buffer, pos, x_ray, thickness, arrowhead_len, color_x);
draw_arrow_ray(G.ui_cmd_buffer, pos, y_ray, thickness, arrowhead_len, color_y);
draw_arrow_ray(G.user_gpu_cmd_store, pos, x_ray, thickness, arrowhead_len, color_x);
draw_arrow_ray(G.user_gpu_cmd_store, pos, y_ray, thickness, arrowhead_len, color_y);
//u32 color_quad = RGBA_F(0, 1, 1, 0.3);
//struct quad quad = quad_from_rect(RECT(0, 0, 1, -1));
//quad = xform_mul_quad(xf, quad_scale(quad, 0.075f));
//draw_quad(G.ui_cmd_buffer, quad, color);
//draw_quad(G.user_gpu_cmd_store, quad, color);
}
INTERNAL void debug_draw_movement(struct sim_ent *ent)
@ -365,11 +361,11 @@ INTERNAL void debug_draw_movement(struct sim_ent *ent)
struct xform xf = sim_ent_get_xform(ent);
struct v2 velocity = ent->linear_velocity;
struct v2 pos = xform_mul_v2(G.world_to_ui_xf, xf.og);
struct v2 vel_ray = xform_basis_mul_v2(G.world_to_ui_xf, velocity);
struct v2 pos = xform_mul_v2(G.world_to_user_xf, xf.og);
struct v2 vel_ray = xform_basis_mul_v2(G.world_to_user_xf, velocity);
if (v2_len(vel_ray) > 0.00001) {
draw_arrow_ray(G.ui_cmd_buffer, pos, vel_ray, thickness, arrow_len, color_vel);
draw_arrow_ray(G.user_gpu_cmd_store, pos, vel_ray, thickness, arrow_len, color_vel);
}
}
@ -539,7 +535,7 @@ INTERNAL void draw_debug_console(i32 level, b32 minimized)
if (log->level <= level) {
/* Draw background */
u32 color = colors[log->level][log->color_index];
draw_quad(G.ui_cmd_buffer, quad_from_rect(log->bounds), ALPHA_F(color, opacity));
draw_quad(G.user_gpu_cmd_store, quad_from_rect(log->bounds), ALPHA_F(color, opacity));
/* Draw text */
struct string text = log->msg;
@ -556,7 +552,7 @@ INTERNAL void draw_debug_console(i32 level, b32 minimized)
}
struct draw_text_params params = DRAW_TEXT_PARAMS(.font = font, .pos = draw_pos, .offset_y = DRAW_TEXT_OFFSET_Y_BOTTOM, .color = ALPHA_F(COLOR_WHITE, opacity), .str = text);
struct rect bounds = draw_text(G.ui_cmd_buffer, params);
struct rect bounds = draw_text(G.user_gpu_cmd_store, params);
struct rect draw_bounds = bounds;
draw_bounds.x -= bg_margin;
@ -780,10 +776,10 @@ INTERNAL void user_update(void)
b32 pressed = event->kind == SYS_EVENT_KIND_BUTTON_DOWN;
#if 0
b32 out_of_bounds = button >= SYS_BTN_M1 && button <= SYS_BTN_M5 &&
(G.ui_cursor.x < 0 ||
G.ui_cursor.y < 0 ||
G.ui_cursor.x > G.ui_size.x ||
G.ui_cursor.y > G.ui_size.y);
(G.user_cursor.x < 0 ||
G.user_cursor.y < 0 ||
G.user_cursor.x > G.user_size.x ||
G.user_cursor.y > G.user_size.y);
#else
b32 out_of_bounds = false;
#endif
@ -931,8 +927,8 @@ INTERNAL void user_update(void)
/* Calculate ui dimensions */
if (G.debug_camera) {
G.ui_size = G.screen_size;
G.ui_screen_offset = V2(0, 0);
G.user_size = G.screen_size;
G.user_screen_offset = V2(0, 0);
} else {
/* Determine ui size by camera & window dimensions */
f32 aspect_ratio = DEFAULT_CAMERA_WIDTH / DEFAULT_CAMERA_HEIGHT;
@ -950,27 +946,27 @@ INTERNAL void user_update(void)
} else {
height = math_ceil(width / aspect_ratio);
}
G.ui_size = V2(width, height);
G.user_size = V2(width, height);
/* Center ui in window */
f32 x = 0;
f32 y = 0;
x = math_round(G.screen_size.x / 2 - width / 2);
y = math_round(G.screen_size.y / 2 - height / 2);
G.ui_screen_offset = V2(x, y);
G.user_screen_offset = V2(x, y);
}
G.ui_center = v2_mul(G.ui_size, 0.5);
G.ui_cursor = v2_sub(G.screen_cursor, G.ui_screen_offset);
G.user_center = v2_mul(G.user_size, 0.5);
G.user_cursor = v2_sub(G.screen_cursor, G.user_screen_offset);
/* ========================== *
* Update view from camera
* ========================== */
if (G.debug_camera) {
G.world_to_ui_xf = xform_basis_with_rotation_world(G.world_to_ui_xf, 0);
G.world_to_user_xf = xform_basis_with_rotation_world(G.world_to_user_xf, 0);
struct v2 world_cursor = xform_invert_mul_v2(G.world_to_ui_xf, G.ui_cursor);
struct v2 world_cursor = xform_invert_mul_v2(G.world_to_user_xf, G.user_cursor);
/* Pan view */
if (G.bind_states[USER_BIND_KIND_PAN].is_held) {
@ -979,8 +975,8 @@ INTERNAL void user_update(void)
G.debug_camera_panning = true;
}
struct v2 offset = v2_neg(v2_sub(G.debug_camera_pan_start, world_cursor));
G.world_to_ui_xf = xform_translated(G.world_to_ui_xf, offset);
world_cursor = xform_invert_mul_v2(G.world_to_ui_xf, G.ui_cursor);
G.world_to_user_xf = xform_translated(G.world_to_user_xf, offset);
world_cursor = xform_invert_mul_v2(G.world_to_user_xf, G.user_cursor);
G.debug_camera_pan_start = world_cursor;
} else {
G.debug_camera_panning = false;
@ -992,9 +988,9 @@ INTERNAL void user_update(void)
/* Zoom to cursor */
f32 zoom_rate = 2;
f32 zoom = math_pow(zoom_rate, input_zooms);
G.world_to_ui_xf = xform_translated(G.world_to_ui_xf, world_cursor);
G.world_to_ui_xf = xform_scaled(G.world_to_ui_xf, V2(zoom, zoom));
G.world_to_ui_xf = xform_translated(G.world_to_ui_xf, v2_neg(world_cursor));
G.world_to_user_xf = xform_translated(G.world_to_user_xf, world_cursor);
G.world_to_user_xf = xform_scaled(G.world_to_user_xf, V2(zoom, zoom));
G.world_to_user_xf = xform_translated(G.world_to_user_xf, v2_neg(world_cursor));
}
} else {
struct xform xf = sim_ent_get_xform(local_camera);
@ -1003,7 +999,7 @@ INTERNAL void user_update(void)
f32 rot = xform_get_rotation(xf);
/* Scale view into viewport based on camera size */
struct v2 size = G.ui_size;
struct v2 size = G.user_size;
{
struct xform quad_xf = xform_mul(xf, local_camera->camera_quad_xform);
struct v2 camera_size = xform_get_scale(quad_xf);
@ -1013,16 +1009,16 @@ INTERNAL void user_update(void)
}
f32 scale_ui = min_f32(size.x, size.y);
struct trs trs = TRS(.t = v2_sub(G.ui_center, center), .r = rot, .s = V2(scale_ui, scale_ui));
struct trs trs = TRS(.t = v2_sub(G.user_center, center), .r = rot, .s = V2(scale_ui, scale_ui));
struct v2 pivot = center;
G.world_to_ui_xf = XFORM_IDENT;
G.world_to_ui_xf = xform_translated(G.world_to_ui_xf, pivot);
G.world_to_ui_xf = xform_translated(G.world_to_ui_xf, trs.t);
G.world_to_ui_xf = xform_rotated(G.world_to_ui_xf, trs.r);
G.world_to_ui_xf = xform_scaled(G.world_to_ui_xf, trs.s);
G.world_to_ui_xf = xform_translated(G.world_to_ui_xf, v2_neg(pivot));
G.world_to_user_xf = XFORM_IDENT;
G.world_to_user_xf = xform_translated(G.world_to_user_xf, pivot);
G.world_to_user_xf = xform_translated(G.world_to_user_xf, trs.t);
G.world_to_user_xf = xform_rotated(G.world_to_user_xf, trs.r);
G.world_to_user_xf = xform_scaled(G.world_to_user_xf, trs.s);
G.world_to_user_xf = xform_translated(G.world_to_user_xf, v2_neg(pivot));
}
G.world_cursor = xform_invert_mul_v2(G.world_to_ui_xf, G.ui_cursor);
G.world_cursor = xform_invert_mul_v2(G.world_to_user_xf, G.user_cursor);
/* ========================== *
* Update listener from view
@ -1030,8 +1026,8 @@ INTERNAL void user_update(void)
{
struct v2 up = V2(0, -1);
struct v2 listener_pos = xform_invert_mul_v2(G.world_to_ui_xf, G.ui_center);
struct v2 listener_dir = v2_norm(xform_basis_invert_mul_v2(G.world_to_ui_xf, up));
struct v2 listener_pos = xform_invert_mul_v2(G.world_to_user_xf, G.user_center);
struct v2 listener_dir = v2_norm(xform_basis_invert_mul_v2(G.world_to_user_xf, up));
mixer_set_listener(listener_pos, listener_dir);
}
@ -1042,14 +1038,14 @@ INTERNAL void user_update(void)
{
f32 thickness = 2;
struct v2 offset = v2_neg(xform_mul_v2(G.world_to_ui_xf, V2(0, 0)));
f32 spacing = xform_get_scale(G.world_to_ui_xf).x;
struct v2 offset = v2_neg(xform_mul_v2(G.world_to_user_xf, V2(0, 0)));
f32 spacing = xform_get_scale(G.world_to_user_xf).x;
struct v2 pos = xform_invert_mul_v2(G.world_to_ui_xf, V2(0, 0));
struct v2 size = xform_basis_invert_mul_v2(G.world_to_ui_xf, G.ui_size);
struct v2 pos = xform_invert_mul_v2(G.world_to_user_xf, V2(0, 0));
struct v2 size = xform_basis_invert_mul_v2(G.world_to_user_xf, G.user_size);
u32 color0 = RGBA_F(0.17f, 0.17f, 0.17f, 1.f);
u32 color1 = RGBA_F(0.15f, 0.15f, 0.15f, 1.f);
draw_grid(G.world_cmd_buffer, RECT_FROM_V2(pos, size), color0, color1, RGBA(0x3f, 0x3f, 0x3f, 0xFF), COLOR_RED, COLOR_GREEN, thickness, spacing, offset);
draw_grid(G.world_gpu_cmd_store, XFORM_TRS(.t = pos, .s = size), color0, color1, RGBA(0x3f, 0x3f, 0x3f, 0xFF), COLOR_RED, COLOR_GREEN, thickness, spacing, offset);
}
#if 0
@ -1231,9 +1227,9 @@ INTERNAL void user_update(void)
u32 color_end = RGBA_F(1, 0.8, 0.4, opacity_b);
if (opacity_b > 0.99f) {
draw_circle(G.world_cmd_buffer, b, thickness / 2, color_end, 20);
draw_circle(G.world_gpu_cmd_store, b, thickness / 2, color_end, 20);
}
draw_gradient_line(G.world_cmd_buffer, a, b, thickness, color_start, color_end);
draw_gradient_line(G.world_gpu_cmd_store, a, b, thickness, color_start, color_end);
}
@ -1252,9 +1248,8 @@ INTERNAL void user_update(void)
if (sheet->loaded) {
u32 tint = ent->sprite_tint;
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 draw_texture_params params = DRAW_TEXTURE_PARAMS(.sprite = sprite, .tint0_srgb = tint, .tint1_srgb = tint, .clip = frame.clip, .quad = quad);
draw_quad_texture(G.world_cmd_buffer, params);
struct draw_texture_params params = DRAW_TEXTURE_PARAMS(.xf = sprite_xform, .sprite = sprite, .tint = tint, .clip = frame.clip);
draw_texture(G.world_gpu_cmd_store, params);
}
}
@ -1271,12 +1266,10 @@ INTERNAL void user_update(void)
//if (tile > -1) {
if (tile == SIM_TILE_KIND_WALL) {
struct v2i32 world_tile_index = sim_world_tile_index_from_local_tile_index(chunk_index, local_tile_index);
struct v2 pos = sim_pos_from_world_tile_index(world_tile_index);
struct quad quad = quad_from_rect(RECT(pos.x, pos.y, tile_size, tile_size));
struct draw_texture_params params = DRAW_TEXTURE_PARAMS(.sprite = tile_sprite, .quad = quad);
draw_quad_texture(G.world_cmd_buffer, params);
struct xform tile_xf = XFORM_TRS(.t = pos, .s = V2(tile_size, tile_size));
struct draw_texture_params params = DRAW_TEXTURE_PARAMS(.xf = tile_xf, .sprite = tile_sprite);
draw_texture(G.world_gpu_cmd_store, params);
}
}
}
@ -1303,8 +1296,8 @@ INTERNAL void user_update(void)
f32 thickness = 1;
u32 color = RGBA_F(1, 0, 1, 0.5);
struct quad quad = quad_from_aabb(aabb);
quad = xform_mul_quad(G.world_to_ui_xf, quad);
draw_quad_line(G.ui_cmd_buffer, quad, thickness, color);
quad = xform_mul_quad(G.world_to_user_xf, quad);
draw_quad_line(G.user_gpu_cmd_store, quad, thickness, color);
}
/* Draw focus arrow */
@ -1312,10 +1305,10 @@ INTERNAL void user_update(void)
struct sprite_sheet *sheet = sprite_sheet_from_tag_async(sprite_frame_scope, ent->sprite);
struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, LIT("attach.wep"), ent->animation_frame);
struct v2 start = xform_mul_v2(sprite_xform, slice.center);
start = xform_mul_v2(G.world_to_ui_xf, start);
start = xform_mul_v2(G.world_to_user_xf, start);
struct v2 end = v2_add(xf.og, ent->control.focus);
end = xform_mul_v2(G.world_to_ui_xf, end);
draw_arrow_line(G.ui_cmd_buffer, start, end, 3, 10, RGBA_F(1, 1, 1, 0.5));
end = xform_mul_v2(G.world_to_user_xf, end);
draw_arrow_line(G.user_gpu_cmd_store, start, end, 3, 10, RGBA_F(1, 1, 1, 0.5));
}
#if 0
@ -1335,22 +1328,22 @@ INTERNAL void user_update(void)
struct sprite_sheet_slice slice = group->frame_slices[(ent->animation_frame * group->per_frame_count) + j];
struct v2 center = xform_mul_v2(sprite_xform, slice.center);
center = xform_mul_v2(G.world_to_ui_xf, center);
center = xform_mul_v2(G.world_to_user_xf, center);
if (!slice.has_ray) {
struct quad quad = quad_from_rect(slice.rect);
quad = xform_mul_quad(sprite_xform, quad);
quad = xform_mul_quad(G.world_to_ui_xf, quad);
draw_quad_line(G.ui_cmd_buffer, quad, 2, quad_color);
quad = xform_mul_quad(G.world_to_user_xf, quad);
draw_quad_line(G.user_gpu_cmd_store, quad, 2, quad_color);
}
draw_circle(G.ui_cmd_buffer, center, 3, point_color, 20);
draw_circle(G.user_gpu_cmd_store, center, 3, point_color, 20);
if (slice.has_ray) {
struct v2 ray = xform_basis_mul_v2(sprite_xform, slice.dir);
ray = xform_basis_mul_v2(G.world_to_ui_xf, ray);
ray = xform_basis_mul_v2(G.world_to_user_xf, ray);
ray = v2_with_len(ray, 25);
draw_arrow_ray(G.ui_cmd_buffer, center, ray, 2, 10, ray_color);
draw_arrow_ray(G.user_gpu_cmd_store, center, ray, 2, 10, ray_color);
}
}
}
@ -1366,8 +1359,8 @@ INTERNAL void user_update(void)
u32 color = COLOR_YELLOW;
f32 radius = 3;
struct v2 point = xform_mul_v2(e1_xf, ent->weld_joint_data.point_local_e1);
point = xform_mul_v2(G.world_to_ui_xf, point);
draw_circle(G.ui_cmd_buffer, point, radius, color, 10);
point = xform_mul_v2(G.world_to_user_xf, point);
draw_circle(G.user_gpu_cmd_store, point, radius, color, 10);
DEBUGBREAKABLE;
}
@ -1380,10 +1373,10 @@ INTERNAL void user_update(void)
u32 color = COLOR_WHITE;
struct v2 point_start = xform_mul_v2(target_xf, ent->mouse_joint_data.point_local_start);
struct v2 point_end = G.world_cursor;
point_start = xform_mul_v2(G.world_to_ui_xf, point_start);
point_end = xform_mul_v2(G.world_to_ui_xf, point_end);
draw_arrow_line(G.ui_cmd_buffer, point_start, point_end, 3, 10, color);
draw_circle(G.ui_cmd_buffer, point_start, 4, color, 10);
point_start = xform_mul_v2(G.world_to_user_xf, point_start);
point_end = xform_mul_v2(G.world_to_user_xf, point_end);
draw_arrow_line(G.user_gpu_cmd_store, point_start, point_end, 3, 10, color);
draw_circle(G.user_gpu_cmd_store, point_start, 4, color, 10);
}
/* Draw collider */
@ -1394,29 +1387,29 @@ INTERNAL void user_update(void)
{
/* Draw collider using support points */
u32 detail = 32;
draw_collider_line(G.ui_cmd_buffer, G.world_to_ui_xf, collider, xf, thickness, color, detail);
draw_collider_line(G.user_gpu_cmd_store, G.world_to_user_xf, collider, xf, thickness, color, detail);
}
{
/* Draw collider shape points */
for (u32 i = 0; i < collider.count; ++i) {
struct v2 p = xform_mul_v2(xform_mul(G.world_to_ui_xf, xf), collider.points[i]);
draw_circle(G.ui_cmd_buffer, p, 3, COLOR_BLUE, 10);
struct v2 p = xform_mul_v2(xform_mul(G.world_to_user_xf, xf), collider.points[i]);
draw_circle(G.user_gpu_cmd_store, p, 3, COLOR_BLUE, 10);
}
}
if (collider.count == 1 && collider.radius > 0) {
/* Draw upwards line for circle */
struct v2 start = xf.og;
struct v2 end = collider_get_support_point(&collider, xf, v2_neg(xf.by)).p;
start = xform_mul_v2(G.world_to_ui_xf, start);
end = xform_mul_v2(G.world_to_ui_xf, end);
draw_line(G.ui_cmd_buffer, start, end, thickness, color);
start = xform_mul_v2(G.world_to_user_xf, start);
end = xform_mul_v2(G.world_to_user_xf, end);
draw_line(G.user_gpu_cmd_store, start, end, thickness, color);
}
#if 0
/* Draw support point at focus dir */
{
struct v2 p = collider_support_point(&collider, xf, ent->control.focus);
p = xform_mul_v2(G.world_to_ui_xf, p);
draw_circle(G.ui_cmd_buffer, p, 3, COLOR_RED, 10);
p = xform_mul_v2(G.world_to_user_xf, p);
draw_circle(G.user_gpu_cmd_store, p, 3, COLOR_RED, 10);
}
#endif
}
@ -1441,7 +1434,7 @@ INTERNAL void user_update(void)
/* Draw point */
{
u32 color = ALPHA_F(COLOR_YELLOW, 0.50);
draw_circle(G.ui_cmd_buffer, xform_mul_v2(G.world_to_ui_xf, dbg_pt), radius, color, 10);
draw_circle(G.user_gpu_cmd_store, xform_mul_v2(G.world_to_user_xf, dbg_pt), radius, color, 10);
}
/* Draw normal */
@ -1450,9 +1443,9 @@ INTERNAL void user_update(void)
f32 len = 0.1f;
f32 arrow_thickness = 2;
f32 arrow_height = 5;
struct v2 start = xform_mul_v2(G.world_to_ui_xf, dbg_pt);
struct v2 end = xform_mul_v2(G.world_to_ui_xf, v2_add(dbg_pt, v2_mul(v2_norm(data->normal), len)));
draw_arrow_line(G.ui_cmd_buffer, start, end, arrow_thickness, arrow_height, color);
struct v2 start = xform_mul_v2(G.world_to_user_xf, dbg_pt);
struct v2 end = xform_mul_v2(G.world_to_user_xf, v2_add(dbg_pt, v2_mul(v2_norm(data->normal), len)));
draw_arrow_line(G.user_gpu_cmd_store, start, end, arrow_thickness, arrow_height, color);
}
#if 0
/* Draw contact info */
@ -1482,7 +1475,7 @@ INTERNAL void user_update(void)
FMT_UINT(data->num_points));
draw_text(G.ui_cmd_buffer, disp_font, v2_add(v2_round(xform_mul_v2(G.world_to_ui_xf, dbg_pt)), V2(0, offset_px)), text);
draw_text(G.user_gpu_cmd_store, disp_font, v2_add(v2_round(xform_mul_v2(G.world_to_user_xf, dbg_pt)), V2(0, offset_px)), text);
}
}
#endif
@ -1508,10 +1501,10 @@ INTERNAL void user_update(void)
{
f32 radius = 4;
u32 color = RGBA_F(1, 1, 0, 0.5);
struct v2 a = xform_mul_v2(G.world_to_ui_xf, data->closest0);
struct v2 b = xform_mul_v2(G.world_to_ui_xf, data->closest1);
draw_circle(G.ui_cmd_buffer, a, radius, color, 10);
draw_circle(G.ui_cmd_buffer, b, radius, color, 10);
struct v2 a = xform_mul_v2(G.world_to_user_xf, data->closest0);
struct v2 b = xform_mul_v2(G.world_to_user_xf, data->closest1);
draw_circle(G.user_gpu_cmd_store, a, radius, color, 10);
draw_circle(G.user_gpu_cmd_store, b, radius, color, 10);
}
#endif
@ -1526,30 +1519,30 @@ INTERNAL void user_update(void)
u32 color_a_clipped = RGBA_F(1, 0, 0, 1);
u32 color_b_clipped = RGBA_F(0, 1, 0, 1);
{
struct v2 a = xform_mul_v2(G.world_to_ui_xf, collider_res.a0);
struct v2 b = xform_mul_v2(G.world_to_ui_xf, collider_res.b0);
draw_line(G.ui_cmd_buffer, a, b, thickness, color_line);
draw_circle(G.ui_cmd_buffer, a, radius, color_a, 10);
draw_circle(G.ui_cmd_buffer, b, radius, color_b, 10);
struct v2 a = xform_mul_v2(G.world_to_user_xf, collider_res.a0);
struct v2 b = xform_mul_v2(G.world_to_user_xf, collider_res.b0);
draw_line(G.user_gpu_cmd_store, a, b, thickness, color_line);
draw_circle(G.user_gpu_cmd_store, a, radius, color_a, 10);
draw_circle(G.user_gpu_cmd_store, b, radius, color_b, 10);
struct v2 a_clipped = xform_mul_v2(G.world_to_ui_xf, collider_res.a0_clipped);
struct v2 b_clipped = xform_mul_v2(G.world_to_ui_xf, collider_res.b0_clipped);
draw_line(G.ui_cmd_buffer, a_clipped, b_clipped, thickness, color_line_clipped);
draw_circle(G.ui_cmd_buffer, a_clipped, radius, color_a_clipped, 10);
draw_circle(G.ui_cmd_buffer, b_clipped, radius, color_b_clipped, 10);
struct v2 a_clipped = xform_mul_v2(G.world_to_user_xf, collider_res.a0_clipped);
struct v2 b_clipped = xform_mul_v2(G.world_to_user_xf, collider_res.b0_clipped);
draw_line(G.user_gpu_cmd_store, a_clipped, b_clipped, thickness, color_line_clipped);
draw_circle(G.user_gpu_cmd_store, a_clipped, radius, color_a_clipped, 10);
draw_circle(G.user_gpu_cmd_store, b_clipped, radius, color_b_clipped, 10);
}
{
struct v2 a = xform_mul_v2(G.world_to_ui_xf, collider_res.a1);
struct v2 b = xform_mul_v2(G.world_to_ui_xf, collider_res.b1);
draw_line(G.ui_cmd_buffer, a, b, thickness, color_line);
draw_circle(G.ui_cmd_buffer, a, radius, color_a, 10);
draw_circle(G.ui_cmd_buffer, b, radius, color_b, 10);
struct v2 a = xform_mul_v2(G.world_to_user_xf, collider_res.a1);
struct v2 b = xform_mul_v2(G.world_to_user_xf, collider_res.b1);
draw_line(G.user_gpu_cmd_store, a, b, thickness, color_line);
draw_circle(G.user_gpu_cmd_store, a, radius, color_a, 10);
draw_circle(G.user_gpu_cmd_store, b, radius, color_b, 10);
struct v2 a_clipped = xform_mul_v2(G.world_to_ui_xf, collider_res.a1_clipped);
struct v2 b_clipped = xform_mul_v2(G.world_to_ui_xf, collider_res.b1_clipped);
draw_line(G.ui_cmd_buffer, a_clipped, b_clipped, thickness, color_line_clipped);
draw_circle(G.ui_cmd_buffer, a_clipped, radius, color_a_clipped, 10);
draw_circle(G.ui_cmd_buffer, b_clipped, radius, color_b_clipped, 10);
struct v2 a_clipped = xform_mul_v2(G.world_to_user_xf, collider_res.a1_clipped);
struct v2 b_clipped = xform_mul_v2(G.world_to_user_xf, collider_res.b1_clipped);
draw_line(G.user_gpu_cmd_store, a_clipped, b_clipped, thickness, color_line_clipped);
draw_circle(G.user_gpu_cmd_store, a_clipped, radius, color_a_clipped, 10);
draw_circle(G.user_gpu_cmd_store, b_clipped, radius, color_b_clipped, 10);
}
}
@ -1590,7 +1583,7 @@ INTERNAL void user_update(void)
FMT_FLOAT_P(xform_get_rotation(e1_xf), 24));
draw_text(G.ui_cmd_buffer, disp_font, v2_add(v2_round(xform_mul_v2(G.world_to_ui_xf, V2(0, 0))), V2(0, offset_px)), text);
draw_text(G.user_gpu_cmd_store, disp_font, v2_add(v2_round(xform_mul_v2(G.world_to_user_xf, V2(0, 0))), V2(0, offset_px)), text);
}
}
#endif
@ -1605,9 +1598,9 @@ INTERNAL void user_update(void)
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_to_ui_xf, m.points[i]);
draw_poly_line(G.ui_cmd_buffer, m, true, thickness, color);
//draw_poly(G.ui_cmd_buffer, m, color);
for (u64 i = 0; i < m.count; ++i) m.points[i] = xform_mul_v2(G.world_to_user_xf, m.points[i]);
draw_poly_line(G.user_gpu_cmd_store, m, true, thickness, color);
//draw_poly(G.user_gpu_cmd_store, m, color);
}
/* Draw cloud */
@ -1618,8 +1611,8 @@ INTERNAL void user_update(void)
struct v2_array m = cloud(temp.arena, &e0_collider, &e1_collider, e0_xf, e1_xf);
for (u64 i = 0; i < m.count; ++i) {
struct v2 p = xform_mul_v2(G.world_to_ui_xf, m.points[i]);
draw_circle(G.ui_cmd_buffer, p, radius, color, 10);
struct v2 p = xform_mul_v2(G.world_to_user_xf, m.points[i]);
draw_circle(G.user_gpu_cmd_store, p, radius, color, 10);
}
}
@ -1632,9 +1625,9 @@ INTERNAL void user_update(void)
.points = collider_res.prototype.points,
.count = collider_res.prototype.len
};
for (u64 i = 0; i < m.count; ++i) m.points[i] = xform_mul_v2(G.world_to_ui_xf, m.points[i]);
draw_poly_line(G.ui_cmd_buffer, m, true, thickness, color);
for (u64 i = 0; i < m.count; ++i) draw_circle(G.ui_cmd_buffer, m.points[i], 10, color, 10);
for (u64 i = 0; i < m.count; ++i) m.points[i] = xform_mul_v2(G.world_to_user_xf, m.points[i]);
draw_poly_line(G.user_gpu_cmd_store, m, true, thickness, color);
for (u64 i = 0; i < m.count; ++i) draw_circle(G.user_gpu_cmd_store, m.points[i], 10, color, 10);
}
/* Draw simplex */
@ -1647,23 +1640,23 @@ INTERNAL void user_update(void)
struct collider_menkowski_simplex simplex = collider_res.simplex;
struct v2 simplex_points[] = { simplex.a.p, simplex.b.p, simplex.c.p };
for (u64 i = 0; i < ARRAY_COUNT(simplex_points); ++i) simplex_points[i] = xform_mul_v2(G.world_to_ui_xf, simplex_points[i]);
for (u64 i = 0; i < ARRAY_COUNT(simplex_points); ++i) simplex_points[i] = xform_mul_v2(G.world_to_user_xf, simplex_points[i]);
struct v2_array simplex_array = { .count = simplex.len, .points = simplex_points };
if (simplex.len >= 1) {
u32 color = simplex.len == 1 ? color_first : (simplex.len == 2 ? color_second : color_third);
draw_circle(G.ui_cmd_buffer, simplex_array.points[0], thickness * 3, color, 10);
draw_circle(G.user_gpu_cmd_store, simplex_array.points[0], thickness * 3, color, 10);
}
if (simplex.len >= 2) {
u32 color = simplex.len == 2 ? color_first : color_second;
draw_circle(G.ui_cmd_buffer, simplex_array.points[1], thickness * 3, color, 10);
draw_circle(G.user_gpu_cmd_store, simplex_array.points[1], thickness * 3, color, 10);
}
if (simplex.len >= 3) {
u32 color = color_first;
draw_circle(G.ui_cmd_buffer, simplex_array.points[2], thickness * 3, color, 10);
draw_circle(G.user_gpu_cmd_store, simplex_array.points[2], thickness * 3, color, 10);
}
if (simplex.len >= 2) {
draw_poly_line(G.ui_cmd_buffer, simplex_array, simplex.len > 2, thickness, line_color);
draw_poly_line(G.user_gpu_cmd_store, simplex_array, simplex.len > 2, thickness, line_color);
}
}
@ -1673,9 +1666,9 @@ INTERNAL void user_update(void)
f32 len = 0.1f;
f32 arrow_thickness = 4;
f32 arrowhead_height = 10;
struct v2 start = xform_mul_v2(G.world_to_ui_xf, V2(0, 0));
struct v2 end = xform_mul_v2(G.world_to_ui_xf, v2_mul(v2_norm(collider_res.normal), len));
draw_arrow_line(G.ui_cmd_buffer, start, end, arrow_thickness, arrowhead_height, color);
struct v2 start = xform_mul_v2(G.world_to_user_xf, V2(0, 0));
struct v2 end = xform_mul_v2(G.world_to_user_xf, v2_mul(v2_norm(collider_res.normal), len));
draw_arrow_line(G.user_gpu_cmd_store, start, end, arrow_thickness, arrowhead_height, color);
}
}
#endif
@ -1689,9 +1682,9 @@ INTERNAL void user_update(void)
f32 thickness = 2;
f32 arrow_height = 15;
struct v2 start = xform_mul_v2(G.world_to_ui_xf, xf.og);
struct v2 end = xform_mul_v2(G.world_to_ui_xf, parent_xf.og);
draw_arrow_line(G.ui_cmd_buffer, start, end, thickness, arrow_height, color);
struct v2 start = xform_mul_v2(G.world_to_user_xf, xf.og);
struct v2 end = xform_mul_v2(G.world_to_user_xf, parent_xf.og);
draw_arrow_line(G.user_gpu_cmd_store, start, end, thickness, arrow_height, color);
}
/* Draw camera rect */
@ -1701,9 +1694,9 @@ INTERNAL void user_update(void)
struct xform quad_xf = xform_mul(xf, ent->camera_quad_xform);
struct quad quad = xform_mul_quad(quad_xf, QUAD_UNIT_SQUARE_CENTERED);
quad = xform_mul_quad(G.world_to_ui_xf, quad);
quad = xform_mul_quad(G.world_to_user_xf, quad);
draw_quad_line(G.ui_cmd_buffer, quad, thickness, color);
draw_quad_line(G.user_gpu_cmd_store, quad, thickness, color);
}
arena_temp_end(temp);
@ -1714,17 +1707,16 @@ INTERNAL void user_update(void)
/* Draw crosshair or show cursor */
if (!G.debug_camera) {
__profscope(draw_crosshair);
struct v2 crosshair_pos = G.ui_cursor;
struct v2 crosshair_pos = G.user_cursor;
struct sprite_tag crosshair_tag = sprite_tag_from_path(LIT("sprites/crosshair.ase"));
struct sprite_texture *t = sprite_texture_from_tag_async(sprite_frame_scope, crosshair_tag);
struct v2 size = V2(t->width, t->height);
struct xform xf = XFORM_TRS(.t = crosshair_pos, .s = size);
struct quad quad = xform_mul_quad(xf, QUAD_UNIT_SQUARE_CENTERED);
draw_quad_texture(G.ui_cmd_buffer, DRAW_TEXTURE_PARAMS(.sprite = crosshair_tag, .quad = quad));
draw_texture(G.user_gpu_cmd_store, DRAW_TEXTURE_PARAMS(.xf = xf, .sprite = crosshair_tag));
struct rect cursor_clip = RECT_FROM_V2(G.ui_screen_offset, G.ui_size);
struct rect cursor_clip = RECT_FROM_V2(G.user_screen_offset, G.user_size);
cursor_clip.pos = v2_add(cursor_clip.pos, v2_mul(size, 0.5f));
cursor_clip.pos = v2_add(cursor_clip.pos, V2(1, 1));
cursor_clip.size = v2_sub(cursor_clip.size, size);
@ -1784,7 +1776,7 @@ INTERNAL void user_update(void)
}
}
input_move_dir = xform_basis_invert_mul_v2(G.world_to_ui_xf, input_move_dir); /* Make move dir relative to world view */
input_move_dir = xform_basis_invert_mul_v2(G.world_to_user_xf, input_move_dir); /* Make move dir relative to world view */
input_move_dir = v2_mul(v2_norm(input_move_dir), move_speed);
}
@ -1908,7 +1900,7 @@ INTERNAL void user_update(void)
if (G.debug_draw && hovered_ent->valid) {
struct sim_ent *ent = hovered_ent;
struct v2 pos = v2_add(G.ui_cursor, V2(15, 15));
struct v2 pos = v2_add(G.user_cursor, V2(15, 15));
struct font *font = font_load_async(LIT("fonts/fixedsys.ttf"), 12.0f);
if (font) {
struct temp_arena temp = arena_temp_begin(scratch.arena);
@ -1916,7 +1908,7 @@ INTERNAL void user_update(void)
struct string dbg_text = ZI;
dbg_text.text = arena_dry_push(temp.arena, u8);
dbg_text.len += get_ent_debug_text(temp.arena, ent).len;
draw_text(G.ui_cmd_buffer, DRAW_TEXT_PARAMS(.font = font, .pos = pos, .str = dbg_text));
draw_text(G.user_gpu_cmd_store, DRAW_TEXT_PARAMS(.font = font, .pos = pos, .str = dbg_text));
arena_temp_end(temp);
}
@ -2016,16 +2008,16 @@ INTERNAL void user_update(void)
//text.len += string_copy(temp.arena, LIT("\n")).len;
#if COLLIDER_DEBUG
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("collider gjk steps: %F"), FMT_UINT(collider_debug_steps)));
draw_text(G.user_gpu_cmd_store, font, pos, string_format(temp.arena, LIT("collider gjk steps: %F"), FMT_UINT(collider_debug_steps)));
pos.y += spacing;
#endif
//draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("blended world entities: %F/%F"), FMT_UINT(G.ss_blended->num_ents_allocated), FMT_UINT(G.ss_blended->num_ents_reserved)));
//draw_text(G.ui_cmd_buffer, font, pos, text);
//draw_text(G.user_gpu_cmd_store, font, pos, string_format(temp.arena, LIT("blended world entities: %F/%F"), FMT_UINT(G.ss_blended->num_ents_allocated), FMT_UINT(G.ss_blended->num_ents_reserved)));
//draw_text(G.user_gpu_cmd_store, font, pos, text);
struct v2 pos = V2(10, G.ui_size.y);
struct v2 pos = V2(10, G.user_size.y);
enum draw_text_offset_y offset_y = DRAW_TEXT_OFFSET_Y_BOTTOM;
draw_text(G.ui_cmd_buffer, DRAW_TEXT_PARAMS(.font = font, .pos = pos, .str = text, .offset_y = offset_y, .color = COLOR_WHITE));
draw_text(G.user_gpu_cmd_store, DRAW_TEXT_PARAMS(.font = font, .pos = pos, .str = text, .offset_y = offset_y, .color = COLOR_WHITE));
arena_temp_end(temp);
}
}
@ -2048,95 +2040,59 @@ INTERNAL void user_update(void)
{
__profscope(render);
struct rect ui_viewport = RECT_FROM_V2(V2(0, 0), G.ui_size);
struct rect user_viewport = RECT_FROM_V2(V2(0, 0), G.user_size);
struct rect backbuffer_viewport = RECT_FROM_V2(V2(0, 0), G.screen_size);
/* Allocate render textures */
struct v2i32 ui_resolution = v2_round_to_int(ui_viewport.size);
struct v2i32 user_resolution = v2_round_to_int(user_viewport.size);
struct v2i32 backbuffer_resolution = v2_round_to_int(backbuffer_viewport.size);
struct v2i32 world_resolution = ui_resolution;
/* Allocate target textures */
{
/* World texture */
if (!G.world_texture.handle || !v2i32_eq(gpu_texture_get_size(G.world_texture), world_resolution)) {
if (G.world_texture.handle) {
gpu_texture_release(G.world_texture);
/* User texture */
if (!G.user_texture.handle || !v2i32_eq(gpu_texture_get_size(G.user_texture), user_resolution)) {
if (G.user_texture.handle) {
gpu_texture_release(G.user_texture);
}
G.world_texture = gpu_texture_alloc(GPU_TEXTURE_FORMAT_R8G8B8A8_UNORM, GPU_TEXTURE_FLAG_TARGET, world_resolution, NULL);
}
/* Ui texture */
if (!G.ui_texture.handle || !v2i32_eq(gpu_texture_get_size(G.ui_texture), ui_resolution)) {
if (G.ui_texture.handle) {
gpu_texture_release(G.ui_texture);
}
G.ui_texture = gpu_texture_alloc(GPU_TEXTURE_FORMAT_R8G8B8A8_UNORM, GPU_TEXTURE_FLAG_TARGET, ui_resolution, NULL);
}
/* Final texture */
if (!G.final_texture.handle || !v2i32_eq(gpu_texture_get_size(G.final_texture), ui_resolution)) {
if (G.final_texture.handle) {
gpu_texture_release(G.final_texture);
}
G.final_texture = gpu_texture_alloc(GPU_TEXTURE_FORMAT_R8G8B8A8_UNORM, GPU_TEXTURE_FLAG_TARGET, ui_resolution, NULL);
G.user_texture = gpu_texture_alloc(GPU_TEXTURE_FORMAT_R8G8B8A8_UNORM, GPU_TEXTURE_FLAG_TARGETABLE, user_resolution, NULL);
}
/* Backbuffer texture */
if (!G.backbuffer_texture.handle || !v2i32_eq(gpu_texture_get_size(G.backbuffer_texture), backbuffer_resolution)) {
G.backbuffer_texture = gpu_recreate_backbuffer(backbuffer_resolution);
}
}
/* Combine render textures w/ quad draw cmds */
/* Draw user texture to backbuffer texture */
{
/* Draw world texture to final */
{
struct quad quad = quad_from_rect(RECT_FROM_V2(V2(0, 0), V2_FROM_V2I32(ui_resolution)));
struct draw_texture_params params = DRAW_TEXTURE_PARAMS(.texture = G.world_texture, .quad = quad);
draw_quad_texture(G.final_cmd_buffer, params);
}
/* Draw ui texture to final */
{
struct quad quad = quad_from_rect(RECT_FROM_V2(V2(0, 0), V2_FROM_V2I32(ui_resolution)));
struct draw_texture_params params = DRAW_TEXTURE_PARAMS(.texture = G.ui_texture, .quad = quad);
draw_quad_texture(G.final_cmd_buffer, params);
}
/* Draw final texture to backbuffer */
{
struct quad quad = quad_from_rect(RECT_FROM_V2(G.ui_screen_offset, V2_FROM_V2I32(G.ui_size)));
struct draw_texture_params params = DRAW_TEXTURE_PARAMS(.texture = G.final_texture, .quad = quad);
draw_quad_texture(G.backbuffer_cmd_buffer, params);
}
//struct xform xf = XFORM_TRS(.t = G.user_screen_offset, .s = G.user_size);
//xf = xform_translated(xf, V2(0.5, 0.5));
//struct xform xf = XFORM_IDENT;
struct xform xf = XFORM_TRS(.t = v2_mul(V2(backbuffer_resolution.x, backbuffer_resolution.y), 0.5), .s = G.user_size);
struct draw_texture_params params = DRAW_TEXTURE_PARAMS(.xf = xf, .texture = G.user_texture);
draw_texture(G.backbuffer_gpu_cmd_store, params);
}
/* Send cmd buffers to GPU */
gpu_cmd_buffer_flush_to_gpu(G.world_cmd_buffer);
gpu_cmd_buffer_flush_to_gpu(G.ui_cmd_buffer);
gpu_cmd_buffer_flush_to_gpu(G.final_cmd_buffer);
gpu_cmd_buffer_flush_to_gpu(G.backbuffer_cmd_buffer);
/* Send cmds to GPU */
gpu_submit_cmds(G.world_gpu_cmd_store);
gpu_submit_cmds(G.user_gpu_cmd_store);
gpu_submit_cmds(G.backbuffer_gpu_cmd_store);
/* Execute render cmds */
/* Clear textures */
gpu_texture_clear(G.user_texture, 0);
gpu_texture_clear(G.backbuffer_texture, RGBA_F(0, 0, 0, 1));
/* Execute cmds */
{
/* Clear textures */
gpu_texture_clear(G.world_texture, 0);
gpu_texture_clear(G.ui_texture, 0);
gpu_texture_clear(G.final_texture, 0);
gpu_texture_clear(G.backbuffer_texture, RGBA_F(0, 0, 0, 1));
/* Render to world texture */
gpu_texture_render(G.world_texture, G.world_cmd_buffer, G.world_to_ui_xf, ui_viewport);
/* Render to UI texture */
gpu_texture_render(G.ui_texture, G.ui_cmd_buffer, XFORM_IDENT, ui_viewport);
/* Render to final texture */
gpu_texture_render(G.final_texture, G.final_cmd_buffer, XFORM_IDENT, ui_viewport);
/* Render to user texture */
gpu_run_cmds(G.world_gpu_cmd_store, G.user_texture, G.world_to_user_xf, user_viewport);
gpu_run_cmds(G.user_gpu_cmd_store, G.user_texture, XFORM_IDENT, user_viewport);
/* Render to backbuffer */
gpu_texture_render(G.backbuffer_texture, G.backbuffer_cmd_buffer, XFORM_IDENT, backbuffer_viewport);
gpu_run_cmds(G.backbuffer_gpu_cmd_store, G.backbuffer_texture, XFORM_IDENT, backbuffer_viewport);
}
/* Present */
gpu_present_backbuffer(VSYNC_ENABLED);
/* Swap backbuffer */
gpu_swap_backbuffer(VSYNC_ENABLED);
}
/* ========================== *