diff options
Diffstat (limited to '')
-rw-r--r-- | res/images/awesomeface.png | bin | 0 -> 59277 bytes | |||
-rw-r--r-- | res/images/container.jpg | bin | 0 -> 184939 bytes | |||
-rw-r--r-- | res/shaders/triangle.fs | 14 | ||||
-rw-r--r-- | res/shaders/triangle.vs | 14 | ||||
-rw-r--r-- | src/main.odin | 162 | ||||
-rw-r--r-- | src/shader/shader.odin | 50 |
6 files changed, 240 insertions, 0 deletions
diff --git a/res/images/awesomeface.png b/res/images/awesomeface.png new file mode 100644 index 0000000..9840caf --- /dev/null +++ b/res/images/awesomeface.png Binary files differdiff --git a/res/images/container.jpg b/res/images/container.jpg new file mode 100644 index 0000000..d07bee4 --- /dev/null +++ b/res/images/container.jpg Binary files differdiff --git a/res/shaders/triangle.fs b/res/shaders/triangle.fs new file mode 100644 index 0000000..70a5f6d --- /dev/null +++ b/res/shaders/triangle.fs @@ -0,0 +1,14 @@ +#version 330 core + +out vec4 FragColor; + +in vec3 our_color; +in vec2 TexCoord; + +uniform sampler2D texture1; +uniform sampler2D texture2; + +void main() +{ + FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.2); +} diff --git a/res/shaders/triangle.vs b/res/shaders/triangle.vs new file mode 100644 index 0000000..57cbc74 --- /dev/null +++ b/res/shaders/triangle.vs @@ -0,0 +1,14 @@ +#version 330 core +layout (location = 0) in vec3 a_pos; +layout (location = 1) in vec3 a_color; +layout (location = 2) in vec2 a_tex_coord; + +out vec3 our_color; +out vec2 TexCoord; + +void main() +{ + gl_Position = vec4(a_pos, 1.0); + our_color = a_color; + TexCoord = vec2(a_tex_coord.x, a_tex_coord.y); +} diff --git a/src/main.odin b/src/main.odin index 75bd82e..47dd6d5 100644 --- a/src/main.odin +++ b/src/main.odin @@ -1,10 +1,15 @@ package main import gl "vendor:OpenGL" import "vendor:glfw" +import "vendor:stb/image" import "base:intrinsics" import "base:runtime" +import "core:c/libc" import "core:fmt" +import "core:os" + +import "shader" GL_MAJOR_VERSION :: 3 GL_MINOR_VERSION :: 3 @@ -48,13 +53,170 @@ main :: proc() { gl.Viewport(0, 0, 800, 600) glfw.SetFramebufferSizeCallback(window, framebuffer_size_callback) + shdr, err := shader.shader_init("res/shaders/triangle.vs", "res/shaders/triangle.fs") + if err == shader.SHADER_LOAD_ERROR { + fmt.eprintln("Could not initialize shader") + return + } + + vertices: []f32 = { + 0.5, + 0.5, + 0.0, + 1.0, + 0.0, + 0.0, + 1.0, + 1.0, // top right + 0.5, + -0.5, + 0.0, + 0.0, + 1.0, + 0.0, + 1.0, + 0.0, // bottom right + -0.5, + -0.5, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, // bottom let + -0.5, + 0.5, + 0.0, + 1.0, + 1.0, + 0.0, + 0.0, + 1.0, + } + + indices := []i32{0, 1, 3, 1, 2, 3} + + vbo, vao, ebo, texture1, texture2: u32 + gl.GenVertexArrays(1, &vao) + gl.GenBuffers(1, &vbo) + gl.GenBuffers(1, &ebo) + + gl.BindVertexArray(vao) + gl.BindBuffer(gl.ARRAY_BUFFER, vbo) + + gl.BufferData( + gl.ARRAY_BUFFER, + size_of(f32) * len(vertices), + raw_data(vertices), + gl.STATIC_DRAW, + ) + gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, ebo) + gl.BufferData( + gl.ELEMENT_ARRAY_BUFFER, + size_of(i32) * len(indices), + raw_data(indices), + gl.STATIC_DRAW, + ) + + + gl.VertexAttribPointer(0, 3, gl.FLOAT, gl.FALSE, 8 * size_of(f32), 0) + gl.EnableVertexAttribArray(0) + + gl.VertexAttribPointer(1, 3, gl.FLOAT, gl.FALSE, 8 * size_of(f32), 3 * size_of(f32)) + gl.EnableVertexAttribArray(1) + + gl.VertexAttribPointer(2, 2, gl.FLOAT, gl.FALSE, 8 * size_of(f32), 6 * size_of(f32)) + gl.EnableVertexAttribArray(2) + + gl.GenTextures(1, &texture1) + gl.BindTexture(gl.TEXTURE_2D, texture1) + gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT) + gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT) + + gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR) + gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) + + width, height, nr_channels: libc.int + assert(os.is_file_path("res/images/container.jpg")) + data := image.load("res/images/container.jpg", &width, &height, &nr_channels, 0) + + if data != nil { + gl.TexImage2D( + gl.TEXTURE_2D, + 0, + gl.RGB, + i32(width), + i32(height), + 0, + gl.RGB, + gl.UNSIGNED_BYTE, + data, + ) + gl.GenerateMipmap(gl.TEXTURE_2D) + } else { + fmt.eprintln("Failed to load texture") + return + } + image.image_free(data) + + gl.GenTextures(1, &texture2) + gl.BindTexture(gl.TEXTURE_2D, texture2) + gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT) + gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT) + + gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR) + gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) + + image.set_flip_vertically_on_load(1) + + assert(os.is_file_path("res/images/awesomeface.png")) + data = image.load("res/images/awesomeface.png", &width, &height, &nr_channels, 0) + + if data != nil { + gl.TexImage2D( + gl.TEXTURE_2D, + 0, + gl.RGBA, + i32(width), + i32(height), + 0, + gl.RGBA, + gl.UNSIGNED_BYTE, + data, + ) + gl.GenerateMipmap(gl.TEXTURE_2D) + } else { + fmt.eprintln("Failed to load texture") + return + } + image.image_free(data) + + shader.use(shdr) + gl.Uniform1i(gl.GetUniformLocation(shdr.id, cstring("texture1")), i32(0)) + gl.Uniform1i(gl.GetUniformLocation(shdr.id, cstring("texture2")), i32(1)) + + //gl.PolygonMode(gl.FRONT_AND_BACK, gl.LINE) + for !glfw.WindowShouldClose(window) { process_input(&window) gl.ClearColor(0.2, 0.3, 0.3, 1.0) gl.Clear(gl.COLOR_BUFFER_BIT) + gl.ActiveTexture(gl.TEXTURE0) + gl.BindTexture(gl.TEXTURE_2D, texture1) + gl.ActiveTexture(gl.TEXTURE1) + gl.BindTexture(gl.TEXTURE_2D, texture2) + + shader.use(shdr) + gl.BindVertexArray(vao) + gl.DrawElements(gl.TRIANGLES, 6, gl.UNSIGNED_INT, nil) + glfw.SwapBuffers(window) glfw.PollEvents() } + + gl.DeleteBuffers(1, &ebo) + gl.DeleteVertexArrays(1, &vao) + gl.DeleteBuffers(1, &vbo) } diff --git a/src/shader/shader.odin b/src/shader/shader.odin new file mode 100644 index 0000000..171d7ad --- /dev/null +++ b/src/shader/shader.odin @@ -0,0 +1,50 @@ +package shader + +import "core:os" +import "core:strings" +import gl "vendor:OpenGL" + +Shader :: struct { + id: u32, +} + +SHADER_LOAD_ERROR :: -1 +SHADER_OK :: 0 + +shader_init :: proc(vsp, fsp: string) -> (^Shader, int) { + assert(os.is_file_path(vsp)) + assert(os.is_file_path(fsp)) + + program_id, ok := gl.load_shaders_file(vsp, fsp) + + if !ok { + return nil, SHADER_LOAD_ERROR + } + + shader := new(Shader) + shader.id = program_id + + return shader, SHADER_OK +} + +use :: proc(using shader: ^Shader) { + gl.UseProgram(id) +} + +set_bool :: proc(using shader: ^Shader, name: cstring, value: bool) { + gl.Uniform1i(gl.GetUniformLocation(id, name), i32(value)) +} + +set_i32 :: proc(using shader: ^Shader, name: cstring, value: i32) { + gl.Uniform1i(gl.GetUniformLocation(id, name), value) +} + +set_f32 :: proc(using shader: ^Shader, name: cstring, value: f32) { + gl.Uniform1f(gl.GetUniformLocation(id, name), value) +} + +set_value :: proc { + set_i32, + set_f32, + set_bool, +} |