--- /dev/null
+#version 300 es
+precision mediump float;
+
+in vec4 v_col;
+in vec2 v_tex;
+
+uniform sampler2D u_texture;
+
+out vec4 fragColor;
+
+void main() {
+ fragColor = v_col;
+}
--- /dev/null
+#version 300 es
+precision mediump float;
+layout(location = 0) in vec2 a_pos;
+layout(location = 1) in vec2 a_tex;
+layout(location = 2) in vec4 a_col;
+
+layout(std140) uniform u_window_matrix_block {
+ mat4 u_window;
+};
+
+out vec4 v_col;
+out vec2 v_tex;
+
+void main() {
+ gl_Position = u_window * vec4(a_pos, 0, 1);
+ v_tex = a_tex;
+ v_col = a_col;
+}
\ No newline at end of file
#load "chunk"
#load "config"
#load "font"
+#load "imgui"
#load "input"
#load "main"
#load "mesh"
shader_use(font_shader);
shader_set_uniform(font_shader, #cstr "u_texture", 0);
+ glDisable(GL_DEPTH_TEST);
glBindVertexArray(font_vao);
glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, ~~0, quad_num);
glBindTexture(GL_TEXTURE_2D, -1);
glBindVertexArray(-1);
+ glEnable(GL_DEPTH_TEST);
}
--- /dev/null
+
+use package core
+use package opengles
+use package glfw3
+
+immediate_init :: () {
+ memory.alloc_slice(^vertex_data, Maximum_Vertex_Count);
+ vertex_count = 0;
+
+ imgui_shader = shader_make(Shader_Vertex_Path, Shader_Fragment_Path);
+ shader_use(imgui_shader);
+ shader_link_window_matrix_block(imgui_shader);
+
+ immediate_mesh = mesh_make(vertex_data, .[], GL_DYNAMIC_DRAW);
+}
+
+immediate_flush :: () {
+ if vertex_count == 0 do return;
+
+ immediate_mesh.vertex_count = vertex_count;
+ mesh_update_verticies(immediate_mesh, vertex_data);
+
+ shader_use(imgui_shader);
+ glDisable(GL_DEPTH_TEST);
+ mesh_draw(immediate_mesh);
+ glEnable(GL_DEPTH_TEST);
+
+ vertex_count = 0;
+}
+
+immediate_vertex :: (position: Vector2, texture := Vector2.{0,0}, color := Color.{1,1,1}) {
+ if vertex_count >= Maximum_Vertex_Count do immediate_flush();
+
+ vertex_data[vertex_count] = .{ position, texture, color };
+}
+
+immediate_triangle :: (x1, x2, x3: Vector2, color := Color.{1,1,1}) {
+ if vertex_count + 3 > Maximum_Vertex_Count do immediate_flush();
+
+ vertex_data[vertex_count + 0] = .{ x1, .{0,0}, color };
+ vertex_data[vertex_count + 1] = .{ x2, .{0,0}, color };
+ vertex_data[vertex_count + 2] = .{ x3, .{0,0}, color };
+ vertex_count += 3;
+}
+
+immediate_rectangle :: (top_left: Vector2, size: Vector2, color := Color.{1,1,1}) {
+ if vertex_count + 6 > Maximum_Vertex_Count do immediate_flush();
+
+ vertex_data[vertex_count + 0] = .{ top_left, .{0,0}, color };
+ vertex_data[vertex_count + 1] = .{ top_left + .{size.x,0}, .{0,0}, color };
+ vertex_data[vertex_count + 2] = .{ top_left + .{size.x,size.y}, .{0,0}, color };
+ vertex_data[vertex_count + 3] = .{ top_left, .{0,0}, color };
+ vertex_data[vertex_count + 4] = .{ top_left + .{size.x,size.y}, .{0,0}, color };
+ vertex_data[vertex_count + 5] = .{ top_left + .{0,size.y}, .{0,0}, color };
+ vertex_count += 6;
+}
+
+immediate_image :: () {}
+
+immediate_ellipse :: () {}
+
+Color :: struct {
+ r, g, b : f32;
+ a := 1.0f;
+}
+
+Immediate_Vertex :: struct {
+ pos: Vector2;
+ tex: Vector2;
+ color: Color;
+}
+
+#local {
+ Shader_Vertex_Path :: "./assets/shaders/imgui_vertex.glsl"
+ Shader_Fragment_Path :: "./assets/shaders/imgui_fragment.glsl"
+ imgui_shader: Shader;
+
+ Maximum_Vertex_Count :: 1023;
+ vertex_count: i32;
+ vertex_data: [] Immediate_Vertex;
+
+ immediate_mesh: ^Mesh(Immediate_Vertex);
+}
shader_set_uniform(world_shader, #cstr "u_fog_start", 40.0f);
shader_set_uniform(world_shader, #cstr "u_fog_range", 5.0f);
+ immediate_init();
+
font = font_lookup(.{"./assets/fonts/calibri.ttf", 32});
shader_use(world_shader);
font_print(font, ~~(ww / 2), ~~(wh / 2), ".");
if debug_screen {
+ immediate_rectangle(.{0, 0}, .{528, 220}, .{1, 0, 1, 0.5});
+ immediate_flush();
+
player_chunk := world_position_to_chunk(world, player.body.pos);
font_print(font, 0, 32, "FPS: {}", game_fps);
font_print(font, 0, 64, "Position: {}", camera.position);
primitive: GLuint = GL_TRIANGLES;
}
-mesh_make :: (verticies: [] $T, indicies: [] u32) -> ^Mesh(T) {
+mesh_make :: (verticies: [] $T, indicies: [] u32, gl_hint := GL_STATIC_DRAW) -> ^Mesh(T) {
mesh := new(Mesh(T));
mesh.vertex_count = verticies.count;
mesh.index_count = indicies.count;
glGenBuffers(1, ^mesh.vertex_handle);
glBindBuffer(GL_ARRAY_BUFFER, mesh.vertex_handle);
- glBufferData(GL_ARRAY_BUFFER, sizeof T * verticies.count, verticies.data, GL_STATIC_DRAW);
+ glBufferData(GL_ARRAY_BUFFER, sizeof T * verticies.count, verticies.data, gl_hint);
vertex_info := cast(^type_info.Type_Info_Struct) type_info.get_type_info(T);
vertex_attr := 0;
case Vector3 do glVertexAttribPointer(vertex_attr, 3, GL_FLOAT, false, sizeof T, ~~attr.offset);
case u32 do glVertexAttribIPointer(vertex_attr, 1, GL_UNSIGNED_INT, sizeof T, ~~attr.offset);
case i32 do glVertexAttribIPointer(vertex_attr, 1, GL_INT, sizeof T, ~~attr.offset);
+
+ // It would be nice to not have to have all the cases here.
+ // Instead allow for an extensible way of defining them at compile time.
+ case Color do glVertexAttribPointer(vertex_attr, 4, GL_FLOAT, false, sizeof T, ~~attr.offset);
+
case #default {
buf: [256] u8;
msg := conv.str_format(buf, "Unknown type for GL vertex attribute, {}.", attr.type);
if indicies.count > 0 {
glGenBuffers(1, ^mesh.index_handle);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.index_handle);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof i32 * indicies.count, indicies.data, GL_STATIC_DRAW);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof i32 * indicies.count, indicies.data, gl_hint);
}
glBindVertexArray(-1);
}
}
+#operator + macro (v1, v2: Vector2) => (typeof v1).{ v1.x + v2.x, v1.y + v2.y };
+#operator - macro (v1, v2: Vector2) => Vector2.{ v1.x - v2.x, v1.y - v2.y };
+#operator * macro (v: Vector2, s: f32) => Vector2.{ v.x * s, v.y * s };
+#operator == macro (v1, v2: Vector2) => v1.x == v2.x && v1.y == v2.y;
+
#operator + macro (v1, v2: Vector3) => Vector3.{ v1.x + v2.x, v1.y + v2.y, v1.z + v2.z };
#operator - macro (v1, v2: Vector3) => Vector3.{ v1.x - v2.x, v1.y - v2.y, v1.z - v2.z };
#operator * macro (v: Vector3, s: f32) => Vector3.{ v.x * s, v.y * s, v.z * s };
// should be a special case for parsing this? I've always hated how parsing
// inside of a #match block works.
//
- (world: ^World, v: Vector3i) -> #auto { return world_get_chunk(world, v.x, v.y, v.z); },
(world: ^World, x, y, z: i32) -> ^Chunk {
d := world.chunk_dist;
if iz < 0 || iz > 2 * world.chunk_dist do return null;
return world.chunks[ix * sl * sl + iy * sl + iz];
- }
+ },
+
+ (world: ^World, v: Vector3i) => world_get_chunk(world, v.x, v.y, v.z)
}
world_set_chunk :: #match {
if chunks_to_load.count > 0 {
chunk_to_load := chunks_to_load[0];
array.delete(^chunks_to_load, 0);
- printf("Loading {}\n", chunk_to_load);
world_load_chunk(world, chunk_to_load);
}
pz := cast(f64) t.z / 24;
n := perlin.noise(px, ~~(10 * seed), pz);
- l := perlin.noise(px, ~~(10 * seed + 6), pz);
- l = (math.clamp(math.abs(l), 0.2, 0.5) - 0.2) / 0.6 + 0.5;
+ l := perlin.noise(px, ~~(10 * seed), pz);
+ l = (math.clamp(math.max(0, l), 0.2, 0.5) - 0.2) / 0.6 + 0.5;
h := cast(i32) (n * 32 + 18);
h = math.max(h, 14);
if n < -0.9 do h += ~~((n + 0.9) * 4);