229 lines
6.1 KiB
C
229 lines
6.1 KiB
C
#include "renderer.h"
|
|
#include "bitmaps.h"
|
|
|
|
static SDL_Window *window;
|
|
static renderer_state renderer;
|
|
|
|
|
|
|
|
void r_resize(int width, int height)
|
|
{
|
|
glViewport(0, 0, width, height);
|
|
}
|
|
|
|
v4 extract_color_v4_from_u32(uint32_t in)
|
|
{
|
|
v4 result;
|
|
result.x = ((in >> 24) & 0xFF) / 255.0f;
|
|
result.y = ((in >> 16) & 0xFF) / 255.0f;
|
|
result.z = ((in >> 8) & 0xFF) / 255.0f;
|
|
result.w = ((in >> 0) & 0xFF) / 255.0f;
|
|
return result;
|
|
}
|
|
|
|
void r_make_draw_call(int num_of_elements, uint32_t color)
|
|
{
|
|
v4 uniform_color = extract_color_v4_from_u32(color);
|
|
|
|
|
|
GLint texture_location = glGetUniformLocation(renderer.shader_program, "texture1");
|
|
glUniform1i(texture_location, 0);
|
|
GLint color_location = glGetUniformLocation(renderer.shader_program, "color");
|
|
glUniform4f(color_location, uniform_color.x, uniform_color.y, uniform_color.z, uniform_color.w);
|
|
|
|
|
|
|
|
glBindVertexArray(renderer.vao);
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, renderer.vbo);
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, renderer.ebo);
|
|
|
|
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(render_target), (void *)(0));
|
|
glEnableVertexAttribArray(0);
|
|
|
|
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(render_target), (void *)(sizeof(v2)));
|
|
glEnableVertexAttribArray(1);
|
|
|
|
glUseProgram(renderer.shader_program);
|
|
|
|
glBindVertexArray(renderer.vao);
|
|
|
|
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
|
glDrawElements(GL_TRIANGLES, num_of_elements, GL_UNSIGNED_INT, 0);
|
|
}
|
|
|
|
void r_draw_text(char *text, float x, float y, uint32_t color, float scaler)
|
|
{
|
|
v2 pos = { .x = x, .y = y };
|
|
size_t size = strlen(text);
|
|
|
|
size_t vert_memory_size = sizeof(render_target) * size * 4;
|
|
size_t indx_memory_size = sizeof(int) * size * 6;
|
|
|
|
render_target *verts = alloca( vert_memory_size );
|
|
unsigned int *indexes = alloca( indx_memory_size );
|
|
|
|
int last_vert = 0;
|
|
int last_index = 0;
|
|
|
|
for (int index = 0; index < size; ++index)
|
|
{
|
|
char c = text[index];
|
|
if(c == '\n')
|
|
{
|
|
pos.x = x;
|
|
pos.y -= (25 * scaler) / ASCII_HEIGHT;
|
|
continue;
|
|
}
|
|
|
|
font_info char_info = base_font_info[c - ' '];
|
|
|
|
|
|
float c_width = char_info.width * scaler;
|
|
float c_height = char_info.height * scaler;
|
|
|
|
v2 t1 = { .x = char_info.pos.x, .y = 1 - char_info.pos.y };
|
|
v2 t2 = { .x = t1.x + char_info.width, .y = t1.y - char_info.height };
|
|
|
|
v2 p1 = { .x = pos.x, .y = pos.y };
|
|
v2 p2 = { .x = p1.x + c_width, .y = p1.y + c_height };
|
|
|
|
p1.y += ((25*scaler) / ASCII_HEIGHT) - (c_height + char_info.y_offset * scaler);
|
|
p2.y += ((25*scaler) / ASCII_HEIGHT) - (c_height + char_info.y_offset * scaler);
|
|
|
|
int vert_offset = last_vert;
|
|
|
|
|
|
verts[last_vert++] = (render_target){ p1.x, p1.y, t1.x, t2.y };
|
|
verts[last_vert++] = (render_target){ p2.x, p1.y, t2.x, t2.y };
|
|
verts[last_vert++] = (render_target){ p2.x, p2.y, t2.x, t1.y };
|
|
verts[last_vert++] = (render_target){ p1.x, p2.y, t1.x, t1.y };
|
|
|
|
indexes[last_index++] = 0 + vert_offset;
|
|
indexes[last_index++] = 1 + vert_offset;
|
|
indexes[last_index++] = 2 + vert_offset;
|
|
indexes[last_index++] = 0 + vert_offset;
|
|
indexes[last_index++] = 2 + vert_offset;
|
|
indexes[last_index++] = 3 + vert_offset;
|
|
|
|
|
|
pos.x += c_width + 15 / ASCII_WIDTH;
|
|
}
|
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, renderer.vbo);
|
|
glBufferSubData(GL_ARRAY_BUFFER, 0, last_vert * sizeof(render_target), verts);
|
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, renderer.ebo);
|
|
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, last_index * sizeof(int), indexes);
|
|
|
|
r_make_draw_call(last_index, color);
|
|
}
|
|
|
|
void r_present(void)
|
|
{
|
|
SDL_GL_SwapWindow(window);
|
|
}
|
|
|
|
void r_compile_shaders(void)
|
|
{
|
|
GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
|
|
GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
|
|
|
|
glShaderSource(vertex_shader, 1, &vertex_shader_src, 0);
|
|
glShaderSource(fragment_shader, 1, &fragment_shader_src, 0);
|
|
|
|
glCompileShader(vertex_shader);
|
|
glCompileShader(fragment_shader);
|
|
|
|
int success;
|
|
char info_log[512] = {0};
|
|
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
|
|
if(!success)
|
|
{
|
|
glGetShaderInfoLog(vertex_shader, 512, NULL, info_log);
|
|
fprintf(stderr, info_log);
|
|
exit(1);
|
|
}
|
|
|
|
|
|
glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
|
|
if(!success)
|
|
{
|
|
glGetShaderInfoLog(fragment_shader, 512, NULL, info_log);
|
|
fprintf(stderr, info_log);
|
|
exit(1);
|
|
}
|
|
|
|
renderer.shader_program = glCreateProgram();
|
|
glAttachShader(renderer.shader_program, vertex_shader);
|
|
glAttachShader(renderer.shader_program, fragment_shader);
|
|
glLinkProgram(renderer.shader_program);
|
|
glUseProgram(renderer.shader_program);
|
|
|
|
glGetProgramiv(renderer.shader_program, GL_LINK_STATUS, &success);
|
|
if(!success)
|
|
{
|
|
glGetProgramInfoLog(renderer.shader_program, 512, NULL, info_log);
|
|
fprintf(stderr, info_log);
|
|
exit(1);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void r_init(init_info info)
|
|
{
|
|
/* Create window and context */
|
|
window = SDL_CreateWindow("Template Window",
|
|
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
|
|
info.width, info.height,
|
|
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
|
|
SDL_GL_CreateContext(window);
|
|
assert(gladLoadGLLoader(SDL_GL_GetProcAddress));
|
|
|
|
/* Initialize OpenGL */
|
|
glEnable(GL_BLEND);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
glDisable(GL_CULL_FACE);
|
|
glDisable(GL_DEPTH_TEST);
|
|
glEnable(GL_SCISSOR_TEST);
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
|
|
r_compile_shaders();
|
|
|
|
/* Set-up GL buffers */
|
|
glGenVertexArrays(1, &renderer.vao);
|
|
glGenBuffers(1, &renderer.vbo);
|
|
glGenBuffers(1, &renderer.ebo);
|
|
|
|
glBindVertexArray(renderer.vao);
|
|
|
|
// 10 MB
|
|
glBindBuffer(GL_ARRAY_BUFFER, renderer.vbo);
|
|
glBufferData(GL_ARRAY_BUFFER, 10*1024*1024, NULL, GL_STREAM_DRAW);
|
|
|
|
// 10 MB
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, renderer.ebo);
|
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 10*1024*1024, NULL, GL_STREAM_DRAW);
|
|
|
|
GLuint id;
|
|
glGenTextures(1, &id);
|
|
glActiveTexture(GL_TEXTURE0);
|
|
glBindTexture(GL_TEXTURE_2D, id);
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ASCII_WIDTH, ASCII_HEIGHT, 0,
|
|
GL_RGBA, GL_UNSIGNED_BYTE, ascii_characters);
|
|
assert(glGetError() == 0);
|
|
|
|
r_resize(info.width, info.height);
|
|
}
|
|
|
|
|
|
|