use package core
use package glfw3
use package opengles
+use package stb_truetype
-main :: (args) => {
- if !glfwInit() {
- println("Failed to initialize GLFW");
- os.exit(1);
- }
+window: GLFWwindow_p;
+create_window :: () => {
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
- window := glfwCreateWindow(800, 600, #cstr "Voxel Shooter");
+ window = glfwCreateWindow(800, 600, #cstr "Voxel Shooter");
+
glfwMakeContextCurrent(window);
+ glfwSetWindowSizeCallback(window, "on_resize");
+}
+
+#export "on_resize" (window: GLFWwindow_p, width, height: u32) {
+ glViewport(0, 0, width, height);
+ update_view_matrix();
+}
+
+Mesh :: struct {
+ handle: GLuint;
+ verticies: [] f32;
+ indicies: [] u16;
+}
+
+cube_verticies :: (x, y, z: f32) -> [] GLfloat {
+ vertex_data := GLfloat.[
+ x-0.5, y-0.5, z-0.5,
+ x+0.5, y-0.5, z-0.5,
+ x+0.5, y+0.5, z-0.5,
+ x-0.5, y-0.5, z-0.5,
+ x+0.5, y+0.5, z-0.5,
+ x-0.5, y+0.5, z-0.5,
+
+ x-0.5, y-0.5, z-0.5,
+ x-0.5, y+0.5, z-0.5,
+ x-0.5, y+0.5, z+0.5,
+ x-0.5, y-0.5, z-0.5,
+ x-0.5, y+0.5, z+0.5,
+ x-0.5, y-0.5, z+0.5,
+
+ x-0.5, y-0.5, z-0.5,
+ x-0.5, y+0.5, z+0.5,
+ x+0.5, y+0.5, z+0.5,
+ x-0.5, y-0.5, z-0.5,
+ x+0.5, y+0.5, z+0.5,
+ x+0.5, y-0.5, z-0.5,
+ ];
+
+ return memory.copy_slice(vertex_data);
+}
+
+vao: GLuint;
+matrix_block_buffer: GLuint;
+
+setup_opengl :: () {
glInit(glfwGetLoadProcAddress());
- while !glfwWindowShouldClose(window) {
- glClearColor(.2, .2, .2, 1);
- glClear(GL_COLOR_BUFFER_BIT);
+ 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);
+ glCompileShader(shader);
+
+ success: GLint;
+ if glGetShaderiv(shader, GL_COMPILE_STATUS, ^success); success == GL_FALSE {
+ buf_data: [1024] u8;
+ buf := str.{ ~~buf_data, 0 };
+ glGetShaderInfoLog(shader, 1024, ^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;
+ }
+
+ vertex_shader := os.get_contents("assets/shaders/basic_vertex.glsl");
+ fragment_shader := os.get_contents("assets/shaders/basic_fragment.glsl");
+ vs := compile_shader(vertex_shader, GL_VERTEX_SHADER);
+ fs := compile_shader(fragment_shader, GL_FRAGMENT_SHADER);
+
+ prog := link_program(vs, fs);
+ glUseProgram(prog);
+
+ matrix: [32] GLfloat;
+ glGenBuffers(1, ^matrix_block_buffer);
+ glBindBuffer(GL_UNIFORM_BUFFER, matrix_block_buffer);
+ glBufferData(GL_UNIFORM_BUFFER, sizeof f32 * (16 + 16), ^matrix, GL_DYNAMIC_DRAW);
+ glBindBuffer(GL_UNIFORM_BUFFER, -1);
+
+ glBindBufferBase(GL_UNIFORM_BUFFER, 0, matrix_block_buffer);
+ matrix_block_index := glGetUniformBlockIndex(prog, #cstr "u_matrix_block");
+ glUniformBlockBinding(prog, matrix_block_index, 0);
+
+ glGenVertexArrays(1, ^vao);
+ glBindVertexArray(vao);
+
+ vbo: GLuint;
+ glGenBuffers(1, ^vbo);
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
+
+ vertex_data := cube_verticies(0, 0, -4);
+ glBufferData(GL_ARRAY_BUFFER, sizeof GLfloat * vertex_data.count, vertex_data.data, GL_STATIC_DRAW);
+
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(0, 3, GL_FLOAT, false, 3 * sizeof GLfloat, ~~0);
+
+ glBindVertexArray(-1);
+ update_view_matrix();
+ update_world_matrix();
+}
+
+update_view_matrix :: () {
+ fov := 75 * math.PI / 180;
+ fov = math.clamp(fov, 0, math.PI - 0.01f);
+
+ width, height: u32;
+ glfwGetWindowSize(window, ^width, ^height);
+ ar := cast(f32) width / cast(f32) height;
+ z_near := 0.01f;
+ z_far := 100.0f;
+ z_range := z_far - z_near;
+ tan_half_fov := math.sin(fov / 2) / math.cos(fov / 2);
+
+ matrix := GLfloat.[
+ 1 / (tan_half_fov * ar), 0, 0, 0,
+ 0, 1 / (tan_half_fov), 0, 0,
+ 0, 0, (-z_far) / z_range, -1,
+ 0, 0, -(z_far*z_near)/z_range, 0,
+ ];
+
+ glBindBuffer(GL_UNIFORM_BUFFER, matrix_block_buffer);
+ glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof typeof matrix, ^matrix);
+ glBindBuffer(GL_UNIFORM_BUFFER, -1);
+}
+
+update_world_matrix :: () {
+ #persist t := 0.0f;
+ t += 0.01;
+
+ c := math.cos(t);
+ s := math.sin(t);
+ matrix := GLfloat.[
+ c, 0, s, 0,
+ 0, 1, 0, 0,
+ -s, 0, c, 0,
+ 0, 0, 0, 1,
+ ];
+
+ glBindBuffer(GL_UNIFORM_BUFFER, matrix_block_buffer);
+ glBufferSubData(GL_UNIFORM_BUFFER, 16 * sizeof f32, sizeof typeof matrix, ^matrix);
+ glBindBuffer(GL_UNIFORM_BUFFER, -1);
+}
+
+update :: (dt: f32) {
+ update_world_matrix();
+}
+
+draw :: () {
+ glClearColor(.2, .2, .2, 1);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glBindVertexArray(vao);
+ glDrawArrays(GL_TRIANGLES, 0, 18);
+ glBindVertexArray(-1);
+
+ glfwSwapBuffers(window);
+}
+
+main_loop :: () {
+ while !glfwWindowShouldClose(window) {
glfwPollEvents();
- glfwSwapBuffers(window);
+
+ update(1.0f / 60);
+ draw();
}
-}
\ No newline at end of file
+}
+
+main :: (args) => {
+ if !glfwInit() {
+ println("Failed to initialize GLFW");
+ os.exit(1);
+ }
+
+ create_window();
+ setup_opengl();
+ main_loop();
+}