--- /dev/null
+#include "gfx.h"
+
+static const char* SIMPLE_SHADER_VERTEX = "#version 300 es\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"
+"\n"
+"uniform mat4 u_view;\n"
+"uniform mat4 u_world;\n"
+"\n"
+"out vec4 v_color;\n"
+"out vec2 v_texture;\n"
+"\n"
+"void main() {\n"
+" gl_Position = u_view * u_world * vec4(a_vertex, 0, 1);\n"
+" v_color = a_color;\n"
+" v_texture = a_texture;\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"
+"out vec4 fragColor;\n"
+"\n"
+"void main() {\n"
+" fragColor = v_color;\n"
+"}";
+
+static b32 compile_shader(GLuint shader_type, const char *src, GLuint *out_shader) {
+ GLuint s = glCreateShader(shader_type);
+
+ glShaderSource(s, 1, src, NULL);
+ glCompileShader(s);
+
+ GLint successful;
+ glGetShaderiv(s, GL_COMPILE_STATUS, &successful);
+ if (successful != GL_TRUE) {
+ GLsizei log_length = 0;
+ GLchar shader_log[1024];
+ glGetShaderInfoLog(s, 1023, &log_length, shader_log);
+
+ bh_printf("Error compiling shader:\n%s\n", shader_log);
+ return 0;
+ }
+
+ *out_shader = s;
+ return 1;
+}
+
+static GLuint link_program(GLuint vertex_shader, GLuint fragment_shader) {
+ GLuint program = glCreateProgram();
+ glAttachShader(program, vertex_shader);
+ glAttachShader(program, fragment_shader);
+ glLinkProgram(program);
+
+ GLuint successful;
+ glGetProgramiv(program, GL_LINK_STATUS, &successful);
+ if (successful != GL_TRUE) {
+ GLsizei log_length = 0;
+ GLchar program_log[1024];
+ glGetShaderInfoLog(s, 1023, &log_length, program_log);
+
+ bh_printf("Error linking program:\n%s\n", program_log);
+ return -1;
+ }
+
+ return program;
+}
+
+Shader gfx_shader_make_from_source(const char *vertex_src, const char *fragment_src) {
+ GLuint vertex_shader, fragment_shader;
+ compile_shader(GL_VERTEX_SHADER, vertex_src, &vertex_shader);
+ compile_shader(GL_FRAGMENT_SHADER, fragment_src, &fragment_shader);
+
+ GLuint program = link_program(vertex_shader, fragment_shader);
+
+ Shader shader;
+ shader.program = program;
+
+ shader.position_loc = glGetAttribLocation(program, "a_position");
+ shader.color_loc = glGetAttribLocation(program, "a_color");
+ shader.texture_loc = glGetAttribLocation(program, "a_texture");
+
+ shader.texture_uniform = glGetUniformLocation(program, "u_texture");
+ shader.view_uniform = glGetUniformLocation(program, "u_view");
+ shader.world_uniform = glGetUniformLocation(program, "u_world");
+
+ return shader;
+}
+
+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_count = 0;
+
+ ir->simple_shader = gfx_shader_make_from_source(SIMPLE_SHADER_VERTEX, SIMPLE_SHADER_FRAGMENT);
+
+ glGenVertexArrays(1, &ir->vertex_array);
+ glBindVertexArray(ir->vertex_array);
+
+ glGenBuffers(1, &ir->vertex_buffer);
+ glBindBuffer(GL_ARRAY_BUFFER, ir->vertex_buffer);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(ImmediateVertex) * VERTEX_DATA_MAX_COUNT, NULL, GL_STREAM_DRAW);
+
+ glBindVertexArray(-1);
+}
\ No newline at end of file