diff --git a/src/main.zig b/src/main.zig index 6d1d81c..54f3d17 100644 --- a/src/main.zig +++ b/src/main.zig @@ -2,46 +2,69 @@ //! you are building an executable. If you are making a library, the convention //! is to delete this file and start with root.zig instead. const std = @import("std"); -const gl = @cImport ({ +const gl = @cImport({ @cDefine("GLAD_GL_IMPLEMENTATION", ""); @cInclude("glad/glad.h"); @cInclude("GLFW/glfw3.h"); }); - -const vertexShaderSource: [*c]const u8 = +const vertexShaderSource: [*c]const u8 = \\ #version 460 core \\ layout (location = 0) in vec3 aPos; + \\ layout (location = 1) in vec3 aColor; + \\ out vec2 vertexColor; + \\ \\ void main() { \\ gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0); + \\ vertexColor = vec2(aColor.x, aColor.y); \\ } - ; +; -const fragementShaderSource: [*c]const u8 = +const fragementShaderSource: [*c]const u8 = \\ #version 330 core \\ out vec4 FragColor; + \\ + \\ uniform float zed_c; + \\ in vec2 vertexColor; \\ void main() { - \\ FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f); + \\ FragColor = vec4(vertexColor.x, vertexColor.y, zed_c, 1.0f); \\ } - ; +; -const ShaderInitError = error { +const rectShaderSource: [*c]const u8 = + \\ #version 460 core + \\ layout (location = 0) in vec3 aPos; + \\ out vec2 vertexColor; + \\ void main() { + \\ gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0); + \\ vertexColor = vec2(aPos.x * 2.0f, aPos.y * 2.0f); + \\ } +; + +const yellowShaderSource: [*c]const u8 = + \\ #version 460 core + \\ out vec4 FragColor; + \\ void main() { + \\ FragColor = vec4(0.8f, 0.8f, 0.1f, 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 }); + 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); @@ -67,42 +90,39 @@ pub fn main() void { // callback function returned? _ = gl.glfwSetFramebufferSizeCallback(window, &framebuffer_resize_callback); - 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(); + const orangeShaderProgram: c_uint = gl.glCreateProgram(); + const yellowShaderProgram: 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", .{}), + init_shader_program(&orangeShaderProgram, &yellowShaderProgram) 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} }; + 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, 4 * 3 * @sizeOf(f32), @ptrCast(&rect_verts), gl.GL_STATIC_DRAW); + // VA-P needs to be defined on every vertex buffer so it knows how to read it gl.glVertexAttribPointer(0, 3, gl.GL_FLOAT, gl.GL_FALSE, 3 * @sizeOf(f32), @ptrCast(&0)); + // and then it needs to be enabled gl.glEnableVertexAttribArray(0); - // gl.glad_glBindBuffer.?(0); + // but it doesn't need to be defined on the index buffer 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} }; + const verticies: [3][6]f32 = .{ .{ -0.5, -0.5, 0.0, 1.0, 0.2, 0.0 }, .{ 0.5, -0.5, 0.0, 0.2, 1.0, 0.0 }, .{ 0.0, 0.5, 0.0, 0.2, 0.2, 0.0 } }; + // Vertex array object var vao: c_uint = undefined; gl.glad_glGenVertexArrays.?(1, @ptrCast(&vao)); @@ -115,15 +135,21 @@ pub fn main() void { // 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); + gl.glBufferData(gl.GL_ARRAY_BUFFER, 3 * 6 * @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.glVertexAttribPointer(0, 3, gl.GL_FLOAT, gl.GL_FALSE, 6 * @sizeOf(f32), @ptrCast(&0)); + // location 1, offset of 3 f32s + gl.glEnableVertexAttribArray(1); + // gl.glVertexAttribPointer(1, 3, gl.GL_FLOAT, gl.GL_FALSE, 6 * @sizeOf(f32), @ptrCast(&(3 * @sizeOf(f32)))); + const offset: [*c]c_uint = 3 * @sizeOf(f32); + gl.glVertexAttribPointer(1, 3, gl.GL_FLOAT, gl.GL_FALSE, 6 * @sizeOf(f32), @ptrCast(offset)); + gl.glad_glBindVertexArray.?(0); @@ -135,33 +161,38 @@ pub fn main() void { gl.glDisable(gl.GL_CULL_FACE); - while(gl.glfwWindowShouldClose(window) == 0) - { - gl.glfwPollEvents(); + var time: f64 = undefined; + var blue_val: f64 = undefined; + const color_loc: c_int = gl.glGetUniformLocation(orangeShaderProgram, "zed_c"); + if (color_loc == -1) { + std.debug.panic("Could not get uniform location of zed_c!", .{}); + } + while (gl.glfwWindowShouldClose(window) == 0) { + time = gl.glfwGetTime(); + blue_val = (@sin(time) / 2.0) + 0.5; + + gl.glfwPollEvents(); handle_input(window.?); 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); - // offset into vertexes, and count + gl.glUseProgram(orangeShaderProgram); + gl.glUniform1f(color_loc, @floatCast(blue_val)); + gl.glad_glBindVertexArray.?(vao); 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.glUseProgram(yellowShaderProgram); gl.glad_glBindVertexArray.?(rect_vao); 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}); + std.debug.print("There was an opengl error: {d}\n", .{gl_err}); gl_err = 0; } @@ -169,12 +200,17 @@ pub fn main() void { gl.glfwSwapBuffers(window); } + // These can't be defered. I think the program has to be + // deleted last gl.glDeleteVertexArrays(1, &vao); + gl.glDeleteVertexArrays(1, &rect_vao); gl.glDeleteBuffers(1, &vbo); - gl.glDeleteProgram(shaderProgram); + gl.glDeleteBuffers(1, &r_vert_buffer); + gl.glDeleteBuffers(1, &element_buffer); + gl.glDeleteProgram(orangeShaderProgram); + gl.glDeleteProgram(yellowShaderProgram); gl.glfwTerminate(); - } export fn framebuffer_resize_callback(_: ?*gl.GLFWwindow, width: c_int, height: c_int) callconv(.C) void { @@ -187,46 +223,87 @@ fn handle_input(window: *gl.GLFWwindow) void { } } -fn init_shader_program(vertex_shader: *const c_uint, frag_shader: *const c_uint, program: *const c_uint) ShaderInitError!void { +fn init_shader_program(orange_program: *const c_uint, yellow_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); + const vertex_shader: c_uint = gl.glCreateShader(gl.GL_VERTEX_SHADER); + const rect_shader: c_uint = gl.glCreateShader(gl.GL_VERTEX_SHADER); + const orange_shader: c_uint = gl.glCreateShader(gl.GL_FRAGMENT_SHADER); + const yellow_shader: c_uint = gl.glCreateShader(gl.GL_FRAGMENT_SHADER); + + 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); + 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); + gl.glShaderSource(orange_shader, 1, &fragementShaderSource, null); + gl.glCompileShader(orange_shader); + gl.glGetShaderiv(orange_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); + gl.glGetShaderInfoLog(orange_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.*); + gl.glAttachShader(orange_program.*, vertex_shader); + gl.glAttachShader(orange_program.*, orange_shader); + gl.glLinkProgram(orange_program.*); std.debug.print("Shader Linking Complete\n", .{}); - gl.glGetProgramiv(program.*, gl.GL_LINK_STATUS, &success); + gl.glGetProgramiv(orange_program.*, gl.GL_LINK_STATUS, &success); if (success == 0) { std.debug.print("Shader linking failed!\n", .{}); - gl.glGetProgramInfoLog(program.*, 512, null, &infoLog); + gl.glGetProgramInfoLog(orange_program.*, 512, null, &infoLog); std.debug.print("Error Log: {s}", .{infoLog}); return ShaderInitError.ShaderProgramLinking; } - gl.glDeleteShader(vertex_shader.*); - gl.glDeleteShader(frag_shader.*); + gl.glShaderSource(rect_shader, 1, &rectShaderSource, null); + gl.glCompileShader(rect_shader); + gl.glGetShaderiv(rect_shader, gl.GL_COMPILE_STATUS, &success); + std.debug.print("Rectangle shader compiled!\n", .{}); + if (success == 0) { + std.debug.print("Rectangle shader compile failed!\n", .{}); + gl.glGetShaderInfoLog(rect_shader, 512, null, &infoLog); + std.debug.print("Error Log: {s}", .{infoLog}); + return ShaderInitError.VertexCompilation; + } + + gl.glShaderSource(yellow_shader, 1, &yellowShaderSource, null); + gl.glCompileShader(yellow_shader); + gl.glGetShaderiv(yellow_shader, gl.GL_COMPILE_STATUS, &success); + std.debug.print("Yellow Fragment shader compiled!\n", .{}); + if (success == 0) { + std.debug.print("Yellow fragement shader compile failed!\n", .{}); + gl.glGetShaderInfoLog(yellow_shader, 512, null, &infoLog); + std.debug.print("Error Log: {s}", .{infoLog}); + return ShaderInitError.FragementCompilation; + } + + gl.glAttachShader(yellow_program.*, rect_shader); + gl.glAttachShader(yellow_program.*, yellow_shader); + gl.glLinkProgram(yellow_program.*); + std.debug.print("Yellow Shader Linking Complete\n", .{}); + gl.glGetProgramiv(orange_program.*, gl.GL_LINK_STATUS, &success); + if (success == 0) { + std.debug.print("Yellow Shader linking failed!\n", .{}); + gl.glGetProgramInfoLog(orange_program.*, 512, null, &infoLog); + std.debug.print("Error Log: {s}", .{infoLog}); + return ShaderInitError.ShaderProgramLinking; + } + + gl.glDeleteShader(rect_shader); + gl.glDeleteShader(vertex_shader); + gl.glDeleteShader(orange_shader); + gl.glDeleteShader(yellow_shader); std.debug.print("Shader program selected, cleaned up compiled shaders\n", .{}); }