diff --git a/src/main.zig b/src/main.zig index 351557e..6f7e550 100644 --- a/src/main.zig +++ b/src/main.zig @@ -9,19 +9,40 @@ const gl = @cImport ({ }); +const vertexShaderSource: [*c]const u8 = + \\ #version 460 core + \\ layout (location = 0) in vec3 aPos; + \\ void main() { + \\ gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0); + \\ } + ; + +const fragementShaderSource: [*c]const u8 = + \\ #version 330 core + \\ out vec4 FragColor; + \\ void main() { + \\ FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f); + \\ } + ; + +const ShaderInitError = error { + VertexCompilation, + FragementCompilation, + ShaderProgramLinking, +}; + + pub fn main() void { // var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); // defer arena.deinit(); - // const alloc = arena.allocator(); + // const alloc = arena.allocator(); const res: c_int = gl.glfwInit(); if (res != gl.GL_TRUE) { std.debug.panic("Could not initialize glfw! Exit code: {d}", .{ res }); } - - gl.glfwWindowHint(gl.GLFW_CONTEXT_VERSION_MAJOR, 4); gl.glfwWindowHint(gl.GLFW_CONTEXT_VERSION_MINOR, 6); gl.glfwWindowHint(gl.GLFW_OPENGL_PROFILE, gl.GLFW_OPENGL_CORE_PROFILE); @@ -29,7 +50,6 @@ pub fn main() void { // the two null params are monitor for fullscreen, and share window resources (???) const window: ?*gl.GLFWwindow = gl.glfwCreateWindow(800, 600, "LearnOpenGL", null, null); - if (window == null) { gl.glfwTerminate(); std.debug.panic("Could not instantiate window!", .{}); @@ -37,38 +57,123 @@ pub fn main() void { } gl.glfwMakeContextCurrent(window); - const version: c_int = gl.gladLoadGL(gl.glfwGetProcAddress); - if (version == 0) { std.debug.panic("Could not initialize GLAD", .{}); return; } gl.glViewport(0, 0, 800, 600); - // callback function returned? _ = gl.glfwSetFramebufferSizeCallback(window, &framebuffer_resize_callback); - const verticies: [3][3]f32 = .{ .{-0.5, -0.5, 0.0}, .{0.5, -0.5, 0.0}, .{0.0, 0.5, 0.0} }; - var vbo: gl.GLuint = undefined; - gl.glad_glGenBuffers.?(1, &vbo); - std.debug.print("buffer id: '{d}'\n", .{ vbo }); - gl.glad_glBindBuffer.?(gl.GL_ARRAY_BUFFER, vbo); - gl.glBufferData(gl.GL_ARRAY_BUFFER, 4 * 3 * @sizeOf(f32), @ptrCast(&verticies), gl.GL_STATIC_DRAW); + const vertexShader: c_uint = gl.glCreateShader(gl.GL_VERTEX_SHADER); + const fragShader: c_uint = gl.glCreateShader(gl.GL_FRAGMENT_SHADER); + const shaderProgram: c_uint = gl.glCreateProgram(); + + init_shader_program(&vertexShader, &fragShader, &shaderProgram) catch |e| switch (e) { + ShaderInitError.VertexCompilation => std.debug.panic("Could not compile vertex shader!\n", .{}), + ShaderInitError.FragementCompilation => std.debug.panic("Could not compile fragment shaders!\n", .{}), + ShaderInitError.ShaderProgramLinking => std.debug.panic("Could not link shader program!\n", .{}), + }; + + var rect_vao: c_uint = undefined; + gl.glad_glGenVertexArrays.?(1, @ptrCast(&rect_vao)); + gl.glad_glBindVertexArray.?(rect_vao); + const rect_verts: [4][3]f32 = .{ .{0.2, 0.2, 0.0}, .{0.8, 0.2, 0.0}, .{0.8, 0.4, 0.0}, .{0.2, 0.4, 0.0} }; + const draw_indices: [2][3]c_uint = .{ .{0, 1, 3}, .{1, 2, 3} }; + + var r_vert_buffer: c_uint = undefined; + gl.glad_glGenBuffers.?(1, &r_vert_buffer); + gl.glad_glBindBuffer.?(gl.GL_ARRAY_BUFFER, r_vert_buffer); + gl.glBufferData(gl.GL_ARRAY_BUFFER, 2 * 3 * @sizeOf(f32), @ptrCast(&rect_verts), gl.GL_STATIC_DRAW); + // gl.glad_glBindBuffer.?(0); + + var element_buffer: c_uint = undefined; + gl.glad_glGenBuffers.?(1, &element_buffer); + gl.glad_glBindBuffer.?(gl.GL_ELEMENT_ARRAY_BUFFER, element_buffer); + gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER, 2 * 3 * @sizeOf(c_uint), @ptrCast(&draw_indices), gl.GL_STATIC_DRAW); + // gl.glad_glBindBuffer.?(0); + gl.glEnableVertexAttribArray(0); + + + + // ----- Simple Triangle ------ + const verticies: [3][3]f32 = .{ .{-0.5, -0.5, 0.0}, .{0.5, -0.5, 0.0}, .{0.0, 0.5, 0.0} }; + // Vertex array object + var vao: c_uint = undefined; + gl.glad_glGenVertexArrays.?(1, @ptrCast(&vao)); + gl.glad_glBindVertexArray.?(vao); + + // vertex buffer object + var vbo: c_uint = undefined; + gl.glad_glGenBuffers.?(1, &vbo); + gl.glad_glBindBuffer.?(gl.GL_ARRAY_BUFFER, vbo); + // type of buffer, size of memory being inserted, the data to be loaded, how the GPU handles the memory + // STREAM - write once, used a few times, STATIC - set once, used many times, DYNAMIC - changed a lot + // used many times + gl.glBufferData(gl.GL_ARRAY_BUFFER, 4 * 3 * @sizeOf(f32), @ptrCast(&verticies), gl.GL_STATIC_DRAW); + // 0 for location=0 from shader + // 3 for number of attributes per stride, + // the type of data + // if we want it to be normalized + // offset of start of data + // The target virtual buffer object is defined by the current state from glVertexAttribPointer + gl.glVertexAttribPointer(0, 3, gl.GL_FLOAT, gl.GL_FALSE, 3 * @sizeOf(f32), @ptrCast(&0)); + gl.glEnableVertexAttribArray(0); + + gl.glad_glBindVertexArray.?(0); + + // ------ END Simple Triangle ------ + + std.debug.print("Vertex buffer assigned\n", .{}); + + var gl_err: gl.GLenum = 0; + + gl.glDisable(gl.GL_CULL_FACE); + while(gl.glfwWindowShouldClose(window) == 0) { gl.glfwPollEvents(); handle_input(window.?); - gl.glClearColor(0.2, 0.3, 0.4, 0.5); // state setting, followed by state using + gl.glClearColor(0.2, 0.3, 0.4, 0.5); // state setting, follo wed by state using gl.glClear(gl.GL_COLOR_BUFFER_BIT); // color buffer, depth buffer, and stencil buffer + gl.glUseProgram(shaderProgram); + gl.glad_glBindVertexArray.?(vao); + gl.glad_glBindBuffer.?(gl.GL_ARRAY_BUFFER, vbo); + // offset into vertexes, and count + // gl.glDrawArrays(gl.GL_TRIANGLES, 0, 3); + + gl_err = gl.glGetError(); + + if (gl_err > 0) { + std.debug.print("There was an opengl error: {d}", .{gl_err}); + gl_err = 0; + } + + gl.glad_glBindVertexArray.?(rect_vao); + gl.glad_glBindBuffer.?(gl.GL_ARRAY_BUFFER, r_vert_buffer); + gl.glad_glBindBuffer.?(gl.GL_ELEMENT_ARRAY_BUFFER, element_buffer); + gl.glDrawElements(gl.GL_TRIANGLES, 6, gl.GL_UNSIGNED_INT, null); + + gl_err = gl.glGetError(); + + if (gl_err > 0) { + std.debug.print("There was an opengl error: {d}", .{gl_err}); + gl_err = 0; + } + // This swaps the "displayed" buffer with the "rendering" buffer gl.glfwSwapBuffers(window); } + gl.glDeleteVertexArrays(1, &vao); + gl.glDeleteBuffers(1, &vbo); + gl.glDeleteProgram(shaderProgram); + gl.glfwTerminate(); } @@ -82,3 +187,47 @@ fn handle_input(window: *gl.GLFWwindow) void { gl.glfwSetWindowShouldClose(window, 1); } } + +fn init_shader_program(vertex_shader: *const c_uint, frag_shader: *const c_uint, program: *const c_uint) ShaderInitError!void { + var success: c_int = undefined; + var infoLog: [512:0]u8 = undefined; + + gl.glShaderSource(vertex_shader.*, 1, &vertexShaderSource, null); + gl.glCompileShader(vertex_shader.*); + gl.glGetShaderiv(vertex_shader.*, gl.GL_COMPILE_STATUS, &success); + std.debug.print("Vertex Shader compiled\n", .{}); + if (success == 0) { + std.debug.print("Shader compile failed!\n", .{}); + gl.glGetShaderInfoLog(vertex_shader.*, 512, null, &infoLog); + std.debug.print("Error Log: {s}\n", .{infoLog}); + return ShaderInitError.VertexCompilation; + } + + gl.glShaderSource(frag_shader.*, 1, &fragementShaderSource, null); + gl.glCompileShader(frag_shader.*); + gl.glGetShaderiv(frag_shader.*, gl.GL_COMPILE_STATUS, &success); + std.debug.print("Fragment Shader compiled\n", .{}); + if (success == 0) { + std.debug.print("Shader compile failed!\n", .{}); + gl.glGetShaderInfoLog(frag_shader.*, 512, null, &infoLog); + std.debug.print("Error Log: {s}\n", .{infoLog}); + return ShaderInitError.FragementCompilation; + } + + gl.glAttachShader(program.*, vertex_shader.*); + gl.glAttachShader(program.*, frag_shader.*); + gl.glLinkProgram(program.*); + std.debug.print("Shader Linking Complete\n", .{}); + gl.glGetProgramiv(program.*, gl.GL_LINK_STATUS, &success); + if (success == 0) { + std.debug.print("Shader linking failed!\n", .{}); + gl.glGetProgramInfoLog(program.*, 512, null, &infoLog); + std.debug.print("Error Log: {s}", .{infoLog}); + return ShaderInitError.ShaderProgramLinking; + } + + gl.glDeleteShader(vertex_shader.*); + gl.glDeleteShader(frag_shader.*); + + std.debug.print("Shader program selected, cleaned up compiled shaders\n", .{}); +}