summary refs log tree commit diff
diff options
context:
space:
mode:
authoriurii plugatarov <[email protected]>2024-08-16 20:51:24 +0200
committeriurii plugatarov <[email protected]>2024-08-16 20:51:24 +0200
commitfc3e2bed46c42a9af6a9e562b6609608e09e9850 (patch)
tree2a33d53214c71898014a8b6d135870aa82b494d3
parent586369b63cdede5fa09f5f9ed73abde6c8264425 (diff)
downloadfunhalla-fc3e2bed46c42a9af6a9e562b6609608e09e9850.tar.gz
shaders and textures
-rw-r--r--res/images/awesomeface.pngbin0 -> 59277 bytes
-rw-r--r--res/images/container.jpgbin0 -> 184939 bytes
-rw-r--r--res/shaders/triangle.fs14
-rw-r--r--res/shaders/triangle.vs14
-rw-r--r--src/main.odin162
-rw-r--r--src/shader/shader.odin50
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,
+}