typedef & PascalCase for ALL structs and enums
This commit is contained in:
@ -7,14 +7,14 @@
|
||||
#include <stb_ds.h>
|
||||
|
||||
|
||||
void push_circle(t_fvec2 position, float radius, t_color color) {
|
||||
struct circle_primitive circle = {
|
||||
void push_circle(Vec2 position, float radius, Color color) {
|
||||
CirclePrimitive circle = {
|
||||
.radius = radius,
|
||||
.color = color,
|
||||
.position = position,
|
||||
};
|
||||
|
||||
struct primitive_2d primitive = {
|
||||
Primitive2D primitive = {
|
||||
.type = PRIMITIVE_2D_CIRCLE,
|
||||
.circle = circle,
|
||||
};
|
||||
@ -24,8 +24,8 @@ void push_circle(t_fvec2 position, float radius, t_color color) {
|
||||
|
||||
/* TODO: caching and reuse scheme */
|
||||
/* vertices_out and indices_out MUST BE FREED */
|
||||
void create_circle_geometry(t_fvec2 position,
|
||||
t_color color,
|
||||
void create_circle_geometry(Vec2 position,
|
||||
Color color,
|
||||
float radius,
|
||||
size_t num_vertices,
|
||||
SDL_Vertex **vertices_out,
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include "twn_util.h"
|
||||
|
||||
|
||||
gpu_texture create_gpu_texture(enum texture_filter filter, bool generate_mipmaps) {
|
||||
GPUTexture create_gpu_texture(TextureFilter filter, bool generate_mipmaps) {
|
||||
GLuint texture;
|
||||
glGenTextures(1, &texture);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
@ -29,12 +29,12 @@ gpu_texture create_gpu_texture(enum texture_filter filter, bool generate_mipmaps
|
||||
}
|
||||
|
||||
|
||||
void delete_gpu_texture(gpu_texture texture) {
|
||||
void delete_gpu_texture(GPUTexture texture) {
|
||||
glDeleteTextures(1, &texture);
|
||||
}
|
||||
|
||||
|
||||
void upload_gpu_texture(gpu_texture texture, void *pixels, int channels, int width, int height) {
|
||||
void upload_gpu_texture(GPUTexture texture, void *pixels, int channels, int width, int height) {
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
int format_internal, format;
|
||||
@ -66,6 +66,6 @@ void upload_gpu_texture(gpu_texture texture, void *pixels, int channels, int wid
|
||||
}
|
||||
|
||||
|
||||
void bind_gpu_texture(gpu_texture texture) {
|
||||
void bind_gpu_texture(GPUTexture texture) {
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
}
|
||||
|
@ -11,50 +11,50 @@
|
||||
/* TODO: use int16_t for uvs */
|
||||
/* TODO: use packed types? */
|
||||
/* TODO: int16_t could be used for positioning, but we would need to have more CPU calcs */
|
||||
struct element_indexed_quad {
|
||||
typedef struct ElementIndexedQuad {
|
||||
/* upper-left */
|
||||
t_fvec2 v0;
|
||||
t_fvec2 uv0;
|
||||
t_color c0;
|
||||
Vec2 v0;
|
||||
Vec2 uv0;
|
||||
Color c0;
|
||||
/* bottom-left */
|
||||
t_fvec2 v1;
|
||||
t_fvec2 uv1;
|
||||
t_color c1;
|
||||
Vec2 v1;
|
||||
Vec2 uv1;
|
||||
Color c1;
|
||||
/* bottom-right */
|
||||
t_fvec2 v2;
|
||||
t_fvec2 uv2;
|
||||
t_color c2;
|
||||
Vec2 v2;
|
||||
Vec2 uv2;
|
||||
Color c2;
|
||||
/* upper-right */
|
||||
t_fvec2 v3;
|
||||
t_fvec2 uv3;
|
||||
t_color c3;
|
||||
};
|
||||
Vec2 v3;
|
||||
Vec2 uv3;
|
||||
Color c3;
|
||||
} ElementIndexedQuad;
|
||||
|
||||
|
||||
struct element_indexed_quad_without_color {
|
||||
typedef struct ElementIndexedQuadWithoutColor {
|
||||
/* upper-left */
|
||||
t_fvec2 v0;
|
||||
t_fvec2 uv0;
|
||||
Vec2 v0;
|
||||
Vec2 uv0;
|
||||
/* bottom-left */
|
||||
t_fvec2 v1;
|
||||
t_fvec2 uv1;
|
||||
Vec2 v1;
|
||||
Vec2 uv1;
|
||||
/* bottom-right */
|
||||
t_fvec2 v2;
|
||||
t_fvec2 uv2;
|
||||
Vec2 v2;
|
||||
Vec2 uv2;
|
||||
/* upper-right */
|
||||
t_fvec2 v3;
|
||||
t_fvec2 uv3;
|
||||
};
|
||||
Vec2 v3;
|
||||
Vec2 uv3;
|
||||
} ElementIndexedQuadWithoutColor;
|
||||
|
||||
|
||||
typedef enum {
|
||||
PIPELINE_NO,
|
||||
PIPELINE_SPACE,
|
||||
PIPELINE_2D,
|
||||
} pipeline;
|
||||
} Pipeline;
|
||||
|
||||
|
||||
static pipeline pipeline_last_used = PIPELINE_NO;
|
||||
static Pipeline pipeline_last_used = PIPELINE_NO;
|
||||
|
||||
|
||||
void use_space_pipeline(void) {
|
||||
@ -117,7 +117,7 @@ void use_2d_pipeline(void) {
|
||||
}
|
||||
|
||||
|
||||
void upload_quad_vertices(t_frect rect) {
|
||||
void upload_quad_vertices(Rect rect) {
|
||||
/* client memory needs to be reachable on glDraw*, so */
|
||||
static float vertices[6 * 2];
|
||||
|
||||
@ -132,7 +132,7 @@ void upload_quad_vertices(t_frect rect) {
|
||||
}
|
||||
|
||||
|
||||
void render_rectangle(const struct rect_primitive *rectangle) {
|
||||
void render_rectangle(const RectPrimitive *rectangle) {
|
||||
glColor4ub(rectangle->color.r, rectangle->color.g,
|
||||
rectangle->color.b, rectangle->color.a);
|
||||
|
||||
@ -144,7 +144,7 @@ void render_rectangle(const struct rect_primitive *rectangle) {
|
||||
}
|
||||
|
||||
|
||||
void render_circle(const struct circle_primitive *circle) {
|
||||
void render_circle(const CirclePrimitive *circle) {
|
||||
SDL_Vertex *vertices = NULL;
|
||||
int *indices = NULL;
|
||||
int num_vertices = (int)circle->radius;
|
||||
@ -181,7 +181,7 @@ void render_circle(const struct circle_primitive *circle) {
|
||||
}
|
||||
|
||||
|
||||
void use_texture_mode(enum texture_mode mode) {
|
||||
void use_texture_mode(TextureMode mode) {
|
||||
if (mode == TEXTURE_MODE_GHOSTLY) {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
@ -203,21 +203,21 @@ void use_texture_mode(enum texture_mode mode) {
|
||||
}
|
||||
|
||||
|
||||
vertex_buffer_builder build_vertex_buffer(vertex_buffer buffer, size_t bytes) {
|
||||
VertexBufferBuilder build_vertex_buffer(VertexBuffer buffer, size_t bytes) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, bytes, NULL, GL_STREAM_DRAW);
|
||||
void *mapping = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
|
||||
if (!mapping)
|
||||
CRY("build_vertex_buffer", "Error mapping a vertex array buffer");
|
||||
|
||||
return (vertex_buffer_builder) {
|
||||
return (VertexBufferBuilder) {
|
||||
.mapping = mapping,
|
||||
.bytes_left = bytes,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
bool push_to_vertex_buffer_builder(vertex_buffer_builder *builder,
|
||||
bool push_to_vertex_buffer_builder(VertexBufferBuilder *builder,
|
||||
void *bytes, size_t size) {
|
||||
if (builder->bytes_left == 0)
|
||||
return false;
|
||||
@ -237,9 +237,9 @@ bool push_to_vertex_buffer_builder(vertex_buffer_builder *builder,
|
||||
}
|
||||
|
||||
|
||||
void finally_render_sprites(const struct primitive_2d primitives[],
|
||||
const struct sprite_batch batch,
|
||||
const vertex_buffer buffer)
|
||||
void finally_render_sprites(const Primitive2D primitives[],
|
||||
const struct SpriteBatch batch,
|
||||
const VertexBuffer buffer)
|
||||
{
|
||||
/* TODO: maybe do, dunno */
|
||||
// glBindBuffer(GL_VERTEX_ARRAY, vertex_buffer);
|
||||
@ -250,13 +250,13 @@ void finally_render_sprites(const struct primitive_2d primitives[],
|
||||
GLsizei uvoff;
|
||||
|
||||
if (!batch.constant_colored) {
|
||||
off = offsetof(struct element_indexed_quad, v1);
|
||||
voff = offsetof(struct element_indexed_quad, v0);
|
||||
uvoff = offsetof(struct element_indexed_quad, uv0);
|
||||
off = offsetof(ElementIndexedQuad, v1);
|
||||
voff = offsetof(ElementIndexedQuad, v0);
|
||||
uvoff = offsetof(ElementIndexedQuad, uv0);
|
||||
} else {
|
||||
off = offsetof(struct element_indexed_quad_without_color, v1);
|
||||
voff = offsetof(struct element_indexed_quad_without_color, v0);
|
||||
uvoff = offsetof(struct element_indexed_quad_without_color, uv0);
|
||||
off = offsetof(ElementIndexedQuadWithoutColor, v1);
|
||||
voff = offsetof(ElementIndexedQuadWithoutColor, v0);
|
||||
uvoff = offsetof(ElementIndexedQuadWithoutColor, uv0);
|
||||
}
|
||||
|
||||
/* vertex specification */
|
||||
@ -278,7 +278,7 @@ void finally_render_sprites(const struct primitive_2d primitives[],
|
||||
glColorPointer(4,
|
||||
GL_UNSIGNED_BYTE,
|
||||
off,
|
||||
(void *)offsetof(struct element_indexed_quad, c0));
|
||||
(void *)offsetof(ElementIndexedQuad, c0));
|
||||
} else
|
||||
glColor4ub(primitives[0].sprite.color.r,
|
||||
primitives[0].sprite.color.g,
|
||||
@ -307,22 +307,22 @@ void finally_render_sprites(const struct primitive_2d primitives[],
|
||||
}
|
||||
|
||||
|
||||
size_t get_sprite_payload_size(struct sprite_batch batch) {
|
||||
size_t get_sprite_payload_size(struct SpriteBatch batch) {
|
||||
if (batch.constant_colored)
|
||||
return sizeof (struct element_indexed_quad_without_color);
|
||||
return sizeof (ElementIndexedQuadWithoutColor);
|
||||
else
|
||||
return sizeof (struct element_indexed_quad);
|
||||
return sizeof (ElementIndexedQuad);
|
||||
}
|
||||
|
||||
|
||||
bool push_sprite_payload_to_vertex_buffer_builder(struct sprite_batch batch,
|
||||
vertex_buffer_builder *builder,
|
||||
t_fvec2 v0, t_fvec2 v1, t_fvec2 v2, t_fvec2 v3,
|
||||
t_fvec2 uv0, t_fvec2 uv1, t_fvec2 uv2, t_fvec2 uv3,
|
||||
t_color color)
|
||||
bool push_sprite_payload_to_vertex_buffer_builder(struct SpriteBatch batch,
|
||||
VertexBufferBuilder *builder,
|
||||
Vec2 v0, Vec2 v1, Vec2 v2, Vec2 v3,
|
||||
Vec2 uv0, Vec2 uv1, Vec2 uv2, Vec2 uv3,
|
||||
Color color)
|
||||
{
|
||||
if (!batch.constant_colored) {
|
||||
struct element_indexed_quad buffer_element = {
|
||||
ElementIndexedQuad buffer_element = {
|
||||
.v0 = v0,
|
||||
.v1 = v1,
|
||||
.v2 = v2,
|
||||
@ -343,7 +343,7 @@ bool push_sprite_payload_to_vertex_buffer_builder(struct sprite_batch batch,
|
||||
return push_to_vertex_buffer_builder(builder, &buffer_element, sizeof buffer_element);
|
||||
|
||||
} else {
|
||||
struct element_indexed_quad_without_color buffer_element = {
|
||||
ElementIndexedQuadWithoutColor buffer_element = {
|
||||
.v0 = v0,
|
||||
.v1 = v1,
|
||||
.v2 = v2,
|
||||
@ -360,9 +360,9 @@ bool push_sprite_payload_to_vertex_buffer_builder(struct sprite_batch batch,
|
||||
}
|
||||
|
||||
|
||||
void finally_draw_uncolored_space_traingle_batch(const struct mesh_batch *batch,
|
||||
const t_texture_key texture_key,
|
||||
const vertex_buffer buffer)
|
||||
void finally_draw_uncolored_space_traingle_batch(const MeshBatch *batch,
|
||||
const TextureKey texture_key,
|
||||
const VertexBuffer buffer)
|
||||
{
|
||||
const size_t primitives_len = arrlenu(batch->primitives);
|
||||
|
||||
@ -374,15 +374,15 @@ void finally_draw_uncolored_space_traingle_batch(const struct mesh_batch *batch,
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(3,
|
||||
GL_FLOAT,
|
||||
offsetof(struct uncolored_space_triangle_payload, v1),
|
||||
(void *)offsetof(struct uncolored_space_triangle_payload, v0));
|
||||
offsetof(struct UncoloredSpaceTrianglePayload, v1),
|
||||
(void *)offsetof(struct UncoloredSpaceTrianglePayload, v0));
|
||||
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glClientActiveTexture(GL_TEXTURE0);
|
||||
glTexCoordPointer(2,
|
||||
GL_FLOAT,
|
||||
offsetof(struct uncolored_space_triangle_payload, v1),
|
||||
(void *)offsetof(struct uncolored_space_triangle_payload, uv0));
|
||||
offsetof(struct UncoloredSpaceTrianglePayload, v1),
|
||||
(void *)offsetof(struct UncoloredSpaceTrianglePayload, uv0));
|
||||
|
||||
/* commit for drawing */
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3 * (GLint)primitives_len);
|
||||
@ -396,32 +396,32 @@ void finally_draw_uncolored_space_traingle_batch(const struct mesh_batch *batch,
|
||||
}
|
||||
|
||||
|
||||
bool push_text_payload_to_vertex_buffer_builder(struct font_data const *font_data,
|
||||
vertex_buffer_builder *builder,
|
||||
bool push_text_payload_to_vertex_buffer_builder(FontData const *font_data,
|
||||
VertexBufferBuilder *builder,
|
||||
stbtt_aligned_quad quad)
|
||||
{
|
||||
(void)font_data;
|
||||
|
||||
struct element_indexed_quad_without_color buffer_element = {
|
||||
.v0 = (t_fvec2){ quad.x0, quad.y0 },
|
||||
.v1 = (t_fvec2){ quad.x1, quad.y0 },
|
||||
.v2 = (t_fvec2){ quad.x1, quad.y1 },
|
||||
.v3 = (t_fvec2){ quad.x0, quad.y1 },
|
||||
ElementIndexedQuadWithoutColor buffer_element = {
|
||||
.v0 = (Vec2){ quad.x0, quad.y0 },
|
||||
.v1 = (Vec2){ quad.x1, quad.y0 },
|
||||
.v2 = (Vec2){ quad.x1, quad.y1 },
|
||||
.v3 = (Vec2){ quad.x0, quad.y1 },
|
||||
|
||||
.uv0 = (t_fvec2){ quad.s0, quad.t0 },
|
||||
.uv1 = (t_fvec2){ quad.s1, quad.t0 },
|
||||
.uv2 = (t_fvec2){ quad.s1, quad.t1 },
|
||||
.uv3 = (t_fvec2){ quad.s0, quad.t1 },
|
||||
.uv0 = (Vec2){ quad.s0, quad.t0 },
|
||||
.uv1 = (Vec2){ quad.s1, quad.t0 },
|
||||
.uv2 = (Vec2){ quad.s1, quad.t1 },
|
||||
.uv3 = (Vec2){ quad.s0, quad.t1 },
|
||||
};
|
||||
|
||||
return push_to_vertex_buffer_builder(builder, &buffer_element, sizeof buffer_element);
|
||||
}
|
||||
|
||||
|
||||
void finally_draw_text(struct font_data const *font_data,
|
||||
void finally_draw_text(FontData const *font_data,
|
||||
size_t len,
|
||||
t_color color,
|
||||
vertex_buffer buffer)
|
||||
Color color,
|
||||
VertexBuffer buffer)
|
||||
{
|
||||
(void)buffer;
|
||||
|
||||
@ -429,15 +429,15 @@ void finally_draw_text(struct font_data const *font_data,
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(2,
|
||||
GL_FLOAT,
|
||||
offsetof(struct element_indexed_quad_without_color, v1),
|
||||
(void *)(size_t)offsetof(struct element_indexed_quad_without_color, v0));
|
||||
offsetof(ElementIndexedQuadWithoutColor, v1),
|
||||
(void *)(size_t)offsetof(ElementIndexedQuadWithoutColor, v0));
|
||||
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glClientActiveTexture(GL_TEXTURE0);
|
||||
glTexCoordPointer(2,
|
||||
GL_FLOAT,
|
||||
offsetof(struct element_indexed_quad_without_color, v1),
|
||||
(void *)(size_t)offsetof(struct element_indexed_quad_without_color, uv0));
|
||||
offsetof(ElementIndexedQuadWithoutColor, v1),
|
||||
(void *)(size_t)offsetof(ElementIndexedQuadWithoutColor, uv0));
|
||||
|
||||
bind_quad_element_buffer();
|
||||
|
||||
@ -462,5 +462,5 @@ void finally_draw_text(struct font_data const *font_data,
|
||||
|
||||
|
||||
size_t get_text_payload_size(void) {
|
||||
return sizeof (struct element_indexed_quad_without_color);
|
||||
return sizeof (ElementIndexedQuadWithoutColor);
|
||||
}
|
||||
|
@ -14,19 +14,19 @@ void setup_viewport(int x, int y, int width, int height) {
|
||||
}
|
||||
|
||||
|
||||
vertex_buffer create_vertex_buffer(void) {
|
||||
VertexBuffer create_vertex_buffer(void) {
|
||||
GLuint result;
|
||||
glGenBuffers(1, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void delete_vertex_buffer(vertex_buffer buffer) {
|
||||
void delete_vertex_buffer(VertexBuffer buffer) {
|
||||
glDeleteBuffers(1, &buffer);
|
||||
}
|
||||
|
||||
|
||||
void specify_vertex_buffer(vertex_buffer buffer, void *data, size_t bytes) {
|
||||
void specify_vertex_buffer(VertexBuffer buffer, void *data, size_t bytes) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, bytes, data, GL_STREAM_DRAW);
|
||||
}
|
||||
|
@ -3,19 +3,19 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef GLuint gpu_texture;
|
||||
typedef GLuint GPUTexture;
|
||||
|
||||
enum texture_filter {
|
||||
typedef enum TextureFilter {
|
||||
TEXTURE_FILTER_NEAREAST,
|
||||
TEXTURE_FILTER_LINEAR,
|
||||
};
|
||||
} TextureFilter;
|
||||
|
||||
gpu_texture create_gpu_texture(enum texture_filter filter, bool generate_mipmaps);
|
||||
GPUTexture create_gpu_texture(TextureFilter filter, bool generate_mipmaps);
|
||||
|
||||
void delete_gpu_texture(gpu_texture texture);
|
||||
void delete_gpu_texture(GPUTexture texture);
|
||||
|
||||
void upload_gpu_texture(gpu_texture texture, void *pixels, int channels, int width, int height);
|
||||
void upload_gpu_texture(GPUTexture texture, void *pixels, int channels, int width, int height);
|
||||
|
||||
void bind_gpu_texture(gpu_texture texture);
|
||||
void bind_gpu_texture(GPUTexture texture);
|
||||
|
||||
#endif
|
||||
|
@ -17,8 +17,8 @@
|
||||
|
||||
|
||||
/* TODO: have a default initialized one */
|
||||
t_matrix4 camera_projection_matrix;
|
||||
t_matrix4 camera_look_at_matrix;
|
||||
Matrix4 camera_projection_matrix;
|
||||
Matrix4 camera_look_at_matrix;
|
||||
|
||||
|
||||
void render_queue_clear(void) {
|
||||
@ -41,13 +41,13 @@ void render_queue_clear(void) {
|
||||
|
||||
|
||||
/* rectangle */
|
||||
void push_rectangle(t_frect rect, t_color color) {
|
||||
struct rect_primitive rectangle = {
|
||||
void push_rectangle(Rect rect, Color color) {
|
||||
RectPrimitive rectangle = {
|
||||
.rect = rect,
|
||||
.color = color,
|
||||
};
|
||||
|
||||
struct primitive_2d primitive = {
|
||||
Primitive2D primitive = {
|
||||
.type = PRIMITIVE_2D_RECT,
|
||||
.rect = rectangle,
|
||||
};
|
||||
@ -64,11 +64,11 @@ static void render_2d(void) {
|
||||
size_t batch_count = 0;
|
||||
|
||||
for (size_t i = 0; i < render_queue_len; ++i) {
|
||||
const struct primitive_2d *current = &ctx.render_queue_2d[i];
|
||||
const Primitive2D *current = &ctx.render_queue_2d[i];
|
||||
|
||||
switch (current->type) {
|
||||
case PRIMITIVE_2D_SPRITE: {
|
||||
const struct sprite_batch batch =
|
||||
const struct SpriteBatch batch =
|
||||
collect_sprite_batch(current, render_queue_len - i);
|
||||
|
||||
/* TODO: what's even the point? just use OR_EQUAL comparison */
|
||||
@ -140,7 +140,7 @@ void render(void) {
|
||||
}
|
||||
|
||||
|
||||
void set_camera(const t_camera *const camera) {
|
||||
void set_camera(const Camera *const camera) {
|
||||
/* TODO: skip recaulculating if it's the same? */
|
||||
camera_projection_matrix = camera_perspective(camera);
|
||||
camera_look_at_matrix = camera_look_at(camera);
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define TWN_RENDERING_C_H
|
||||
|
||||
#include "twn_textures_c.h"
|
||||
#include "twn_text_c.h"
|
||||
#include "twn_util.h"
|
||||
#include "twn_option.h"
|
||||
|
||||
@ -16,107 +17,107 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
extern t_matrix4 camera_projection_matrix;
|
||||
extern t_matrix4 camera_look_at_matrix;
|
||||
extern Matrix4 camera_projection_matrix;
|
||||
extern Matrix4 camera_look_at_matrix;
|
||||
|
||||
#define QUAD_ELEMENT_BUFFER_LENGTH (65536 / 6)
|
||||
|
||||
|
||||
typedef GLuint vertex_buffer;
|
||||
typedef GLuint VertexBuffer;
|
||||
|
||||
typedef struct vertex_buffer_builder {
|
||||
typedef struct VertexBufferBuilder {
|
||||
size_t bytes_left;
|
||||
void *mapping;
|
||||
} vertex_buffer_builder;
|
||||
} VertexBufferBuilder;
|
||||
|
||||
|
||||
struct sprite_primitive {
|
||||
t_frect rect;
|
||||
t_color color;
|
||||
typedef struct SpritePrimitive {
|
||||
Rect rect;
|
||||
Color color;
|
||||
float rotation;
|
||||
t_texture_key texture_key;
|
||||
TextureKey texture_key;
|
||||
bool flip_x;
|
||||
bool flip_y;
|
||||
bool repeat;
|
||||
|
||||
m_option_list(
|
||||
t_frect, texture_region )
|
||||
};
|
||||
Rect, texture_region )
|
||||
} SpritePrimitive;
|
||||
|
||||
struct rect_primitive {
|
||||
t_frect rect;
|
||||
t_color color;
|
||||
};
|
||||
typedef struct RectPrimitive {
|
||||
Rect rect;
|
||||
Color color;
|
||||
} RectPrimitive;
|
||||
|
||||
struct circle_primitive {
|
||||
typedef struct CirclePrimitive {
|
||||
float radius;
|
||||
t_color color;
|
||||
t_fvec2 position;
|
||||
};
|
||||
Color color;
|
||||
Vec2 position;
|
||||
} CirclePrimitive;
|
||||
|
||||
struct text_primitive {
|
||||
t_color color;
|
||||
t_fvec2 position;
|
||||
typedef struct TextPrimitive {
|
||||
Color color;
|
||||
Vec2 position;
|
||||
char *text;
|
||||
const char *font;
|
||||
int height_px;
|
||||
};
|
||||
} TextPrimitive;
|
||||
|
||||
enum primitive_2d_type {
|
||||
typedef enum Primitive2DType {
|
||||
PRIMITIVE_2D_SPRITE,
|
||||
PRIMITIVE_2D_RECT,
|
||||
PRIMITIVE_2D_CIRCLE,
|
||||
PRIMITIVE_2D_TEXT,
|
||||
};
|
||||
} Primitive2DType;
|
||||
|
||||
struct primitive_2d {
|
||||
enum primitive_2d_type type;
|
||||
typedef struct Primitive2D {
|
||||
Primitive2DType type;
|
||||
|
||||
union {
|
||||
struct sprite_primitive sprite;
|
||||
struct rect_primitive rect;
|
||||
struct circle_primitive circle;
|
||||
struct text_primitive text;
|
||||
SpritePrimitive sprite;
|
||||
RectPrimitive rect;
|
||||
CirclePrimitive circle;
|
||||
TextPrimitive text;
|
||||
};
|
||||
};
|
||||
} Primitive2D;
|
||||
|
||||
/* union for in-place recalculation of texture coordinates */
|
||||
union uncolored_space_triangle {
|
||||
union UncoloredSpaceTriangle {
|
||||
/* pending for sending, uvs are not final as texture atlases could update */
|
||||
struct uncolored_space_triangle_primitive {
|
||||
t_fvec3 v0;
|
||||
t_fvec2 uv0; /* in pixels */
|
||||
t_fvec3 v1;
|
||||
t_fvec2 uv1; /* in pixels */
|
||||
t_fvec3 v2;
|
||||
t_fvec2 uv2; /* in pixels */
|
||||
struct UncoloredSpaceTrianglePrimitive {
|
||||
Vec3 v0;
|
||||
Vec2 uv0; /* in pixels */
|
||||
Vec3 v1;
|
||||
Vec2 uv1; /* in pixels */
|
||||
Vec3 v2;
|
||||
Vec2 uv2; /* in pixels */
|
||||
} primitive;
|
||||
|
||||
/* TODO: have it packed? */
|
||||
/* structure that is passed in opengl vertex array */
|
||||
struct uncolored_space_triangle_payload {
|
||||
t_fvec3 v0;
|
||||
t_fvec2 uv0;
|
||||
t_fvec3 v1;
|
||||
t_fvec2 uv1;
|
||||
t_fvec3 v2;
|
||||
t_fvec2 uv2;
|
||||
struct UncoloredSpaceTrianglePayload {
|
||||
Vec3 v0;
|
||||
Vec2 uv0;
|
||||
Vec3 v1;
|
||||
Vec2 uv1;
|
||||
Vec3 v2;
|
||||
Vec2 uv2;
|
||||
} payload;
|
||||
};
|
||||
|
||||
/* batch of primitives with overlapping properties */
|
||||
struct mesh_batch {
|
||||
typedef struct MeshBatch {
|
||||
uint8_t *primitives;
|
||||
};
|
||||
} MeshBatch;
|
||||
|
||||
struct mesh_batch_item {
|
||||
t_texture_key key;
|
||||
struct mesh_batch value;
|
||||
};
|
||||
typedef struct MeshBatchItem {
|
||||
TextureKey key;
|
||||
struct MeshBatch value;
|
||||
} MeshBatchItem;
|
||||
|
||||
struct text_cache {
|
||||
struct font_data **data;
|
||||
};
|
||||
typedef struct TextCache {
|
||||
struct FontData **data;
|
||||
} TextCache;
|
||||
|
||||
|
||||
/* renders the background, then the primitives in all render queues */
|
||||
@ -125,47 +126,47 @@ void render(void);
|
||||
/* clears all render queues */
|
||||
void render_queue_clear(void);
|
||||
|
||||
void create_circle_geometry(t_fvec2 position,
|
||||
t_color color,
|
||||
void create_circle_geometry(Vec2 position,
|
||||
Color color,
|
||||
float radius,
|
||||
size_t num_vertices,
|
||||
SDL_Vertex **vertices_out,
|
||||
int **indices_out);
|
||||
|
||||
struct sprite_batch {
|
||||
struct SpriteBatch {
|
||||
size_t size; /* how many primitives are in current batch */
|
||||
enum texture_mode mode;
|
||||
TextureMode mode;
|
||||
bool constant_colored; /* whether colored batch is uniformly colored */
|
||||
bool repeat; /* whether repeat is needed */
|
||||
} collect_sprite_batch(const struct primitive_2d primitives[], size_t len);
|
||||
} collect_sprite_batch(const Primitive2D primitives[], size_t len);
|
||||
|
||||
void render_sprites(const struct primitive_2d primitives[],
|
||||
const struct sprite_batch batch);
|
||||
void render_sprites(const Primitive2D primitives[],
|
||||
const struct SpriteBatch batch);
|
||||
|
||||
void draw_uncolored_space_traingle_batch(struct mesh_batch *batch,
|
||||
t_texture_key texture_key);
|
||||
void draw_uncolored_space_traingle_batch(MeshBatch *batch,
|
||||
TextureKey texture_key);
|
||||
|
||||
/* text */
|
||||
|
||||
void render_text(const struct text_primitive *text);
|
||||
void render_text(const TextPrimitive *text);
|
||||
|
||||
void text_cache_init(struct text_cache *cache);
|
||||
void text_cache_init(TextCache *cache);
|
||||
|
||||
void text_cache_deinit(struct text_cache *cache);
|
||||
void text_cache_deinit(TextCache *cache);
|
||||
|
||||
/* vertex buffer */
|
||||
|
||||
vertex_buffer create_vertex_buffer(void);
|
||||
VertexBuffer create_vertex_buffer(void);
|
||||
|
||||
void delete_vertex_buffer(vertex_buffer buffer);
|
||||
void delete_vertex_buffer(VertexBuffer buffer);
|
||||
|
||||
void specify_vertex_buffer(vertex_buffer buffer, void *data, size_t bytes);
|
||||
void specify_vertex_buffer(VertexBuffer buffer, void *data, size_t bytes);
|
||||
|
||||
/* uses present in 1.5 buffer mapping feature */
|
||||
vertex_buffer_builder build_vertex_buffer(vertex_buffer buffer, size_t bytes);
|
||||
VertexBufferBuilder build_vertex_buffer(VertexBuffer buffer, size_t bytes);
|
||||
|
||||
/* collects bytes for sending to the gpu until all is pushed, which is when false is returned */
|
||||
bool push_to_vertex_buffer_builder(vertex_buffer_builder *builder,
|
||||
bool push_to_vertex_buffer_builder(VertexBufferBuilder *builder,
|
||||
void *bytes,
|
||||
size_t size);
|
||||
|
||||
@ -181,41 +182,41 @@ void set_depth_range(double low, double high);
|
||||
|
||||
void bind_quad_element_buffer(void);
|
||||
|
||||
void render_circle(const struct circle_primitive *circle);
|
||||
void render_circle(const CirclePrimitive *circle);
|
||||
|
||||
void render_rectangle(const struct rect_primitive *rectangle);
|
||||
void render_rectangle(const RectPrimitive *rectangle);
|
||||
|
||||
void use_space_pipeline(void);
|
||||
|
||||
void use_2d_pipeline(void);
|
||||
|
||||
void use_texture_mode(enum texture_mode mode);
|
||||
void use_texture_mode(TextureMode mode);
|
||||
|
||||
void finally_render_sprites(struct primitive_2d const primitives[],
|
||||
struct sprite_batch batch,
|
||||
vertex_buffer buffer);
|
||||
void finally_render_sprites(Primitive2D const primitives[],
|
||||
struct SpriteBatch batch,
|
||||
VertexBuffer buffer);
|
||||
|
||||
size_t get_sprite_payload_size(struct sprite_batch batch);
|
||||
size_t get_sprite_payload_size(struct SpriteBatch batch);
|
||||
|
||||
bool push_sprite_payload_to_vertex_buffer_builder(struct sprite_batch batch,
|
||||
vertex_buffer_builder *builder,
|
||||
t_fvec2 v0, t_fvec2 v1, t_fvec2 v2, t_fvec2 v3,
|
||||
t_fvec2 uv0, t_fvec2 uv1, t_fvec2 uv2, t_fvec2 uv3,
|
||||
t_color color);
|
||||
bool push_sprite_payload_to_vertex_buffer_builder(struct SpriteBatch batch,
|
||||
VertexBufferBuilder *builder,
|
||||
Vec2 v0, Vec2 v1, Vec2 v2, Vec2 v3,
|
||||
Vec2 uv0, Vec2 uv1, Vec2 uv2, Vec2 uv3,
|
||||
Color color);
|
||||
|
||||
void finally_draw_uncolored_space_traingle_batch(struct mesh_batch const *batch,
|
||||
t_texture_key texture_key,
|
||||
vertex_buffer buffer);
|
||||
void finally_draw_uncolored_space_traingle_batch(MeshBatch const *batch,
|
||||
TextureKey texture_key,
|
||||
VertexBuffer buffer);
|
||||
|
||||
size_t get_text_payload_size(void);
|
||||
|
||||
bool push_text_payload_to_vertex_buffer_builder(struct font_data const *font_data,
|
||||
vertex_buffer_builder *builder,
|
||||
bool push_text_payload_to_vertex_buffer_builder(FontData const *font_data,
|
||||
VertexBufferBuilder *builder,
|
||||
stbtt_aligned_quad quad);
|
||||
|
||||
void finally_draw_text(struct font_data const *font_data,
|
||||
void finally_draw_text(FontData const *font_data,
|
||||
size_t len,
|
||||
t_color color,
|
||||
vertex_buffer buffer);
|
||||
Color color,
|
||||
VertexBuffer buffer);
|
||||
|
||||
#endif
|
||||
|
@ -17,10 +17,10 @@
|
||||
*/
|
||||
/* TODO: it might make sense to infer alpha channel presence / meaningfulness for textures in atlas */
|
||||
/* so that they are rendered with no blend / batched in a way to reduce overdraw automatically */
|
||||
void push_sprite(const t_push_sprite_args args) {
|
||||
struct sprite_primitive sprite = {
|
||||
void push_sprite(const PushSpriteArgs args) {
|
||||
SpritePrimitive sprite = {
|
||||
.rect = args.rect,
|
||||
.color = m_or(args, color, ((t_color) { 255, 255, 255, 255 })),
|
||||
.color = m_or(args, color, ((Color) { 255, 255, 255, 255 })),
|
||||
.rotation = m_or(args, rotation, 0.0f),
|
||||
.texture_key = textures_get_key(&ctx.texture_cache, args.path),
|
||||
.flip_x = m_or(args, flip_x, false),
|
||||
@ -29,7 +29,7 @@ void push_sprite(const t_push_sprite_args args) {
|
||||
m_opt_from(texture_region, args, texture_region)
|
||||
};
|
||||
|
||||
struct primitive_2d primitive = {
|
||||
Primitive2D primitive = {
|
||||
.type = PRIMITIVE_2D_SPRITE,
|
||||
.sprite = sprite,
|
||||
};
|
||||
@ -38,12 +38,12 @@ void push_sprite(const t_push_sprite_args args) {
|
||||
}
|
||||
|
||||
|
||||
struct sprite_batch collect_sprite_batch(const struct primitive_2d primitives[], size_t len) {
|
||||
struct SpriteBatch collect_sprite_batch(const Primitive2D primitives[], size_t len) {
|
||||
/* assumes that first primitive is already a sprite */
|
||||
const uint16_t texture_key_id = primitives[0].sprite.texture_key.id;
|
||||
const int atlas_id = textures_get_atlas_id(&ctx.texture_cache, primitives[0].sprite.texture_key);
|
||||
|
||||
struct sprite_batch batch = {
|
||||
struct SpriteBatch batch = {
|
||||
.mode = textures_get_mode(&ctx.texture_cache, primitives[0].sprite.texture_key),
|
||||
.constant_colored = true,
|
||||
.repeat = primitives[0].sprite.repeat,
|
||||
@ -56,14 +56,14 @@ struct sprite_batch collect_sprite_batch(const struct primitive_2d primitives[],
|
||||
len = QUAD_ELEMENT_BUFFER_LENGTH;
|
||||
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
const struct primitive_2d *const current = &primitives[i];
|
||||
const Primitive2D *const current = &primitives[i];
|
||||
|
||||
/* don't touch things other than sprites */
|
||||
if (current->type != PRIMITIVE_2D_SPRITE)
|
||||
break;
|
||||
|
||||
/* only collect the same blend modes */
|
||||
const enum texture_mode mode = textures_get_mode(&ctx.texture_cache, current->sprite.texture_key);
|
||||
const TextureMode mode = textures_get_mode(&ctx.texture_cache, current->sprite.texture_key);
|
||||
if (mode != batch.mode)
|
||||
break;
|
||||
|
||||
@ -94,32 +94,32 @@ struct sprite_batch collect_sprite_batch(const struct primitive_2d primitives[],
|
||||
|
||||
|
||||
/* assumes that orthogonal matrix setup is done already */
|
||||
void render_sprites(const struct primitive_2d primitives[],
|
||||
const struct sprite_batch batch)
|
||||
void render_sprites(const Primitive2D primitives[],
|
||||
const struct SpriteBatch batch)
|
||||
{
|
||||
/* single vertex array is used for every batch with NULL glBufferData() trick at the end */
|
||||
static vertex_buffer vertex_array = 0;
|
||||
static VertexBuffer vertex_array = 0;
|
||||
if (vertex_array == 0)
|
||||
vertex_array = create_vertex_buffer();
|
||||
|
||||
use_texture_mode(batch.mode);
|
||||
|
||||
const t_frect dims =
|
||||
const Rect dims =
|
||||
textures_get_dims(&ctx.texture_cache, primitives->sprite.texture_key);
|
||||
|
||||
/* vertex population over a vertex buffer builder interface */
|
||||
{
|
||||
vertex_buffer_builder payload = build_vertex_buffer(vertex_array, get_sprite_payload_size(batch) * batch.size);
|
||||
VertexBufferBuilder payload = build_vertex_buffer(vertex_array, get_sprite_payload_size(batch) * batch.size);
|
||||
|
||||
for (size_t i = 0; i < batch.size; ++i) {
|
||||
/* render opaques front to back */
|
||||
const size_t cur = batch.mode == TEXTURE_MODE_GHOSTLY ? i : batch.size - i - 1;
|
||||
const struct sprite_primitive sprite = primitives[cur].sprite;
|
||||
const SpritePrimitive sprite = primitives[cur].sprite;
|
||||
|
||||
const t_frect srcrect =
|
||||
const Rect srcrect =
|
||||
textures_get_srcrect(&ctx.texture_cache, primitives[cur].sprite.texture_key);
|
||||
|
||||
t_fvec2 uv0, uv1, uv2, uv3;
|
||||
Vec2 uv0, uv1, uv2, uv3;
|
||||
|
||||
if (!sprite.repeat) {
|
||||
const float wr = srcrect.w / dims.w;
|
||||
@ -128,20 +128,20 @@ void render_sprites(const struct primitive_2d primitives[],
|
||||
const float yr = srcrect.y / dims.h;
|
||||
|
||||
if (!m_is_set(sprite, texture_region)) {
|
||||
uv0 = (t_fvec2){ xr + wr * sprite.flip_x, yr + hr * sprite.flip_y };
|
||||
uv1 = (t_fvec2){ xr + wr * sprite.flip_x, yr + hr * !sprite.flip_y };
|
||||
uv2 = (t_fvec2){ xr + wr * !sprite.flip_x, yr + hr * !sprite.flip_y };
|
||||
uv3 = (t_fvec2){ xr + wr * !sprite.flip_x, yr + hr * sprite.flip_y };
|
||||
uv0 = (Vec2){ xr + wr * sprite.flip_x, yr + hr * sprite.flip_y };
|
||||
uv1 = (Vec2){ xr + wr * sprite.flip_x, yr + hr * !sprite.flip_y };
|
||||
uv2 = (Vec2){ xr + wr * !sprite.flip_x, yr + hr * !sprite.flip_y };
|
||||
uv3 = (Vec2){ xr + wr * !sprite.flip_x, yr + hr * sprite.flip_y };
|
||||
} else {
|
||||
const float offx = (sprite.texture_region_opt.x / srcrect.w) * (srcrect.w / dims.w);
|
||||
const float offy = (sprite.texture_region_opt.y / srcrect.h) * (srcrect.h / dims.h);
|
||||
const float offw = (1.0f - (sprite.texture_region_opt.w / srcrect.w)) * (srcrect.w / dims.w);
|
||||
const float offh = (1.0f - (sprite.texture_region_opt.h / srcrect.h)) * (srcrect.h / dims.h);
|
||||
|
||||
uv0 = (t_fvec2){ xr + offx + wr * sprite.flip_x, yr + offy + hr * sprite.flip_y };
|
||||
uv1 = (t_fvec2){ xr + offx + wr * sprite.flip_x, yr - offh + hr * !sprite.flip_y };
|
||||
uv2 = (t_fvec2){ xr - offw + wr * !sprite.flip_x, yr - offh + hr * !sprite.flip_y };
|
||||
uv3 = (t_fvec2){ xr - offw + wr * !sprite.flip_x, yr + offy + hr * sprite.flip_y };
|
||||
uv0 = (Vec2){ xr + offx + wr * sprite.flip_x, yr + offy + hr * sprite.flip_y };
|
||||
uv1 = (Vec2){ xr + offx + wr * sprite.flip_x, yr - offh + hr * !sprite.flip_y };
|
||||
uv2 = (Vec2){ xr - offw + wr * !sprite.flip_x, yr - offh + hr * !sprite.flip_y };
|
||||
uv3 = (Vec2){ xr - offw + wr * !sprite.flip_x, yr + offy + hr * sprite.flip_y };
|
||||
}
|
||||
} else {
|
||||
/* try fitting texture into supplied destination rectangle */
|
||||
@ -149,10 +149,10 @@ void render_sprites(const struct primitive_2d primitives[],
|
||||
const float rx = sprite.rect.w / srcrect.w;
|
||||
const float ry = sprite.rect.h / srcrect.h;
|
||||
|
||||
uv0 = (t_fvec2){ rx * sprite.flip_x, ry * sprite.flip_y };
|
||||
uv1 = (t_fvec2){ rx * sprite.flip_x, ry * !sprite.flip_y };
|
||||
uv2 = (t_fvec2){ rx * !sprite.flip_x, ry * !sprite.flip_y };
|
||||
uv3 = (t_fvec2){ rx * !sprite.flip_x, ry * sprite.flip_y };
|
||||
uv0 = (Vec2){ rx * sprite.flip_x, ry * sprite.flip_y };
|
||||
uv1 = (Vec2){ rx * sprite.flip_x, ry * !sprite.flip_y };
|
||||
uv2 = (Vec2){ rx * !sprite.flip_x, ry * !sprite.flip_y };
|
||||
uv3 = (Vec2){ rx * !sprite.flip_x, ry * sprite.flip_y };
|
||||
|
||||
if (m_is_set(sprite, texture_region)) {
|
||||
/* displace origin */
|
||||
@ -165,44 +165,44 @@ void render_sprites(const struct primitive_2d primitives[],
|
||||
}
|
||||
}
|
||||
|
||||
t_fvec2 v0, v1, v2, v3;
|
||||
Vec2 v0, v1, v2, v3;
|
||||
|
||||
/* todo: fast PI/2 degree divisible rotations? */
|
||||
if (sprite.rotation == 0.0f) {
|
||||
/* non-rotated case */
|
||||
|
||||
v0 = (t_fvec2){ sprite.rect.x, sprite.rect.y };
|
||||
v1 = (t_fvec2){ sprite.rect.x, sprite.rect.y + sprite.rect.h };
|
||||
v2 = (t_fvec2){ sprite.rect.x + sprite.rect.w, sprite.rect.y + sprite.rect.h };
|
||||
v3 = (t_fvec2){ sprite.rect.x + sprite.rect.w, sprite.rect.y };
|
||||
v0 = (Vec2){ sprite.rect.x, sprite.rect.y };
|
||||
v1 = (Vec2){ sprite.rect.x, sprite.rect.y + sprite.rect.h };
|
||||
v2 = (Vec2){ sprite.rect.x + sprite.rect.w, sprite.rect.y + sprite.rect.h };
|
||||
v3 = (Vec2){ sprite.rect.x + sprite.rect.w, sprite.rect.y };
|
||||
|
||||
} else if (sprite.rect.w == sprite.rect.h) {
|
||||
/* rotated square case */
|
||||
|
||||
const t_fvec2 c = frect_center(sprite.rect);
|
||||
const t_fvec2 t = fast_cossine(sprite.rotation + (float)M_PI_4);
|
||||
const t_fvec2 d = {
|
||||
const Vec2 c = frect_center(sprite.rect);
|
||||
const Vec2 t = fast_cossine(sprite.rotation + (float)M_PI_4);
|
||||
const Vec2 d = {
|
||||
.x = t.x * sprite.rect.w * (float)M_SQRT1_2,
|
||||
.y = t.y * sprite.rect.h * (float)M_SQRT1_2,
|
||||
};
|
||||
|
||||
v0 = (t_fvec2){ c.x - d.x, c.y - d.y };
|
||||
v1 = (t_fvec2){ c.x - d.y, c.y + d.x };
|
||||
v2 = (t_fvec2){ c.x + d.x, c.y + d.y };
|
||||
v3 = (t_fvec2){ c.x + d.y, c.y - d.x };
|
||||
v0 = (Vec2){ c.x - d.x, c.y - d.y };
|
||||
v1 = (Vec2){ c.x - d.y, c.y + d.x };
|
||||
v2 = (Vec2){ c.x + d.x, c.y + d.y };
|
||||
v3 = (Vec2){ c.x + d.y, c.y - d.x };
|
||||
|
||||
} else {
|
||||
/* rotated non-square case*/
|
||||
|
||||
const t_fvec2 c = frect_center(sprite.rect);
|
||||
const t_fvec2 t = fast_cossine(sprite.rotation);
|
||||
const Vec2 c = frect_center(sprite.rect);
|
||||
const Vec2 t = fast_cossine(sprite.rotation);
|
||||
|
||||
const t_fvec2 h = { sprite.rect.w / 2, sprite.rect.h / 2 };
|
||||
const Vec2 h = { sprite.rect.w / 2, sprite.rect.h / 2 };
|
||||
|
||||
v0 = (t_fvec2){ c.x + t.x * -h.x - t.y * -h.y, c.y + t.y * -h.x + t.x * -h.y };
|
||||
v1 = (t_fvec2){ c.x + t.x * -h.x - t.y * +h.y, c.y + t.y * -h.x + t.x * +h.y };
|
||||
v2 = (t_fvec2){ c.x + t.x * +h.x - t.y * +h.y, c.y + t.y * +h.x + t.x * +h.y };
|
||||
v3 = (t_fvec2){ c.x + t.x * +h.x - t.y * -h.y, c.y + t.y * +h.x + t.x * -h.y };
|
||||
v0 = (Vec2){ c.x + t.x * -h.x - t.y * -h.y, c.y + t.y * -h.x + t.x * -h.y };
|
||||
v1 = (Vec2){ c.x + t.x * -h.x - t.y * +h.y, c.y + t.y * -h.x + t.x * +h.y };
|
||||
v2 = (Vec2){ c.x + t.x * +h.x - t.y * +h.y, c.y + t.y * +h.x + t.x * +h.y };
|
||||
v3 = (Vec2){ c.x + t.x * +h.x - t.y * -h.y, c.y + t.y * +h.x + t.x * -h.y };
|
||||
}
|
||||
|
||||
push_sprite_payload_to_vertex_buffer_builder(batch, &payload, v0, v1, v2, v3, uv0, uv1, uv2, uv3, sprite.color);
|
||||
|
@ -12,26 +12,8 @@
|
||||
#define NUM_DISPLAY_ASCII ((ASCII_END - ASCII_START) + 1)
|
||||
|
||||
|
||||
struct font_data {
|
||||
stbtt_packedchar char_data[NUM_DISPLAY_ASCII];
|
||||
stbtt_fontinfo info;
|
||||
|
||||
const char *file_path;
|
||||
unsigned char *file_bytes;
|
||||
size_t file_bytes_len;
|
||||
|
||||
gpu_texture texture;
|
||||
|
||||
int height_px;
|
||||
float scale_factor;
|
||||
int ascent;
|
||||
int descent;
|
||||
int line_gap;
|
||||
};
|
||||
|
||||
|
||||
static struct font_data *text_load_font_data(const char *path, int height_px) {
|
||||
struct font_data *font_data = ccalloc(1, sizeof *font_data);
|
||||
static FontData *text_load_font_data(const char *path, int height_px) {
|
||||
FontData *font_data = ccalloc(1, sizeof *font_data);
|
||||
font_data->file_path = path;
|
||||
font_data->height_px = height_px;
|
||||
|
||||
@ -77,21 +59,21 @@ static struct font_data *text_load_font_data(const char *path, int height_px) {
|
||||
}
|
||||
|
||||
|
||||
static void text_destroy_font_data(struct font_data *font_data) {
|
||||
static void text_destroy_font_data(FontData *font_data) {
|
||||
free(font_data->file_bytes);
|
||||
delete_gpu_texture(font_data->texture);
|
||||
free(font_data);
|
||||
}
|
||||
|
||||
|
||||
static void text_draw_with(struct font_data* font_data, char* text, t_fvec2 position, t_color color) {
|
||||
static vertex_buffer vertex_array = 0;
|
||||
static void text_draw_with(FontData* font_data, char* text, Vec2 position, Color color) {
|
||||
VertexBuffer vertex_array = 0;
|
||||
if (vertex_array == 0)
|
||||
vertex_array = create_vertex_buffer();
|
||||
|
||||
const size_t len = SDL_strlen(text);
|
||||
|
||||
vertex_buffer_builder payload = build_vertex_buffer(vertex_array, get_text_payload_size() * len);
|
||||
VertexBufferBuilder payload = build_vertex_buffer(vertex_array, get_text_payload_size() * len);
|
||||
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
const char c = text[i];
|
||||
@ -131,21 +113,21 @@ static void ensure_font_cache(const char *font_path, int height_px) {
|
||||
/* HACK: stupid, bad, don't do this */
|
||||
bool is_cached = false;
|
||||
for (size_t i = 0; i < arrlenu(ctx.text_cache.data); ++i) {
|
||||
struct font_data *font_data = ctx.text_cache.data[i];
|
||||
FontData *font_data = ctx.text_cache.data[i];
|
||||
if ((strcmp(font_path, font_data->file_path) == 0) && height_px == font_data->height_px) {
|
||||
is_cached = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!is_cached) {
|
||||
struct font_data *new_font_data = text_load_font_data(font_path, height_px);
|
||||
FontData *new_font_data = text_load_font_data(font_path, height_px);
|
||||
arrput(ctx.text_cache.data, new_font_data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct font_data *get_font_data(const char *font_path, int height_px) {
|
||||
struct font_data *font_data = NULL;
|
||||
static FontData *get_font_data(const char *font_path, int height_px) {
|
||||
FontData *font_data = NULL;
|
||||
for (size_t i = 0; i < arrlenu(ctx.text_cache.data); ++i) {
|
||||
font_data = ctx.text_cache.data[i];
|
||||
if ((strcmp(font_path, font_data->file_path) == 0) && height_px == font_data->height_px) {
|
||||
@ -156,18 +138,18 @@ static struct font_data *get_font_data(const char *font_path, int height_px) {
|
||||
}
|
||||
|
||||
|
||||
void render_text(const struct text_primitive *text) {
|
||||
struct font_data *font_data = get_font_data(text->font, text->height_px);
|
||||
void render_text(const TextPrimitive *text) {
|
||||
FontData *font_data = get_font_data(text->font, text->height_px);
|
||||
text_draw_with(font_data, text->text, text->position, text->color);
|
||||
}
|
||||
|
||||
|
||||
void text_cache_init(struct text_cache *cache) {
|
||||
void text_cache_init(TextCache *cache) {
|
||||
arrsetlen(cache->data, 0);
|
||||
}
|
||||
|
||||
|
||||
void text_cache_deinit(struct text_cache *cache) {
|
||||
void text_cache_deinit(TextCache *cache) {
|
||||
for (size_t i = 0; i < arrlenu(ctx.text_cache.data); ++i) {
|
||||
text_destroy_font_data(ctx.text_cache.data[i]);
|
||||
}
|
||||
@ -176,7 +158,7 @@ void text_cache_deinit(struct text_cache *cache) {
|
||||
}
|
||||
|
||||
|
||||
void push_text(char *string, t_fvec2 position, int height_px, t_color color, const char *font_path) {
|
||||
void push_text(char *string, Vec2 position, int height_px, Color color, const char *font_path) {
|
||||
ensure_font_cache(font_path, height_px);
|
||||
|
||||
/* the string might not be around by the time it's used, so copy it */
|
||||
@ -185,7 +167,7 @@ void push_text(char *string, t_fvec2 position, int height_px, t_color color, con
|
||||
char *dup_string = cmalloc(strlen(string) + 1);
|
||||
strcpy(dup_string, string);
|
||||
|
||||
struct text_primitive text = {
|
||||
TextPrimitive text = {
|
||||
.color = color,
|
||||
.position = position,
|
||||
.text = dup_string,
|
||||
@ -193,7 +175,7 @@ void push_text(char *string, t_fvec2 position, int height_px, t_color color, con
|
||||
.height_px = height_px,
|
||||
};
|
||||
|
||||
struct primitive_2d primitive = {
|
||||
Primitive2D primitive = {
|
||||
.type = PRIMITIVE_2D_TEXT,
|
||||
.text = text,
|
||||
};
|
||||
@ -204,7 +186,7 @@ void push_text(char *string, t_fvec2 position, int height_px, t_color color, con
|
||||
|
||||
int get_text_width(char *string, int height_px, const char *font_path) {
|
||||
ensure_font_cache(font_path, height_px);
|
||||
struct font_data *font_data = get_font_data(font_path, height_px);
|
||||
FontData *font_data = get_font_data(font_path, height_px);
|
||||
|
||||
int length = 0;
|
||||
for (const char *p = string; *p != '\0'; ++p) {
|
||||
|
@ -1,3 +1,10 @@
|
||||
#ifndef TWN_TEXT_C_H
|
||||
#define TWN_TEXT_C_H
|
||||
|
||||
|
||||
#include "twn_gpu_texture_c.h"
|
||||
|
||||
|
||||
#include <stb_truetype.h>
|
||||
|
||||
|
||||
@ -6,7 +13,7 @@
|
||||
#define NUM_DISPLAY_ASCII ((ASCII_END - ASCII_START) + 1)
|
||||
|
||||
|
||||
struct font_data {
|
||||
typedef struct FontData {
|
||||
stbtt_packedchar char_data[NUM_DISPLAY_ASCII];
|
||||
stbtt_fontinfo info;
|
||||
|
||||
@ -14,11 +21,14 @@ struct font_data {
|
||||
unsigned char *file_bytes;
|
||||
size_t file_bytes_len;
|
||||
|
||||
gpu_texture texture;
|
||||
GPUTexture texture;
|
||||
|
||||
int height_px;
|
||||
float scale_factor;
|
||||
int ascent;
|
||||
int descent;
|
||||
int line_gap;
|
||||
};
|
||||
} FontData;
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -9,42 +9,42 @@
|
||||
/* TODO: automatic handling of repeating textures */
|
||||
/* for that we could allocate a loner texture */
|
||||
void unfurl_triangle(const char *path,
|
||||
t_fvec3 v0,
|
||||
t_fvec3 v1,
|
||||
t_fvec3 v2,
|
||||
t_shvec2 uv0,
|
||||
t_shvec2 uv1,
|
||||
t_shvec2 uv2)
|
||||
Vec3 v0,
|
||||
Vec3 v1,
|
||||
Vec3 v2,
|
||||
Vec2sh uv0,
|
||||
Vec2sh uv1,
|
||||
Vec2sh uv2)
|
||||
{
|
||||
const t_texture_key texture_key = textures_get_key(&ctx.texture_cache, path);
|
||||
const TextureKey texture_key = textures_get_key(&ctx.texture_cache, path);
|
||||
|
||||
struct mesh_batch_item *batch_p = hmgetp_null(ctx.uncolored_mesh_batches, texture_key);
|
||||
struct MeshBatchItem *batch_p = hmgetp_null(ctx.uncolored_mesh_batches, texture_key);
|
||||
if (!batch_p) {
|
||||
struct mesh_batch item = {0};
|
||||
struct MeshBatch item = {0};
|
||||
hmput(ctx.uncolored_mesh_batches, texture_key, item);
|
||||
batch_p = &ctx.uncolored_mesh_batches[hmlenu(ctx.uncolored_mesh_batches) - 1]; /* TODO: can last index be used? */
|
||||
}
|
||||
|
||||
union uncolored_space_triangle triangle = { .primitive = {
|
||||
union UncoloredSpaceTriangle triangle = { .primitive = {
|
||||
.v0 = v0,
|
||||
.v1 = v1,
|
||||
.v2 = v2,
|
||||
.uv1 = m_to_fvec2(uv1),
|
||||
.uv0 = m_to_fvec2(uv0),
|
||||
.uv2 = m_to_fvec2(uv2),
|
||||
.uv1 = m_vec2_from(uv1),
|
||||
.uv0 = m_vec2_from(uv0),
|
||||
.uv2 = m_vec2_from(uv2),
|
||||
}};
|
||||
|
||||
union uncolored_space_triangle *triangles = (union uncolored_space_triangle *)batch_p->value.primitives;
|
||||
union UncoloredSpaceTriangle *triangles = (union UncoloredSpaceTriangle *)batch_p->value.primitives;
|
||||
|
||||
arrpush(triangles, triangle);
|
||||
batch_p->value.primitives = (uint8_t *)triangles;
|
||||
}
|
||||
|
||||
|
||||
void draw_uncolored_space_traingle_batch(struct mesh_batch *batch,
|
||||
t_texture_key texture_key)
|
||||
void draw_uncolored_space_traingle_batch(struct MeshBatch *batch,
|
||||
TextureKey texture_key)
|
||||
{
|
||||
static vertex_buffer vertex_array = 0;
|
||||
static VertexBuffer vertex_array = 0;
|
||||
if (vertex_array == 0)
|
||||
vertex_array = create_vertex_buffer();
|
||||
|
||||
@ -54,8 +54,8 @@ void draw_uncolored_space_traingle_batch(struct mesh_batch *batch,
|
||||
if (primitives_len == 0)
|
||||
return;
|
||||
|
||||
const t_frect srcrect = textures_get_srcrect(&ctx.texture_cache, texture_key);
|
||||
const t_frect dims = textures_get_dims(&ctx.texture_cache, texture_key);
|
||||
const Rect srcrect = textures_get_srcrect(&ctx.texture_cache, texture_key);
|
||||
const Rect dims = textures_get_dims(&ctx.texture_cache, texture_key);
|
||||
|
||||
const float wr = srcrect.w / dims.w;
|
||||
const float hr = srcrect.h / dims.h;
|
||||
@ -64,8 +64,8 @@ void draw_uncolored_space_traingle_batch(struct mesh_batch *batch,
|
||||
|
||||
/* update pixel-based uvs to correspond with texture atlases */
|
||||
for (size_t i = 0; i < primitives_len; ++i) {
|
||||
struct uncolored_space_triangle_payload *payload =
|
||||
&((union uncolored_space_triangle *)batch->primitives)[i].payload;
|
||||
struct UncoloredSpaceTrianglePayload *payload =
|
||||
&((union UncoloredSpaceTriangle *)batch->primitives)[i].payload;
|
||||
|
||||
payload->uv0.x = xr + ((float)payload->uv0.x / srcrect.w) * wr;
|
||||
payload->uv0.y = yr + ((float)payload->uv0.y / srcrect.h) * hr;
|
||||
@ -75,7 +75,7 @@ void draw_uncolored_space_traingle_batch(struct mesh_batch *batch,
|
||||
payload->uv2.y = yr + ((float)payload->uv2.y / srcrect.h) * hr;
|
||||
}
|
||||
|
||||
specify_vertex_buffer(vertex_array, batch->primitives, primitives_len * sizeof (struct uncolored_space_triangle_payload));
|
||||
specify_vertex_buffer(vertex_array, batch->primitives, primitives_len * sizeof (struct UncoloredSpaceTrianglePayload));
|
||||
|
||||
finally_draw_uncolored_space_traingle_batch(batch, texture_key, vertex_array);
|
||||
}
|
||||
|
Reference in New Issue
Block a user