townengine/src/rendering/twn_gl_any_rendering.c

123 lines
3.4 KiB
C

#include "twn_gl_any_rendering_c.h"
#include "twn_draw_c.h"
#include "twn_engine_context_c.h"
#include <stb_ds.h>
#ifdef EMSCRIPTEN
#include <GLES2/gl2.h>
#else
#include <glad/glad.h>
#endif
void setup_viewport(int x, int y, int width, int height) {
glViewport(x, y, width, height);
}
VertexBuffer create_vertex_buffer(void) {
GLuint result;
glGenBuffers(1, &result);
return result;
}
void delete_vertex_buffer(VertexBuffer buffer) {
glDeleteBuffers(1, &buffer);
}
void specify_vertex_buffer(VertexBuffer buffer, void const *data, size_t bytes) {
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, bytes, data, GL_STREAM_DRAW);
}
VertexBuffer get_quad_element_buffer(void) {
static VertexBuffer buffer = 0;
/* it's only generated once at runtime */
/* TODO: use builder interface, not direct calls (glMapBuffer isn't portable) */
if (buffer == 0) {
buffer = create_vertex_buffer();
VertexBufferBuilder builder = build_vertex_buffer(buffer, sizeof (GLshort) * QUAD_ELEMENT_BUFFER_LENGTH * 6 );
for (size_t i = 0; i < QUAD_ELEMENT_BUFFER_LENGTH; ++i) {
GLshort indices[6];
indices[0] = (GLshort)(i * 4 + 0);
indices[1] = (GLshort)(i * 4 + 1);
indices[2] = (GLshort)(i * 4 + 2);
indices[3] = (GLshort)(i * 4 + 2);
indices[4] = (GLshort)(i * 4 + 3);
indices[5] = (GLshort)(i * 4 + 0);
push_to_vertex_buffer_builder(&builder, indices, sizeof indices);
}
}
SDL_assert_always(buffer);
return buffer;
}
VertexBuffer get_circle_element_buffer(void) {
static VertexBuffer buffer = 0;
if (buffer == 0) {
buffer = create_vertex_buffer();
VertexBufferBuilder builder = build_vertex_buffer(buffer, sizeof (GLshort) * (CIRCLE_VERTICES_MAX - 2) * 3);
for (size_t i = 1; i < CIRCLE_VERTICES_MAX - 1; ++i) {
/* first one is center point index, always zero */
GLshort indices[3];
indices[0] = 0;
/* generated point index */
indices[1] = (GLshort)i;
indices[2] = (GLshort)i + 1;
push_to_vertex_buffer_builder(&builder, indices, sizeof indices);
}
}
SDL_assert_always(buffer);
return buffer;
}
/* potentially double buffered array of vertex array handles */
/* we assume they will be refilled fully each frame */
static size_t scratch_va_front_used, scratch_va_back_used;
static GLuint *front_scratch_vertex_arrays, *back_scratch_vertex_arrays;
static GLuint **current_scratch_vertex_array = &front_scratch_vertex_arrays;
void restart_scratch_vertex_arrays(void) {
scratch_va_front_used = 0;
scratch_va_back_used = 0;
if (ctx.render_double_buffered) {
current_scratch_vertex_array = current_scratch_vertex_array == &front_scratch_vertex_arrays ?
&back_scratch_vertex_arrays : &front_scratch_vertex_arrays;
}
}
GLuint get_scratch_vertex_array(void) {
size_t *used = current_scratch_vertex_array == &front_scratch_vertex_arrays ?
&scratch_va_front_used : &scratch_va_back_used;
if (arrlenu(*current_scratch_vertex_array) <= *used) {
GLuint handle;
glGenBuffers(1, &handle);
arrpush(*current_scratch_vertex_array, handle);
}
(*used)++;
return (*current_scratch_vertex_array)[*used - 1];
}