2024-09-16 06:07:01 +00:00
|
|
|
#include "twn_rendering_c.h"
|
2024-09-16 13:17:00 +00:00
|
|
|
#include "twn_util.h"
|
2024-09-26 18:02:56 +00:00
|
|
|
#include "twn_util_c.h"
|
2024-09-16 13:17:00 +00:00
|
|
|
#include "twn_config.h"
|
|
|
|
#include "twn_engine_context_c.h"
|
2024-09-16 06:07:01 +00:00
|
|
|
#include "twn_text_c.h"
|
|
|
|
|
|
|
|
#include <glad/glad.h>
|
|
|
|
|
|
|
|
|
|
|
|
/* interleaved vertex array data */
|
|
|
|
/* 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 */
|
2024-09-23 17:43:16 +00:00
|
|
|
typedef struct ElementIndexedQuad {
|
2024-09-16 06:07:01 +00:00
|
|
|
/* upper-left */
|
2024-09-23 17:43:16 +00:00
|
|
|
Vec2 v0;
|
|
|
|
Vec2 uv0;
|
|
|
|
Color c0;
|
2024-09-16 06:07:01 +00:00
|
|
|
/* bottom-left */
|
2024-09-23 17:43:16 +00:00
|
|
|
Vec2 v1;
|
|
|
|
Vec2 uv1;
|
|
|
|
Color c1;
|
2024-09-16 06:07:01 +00:00
|
|
|
/* bottom-right */
|
2024-09-23 17:43:16 +00:00
|
|
|
Vec2 v2;
|
|
|
|
Vec2 uv2;
|
|
|
|
Color c2;
|
2024-09-16 06:07:01 +00:00
|
|
|
/* upper-right */
|
2024-09-23 17:43:16 +00:00
|
|
|
Vec2 v3;
|
|
|
|
Vec2 uv3;
|
|
|
|
Color c3;
|
|
|
|
} ElementIndexedQuad;
|
2024-09-16 06:07:01 +00:00
|
|
|
|
|
|
|
|
2024-09-23 17:43:16 +00:00
|
|
|
typedef struct ElementIndexedQuadWithoutColor {
|
2024-09-16 06:07:01 +00:00
|
|
|
/* upper-left */
|
2024-09-23 17:43:16 +00:00
|
|
|
Vec2 v0;
|
|
|
|
Vec2 uv0;
|
2024-09-16 06:07:01 +00:00
|
|
|
/* bottom-left */
|
2024-09-23 17:43:16 +00:00
|
|
|
Vec2 v1;
|
|
|
|
Vec2 uv1;
|
2024-09-16 06:07:01 +00:00
|
|
|
/* bottom-right */
|
2024-09-23 17:43:16 +00:00
|
|
|
Vec2 v2;
|
|
|
|
Vec2 uv2;
|
2024-09-16 06:07:01 +00:00
|
|
|
/* upper-right */
|
2024-09-23 17:43:16 +00:00
|
|
|
Vec2 v3;
|
|
|
|
Vec2 uv3;
|
|
|
|
} ElementIndexedQuadWithoutColor;
|
2024-09-16 06:07:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
PIPELINE_NO,
|
|
|
|
PIPELINE_SPACE,
|
|
|
|
PIPELINE_2D,
|
2024-09-23 17:43:16 +00:00
|
|
|
} Pipeline;
|
2024-09-16 06:07:01 +00:00
|
|
|
|
|
|
|
|
2024-09-23 17:43:16 +00:00
|
|
|
static Pipeline pipeline_last_used = PIPELINE_NO;
|
2024-09-16 06:07:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
void use_space_pipeline(void) {
|
2024-10-01 11:58:00 +00:00
|
|
|
static GLuint list = 0;
|
|
|
|
if (!list) {
|
|
|
|
list = glGenLists(1);
|
|
|
|
|
|
|
|
glNewList(list, GL_COMPILE); {
|
|
|
|
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
|
|
|
|
glShadeModel(GL_SMOOTH);
|
|
|
|
|
|
|
|
if (GLAD_GL_ARB_depth_clamp)
|
|
|
|
glDisable(GL_DEPTH_CLAMP);
|
|
|
|
|
|
|
|
glEnable(GL_CULL_FACE);
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
glDepthMask(GL_TRUE);
|
|
|
|
glDepthFunc(GL_LESS);
|
|
|
|
glDepthRange(0, 1);
|
|
|
|
glDisable(GL_BLEND);
|
|
|
|
glEnable(GL_ALPHA_TEST); /* TODO: infer its usage? */
|
|
|
|
glAlphaFunc(GL_EQUAL, 1.0f);
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glActiveTexture(GL_TEXTURE0);
|
|
|
|
|
|
|
|
/* solid white, no modulation */
|
|
|
|
glColor4ub(255, 255, 255, 255);
|
|
|
|
} glEndList();
|
|
|
|
}
|
2024-09-16 06:07:01 +00:00
|
|
|
|
2024-10-01 11:58:00 +00:00
|
|
|
glCallList(list);
|
2024-09-16 06:07:01 +00:00
|
|
|
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadMatrixf(&camera_projection_matrix.row[0].x);
|
|
|
|
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadMatrixf(&camera_look_at_matrix.row[0].x);
|
|
|
|
|
|
|
|
pipeline_last_used = PIPELINE_SPACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void use_2d_pipeline(void) {
|
|
|
|
if (pipeline_last_used == PIPELINE_SPACE) {
|
|
|
|
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
|
|
|
glFlush();
|
|
|
|
}
|
|
|
|
|
2024-10-01 11:58:00 +00:00
|
|
|
static GLuint list = 0;
|
|
|
|
if (!list) {
|
|
|
|
list = glGenLists(1);
|
|
|
|
|
|
|
|
glNewList(list, GL_COMPILE); {
|
|
|
|
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
|
|
|
|
glShadeModel(GL_FLAT);
|
|
|
|
|
|
|
|
/* removes near/far plane comparison and discard */
|
|
|
|
if (GLAD_GL_ARB_depth_clamp)
|
|
|
|
glDisable(GL_DEPTH_CLAMP);
|
|
|
|
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glActiveTexture(GL_TEXTURE0);
|
|
|
|
glDisable(GL_CULL_FACE);
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
} glEndList();
|
|
|
|
}
|
2024-09-16 06:07:01 +00:00
|
|
|
|
2024-10-01 11:58:00 +00:00
|
|
|
glCallList(list);
|
2024-09-16 06:07:01 +00:00
|
|
|
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadIdentity();
|
2024-10-01 00:13:58 +00:00
|
|
|
glOrtho(0, (double)ctx.base_render_width, (double)ctx.base_render_height, 0, -1, 1);
|
2024-09-16 06:07:01 +00:00
|
|
|
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
|
|
|
|
|
|
|
pipeline_last_used = PIPELINE_2D;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-09-23 17:43:16 +00:00
|
|
|
void upload_quad_vertices(Rect rect) {
|
2024-09-16 06:07:01 +00:00
|
|
|
/* client memory needs to be reachable on glDraw*, so */
|
|
|
|
static float vertices[6 * 2];
|
|
|
|
|
|
|
|
vertices[0] = rect.x; vertices[1] = rect.y;
|
|
|
|
vertices[2] = rect.x; vertices[3] = rect.y + rect.h;
|
|
|
|
vertices[4] = rect.x + rect.w; vertices[5] = rect.y + rect.h;
|
|
|
|
vertices[6] = rect.x + rect.w; vertices[7] = rect.y + rect.h;
|
|
|
|
vertices[8] = rect.x + rect.w; vertices[9] = rect.y;
|
|
|
|
vertices[10] = rect.x; vertices[11] = rect.y;
|
|
|
|
|
|
|
|
glVertexPointer(2, GL_FLOAT, 0, (void *)&vertices);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-09-23 17:43:16 +00:00
|
|
|
void render_rectangle(const RectPrimitive *rectangle) {
|
2024-09-16 06:07:01 +00:00
|
|
|
glColor4ub(rectangle->color.r, rectangle->color.g,
|
|
|
|
rectangle->color.b, rectangle->color.a);
|
|
|
|
|
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
upload_quad_vertices(rectangle->rect);
|
|
|
|
|
|
|
|
glDrawArrays(GL_TRIANGLES, 0, 6);
|
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-09-23 17:43:16 +00:00
|
|
|
void render_circle(const CirclePrimitive *circle) {
|
2024-09-16 06:07:01 +00:00
|
|
|
SDL_Vertex *vertices = NULL;
|
|
|
|
int *indices = NULL;
|
|
|
|
int num_vertices = (int)circle->radius;
|
|
|
|
|
|
|
|
create_circle_geometry(circle->position,
|
|
|
|
circle->color,
|
|
|
|
circle->radius,
|
|
|
|
num_vertices,
|
|
|
|
&vertices,
|
|
|
|
&indices);
|
|
|
|
|
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glVertexPointer(2,
|
|
|
|
GL_FLOAT,
|
|
|
|
sizeof (SDL_Vertex),
|
|
|
|
&vertices->position);
|
|
|
|
|
|
|
|
glEnableClientState(GL_COLOR_ARRAY);
|
|
|
|
glColorPointer(4,
|
|
|
|
GL_UNSIGNED_BYTE,
|
|
|
|
sizeof (SDL_Vertex),
|
|
|
|
&vertices->color);
|
|
|
|
|
|
|
|
glDrawElements(GL_TRIANGLES,
|
|
|
|
num_vertices * 3,
|
|
|
|
GL_UNSIGNED_INT,
|
|
|
|
indices);
|
|
|
|
|
|
|
|
glDisableClientState(GL_COLOR_ARRAY);
|
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
|
|
|
2024-09-25 22:42:34 +00:00
|
|
|
SDL_free(vertices);
|
|
|
|
SDL_free(indices);
|
2024-09-16 06:07:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-09-23 17:43:16 +00:00
|
|
|
void use_texture_mode(TextureMode mode) {
|
2024-10-01 11:58:00 +00:00
|
|
|
GLuint lists = 0;
|
|
|
|
if (!lists) {
|
|
|
|
lists = glGenLists(3);
|
|
|
|
|
|
|
|
glNewList(lists + 0, GL_COMPILE); {
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
glDepthFunc(GL_ALWAYS);
|
|
|
|
glDepthMask(GL_FALSE);
|
|
|
|
glDisable(GL_ALPHA_TEST);
|
|
|
|
} glEndList();
|
|
|
|
|
|
|
|
glNewList(lists + 1, GL_COMPILE); {
|
|
|
|
glDisable(GL_BLEND);
|
|
|
|
glDepthFunc(GL_LEQUAL);
|
|
|
|
glDepthMask(GL_TRUE);
|
|
|
|
glEnable(GL_ALPHA_TEST);
|
|
|
|
glAlphaFunc(GL_EQUAL, 1.0f);
|
|
|
|
} glEndList();
|
|
|
|
|
|
|
|
glNewList(lists + 2, GL_COMPILE); {
|
|
|
|
glDisable(GL_BLEND);
|
|
|
|
glDepthFunc(GL_LESS);
|
|
|
|
glDepthMask(GL_TRUE);
|
|
|
|
glDisable(GL_ALPHA_TEST);
|
|
|
|
} glEndList();
|
|
|
|
}
|
|
|
|
|
2024-09-16 06:07:01 +00:00
|
|
|
if (mode == TEXTURE_MODE_GHOSTLY) {
|
2024-10-01 11:58:00 +00:00
|
|
|
glCallList(lists + 0);
|
2024-09-16 06:07:01 +00:00
|
|
|
} else if (mode == TEXTURE_MODE_SEETHROUGH) {
|
2024-10-01 11:58:00 +00:00
|
|
|
glCallList(lists + 1);
|
2024-09-16 06:07:01 +00:00
|
|
|
} else {
|
2024-10-01 11:58:00 +00:00
|
|
|
glCallList(lists + 2);
|
2024-09-16 06:07:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-09-23 17:43:16 +00:00
|
|
|
VertexBufferBuilder build_vertex_buffer(VertexBuffer buffer, size_t bytes) {
|
2024-09-16 06:07:01 +00:00
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, buffer);
|
2024-09-16 13:17:00 +00:00
|
|
|
glBufferData(GL_ARRAY_BUFFER, bytes, NULL, GL_STREAM_DRAW);
|
2024-09-16 06:07:01 +00:00
|
|
|
void *mapping = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
|
|
|
|
if (!mapping)
|
|
|
|
CRY("build_vertex_buffer", "Error mapping a vertex array buffer");
|
|
|
|
|
2024-09-23 17:43:16 +00:00
|
|
|
return (VertexBufferBuilder) {
|
2024-09-16 06:07:01 +00:00
|
|
|
.mapping = mapping,
|
|
|
|
.bytes_left = bytes,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-09-23 17:43:16 +00:00
|
|
|
bool push_to_vertex_buffer_builder(VertexBufferBuilder *builder,
|
2024-09-16 06:07:01 +00:00
|
|
|
void *bytes, size_t size) {
|
|
|
|
if (builder->bytes_left == 0)
|
|
|
|
return false;
|
|
|
|
|
2024-09-25 22:42:34 +00:00
|
|
|
SDL_memcpy(builder->mapping, bytes, size);
|
2024-09-16 06:07:01 +00:00
|
|
|
builder->bytes_left -= size;
|
|
|
|
|
|
|
|
/* trigger data send */
|
|
|
|
if (builder->bytes_left == 0) {
|
|
|
|
glUnmapBuffer(GL_ARRAY_BUFFER);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-09-16 13:17:00 +00:00
|
|
|
builder->mapping = (void *)((uintptr_t)builder->mapping + size);
|
|
|
|
|
2024-09-16 06:07:01 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-09-23 17:43:16 +00:00
|
|
|
void finally_render_sprites(const Primitive2D primitives[],
|
|
|
|
const struct SpriteBatch batch,
|
|
|
|
const VertexBuffer buffer)
|
2024-09-16 06:07:01 +00:00
|
|
|
{
|
|
|
|
/* TODO: maybe do, dunno */
|
|
|
|
// glBindBuffer(GL_VERTEX_ARRAY, vertex_buffer);
|
2024-09-16 13:17:00 +00:00
|
|
|
(void)buffer;
|
2024-09-16 06:07:01 +00:00
|
|
|
|
|
|
|
GLsizei off;
|
|
|
|
GLsizei voff;
|
|
|
|
GLsizei uvoff;
|
|
|
|
|
|
|
|
if (!batch.constant_colored) {
|
2024-09-23 17:43:16 +00:00
|
|
|
off = offsetof(ElementIndexedQuad, v1);
|
|
|
|
voff = offsetof(ElementIndexedQuad, v0);
|
|
|
|
uvoff = offsetof(ElementIndexedQuad, uv0);
|
2024-09-16 06:07:01 +00:00
|
|
|
} else {
|
2024-09-23 17:43:16 +00:00
|
|
|
off = offsetof(ElementIndexedQuadWithoutColor, v1);
|
|
|
|
voff = offsetof(ElementIndexedQuadWithoutColor, v0);
|
|
|
|
uvoff = offsetof(ElementIndexedQuadWithoutColor, uv0);
|
2024-09-16 06:07:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* vertex specification */
|
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glVertexPointer(2,
|
|
|
|
GL_FLOAT,
|
|
|
|
off,
|
|
|
|
(void *)(size_t)voff);
|
|
|
|
|
|
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
glClientActiveTexture(GL_TEXTURE0);
|
|
|
|
glTexCoordPointer(2,
|
|
|
|
GL_FLOAT,
|
|
|
|
off,
|
|
|
|
(void *)(size_t)uvoff);
|
|
|
|
|
|
|
|
if (!batch.constant_colored) {
|
|
|
|
glEnableClientState(GL_COLOR_ARRAY);
|
|
|
|
glColorPointer(4,
|
|
|
|
GL_UNSIGNED_BYTE,
|
|
|
|
off,
|
2024-09-23 17:43:16 +00:00
|
|
|
(void *)offsetof(ElementIndexedQuad, c0));
|
2024-09-16 06:07:01 +00:00
|
|
|
} else
|
|
|
|
glColor4ub(primitives[0].sprite.color.r,
|
|
|
|
primitives[0].sprite.color.g,
|
|
|
|
primitives[0].sprite.color.b,
|
|
|
|
primitives[0].sprite.color.a);
|
|
|
|
|
|
|
|
if (!batch.repeat)
|
|
|
|
textures_bind(&ctx.texture_cache, primitives->sprite.texture_key);
|
|
|
|
else
|
|
|
|
textures_bind_repeating(&ctx.texture_cache, primitives->sprite.texture_key);
|
|
|
|
|
|
|
|
bind_quad_element_buffer();
|
|
|
|
|
|
|
|
glDrawElements(GL_TRIANGLES, 6 * (GLsizei)batch.size, GL_UNSIGNED_SHORT, NULL);
|
|
|
|
|
|
|
|
/* clear the state */
|
|
|
|
glBufferData(GL_ARRAY_BUFFER, 0, NULL, GL_STREAM_DRAW);
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
|
|
|
|
|
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glDisableClientState(GL_COLOR_ARRAY);
|
|
|
|
|
|
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-09-23 17:43:16 +00:00
|
|
|
size_t get_sprite_payload_size(struct SpriteBatch batch) {
|
2024-09-16 06:07:01 +00:00
|
|
|
if (batch.constant_colored)
|
2024-09-23 17:43:16 +00:00
|
|
|
return sizeof (ElementIndexedQuadWithoutColor);
|
2024-09-16 06:07:01 +00:00
|
|
|
else
|
2024-09-23 17:43:16 +00:00
|
|
|
return sizeof (ElementIndexedQuad);
|
2024-09-16 06:07:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-09-23 17:43:16 +00:00
|
|
|
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)
|
2024-09-16 06:07:01 +00:00
|
|
|
{
|
|
|
|
if (!batch.constant_colored) {
|
2024-09-23 17:43:16 +00:00
|
|
|
ElementIndexedQuad buffer_element = {
|
2024-09-16 06:07:01 +00:00
|
|
|
.v0 = v0,
|
|
|
|
.v1 = v1,
|
|
|
|
.v2 = v2,
|
|
|
|
.v3 = v3,
|
|
|
|
|
|
|
|
.uv0 = uv0,
|
|
|
|
.uv1 = uv1,
|
|
|
|
.uv2 = uv2,
|
|
|
|
.uv3 = uv3,
|
|
|
|
|
|
|
|
/* equal for all (flat shaded) */
|
|
|
|
.c0 = color,
|
|
|
|
.c1 = color,
|
|
|
|
.c2 = color,
|
|
|
|
.c3 = color,
|
|
|
|
};
|
|
|
|
|
|
|
|
return push_to_vertex_buffer_builder(builder, &buffer_element, sizeof buffer_element);
|
|
|
|
|
|
|
|
} else {
|
2024-09-23 17:43:16 +00:00
|
|
|
ElementIndexedQuadWithoutColor buffer_element = {
|
2024-09-16 06:07:01 +00:00
|
|
|
.v0 = v0,
|
|
|
|
.v1 = v1,
|
|
|
|
.v2 = v2,
|
|
|
|
.v3 = v3,
|
|
|
|
|
|
|
|
.uv0 = uv0,
|
|
|
|
.uv1 = uv1,
|
|
|
|
.uv2 = uv2,
|
|
|
|
.uv3 = uv3,
|
|
|
|
};
|
|
|
|
|
|
|
|
return push_to_vertex_buffer_builder(builder, &buffer_element, sizeof buffer_element);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-09-23 17:43:16 +00:00
|
|
|
void finally_draw_uncolored_space_traingle_batch(const MeshBatch *batch,
|
|
|
|
const TextureKey texture_key,
|
|
|
|
const VertexBuffer buffer)
|
2024-09-16 06:07:01 +00:00
|
|
|
{
|
|
|
|
const size_t primitives_len = arrlenu(batch->primitives);
|
|
|
|
|
|
|
|
textures_bind(&ctx.texture_cache, texture_key);
|
|
|
|
|
2024-09-16 13:17:00 +00:00
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, buffer);
|
2024-09-16 06:07:01 +00:00
|
|
|
|
|
|
|
/* vertex specification*/
|
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glVertexPointer(3,
|
|
|
|
GL_FLOAT,
|
2024-09-23 17:43:16 +00:00
|
|
|
offsetof(struct UncoloredSpaceTrianglePayload, v1),
|
|
|
|
(void *)offsetof(struct UncoloredSpaceTrianglePayload, v0));
|
2024-09-16 06:07:01 +00:00
|
|
|
|
|
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
glClientActiveTexture(GL_TEXTURE0);
|
|
|
|
glTexCoordPointer(2,
|
|
|
|
GL_FLOAT,
|
2024-09-23 17:43:16 +00:00
|
|
|
offsetof(struct UncoloredSpaceTrianglePayload, v1),
|
|
|
|
(void *)offsetof(struct UncoloredSpaceTrianglePayload, uv0));
|
2024-09-16 06:07:01 +00:00
|
|
|
|
|
|
|
/* commit for drawing */
|
|
|
|
glDrawArrays(GL_TRIANGLES, 0, 3 * (GLint)primitives_len);
|
|
|
|
|
|
|
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
|
|
|
|
|
|
/* invalidate the buffer immediately */
|
|
|
|
glBufferData(GL_ARRAY_BUFFER, 0, NULL, GL_STREAM_DRAW);
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-09-23 17:43:16 +00:00
|
|
|
bool push_text_payload_to_vertex_buffer_builder(FontData const *font_data,
|
|
|
|
VertexBufferBuilder *builder,
|
2024-09-16 06:07:01 +00:00
|
|
|
stbtt_aligned_quad quad)
|
|
|
|
{
|
|
|
|
(void)font_data;
|
2024-09-18 16:01:43 +00:00
|
|
|
|
2024-09-23 17:43:16 +00:00
|
|
|
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 },
|
2024-09-18 16:01:43 +00:00
|
|
|
|
2024-09-23 17:43:16 +00:00
|
|
|
.uv0 = (Vec2){ quad.s0, quad.t0 },
|
|
|
|
.uv1 = (Vec2){ quad.s1, quad.t0 },
|
|
|
|
.uv2 = (Vec2){ quad.s1, quad.t1 },
|
|
|
|
.uv3 = (Vec2){ quad.s0, quad.t1 },
|
2024-09-18 16:01:43 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
return push_to_vertex_buffer_builder(builder, &buffer_element, sizeof buffer_element);
|
2024-09-16 06:07:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-09-23 17:43:16 +00:00
|
|
|
void finally_draw_text(FontData const *font_data,
|
2024-09-16 06:07:01 +00:00
|
|
|
size_t len,
|
2024-09-23 17:43:16 +00:00
|
|
|
Color color,
|
|
|
|
VertexBuffer buffer)
|
2024-09-16 06:07:01 +00:00
|
|
|
{
|
2024-09-16 13:17:00 +00:00
|
|
|
(void)buffer;
|
|
|
|
|
2024-09-18 16:01:43 +00:00
|
|
|
/* vertex specification */
|
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glVertexPointer(2,
|
|
|
|
GL_FLOAT,
|
2024-09-23 17:43:16 +00:00
|
|
|
offsetof(ElementIndexedQuadWithoutColor, v1),
|
|
|
|
(void *)(size_t)offsetof(ElementIndexedQuadWithoutColor, v0));
|
2024-09-18 16:01:43 +00:00
|
|
|
|
|
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
glClientActiveTexture(GL_TEXTURE0);
|
|
|
|
glTexCoordPointer(2,
|
|
|
|
GL_FLOAT,
|
2024-09-23 17:43:16 +00:00
|
|
|
offsetof(ElementIndexedQuadWithoutColor, v1),
|
|
|
|
(void *)(size_t)offsetof(ElementIndexedQuadWithoutColor, uv0));
|
2024-09-18 16:01:43 +00:00
|
|
|
|
|
|
|
bind_quad_element_buffer();
|
|
|
|
|
2024-09-16 06:07:01 +00:00
|
|
|
use_texture_mode(TEXTURE_MODE_GHOSTLY);
|
|
|
|
|
|
|
|
glBindTexture(GL_TEXTURE_2D, font_data->texture);
|
|
|
|
|
|
|
|
glColor4ub(color.r, color.g, color.b, color.a);
|
2024-09-18 16:01:43 +00:00
|
|
|
|
|
|
|
glDrawElements(GL_TRIANGLES, 6 * (GLsizei)len, GL_UNSIGNED_SHORT, NULL);
|
|
|
|
|
|
|
|
/* clear the state */
|
|
|
|
glBufferData(GL_ARRAY_BUFFER, 0, NULL, GL_STREAM_DRAW);
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
|
|
|
|
|
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
|
|
|
|
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
2024-09-16 06:07:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
size_t get_text_payload_size(void) {
|
2024-09-23 17:43:16 +00:00
|
|
|
return sizeof (ElementIndexedQuadWithoutColor);
|
2024-09-16 06:07:01 +00:00
|
|
|
}
|
2024-09-26 18:02:56 +00:00
|
|
|
|
|
|
|
static void load_cubemap_side(const char *path, GLenum target) {
|
|
|
|
SDL_Surface *surface = textures_load_surface(path);
|
|
|
|
/* TODO: sanity check whether all of them have same dimensions? */
|
|
|
|
glTexImage2D(target,
|
|
|
|
0,
|
|
|
|
GL_RGBA8,
|
|
|
|
surface->w, surface->h,
|
|
|
|
0,
|
|
|
|
surface->format->BytesPerPixel == 4 ? GL_RGBA : GL_RGB,
|
|
|
|
GL_UNSIGNED_BYTE,
|
|
|
|
surface->pixels);
|
|
|
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
|
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
|
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
|
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
|
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
|
|
|
|
|
|
|
SDL_free(surface->pixels);
|
|
|
|
SDL_FreeSurface(surface);
|
|
|
|
}
|
|
|
|
|
|
|
|
void finally_render_skybox(char *paths) {
|
|
|
|
static GLuint cubemap = 0;
|
|
|
|
static char *paths_cache = NULL;
|
|
|
|
|
|
|
|
bool loading_needed = false;
|
|
|
|
|
|
|
|
/* drop it */
|
|
|
|
if (!paths_cache || (SDL_strcmp(paths_cache, paths) != 0)) {
|
|
|
|
if (cubemap)
|
|
|
|
glDeleteTextures(1, &cubemap);
|
|
|
|
glGenTextures(1, &cubemap);
|
|
|
|
if (paths_cache)
|
|
|
|
SDL_free(paths_cache);
|
|
|
|
paths_cache = paths;
|
|
|
|
loading_needed = true;
|
2024-10-01 10:22:20 +00:00
|
|
|
} else
|
|
|
|
SDL_free(paths);
|
2024-09-26 18:02:56 +00:00
|
|
|
|
|
|
|
Matrix4 camera_look_at_matrix_solipsist = camera_look_at_matrix;
|
|
|
|
camera_look_at_matrix_solipsist.row[3].x = 0;
|
|
|
|
camera_look_at_matrix_solipsist.row[3].y = 0;
|
|
|
|
camera_look_at_matrix_solipsist.row[3].z = 0;
|
|
|
|
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadMatrixf(&camera_look_at_matrix_solipsist.row[0].x);
|
|
|
|
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
glEnable(GL_TEXTURE_CUBE_MAP);
|
|
|
|
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap);
|
|
|
|
|
|
|
|
if (loading_needed) {
|
|
|
|
/* load all the sides */
|
|
|
|
char *expanded = expand_asterisk(paths, "up");
|
|
|
|
load_cubemap_side(expanded, GL_TEXTURE_CUBE_MAP_POSITIVE_Y);
|
|
|
|
SDL_free(expanded);
|
|
|
|
|
|
|
|
expanded = expand_asterisk(paths, "down");
|
|
|
|
load_cubemap_side(expanded, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y);
|
|
|
|
SDL_free(expanded);
|
|
|
|
|
|
|
|
expanded = expand_asterisk(paths, "east");
|
|
|
|
load_cubemap_side(expanded, GL_TEXTURE_CUBE_MAP_POSITIVE_X);
|
|
|
|
SDL_free(expanded);
|
|
|
|
|
|
|
|
expanded = expand_asterisk(paths, "north");
|
|
|
|
load_cubemap_side(expanded, GL_TEXTURE_CUBE_MAP_POSITIVE_Z);
|
|
|
|
SDL_free(expanded);
|
|
|
|
|
|
|
|
expanded = expand_asterisk(paths, "west");
|
|
|
|
load_cubemap_side(expanded, GL_TEXTURE_CUBE_MAP_NEGATIVE_X);
|
|
|
|
SDL_free(expanded);
|
|
|
|
|
|
|
|
expanded = expand_asterisk(paths, "south");
|
|
|
|
load_cubemap_side(expanded, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
|
|
|
|
SDL_free(expanded);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO: figure out which coordinates to use to not have issues with far z */
|
2024-10-01 11:58:00 +00:00
|
|
|
/* TODO: recalculate the list if far z requirement changes */
|
|
|
|
|
|
|
|
static GLuint list = 0;
|
|
|
|
if (!list) {
|
|
|
|
list = glGenLists(1);
|
|
|
|
|
|
|
|
glNewList(list, GL_COMPILE); {
|
|
|
|
/* note: assumes that space pipeline is applied already */
|
|
|
|
glDisable(GL_ALPHA_TEST);
|
|
|
|
glDepthMask(GL_TRUE);
|
|
|
|
|
|
|
|
glBegin(GL_QUADS); {
|
|
|
|
/* up */
|
|
|
|
glTexCoord3f(50.f, 50.f, 50.f);
|
|
|
|
glVertex3f(50.f, 50.f, 50.f);
|
|
|
|
glTexCoord3f(-50.f, 50.f, 50.f);
|
|
|
|
glVertex3f(-50.f, 50.f, 50.f);
|
|
|
|
glTexCoord3f(-50.f, 50.f, -50.f);
|
|
|
|
glVertex3f(-50.f, 50.f, -50.f);
|
|
|
|
glTexCoord3f(50.f, 50.f, -50.f);
|
|
|
|
glVertex3f(50.f, 50.f, -50.f);
|
|
|
|
|
|
|
|
/* down */
|
|
|
|
glTexCoord3f(50.f, -50.f, 50.f);
|
|
|
|
glVertex3f(50.f, -50.f, 50.f);
|
|
|
|
glTexCoord3f(50.f, -50.f, -50.f);
|
|
|
|
glVertex3f(50.f, -50.f, -50.f);
|
|
|
|
glTexCoord3f(-50.f, -50.f, -50.f);
|
|
|
|
glVertex3f(-50.f, -50.f, -50.f);
|
|
|
|
glTexCoord3f(-50.f, -50.f, 50.f);
|
|
|
|
glVertex3f(-50.f, -50.f, 50.f);
|
|
|
|
|
|
|
|
/* east */
|
|
|
|
glTexCoord3f(50.f, -50.f, 50.f);
|
|
|
|
glVertex3f(50.f, -50.f, 50.f);
|
|
|
|
glTexCoord3f(50.f, 50.f, 50.f);
|
|
|
|
glVertex3f(50.f, 50.f, 50.f);
|
|
|
|
glTexCoord3f(50.f, 50.f, -50.f);
|
|
|
|
glVertex3f(50.f, 50.f, -50.f);
|
|
|
|
glTexCoord3f(50.f, -50.f, -50.f);
|
|
|
|
glVertex3f(50.f, -50.f, -50.f);
|
|
|
|
|
|
|
|
/* west */
|
|
|
|
glTexCoord3f(-50.f, -50.f, 50.f);
|
|
|
|
glVertex3f(-50.f, -50.f, 50.f);
|
|
|
|
glTexCoord3f(-50.f, -50.f, -50.f);
|
|
|
|
glVertex3f(-50.f, -50.f, -50.f);
|
|
|
|
glTexCoord3f(-50.f, 50.f, -50.f);
|
|
|
|
glVertex3f(-50.f, 50.f, -50.f);
|
|
|
|
glTexCoord3f(-50.f, 50.f, 50.f);
|
|
|
|
glVertex3f(-50.f, 50.f, 50.f);
|
|
|
|
|
|
|
|
/* north */
|
|
|
|
glTexCoord3f(-50.f, -50.f, 50.f);
|
|
|
|
glVertex3f(-50.f, -50.f, 50.f);
|
|
|
|
glTexCoord3f(-50.f, 50.f, 50.f);
|
|
|
|
glVertex3f(-50.f, 50.f, 50.f);
|
|
|
|
glTexCoord3f(50.f, 50.f, 50.f);
|
|
|
|
glVertex3f(50.f, 50.f, 50.f);
|
|
|
|
glTexCoord3f(50.f, -50.f, 50.f);
|
|
|
|
glVertex3f(50.f, -50.f, 50.f);
|
|
|
|
|
|
|
|
/* south */
|
|
|
|
glTexCoord3f(-50.f, -50.f, -50.f);
|
|
|
|
glVertex3f(-50.f, -50.f, -50.f);
|
|
|
|
glTexCoord3f(50.f, -50.f, -50.f);
|
|
|
|
glVertex3f(50.f, -50.f, -50.f);
|
|
|
|
glTexCoord3f(50.f, 50.f, -50.f);
|
|
|
|
glVertex3f(50.f, 50.f, -50.f);
|
|
|
|
glTexCoord3f(-50.f, 50.f, -50.f);
|
|
|
|
glVertex3f(-50.f, 50.f, -50.f);
|
|
|
|
} glEnd();
|
|
|
|
|
|
|
|
glDisable(GL_TEXTURE_CUBE_MAP);
|
|
|
|
|
|
|
|
} glEndList();
|
|
|
|
}
|
2024-09-26 18:02:56 +00:00
|
|
|
|
2024-10-01 11:58:00 +00:00
|
|
|
glCallList(list);
|
2024-09-26 18:02:56 +00:00
|
|
|
}
|