--- /dev/null
+precision mediump float;
+
+COMM vec4 v_col;
+
+#ifdef VERTEX_SHADER
+
+layout(location = 0) in vec2 a_pos;
+layout(location = 1) in vec4 a_col;
+
+layout(std140) uniform u_window_matrix_block {
+ mat4 u_view;
+};
+
+layout(std140) uniform u_world_matrix_block {
+ mat4 u_world;
+ mat4 u_model;
+};
+
+void main() {
+ gl_Position = u_view * u_world * u_model * vec4(a_pos, 0, 1);
+ v_col = a_col;
+}
+
+#endif
+
+#ifdef FRAGMENT_SHADER
+
+out vec4 fragColor;
+
+void main() {
+ fragColor = vec4(v_col.xyz, 1);
+}
+
+#endif
+++ /dev/null
-#version 300 es
-precision mediump float;
-
-uniform sampler2D u_sampler;
-uniform float u_sampler_enabled;
-
-in vec2 v_tex;
-
-out vec4 fragColor;
-void main() {
- fragColor = mix(vec4(0.8, 0.8, 0.8, 1), texture(u_sampler, v_tex), u_sampler_enabled);
-}
+++ /dev/null
-#version 300 es
-layout(location = 0) in vec3 a_pos;
-layout(location = 1) in vec2 a_tex;
-
-layout(std140) uniform u_world_matrix_block {
- mat4 u_view;
- mat4 u_world;
- mat4 u_model;
-};
-
-out vec2 v_tex;
-
-void main() {
- gl_Position = u_view * u_world * vec4(a_pos, 1);
- v_tex = a_tex;
-}
--- /dev/null
+precision mediump float;
+
+COMM vec2 v_texture;
+
+#ifdef VERTEX_SHADER
+
+layout(location = 0) in vec2 a_interp;
+layout(location = 1) in vec2 a_pos_top_left;
+layout(location = 2) in vec2 a_pos_bottom_right;
+layout(location = 3) in vec2 a_tex_top_left;
+layout(location = 4) in vec2 a_tex_bottom_right;
+
+layout(std140) uniform u_window_matrix_block {
+ mat4 u_window;
+};
+
+void main() {
+ gl_Position = u_window * vec4(mix(a_pos_top_left, a_pos_bottom_right, a_interp), 0, 1);
+ v_texture = mix(a_tex_top_left, a_tex_bottom_right, a_interp);
+}
+
+#endif
+
+#ifdef FRAGMENT_SHADER
+
+uniform sampler2D u_texture;
+uniform vec4 u_color;
+
+out vec4 fragColor;
+
+void main() {
+ fragColor = vec4(u_color.rgb, u_color.a * texture(u_texture, v_texture).a);
+}
+
+#endif
+++ /dev/null
-#version 300 es
-precision mediump float;
-
-in vec4 v_color;
-in vec2 v_texture;
-
-uniform sampler2D u_texture;
-
-out vec4 fragColor;
-
-void main() {
- fragColor = vec4(v_color.rgb, v_color.a * texture(u_texture, v_texture).a);
-}
+++ /dev/null
-#version 300 es
-precision mediump float;
-layout(location = 0) in vec2 a_interp;
-layout(location = 1) in vec2 a_pos_top_left;
-layout(location = 2) in vec2 a_pos_bottom_right;
-layout(location = 3) in vec2 a_tex_top_left;
-layout(location = 4) in vec2 a_tex_bottom_right;
-
-layout(std140) uniform u_window_matrix_block {
- mat4 u_window;
-};
-
-out vec4 v_color;
-out vec2 v_texture;
-
-void main() {
- gl_Position = u_window * vec4(mix(a_pos_top_left, a_pos_bottom_right, a_interp), 0, 1);
- v_texture = mix(a_tex_top_left, a_tex_bottom_right, a_interp);
- v_color = vec4(0, 0, 0, 1);
-}
-
--- /dev/null
+precision mediump float;
+
+COMM vec4 v_col;
+COMM vec2 v_tex;
+
+#ifdef VERTEX_SHADER
+
+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;
+};
+
+void main() {
+ gl_Position = u_window * vec4(a_pos, 0, 1);
+ v_tex = a_tex;
+ v_col = a_col;
+}
+
+#endif
+
+#ifdef FRAGMENT_SHADER
+
+uniform sampler2D u_texture;
+uniform float u_texture_enabled;
+
+out vec4 fragColor;
+
+void main() {
+ fragColor = v_col * mix(vec4(1), texture(u_texture, v_tex), vec4(u_texture_enabled));
+}
+
+#endif
+++ /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
--- /dev/null
+precision mediump float;
+
+COMM vec4 v_color;
+COMM vec2 v_tex;
+COMM float v_tex_enabled;
+COMM float v_dist;
+
+#ifdef VERTEX_SHADER
+
+layout(location = 0) in vec3 a_pos;
+layout(location = 1) in vec2 a_tex;
+layout(location = 2) in uint a_data;
+
+layout(std140) uniform u_world_matrix_block {
+ mat4 u_view;
+ mat4 u_world;
+ mat4 u_model;
+};
+
+void main() {
+ vec4 pos = u_world * u_model * vec4(a_pos, 1);
+ v_dist = length(pos);
+ gl_Position = u_view * pos;
+
+ vec3 block_color = vec3(
+ float((a_data & 0x0000FU) >> 0U) / 15.0,
+ float((a_data & 0x000F0U) >> 4U) / 15.0,
+ float((a_data & 0x00F00U) >> 8U) / 15.0
+ ) * (float((a_data & 0x0F000U) >> 12U) / 15.0);
+
+ v_color = vec4(block_color, 1);
+ v_tex = a_tex;
+ v_tex_enabled = float((a_data & 0x10000U) >> 16U);
+}
+
+
+#endif
+
+#ifdef FRAGMENT_SHADER
+
+uniform sampler2D u_sampler;
+
+uniform vec3 u_fog_color;
+uniform float u_fog_start;
+uniform float u_fog_range;
+
+out vec4 fragColor;
+void main() {
+ vec4 tile_color = vec4((v_color * mix(vec4(1), texture(u_sampler, v_tex), v_tex_enabled)).xyz, 1);
+
+ // Not going to rely on clamp() existing.
+ float fog = min(1.0f, max(0.0f, (v_dist - u_fog_start) / u_fog_range));
+
+ fragColor = mix(tile_color, vec4(u_fog_color, 1), fog);
+}
+
+
+#endif
#load "chunk"
#load "config"
#load "font"
-#load "imgui"
+#load "immediate"
#load "input"
#load "main"
#load "mesh"
font_vao: GLint;
font_shader: Shader;
+ font_color: Color;
}
fonts_init :: () {
map.init(^font_registry);
- font_shader = shader_make("./assets/shaders/font_vertex.glsl", "./assets/shaders/font_fragment.glsl");
+ font_shader = shader_make("./assets/shaders/font.glsl");
shader_use(font_shader);
shader_link_window_matrix_block(font_shader);
glBindBuffer(GL_ARRAY_BUFFER, -1);
glBindVertexArray(-1);
+
+ font_set_color(.{0,0,0});
}
texture: GLint;
texture_width, texture_height: i32;
chars: [] stbtt_packedchar;
+ em: f32;
}
font_make :: (fd: FontDescriptor) -> Font {
texture = texture,
texture_width = texture_size,
texture_height = texture_size,
- chars = char_data
+ chars = char_data,
+ em = ~~fd.size,
};
+ font_registry[fd] = font;
+
return font;
}
+font_set_color :: (color: Color) {
+ font_color = color;
+}
+
font_print :: (font: Font, x, y: f32, format: str, va: ..any) {
buf: [1024] u8;
msg := conv.format_va(buf, format, va);
x_, y_ := x, y;
for msg {
+ if it == #char "\n" {
+ x_ = x;
+ y_ += font.em + 2;
+ }
+
+ stbtt_GetPackedQuad(font.chars.data, font.texture_width, font.texture_height,
+ ~~(it - #char " "), ^x_, ^y_, ^quads[quad_num], false);
+
+ quad_num += 1;
+ }
+
+ font_render(font, quads[0 .. quad_num]);
+}
+
+font_draw_centered :: (font: Font, x, y, max_width: f32, msg: str) {
+ quads: ^stbtt_aligned_quad = alloc.from_stack(msg.count * sizeof stbtt_aligned_quad);
+ quad_num := 0;
+
+ width := font_get_width(font, msg);
+ x_, y_ := x, y;
+ x_ = (max_width - width) / 2 + x;
+
+ for msg {
+ if it == #char "\n" {
+ x_ = (max_width - width) / 2 + x;
+ y_ += font.em + 2;
+ }
+
stbtt_GetPackedQuad(font.chars.data, font.texture_width, font.texture_height,
~~(it - #char " "), ^x_, ^y_, ^quads[quad_num], false);
quad_num += 1;
}
+ font_render(font, quads[0 .. quad_num]);
+}
+
+#local font_render :: (font: Font, quads: [] stbtt_aligned_quad) {
+ // If this is being used in conjunction with the immediate
+ // rendering system, make sure the immediate objects are flushed
+ // before trying to render over them.
+ #if #defined(immediate_flush) {
+ immediate_flush();
+ }
+
glBindBuffer(GL_ARRAY_BUFFER, font_vbo);
- glBufferSubData(GL_ARRAY_BUFFER, 0, quad_num * sizeof stbtt_aligned_quad, quads);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, quads.count * sizeof stbtt_aligned_quad, quads.data);
glBindBuffer(GL_ARRAY_BUFFER, -1);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, font.texture);
shader_use(font_shader);
shader_set_uniform(font_shader, #cstr "u_texture", 0);
+ shader_set_uniform(font_shader, #cstr "u_color", font_color);
glDisable(GL_DEPTH_TEST);
glBindVertexArray(font_vao);
- glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, ~~0, quad_num);
+ glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, ~~0, quads.count);
glBindTexture(GL_TEXTURE_2D, -1);
glBindVertexArray(-1);
- glEnable(GL_DEPTH_TEST);
}
+font_get_width :: (font: Font, msg: str) -> f32 {
+ x_, y_ := 0.0f, 0.0f;
+ width := 0.0f;
+
+ quad: stbtt_aligned_quad;
+ for msg {
+ if it == #char "\n" {
+ width = math.max(width, x_);
+ x_ = 0;
+ y_ += font.em + 2;
+ continue;
+ }
+
+ stbtt_GetPackedQuad(font.chars.data, font.texture_width, font.texture_height,
+ ~~(it - #char " "), ^x_, ^y_, ^quad, false);
+ }
+
+ return math.max(x_, width);
+}
FontDescriptor :: struct {
+++ /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);
-}
--- /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_Path);
+ shader_use(imgui_shader);
+ shader_link_window_matrix_block(imgui_shader);
+ shader_set_uniform(imgui_shader, #cstr "u_texture_enabled", 0.0f);
+ shader_set_uniform(imgui_shader, #cstr "u_texture", 0);
+
+ immediate_mesh = mesh_make(vertex_data, .[], GL_DYNAMIC_DRAW);
+ immediate_color = .{0,0,0};
+}
+
+immediate_flush :: () {
+ if vertex_count == 0 do return;
+
+ shader_use(imgui_shader);
+ shader_set_uniform(imgui_shader, #cstr "u_texture_enabled", 1.0f if rendering_type == .Image else 0.0f);
+
+ immediate_mesh.vertex_count = vertex_count;
+ mesh_update_verticies(immediate_mesh, vertex_data);
+
+ mesh_draw(immediate_mesh);
+
+ vertex_count = 0;
+ rendering_type = .Plain;
+}
+
+immediate_clear :: (color: Color) {
+ glClearColor(color.r, color.g, color.b, color.a);
+ glClear(GL_COLOR_BUFFER_BIT);
+}
+
+immediate_set_color :: (color: Color) {
+ immediate_color = color;
+}
+
+immediate_vertex :: (x, y: f32, t_x := 0.0f, t_y := 0.0f) {
+ if vertex_count >= Maximum_Vertex_Count do immediate_flush();
+ set_rendering_type(.Plain);
+
+ vertex_data[vertex_count] = .{ .{x, y}, .{t_x, t_y}, immediate_color };
+}
+
+immediate_triangle :: (x1, x2, x3: Vector2) {
+ if vertex_count + 3 > Maximum_Vertex_Count do immediate_flush();
+ set_rendering_type(.Plain);
+
+ vertex_data[vertex_count + 0] = .{ x1, .{0,0}, immediate_color };
+ vertex_data[vertex_count + 1] = .{ x2, .{0,0}, immediate_color };
+ vertex_data[vertex_count + 2] = .{ x3, .{0,0}, immediate_color };
+ vertex_count += 3;
+}
+
+immediate_rectangle :: (x, y, w, h: f32) {
+ if vertex_count + 6 > Maximum_Vertex_Count do immediate_flush();
+ set_rendering_type(.Plain);
+
+ vertex_data[vertex_count + 0] = .{ .{x, y}, .{0,0}, immediate_color };
+ vertex_data[vertex_count + 1] = .{ .{x+w, y}, .{0,0}, immediate_color };
+ vertex_data[vertex_count + 2] = .{ .{x+w, y+h}, .{0,0}, immediate_color };
+ vertex_data[vertex_count + 3] = .{ .{x, y}, .{0,0}, immediate_color };
+ vertex_data[vertex_count + 4] = .{ .{x+w, y+h}, .{0,0}, immediate_color };
+ vertex_data[vertex_count + 5] = .{ .{x, y+h}, .{0,0}, immediate_color };
+ vertex_count += 6;
+}
+
+immediate_image :: (image: ^Texture, x, y, w, h: f32) {
+ if vertex_count > 0 do immediate_flush();
+
+ set_rendering_type(.Image);
+ texture_use(image);
+ shader_use(imgui_shader);
+ shader_set_uniform(imgui_shader, #cstr "u_texture", 0);
+
+ vertex_data[vertex_count + 0] = .{ .{x, y}, .{0,0}, immediate_color };
+ vertex_data[vertex_count + 1] = .{ .{x+w, y}, .{1,0}, immediate_color };
+ vertex_data[vertex_count + 2] = .{ .{x+w, y+h}, .{1,1}, immediate_color };
+ vertex_data[vertex_count + 3] = .{ .{x, y}, .{0,0}, immediate_color };
+ vertex_data[vertex_count + 4] = .{ .{x+w, y+h}, .{1,1}, immediate_color };
+ vertex_data[vertex_count + 5] = .{ .{x, y+h}, .{0,1}, immediate_color };
+ vertex_count += 6;
+}
+
+immediate_ellipse :: () {}
+
+Color :: struct {
+ r, g, b : f32;
+ a := 1.0f;
+}
+
+Immediate_Vertex :: struct {
+ pos: Vector2;
+ tex: Vector2;
+ color: Color;
+}
+
+#local {
+ Shader_Path :: "./assets/shaders/imgui.glsl"
+ imgui_shader: Shader;
+
+ Maximum_Vertex_Count :: 1023;
+ vertex_count: i32;
+ vertex_data: [] Immediate_Vertex;
+
+ immediate_color: Color;
+
+ immediate_mesh: ^Mesh(Immediate_Vertex);
+
+ Rendering_Type :: enum {
+ Plain;
+ Image;
+ }
+ rendering_type := Rendering_Type.Plain;
+
+ set_rendering_type :: (new_type: typeof rendering_type) {
+ if rendering_type != new_type {
+ immediate_flush();
+ rendering_type = new_type;
+ }
+ }
+}
shaders_init();
fonts_init();
- world_shader = shader_make(
- "assets/shaders/world_vertex.glsl",
- "assets/shaders/world_fragment.glsl");
+ world_shader = shader_make("assets/shaders/world.glsl");
shader_link_world_matrix_block(world_shader);
- shader_set_uniform(world_shader, #cstr "u_fog_start", 40.0f);
- shader_set_uniform(world_shader, #cstr "u_fog_range", 5.0f);
+ shader_set_uniform(world_shader, #cstr "u_fog_start", 50.0f);
+ shader_set_uniform(world_shader, #cstr "u_fog_range", 10.0f);
immediate_init();
}
draw :: () {
- // glClearColor(.7, .7, .9, 1);
- // glClearColor(0.1, 0.1, 0.1, 1);
+ draw_scene();
+}
+
+draw_scene :: () {
glClearColor(fog_color.x, fog_color.y, fog_color.z, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shader_use(world_shader);
shader_set_uniform(world_shader, #cstr "u_fog_color", fog_color);
shader_set_uniform(world_shader, #cstr "u_texture", 0);
+ glEnable(GL_DEPTH_TEST);
world_draw(world);
glLineWidth(2);
font_print(font, ~~(ww / 2), ~~(wh / 2), ".");
if debug_screen {
- immediate_rectangle(.{0, 0}, .{528, 220}, .{1, 0, 1, 0.5});
+ immediate_set_color(.{1, 0, 1, 0.5});
+ immediate_rectangle(0, 0, 528, 220);
immediate_flush();
player_chunk := world_position_to_chunk(world, player.body.pos);
glBindBufferBase(GL_UNIFORM_BUFFER, WORLD_MATRIX_BLOCK, world_matrix_block_buffer);
}
-shader_make :: (vertex_path, fragment_path: str) -> Shader {
- vertex_shader := os.get_contents(vertex_path);
- fragment_shader := os.get_contents(fragment_path);
- vs := compile_shader(vertex_shader, GL_VERTEX_SHADER);
- fs := compile_shader(fragment_shader, 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);
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;
#local {
compile_shader :: (source: str, type: GLenum) -> GLint {
shader := glCreateShader(type);
- source_data := source.data;
- source_len := source.count;
- glShaderSource(shader, 1, ^source_data, ^source_len);
+
+ #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: [1024] u8;
+ buf_data: [2048] u8;
buf := str.{ ~~buf_data, 0 };
- glGetShaderInfoLog(shader, 1024, ^buf.count, buf.data);
+ glGetShaderInfoLog(shader, 2048, ^buf.count, buf.data);
println(buf);
}