#load "chunk"
#load "config"
#load "input"
+#load "logger"
#load "main"
#load "physics"
#load "player"
-#load "shader"
#load "utils"
#load "vecmath"
#load "world"
#load "gfx/font"
#load "gfx/immediate"
#load "gfx/mesh"
-// #load "gfx/shader"
+#load "gfx/shader"
#load "gfx/texture"
#load "gfx/ui"
#local block_texture: Texture;
chunk_draw :: (chunk: ^Chunk) {
if block_texture.filename.data == null {
- block_texture = texture_make(#cstr "assets/textures/block.png");
+ block_texture', _ := texture_lookup("assets/textures/block.png");
}
texture_use(^block_texture);
vertex_count = 0;
rendering_type = .Plain;
+ immediate_mesh.primitive = GL_TRIANGLES;
}
immediate_clear :: (color: Color) {
vertex_data[vertex_count] = .{ .{x, y}, .{t_x, t_y}, immediate_color };
}
+immediate_line :: (x1, y1, x2, y2: f32) {
+ if vertex_count >= Maximum_Vertex_Count do immediate_flush();
+ set_rendering_type(.Line);
+ immediate_mesh.primitive = GL_LINES;
+
+ vertex_data[vertex_count + 0] = .{ .{x1, y1}, .{0, 0}, immediate_color };
+ vertex_data[vertex_count + 1] = .{ .{x2, y2}, .{0, 0}, immediate_color };
+ vertex_count += 2;
+}
+
immediate_triangle :: (x1, x2, x3: Vector2) {
if vertex_count + 3 > Maximum_Vertex_Count do immediate_flush();
set_rendering_type(.Plain);
scissors << .{x, y, w, h};
glEnable(GL_SCISSOR_TEST);
- glScissor(~~x, ~~(window_height - (y + h)), ~~w, ~~h);
+ glScissor(~~x, ~~(window_height - ~~(y + h)), ~~w, ~~h);
}
immediate_pop_scissor :: () {
Rendering_Type :: enum {
Plain;
+ Line;
Image;
}
rendering_type := Rendering_Type.Plain;
glBufferData(GL_UNIFORM_BUFFER, sizeof f32 * 16, null, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, world_matrix_block_buffer);
- glBufferData(GL_UNIFORM_BUFFER, sizeof f32 * (16 + 16), null, GL_DYNAMIC_DRAW);
+ glBufferData(GL_UNIFORM_BUFFER, sizeof f32 * (16 + 16 + 16), null, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, -1);
glBindBufferBase(GL_UNIFORM_BUFFER, WORLD_MATRIX_BLOCK, world_matrix_block_buffer);
}
-shader_make :: (shader_path: str) -> Shader {
- shader_source := os.get_contents(shader_path);
- vs := compile_shader(shader_source, GL_VERTEX_SHADER);
- fs := compile_shader(shader_source, GL_FRAGMENT_SHADER);
+shader_make :: (path: str) -> Shader {
+ shader := os.get_contents(path);
+ vs := compile_shader(shader, GL_VERTEX_SHADER);
+ fs := compile_shader(shader, GL_FRAGMENT_SHADER);
prog := link_program(vs, fs);
}
update_view_matrix :: () {
- matrix : [16] f32;
- top := 0.0f;
- left := 0.0f;
- right := cast(f32) window_width;
- bottom := cast(f32) window_height;
- far := 10.0f;
- near := 0f;
-
- matrix[0] = 2 / (right - left);
- matrix[5] = 2 / (top - bottom);
- matrix[10] = -2 / (far - near);
- matrix[12] = -(right + left) / (right - left);
- matrix[13] = -(top + bottom) / (top - bottom);
- matrix[14] = -(far + near) / (far - near);
- matrix[15] = 1;
+ view_mat: [16] f32;
+ camera_get_view_matrix(^camera, view_mat);
- glBindBuffer(GL_UNIFORM_BUFFER, window_matrix_block_buffer);
- glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof typeof matrix, ^matrix);
+ glBindBuffer(GL_UNIFORM_BUFFER, world_matrix_block_buffer);
+ glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof typeof view_mat, ^view_mat);
glBindBuffer(GL_UNIFORM_BUFFER, -1);
}
update_world_matrix :: () {
world_mat: [16] f32;
- world_mat[0] = 1;
- world_mat[5] = 1;
- world_mat[10] = 1;
- world_mat[15] = 1;
+ camera_get_world_matrix(^camera, world_mat);
glBindBuffer(GL_UNIFORM_BUFFER, world_matrix_block_buffer);
- glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof typeof world_mat, ^world_mat);
+ glBufferSubData(GL_UNIFORM_BUFFER, 16 * sizeof f32, sizeof typeof world_mat, ^world_mat);
+ glBindBuffer(GL_UNIFORM_BUFFER, -1);
+}
+
+update_window_matrix :: () {
+ window_mat: [16] f32;
+ camera_get_window_matrix(^camera, window_mat);
+
+ glBindBuffer(GL_UNIFORM_BUFFER, window_matrix_block_buffer);
+ glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof typeof window_mat, ^window_mat);
glBindBuffer(GL_UNIFORM_BUFFER, -1);
}
-update_model_matrix :: (v: Vector2) {
+update_model_matrix :: (v: Vector3) {
model_mat: [16] f32;
model_mat[0] = 1;
model_mat[5] = 1;
model_mat[10] = 1;
model_mat[12] = v.x;
model_mat[13] = v.y;
- model_mat[14] = 0;
+ model_mat[14] = v.z;
model_mat[15] = 1;
glBindBuffer(GL_UNIFORM_BUFFER, world_matrix_block_buffer);
- glBufferSubData(GL_UNIFORM_BUFFER, 16 * sizeof f32, sizeof typeof model_mat, ^model_mat);
+ glBufferSubData(GL_UNIFORM_BUFFER, 32 * sizeof f32, sizeof typeof model_mat, ^model_mat);
glBindBuffer(GL_UNIFORM_BUFFER, -1);
}
use package core
+use package core.intrinsics.onyx { __zero_value as Zero }
use package opengles
use package stb_image
+#local texture_cache: Map(str, Texture);
+
Texture :: struct {
texture: GLint;
width, height, channels: i32;
filename: str;
}
-texture_make :: (path: cstr) -> Texture {
+texture_lookup :: #match {}
+#match texture_lookup (filename: str) -> (Texture, bool) {
+ if texture_cache->has(filename) {
+ return texture_cache[filename], true;
+ }
+
+ buffer: [512] u8;
+ memory.copy(~~ buffer, filename.data, math.min(filename.count, 511));
+ return texture_lookup(cast(cstr) buffer);
+}
+
+#match texture_lookup (path: cstr) -> (Texture, bool) {
+ filename := string.from_cstr(path);
+ if texture_cache->has(filename) {
+ return texture_cache[filename], true;
+ }
+
tex: Texture;
- tex.filename = path |> string.from_cstr();
+ tex.filename = filename;
pixels := stbi_load(path, ^tex.width, ^tex.height, ^tex.channels, 4);
- assert(pixels != null, "Failed to load texture.");
+ if pixels == null {
+ debug_log(.Warning, "Failed to load texture: {}", filename);
+ return Zero(Texture), false;
+ }
defer stbi_image_free(pixels);
glGenTextures(1, ^tex.texture);
glBindTexture(GL_TEXTURE_2D, 0);
- return tex;
+ // This assumes that the filename data is going to be persistant forever.
+ // Not a great assumption to make but is it really worth copying it?
+ texture_cache[filename] = tex;
+ debug_log(.Info, "Loaded texture: {}", filename);
+ return tex, true;
+}
+
+texture_free :: (use tex: ^Texture) {
+ glDeleteTextures(1, ^texture);
}
texture_use :: (use tex: ^Texture, texture_binding := 0) {
glActiveTexture(GL_TEXTURE0 + texture_binding);
glBindTexture(GL_TEXTURE_2D, texture);
}
-
--- /dev/null
+//
+// This may become an in-game or external file logger in the future,
+// but for now this is just for logging to the command line.
+
+use package core
+
+Log_Level :: enum {
+ Debug;
+ Info;
+ Warning;
+ Error;
+ Critical;
+}
+
+debug_log :: (level: Log_Level, format: str, args: ..any) {
+ debug_log_va(level, format, ~~args);
+}
+
+debug_log_va :: (level: Log_Level, format: str, args: [] any) {
+ buf: [2048] u8;
+ output := conv.format_va(buf, format, args);
+ printf("[{}] {}\n", level_string(level), output);
+}
+
+#local level_string :: (level: Log_Level) => {
+ switch level {
+ case .Debug do return "DEBUG";
+ case .Info do return "INFO ";
+ case .Warning do return "WARN ";
+ case .Error do return "ERROR";
+ case .Critical do return "CRIT ";
+ }
+
+ return " ";
+}
+++ /dev/null
-
-use package core
-use package opengles
-
-Shader :: struct {
- vs, fs: GLuint;
- prog: GLuint;
-}
-
-window_matrix_block_buffer: GLuint;
-world_matrix_block_buffer: GLuint;
-
-shaders_init :: () {
- glGenBuffers(1, ^window_matrix_block_buffer);
- glGenBuffers(1, ^world_matrix_block_buffer);
-
- glBindBuffer(GL_UNIFORM_BUFFER, window_matrix_block_buffer);
- glBufferData(GL_UNIFORM_BUFFER, sizeof f32 * 16, null, GL_DYNAMIC_DRAW);
-
- glBindBuffer(GL_UNIFORM_BUFFER, world_matrix_block_buffer);
- glBufferData(GL_UNIFORM_BUFFER, sizeof f32 * (16 + 16 + 16), null, GL_DYNAMIC_DRAW);
-
- glBindBuffer(GL_UNIFORM_BUFFER, -1);
-
- glBindBufferBase(GL_UNIFORM_BUFFER, WINDOW_MATRIX_BLOCK, window_matrix_block_buffer);
- glBindBufferBase(GL_UNIFORM_BUFFER, WORLD_MATRIX_BLOCK, world_matrix_block_buffer);
-}
-
-shader_make :: (path: str) -> Shader {
- shader := os.get_contents(path);
- vs := compile_shader(shader, GL_VERTEX_SHADER);
- fs := compile_shader(shader, GL_FRAGMENT_SHADER);
-
- prog := link_program(vs, fs);
-
- return Shader.{vs, fs, prog};
-}
-
-shader_use :: (shader: Shader) {
- glUseProgram(shader.prog);
-}
-
-#local {
- WINDOW_MATRIX_BLOCK :: 0;
- WORLD_MATRIX_BLOCK :: 1;
-}
-
-shader_link_window_matrix_block :: (use shader: Shader) {
- matrix_block_index := glGetUniformBlockIndex(prog, #cstr "u_window_matrix_block");
- glUniformBlockBinding(prog, matrix_block_index, WINDOW_MATRIX_BLOCK);
-}
-
-shader_link_world_matrix_block :: (use shader: Shader) {
- matrix_block_index := glGetUniformBlockIndex(prog, #cstr "u_world_matrix_block");
- glUniformBlockBinding(prog, matrix_block_index, WORLD_MATRIX_BLOCK);
-}
-
-shader_set_uniform :: (shader: Shader, uniform: cstr, value: $T) {
- glUseProgram(shader.prog);
- location := glGetUniformLocation(shader.prog, uniform);
-
- set_uniform_internal(location, value);
-
- set_uniform_internal :: #match {
- macro (location: GLint, value: u32) do glUniform1i(location, value); ,
- macro (location: GLint, value: f32) do glUniform1f(location, value); ,
- macro (location: GLint, value: Vector3) do glUniform3f(location, value.x, value.y, value.z); ,
- macro (location: GLint, value: Color) do glUniform4f(location, value.r, value.g, value.b, value.a); ,
-
- macro (location: GLint, value: $T) {
- buffer: [1024] u8;
- assert(false, conv.format(buffer, "Bad shader_set_uniform case: {}", T));
- }
- }
-}
-
-update_view_matrix :: () {
- view_mat: [16] f32;
- camera_get_view_matrix(^camera, view_mat);
-
- glBindBuffer(GL_UNIFORM_BUFFER, world_matrix_block_buffer);
- glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof typeof view_mat, ^view_mat);
- glBindBuffer(GL_UNIFORM_BUFFER, -1);
-}
-
-update_world_matrix :: () {
- world_mat: [16] f32;
- camera_get_world_matrix(^camera, world_mat);
-
- glBindBuffer(GL_UNIFORM_BUFFER, world_matrix_block_buffer);
- glBufferSubData(GL_UNIFORM_BUFFER, 16 * sizeof f32, sizeof typeof world_mat, ^world_mat);
- glBindBuffer(GL_UNIFORM_BUFFER, -1);
-}
-
-update_window_matrix :: () {
- window_mat: [16] f32;
- camera_get_window_matrix(^camera, window_mat);
-
- glBindBuffer(GL_UNIFORM_BUFFER, window_matrix_block_buffer);
- glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof typeof window_mat, ^window_mat);
- glBindBuffer(GL_UNIFORM_BUFFER, -1);
-}
-
-update_model_matrix :: (v: Vector3) {
- model_mat: [16] f32;
- model_mat[0] = 1;
- model_mat[5] = 1;
- model_mat[10] = 1;
- model_mat[12] = v.x;
- model_mat[13] = v.y;
- model_mat[14] = v.z;
- model_mat[15] = 1;
-
- glBindBuffer(GL_UNIFORM_BUFFER, world_matrix_block_buffer);
- glBufferSubData(GL_UNIFORM_BUFFER, 32 * sizeof f32, sizeof typeof model_mat, ^model_mat);
- glBindBuffer(GL_UNIFORM_BUFFER, -1);
-}
-
-
-#local {
- compile_shader :: (source: str, type: GLenum) -> GLint {
- shader := glCreateShader(type);
-
- #persist VERTEX_HEADER := """
-#version 300 es
-#define VERTEX_SHADER 1
-#define COMM out
- """;
-
- #persist FRAGMENT_HEADER := """
-#version 300 es
-#define FRAGMENT_SHADER 1
-#define COMM in
- """;
-
- header := VERTEX_HEADER if type == GL_VERTEX_SHADER else FRAGMENT_HEADER;
- sources : [] ^u8 = .[ header.data, source.data ];
- source_lens : [] i32 = .[ header.count, source.count ];
-
- glShaderSource(shader, 2, sources.data, source_lens.data);
- glCompileShader(shader);
-
- success: GLint;
- if glGetShaderiv(shader, GL_COMPILE_STATUS, ^success); success == GL_FALSE {
- buf_data: [2048] u8;
- buf := str.{ ~~buf_data, 0 };
- glGetShaderInfoLog(shader, 2048, ^buf.count, buf.data);
- println(buf);
- }
-
- return shader;
- }
-
- link_program :: (vertex_shader, fragment_shader: GLint) -> GLuint {
- prog := glCreateProgram();
- glAttachShader(prog, vertex_shader);
- glAttachShader(prog, fragment_shader);
- glLinkProgram(prog);
-
- success: GLint;
- if glGetProgramiv(prog, GL_LINK_STATUS, ^success); success == GL_FALSE {
- buf_data: [1024] u8;
- buf := str.{ ~~buf_data, 0 };
- glGetProgramInfoLog(prog, 1024, ^buf.count, buf.data);
- println(buf);
- }
-
- return prog;
- }
-}
-