templates/SDLOpenGL/code/renderer.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);
}