Shader gfx_shader_make_from_source(const char* vertex_src, const char* fragment_src);
+typedef struct ImmediateColor {
+ f32 r, g, b, a;
+} ImmediateColor;
+
typedef struct ImmediateVertex {
f32 x, y;
- f32 r, g, b, a;
f32 u, v;
+ ImmediateColor color;
} ImmediateVertex;
#define VERTEX_DATA_MAX_COUNT 1020
ImmediateVertex* vertex_data;
u32 vertex_count;
+ ImmediateColor current_color;
+
GLint vertex_array;
GLint vertex_buffer;
} ImmediateRenderer;
void gfx_immediate_renderer_init(ImmediateRenderer *ir);
+void gfx_immediate_renderer_flush(ImmediateRenderer *ir);
+void gfx_immediate_renderer_set_color(ImmediateRenderer *ir, ImmediateColor color);
+void gfx_immediate_renderer_push_vertex(ImmediateRenderer *ir, f32 x, f32 y, f32 u, f32 v);
+void gfx_immediate_renderer_push_triangle(ImmediateRenderer *ir,
+ f32 x1, f32 y1, f32 u1, f32 v1,
+ f32 x2, f32 y2, f32 u2, f32 v2,
+ f32 x3, f32 y3, f32 u3, f32 v3);
+void gfx_immediate_renderer_update_window_size(ImmediateRenderer *ir, f32 width, f32 height);
#endif
\ No newline at end of file
#include "gfx.h"
+#include "utils.h"
static const char* SIMPLE_SHADER_VERTEX = "#version 300 es\n"
+"precision mediump float;\n"
"layout(location = 0) in vec2 a_vertex;\n"
-"layout(location = 1) in vec4 a_color;\n"
-"layout(location = 2) in vec2 a_texture;\n"
+"layout(location = 1) in vec2 a_texture;\n"
+"layout(location = 2) in vec4 a_color;\n"
"\n"
"uniform mat4 u_view;\n"
"uniform mat4 u_world;\n"
static const char* SIMPLE_SHADER_FRAGMENT = "#version 300 es\n"
"precision mediump float;\n"
-"uniform sample2D u_texture;\n"
-"\n"
"in vec4 v_color;\n"
"in vec2 v_texture;\n"
"\n"
+"uniform sampler2D u_texture;\n"
+"\n"
"out vec4 fragColor;\n"
"\n"
"void main() {\n"
static b32 compile_shader(GLuint shader_type, const char *src, GLuint *out_shader) {
GLuint s = glCreateShader(shader_type);
- glShaderSource(s, 1, src, NULL);
+ glShaderSource(s, 1, (const char * const *) &src, NULL);
glCompileShader(s);
GLint successful;
if (successful != GL_TRUE) {
GLsizei log_length = 0;
GLchar program_log[1024];
- glGetShaderInfoLog(s, 1023, &log_length, program_log);
+ glGetProgramInfoLog(program, 1023, &log_length, program_log);
bh_printf("Error linking program:\n%s\n", program_log);
return -1;
Shader shader;
shader.program = program;
- shader.position_loc = glGetAttribLocation(program, "a_position");
+ shader.position_loc = glGetAttribLocation(program, "a_vertex");
shader.color_loc = glGetAttribLocation(program, "a_color");
shader.texture_loc = glGetAttribLocation(program, "a_texture");
void gfx_immediate_renderer_init(ImmediateRenderer *ir) {
ir->vertex_allocator = bh_heap_allocator();
- ir->vertex_data = bh_alloc(ir->vertex_allocator, sizeof(ImmediateVertex) * VERTEX_DATA_MAX_COUN);
+ ir->vertex_data = bh_alloc(ir->vertex_allocator, sizeof(ImmediateVertex) * VERTEX_DATA_MAX_COUNT);
ir->vertex_count = 0;
ir->simple_shader = gfx_shader_make_from_source(SIMPLE_SHADER_VERTEX, SIMPLE_SHADER_FRAGMENT);
glBindBuffer(GL_ARRAY_BUFFER, ir->vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(ImmediateVertex) * VERTEX_DATA_MAX_COUNT, NULL, GL_STREAM_DRAW);
+ glEnableVertexAttribArray(ir->simple_shader.position_loc);
+ glEnableVertexAttribArray(ir->simple_shader.texture_loc);
+ glEnableVertexAttribArray(ir->simple_shader.color_loc);
+
+ glVertexAttribPointer(ir->simple_shader.position_loc, 2, GL_FLOAT, false, sizeof(ImmediateVertex), (void*) offsetof(ImmediateVertex, x));
+ glVertexAttribPointer(ir->simple_shader.texture_loc, 2, GL_FLOAT, false, sizeof(ImmediateVertex), (void*) offsetof(ImmediateVertex, u));
+ glVertexAttribPointer(ir->simple_shader.color_loc, 4, GL_FLOAT, false, sizeof(ImmediateVertex), (void*) offsetof(ImmediateVertex, color));
+ glBindBuffer(GL_ARRAY_BUFFER, -1);
+
+ glBindVertexArray(-1);
+
+ glUseProgram(ir->simple_shader.program);
+
+ static const f32 identity_matrix[] = {
+ 1,0,0,0,
+ 0,1,0,0,
+ 0,0,1,0,
+ 0,0,0,1
+ };
+
+ glUniformMatrix4fv(ir->simple_shader.view_uniform, 1, 0, identity_matrix);
+ glUniformMatrix4fv(ir->simple_shader.world_uniform, 1, 0, identity_matrix);
+
+ ir->current_color = (ImmediateColor) { 1, 1, 1, 1 };
+}
+
+void gfx_immediate_renderer_flush(ImmediateRenderer *ir) {
+ glBindBuffer(GL_ARRAY_BUFFER, ir->vertex_buffer);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(ImmediateVertex) * ir->vertex_count, ir->vertex_data);
+ glBindBuffer(GL_ARRAY_BUFFER, -1);
+
+ glUseProgram(ir->simple_shader.program);
+ glBindVertexArray(ir->vertex_array);
+ glDrawArrays(GL_TRIANGLES, 0, ir->vertex_count);
glBindVertexArray(-1);
+
+ ir->vertex_count = 0;
+}
+
+void gfx_immediate_renderer_set_color(ImmediateRenderer *ir, ImmediateColor color) {
+ ir->current_color = color;
+}
+
+void gfx_immediate_renderer_push_vertex(ImmediateRenderer *ir, f32 x, f32 y, f32 u, f32 v) {
+ ir->vertex_data[ir->vertex_count++] = (ImmediateVertex) { x, y, u, v, ir->current_color };
+}
+
+void gfx_immediate_renderer_push_triangle(ImmediateRenderer *ir,
+ f32 x1, f32 y1, f32 u1, f32 v1,
+ f32 x2, f32 y2, f32 u2, f32 v2,
+ f32 x3, f32 y3, f32 u3, f32 v3) {
+
+ if (ir->vertex_count - 3 >= VERTEX_DATA_MAX_COUNT) {
+ gfx_immediate_renderer_flush(ir);
+ }
+
+ assert(ir->vertex_count % 3 == 0); // Must be aligned to a triangle
+
+ ir->vertex_data[ir->vertex_count + 0] = (ImmediateVertex) { x1, y1, u1, v1, ir->current_color };
+ ir->vertex_data[ir->vertex_count + 1] = (ImmediateVertex) { x2, y2, u2, v2, ir->current_color };
+ ir->vertex_data[ir->vertex_count + 2] = (ImmediateVertex) { x3, y3, u3, v3, ir->current_color };
+ ir->vertex_count += 3;
+}
+
+void gfx_immediate_renderer_update_window_size(ImmediateRenderer *ir, f32 width, f32 height) {
+ f32 left = 0;
+ f32 right = width;
+ f32 top = 0;
+ f32 bottom = height;
+ f32 far = 100.0;
+ f32 near = 0.0;
+
+ f32 camera_matrix[] = {
+ 2 / (right - left), 0, 0, 0,
+ 0, 2 / (top - bottom), 0, 0,
+ 0, 0, -2 / (far - near), 0,
+ -(right + left) / (right - left), -(top + bottom) / (top - bottom), -(far + near) / (far - near), 1,
+ };
+
+ glUniformMatrix4fv(ir->simple_shader.view_uniform, 1, false, camera_matrix);
}
\ No newline at end of file