1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125  static void
opengl_sprite_list_output(uint32_t atlas, render_command_sprite_list_t* spriteList,
sprite_t* spriteTable, sorter_t sorter, vec2_t windowDim, gl_context_t* glContext,
memory_region_t* tMem)
{
uint32_t verticesCount = spriteList>used * 32;
uint32_t verticesSize = verticesCount * sizeof(float);
float* vertices = push_array(tMem, float, verticesCount);
uint32_t indicesCount = spriteList>used * 6;
uint32_t indicesSize = indicesCount * sizeof(uint32_t);
uint32_t* indices = push_array(tMem, uint32_t, indicesCount);
// 1 px size in texture space
// used to eliminate transparent 1px border around the sprite
float dc = 1.0f / 512.0f;
for (uint32_t index = 0;
index < sorter.entryCount;
++index)
{
uint32_t sortIndex = sorter.entries[index].listIndex;
render_command_sprite_t* command = &spriteList>array[sortIndex];
transform_t t = command>transform;
float r = command>color.r;
float g = command>color.g;
float b = command>color.b;
float a = command>color.a;
// default values just in case something went wrong and the sprite will not be found
float u0 = 0;
float v0 = 0;
float u1 = 1;
float v1 = 1;
// If spriteTable is available get sprite data
if (spriteTable)
{
sprite_t sprite = sprite_get(spriteTable, command>sprite);
u0 = sprite.uv.x + dc;
v0 = sprite.uv.y + dc;
u1 = sprite.duv.x  dc;
v1 = sprite.duv.y  dc;
}
// If passed uv and duv coords to this function
// then, calculate new uv coords relative to the original uvs
vec2_t uv = command>uv;
vec2_t duv = command>duv;
if (uv != V2_0  duv != V2_0)
{
float originalU = u0;
float originalV = v0;
float newWidth = (u1  u0);
float newHeight = (v1  v0);
u0 = originalU + uv.x * newWidth;
u1 = originalU + duv.x * newWidth;
v0 = originalV + uv.y * newHeight;
v1 = originalV + duv.y * newHeight;
}
// transformations
mat4_t scale = scale_matrix(t.scale.x, t.scale.y);
mat4_t translate = translate_matrix(t.position.x, t.position.y);
mat4_t modelview = translate;
if (t.rotation)
{
mat4_t zRotation = z_rotation_matrix(t.rotation);
modelview = zRotation * modelview;
}
modelview = (scale * modelview);
// final vertices
vec4_t va = vec4_t{ 0.5f, 0.5f, 0, 1 } * modelview;
vec4_t vb = vec4_t{ +0.5f, 0.5f, 0, 1 } * modelview;
vec4_t vc = vec4_t{ +0.5f, +0.5f, 0, 1 } * modelview;
vec4_t vd = vec4_t{ 0.5f, +0.5f, 0, 1 } * modelview;
// build temp versions
float tempV[] =
{
va.x, va.y, u0, v0, r, g, b, a,
vb.x, vb.y, u1, v0, r, g, b, a,
vc.x, vc.y, u1, v1, r, g, b, a,
vd.x, vd.y, u0, v1, r, g, b, a
};
uint32_t tempI[] =
{
(index * 4) + 0, (index * 4) + 1, (index * 4) + 2,
(index * 4) + 2, (index * 4) + 3, (index * 4) + 0
};
// copy temp versions into place
memcpy((void*)(vertices + 32 * index), tempV, sizeof(tempV));
memcpy((void*)(indices + 6 * index), tempI, sizeof(tempI));
}
// set up opengl
gl_shader_t* shader = &glContext>shaders[0];
opengl_shader_use(shader);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, (int)windowDim.x, (int)windowDim.y);
tex2d_bind(atlas);
glUniformMatrix4fv(shader>uniforms[0], 1, GL_FALSE, projection);
vbo_subdata(shader>vbo, vertices, verticesSize);
ebo_subdata(shader>ebo, indices, indicesSize);
// draw triangles
triangles(indicesCount, 0);
tex2d_bind(0);
}
