├── .gitignore ├── README.md ├── _assets ├── fonts │ └── huge_agb_v5.ttf ├── getting_started │ ├── 0.cube │ │ └── square.png │ ├── 3.shaders │ │ ├── basic.frag │ │ ├── basic.vs │ │ ├── ex4.frag │ │ ├── ex4.vs │ │ ├── offset.vs │ │ ├── reverse.vs │ │ └── uniform.frag │ ├── 4.textures │ │ ├── texture.frag │ │ ├── texture.vs │ │ ├── textureex1.frag │ │ └── textureex4.frag │ ├── 5.transformations │ │ ├── transform.frag │ │ └── transform.vs │ └── 6.coordinates │ │ ├── coordinate.frag │ │ └── coordinate.vs ├── images │ ├── awesomeface.png │ ├── container.jpg │ └── container.png ├── lighting │ ├── 1.colors │ │ ├── colors.frag │ │ ├── colors.vs │ │ ├── lamp.frag │ │ └── lamp.vs │ ├── 2.basic │ │ ├── lamp.frag │ │ ├── lamp.vs │ │ ├── lighting.frag │ │ └── lighting.vs │ └── 3.materials │ │ ├── lamp.frag │ │ ├── lamp.vs │ │ ├── materials.frag │ │ └── materials.vs ├── model_loading │ ├── shader.frag │ └── shader.vs ├── objects │ ├── cyborg │ │ ├── LICENSE.txt │ │ ├── cyborg.blend │ │ ├── cyborg.blend1 │ │ ├── cyborg.mtl │ │ ├── cyborg.obj │ │ ├── cyborg_diffuse.png │ │ ├── cyborg_normal.png │ │ └── cyborg_specular.png │ ├── nanosuit │ │ ├── arm_dif.png │ │ ├── arm_showroom_ddn.png │ │ ├── arm_showroom_refl.png │ │ ├── arm_showroom_spec.png │ │ ├── back.jpg │ │ ├── body_dif.png │ │ ├── body_showroom_ddn.png │ │ ├── body_showroom_refl.png │ │ ├── body_showroom_spec.png │ │ ├── cell_arm_alpha.png │ │ ├── cell_body_alpha.png │ │ ├── cell_ddn.png │ │ ├── cell_hand_alpha.png │ │ ├── cell_helmet_alpha.png │ │ ├── cell_leg_alpha.png │ │ ├── front.jpg │ │ ├── glass_ddn.png │ │ ├── glass_dif.png │ │ ├── glass_refl.png │ │ ├── hand_dif.png │ │ ├── hand_showroom_ddn.png │ │ ├── hand_showroom_refl.png │ │ ├── hand_showroom_spec.png │ │ ├── helmet_diff.png │ │ ├── helmet_showroom_ddn.png │ │ ├── helmet_showroom_refl.png │ │ ├── helmet_showroom_spec.png │ │ ├── leg_dif.png │ │ ├── leg_showroom_ddn.png │ │ ├── leg_showroom_refl.png │ │ ├── leg_showroom_spec.png │ │ ├── nanosuit.mtl │ │ └── nanosuit.obj │ ├── planet │ │ ├── planet.mtl │ │ ├── planet.obj │ │ └── planet_Quom1200.png │ └── rock │ │ ├── rock.mtl │ │ ├── rock.obj │ │ └── rock.png └── textures │ ├── awesomeface.png │ ├── bricks2.jpg │ ├── bricks2_disp.jpg │ ├── bricks2_normal.jpg │ ├── brickwall.jpg │ ├── brickwall_normal.jpg │ ├── container.jpg │ ├── container2.png │ ├── container2_specular.png │ ├── grass.png │ ├── marble.jpg │ ├── metal.png │ ├── pbr │ └── rusted_iron │ │ ├── albedo.png │ │ ├── ao.png │ │ ├── metallic.png │ │ ├── normal.png │ │ └── roughness.png │ ├── skybox │ ├── back.jpg │ ├── bottom.jpg │ ├── front.jpg │ ├── left.jpg │ ├── right.jpg │ └── top.jpg │ ├── toy_box_diffuse.png │ ├── toy_box_disp.png │ ├── toy_box_normal.png │ ├── window.png │ └── wood.png ├── data └── .gitignore ├── screenshot.png ├── sections ├── base.go ├── getstarted │ ├── 0.hellocube.go │ ├── 1.hellowindow.go │ ├── 2.hellotriangle.go │ ├── 3.shaders.go │ ├── 4.textures.go │ ├── 5.transformations.go │ ├── 6.coordinates.go │ └── 7.camera.go ├── lighting │ ├── 1.colors.go │ ├── 2.basic.go │ └── 3.materials.go ├── modelloading │ └── 1.model_loading.go └── title_slide.go └── tutorial.go /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | .DS_Store 3 | .idea/ 4 | *.gob -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### OpenGL Tutorial in Go 2 | * Based on the excellent [tutorial](https://learnopengl.com/) by Joey de Vries 3 | * uses [go-gl](https://github.com/go-gl) for all OpenGL Go bindings 4 | 5 | ### Installation 6 | 7 | This is setup has only been tested on macOS. 8 | I am currently working with the 4.1 core profile on macOS, which is the latest version that [ships](https://support.apple.com/en-us/HT202823) with it. I didn't want to delve into upgrading that manually. 9 | 10 | I figured I would get linux machine at a later time if I needed to use newer features in the API. 11 | The nice thing about go-gl is that you can install multiple profiles and write different programs targeting different version of OpenGL. 12 | 13 | #### go-gl packages 14 | 15 | 1- **[gl](https://github.com/go-gl/gl)** - OpenGL core profile v4.1 16 | `go get -u github.com/go-gl/gl/v4.1-core/gl` 17 | 18 | 2- [**Glow**](https://github.com/go-gl/glow) - Go binding generator for OpenGL 19 | 20 | ```shell 21 | go get github.com/go-gl/glow 22 | cd $GOPATH/src/github.com/go-gl/glow 23 | go build 24 | ./glow download 25 | ./glow generate -api=gl -version=4.1 -profile=core -remext=GL_ARB_cl_event 26 | # the profile is now installed in a gl directory 27 | go install ./gl 28 | ``` 29 | 30 | 3- [**GLFW 3.2**](https://github.com/go-gl/glfw) - Go bindings for GLFW 3 31 | `go get -u github.com/go-gl/glfw/v3.2/glfw` 32 | 33 | 4- [**MathGL**](https://github.com/go-gl/mathgl) - A pure Go 3D math library 34 | `go get github.com/go-gl/mathgl/...` 35 | 36 | This package is the equivalent of the GLM library and probably has all the functionality but after some differences. 37 | I didnt dive too deep into it, but I am getting different matrices when running the same sample in C++ with glm vs Go with mgl32. 38 | 39 | 40 | To test that the installation is working, try the examples from go-gl. 41 | 42 | ```shell 43 | go get github.com/go-gl/example 44 | cd $GOPATH/src/github.com/go-gl/example 45 | go run gl41core-cube/cube.go 46 | ``` 47 | 48 | #### learnopengl.com tutorial 49 | 50 | 1- [**assimp**](https://github.com/raedatoui/assimp) - Go wrapper of [Assimp](http://www.assimp.org/) 51 | 52 | First, install Assimp on macOS using homebrew `brew install assimp` 53 | 54 | Then install wrapper, `go get github.com/raedatoui/assimp` 55 | 56 | 2- [**glutils**](https://github.com/raedatoui/glutils) 57 | 58 | Some of the utllities developed throughout the tutorials like shader compilation and linking, camera, loading textures, loading models from assimp, other redundant GL commands,etc were packaged together. Initially, these lived within the tutorial repo as the `utils` package and we later moved to a dedicated [repo](https://github.com/raedatoui/glutils) in the hope of being useful for other projects. 59 | 60 | `go get github.com/raedatoui/glutils` 61 | 62 | 3- [**glfont**](https://github.com/raedatoui/glfont) - A modern opengl text rendering library for golang 63 | 64 | `go get github.com/raedatoui/glfont` 65 | 66 | I made minor changes to this package where I use the shader functions from the `glutils` package and I explicitly set the profile version in the imports to `4.1` intead of `all-core` 67 | 68 | Text rendering sucks and is not intended to look good, but good enough and easy to use for the sake of this tutorial. 69 | 70 | ### Run 71 | 72 | ```shell 73 | go get github.com/raedatoui/learn-opengl-golang 74 | cd $GOPATH/src/github.com/raedatoui/learn-opengl-golang 75 | go run tutorial.go 76 | ``` 77 | and you should see this screen 78 | 79 | Use the right and left arrow keys to navigate through the tutorials. 80 | 81 | Use the num keys to jump between sections. 82 | 83 | ![Alt text](/screenshot.png?raw=true "Screenshot") 84 | 85 | 86 | ### Notes 87 | 88 | When configuring vertex attribute arrays, the stride is calculated using the size of 89 | a float32 type. 90 | * sizeof(GLfloat) is 4 , float32 91 | * size of uint32 - 4 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /_assets/fonts/huge_agb_v5.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/fonts/huge_agb_v5.ttf -------------------------------------------------------------------------------- /_assets/getting_started/0.cube/square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/getting_started/0.cube/square.png -------------------------------------------------------------------------------- /_assets/getting_started/3.shaders/basic.frag: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | in vec3 ourColor; 3 | 4 | out vec4 color; 5 | 6 | void main() 7 | { 8 | color = vec4(ourColor, 1.0f); 9 | } -------------------------------------------------------------------------------- /_assets/getting_started/3.shaders/basic.vs: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | layout (location = 0) in vec3 position; 3 | layout (location = 1) in vec3 color; 4 | 5 | out vec3 ourColor; 6 | 7 | void main() 8 | { 9 | gl_Position = vec4(position, 1.0f); 10 | ourColor = color; 11 | } -------------------------------------------------------------------------------- /_assets/getting_started/3.shaders/ex4.frag: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | // in vec3 ourColor; 3 | in vec3 ourPosition; 4 | 5 | out vec4 color; 6 | 7 | void main() 8 | { 9 | color = vec4(ourPosition, 1.0f); // Note how the position value is linearly interpolated to get all the different colors 10 | } -------------------------------------------------------------------------------- /_assets/getting_started/3.shaders/ex4.vs: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | layout (location = 0) in vec3 position; 3 | layout (location = 1) in vec3 color; 4 | 5 | // out vec3 ourColor; 6 | out vec3 ourPosition; 7 | 8 | void main() 9 | { 10 | gl_Position = vec4(position, 1.0f); 11 | // ourColor = color; 12 | ourPosition = position; 13 | } -------------------------------------------------------------------------------- /_assets/getting_started/3.shaders/offset.vs: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | layout (location = 0) in vec3 position; 3 | layout (location = 1) in vec3 color; 4 | 5 | out vec3 ourColor; 6 | 7 | uniform float xOffset; 8 | 9 | void main() 10 | { 11 | gl_Position = vec4(position.x + xOffset, position.y, position.z, 1.0f); // Add the xOffset to the x position of the vertex position 12 | ourColor = color; 13 | } -------------------------------------------------------------------------------- /_assets/getting_started/3.shaders/reverse.vs: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | layout (location = 0) in vec3 position; 3 | layout (location = 1) in vec3 color; 4 | 5 | out vec3 ourColor; 6 | 7 | void main() 8 | { 9 | gl_Position = vec4(position.x, -position.y, position.z, 1.0f); // Just add a - to the y position 10 | ourColor = color; 11 | } 12 | 13 | 14 | -------------------------------------------------------------------------------- /_assets/getting_started/3.shaders/uniform.frag: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | out vec4 color; 3 | 4 | uniform vec4 ourColor; // We set this variable in the OpenGL code. 5 | 6 | void main() 7 | { 8 | color = ourColor; 9 | } -------------------------------------------------------------------------------- /_assets/getting_started/4.textures/texture.frag: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | in vec3 ourColor; 3 | in vec2 TexCoord; 4 | 5 | out vec4 color; 6 | 7 | uniform sampler2D ourTexture1; 8 | uniform sampler2D ourTexture2; 9 | 10 | void main() 11 | { 12 | color = mix(texture(ourTexture1, TexCoord), texture(ourTexture2, TexCoord), 0.2); 13 | } -------------------------------------------------------------------------------- /_assets/getting_started/4.textures/texture.vs: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | layout (location = 0) in vec3 position; 3 | layout (location = 1) in vec3 color; 4 | layout (location = 2) in vec2 texCoord; 5 | 6 | out vec3 ourColor; 7 | out vec2 TexCoord; 8 | 9 | void main() 10 | { 11 | gl_Position = vec4(position, 1.0f); 12 | ourColor = color; 13 | 14 | TexCoord = vec2(texCoord.x, 1.0 - texCoord.y); 15 | } -------------------------------------------------------------------------------- /_assets/getting_started/4.textures/textureex1.frag: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | in vec3 ourColor; 3 | in vec2 TexCoord; 4 | 5 | out vec4 color; 6 | 7 | uniform sampler2D ourTexture1; 8 | uniform sampler2D ourTexture2; 9 | 10 | void main() 11 | { 12 | color = mix(texture(ourTexture1, TexCoord), texture(ourTexture2, vec2(1.0 - TexCoord.x, TexCoord.y)), 0.2); 13 | } -------------------------------------------------------------------------------- /_assets/getting_started/4.textures/textureex4.frag: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | in vec3 ourColor; 3 | in vec2 TexCoord; 4 | 5 | out vec4 color; 6 | 7 | uniform sampler2D ourTexture1; 8 | uniform sampler2D ourTexture2; 9 | uniform float mixValue; 10 | 11 | void main() 12 | { 13 | color = mix(texture(ourTexture1, TexCoord), texture(ourTexture2, vec2(1.0 - TexCoord.x, TexCoord.y)), mixValue); 14 | } -------------------------------------------------------------------------------- /_assets/getting_started/5.transformations/transform.frag: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | in vec2 TexCoord; 3 | 4 | out vec4 color; 5 | 6 | uniform sampler2D ourTexture1; 7 | uniform sampler2D ourTexture2; 8 | 9 | void main() 10 | { 11 | color = mix(texture(ourTexture1, TexCoord), texture(ourTexture2, TexCoord), 0.2); 12 | } -------------------------------------------------------------------------------- /_assets/getting_started/5.transformations/transform.vs: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | layout (location = 0) in vec3 position; 3 | layout (location = 2) in vec2 texCoord; 4 | 5 | out vec2 TexCoord; 6 | 7 | uniform mat4 transform; 8 | 9 | void main() 10 | { 11 | gl_Position = transform * vec4(position, 1.0f); 12 | TexCoord = vec2(texCoord.x, 1.0 - texCoord.y); 13 | } -------------------------------------------------------------------------------- /_assets/getting_started/6.coordinates/coordinate.frag: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | in vec2 TexCoord; 3 | 4 | out vec4 color; 5 | 6 | uniform sampler2D ourTexture1; 7 | uniform sampler2D ourTexture2; 8 | 9 | void main() 10 | { 11 | color = mix(texture(ourTexture1, TexCoord), texture(ourTexture2, TexCoord), 0.2); 12 | } -------------------------------------------------------------------------------- /_assets/getting_started/6.coordinates/coordinate.vs: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | layout (location = 0) in vec3 position; 3 | layout (location = 2) in vec2 texCoord; 4 | 5 | out vec2 TexCoord; 6 | 7 | uniform mat4 model; 8 | uniform mat4 view; 9 | uniform mat4 projection; 10 | 11 | void main() 12 | { 13 | gl_Position = projection * view * model * vec4(position, 1.0f); 14 | TexCoord = vec2(texCoord.x, 1.0 - texCoord.y); 15 | } -------------------------------------------------------------------------------- /_assets/images/awesomeface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/images/awesomeface.png -------------------------------------------------------------------------------- /_assets/images/container.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/images/container.jpg -------------------------------------------------------------------------------- /_assets/images/container.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/images/container.png -------------------------------------------------------------------------------- /_assets/lighting/1.colors/colors.frag: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | out vec4 color; 3 | 4 | uniform vec3 objectColor; 5 | uniform vec3 lightColor; 6 | 7 | void main() 8 | { 9 | color = vec4(lightColor * objectColor, 1.0f); 10 | } -------------------------------------------------------------------------------- /_assets/lighting/1.colors/colors.vs: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | layout (location = 0) in vec3 position; 3 | 4 | uniform mat4 model; 5 | uniform mat4 view; 6 | uniform mat4 projection; 7 | 8 | void main() 9 | { 10 | gl_Position = projection * view * model * vec4(position, 1.0f); 11 | } -------------------------------------------------------------------------------- /_assets/lighting/1.colors/lamp.frag: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | out vec4 color; 3 | 4 | void main() 5 | { 6 | color = vec4(1.0f); // Set alle 4 vector values to 1.0f 7 | } -------------------------------------------------------------------------------- /_assets/lighting/1.colors/lamp.vs: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | layout (location = 0) in vec3 position; 3 | 4 | uniform mat4 model; 5 | uniform mat4 view; 6 | uniform mat4 projection; 7 | 8 | void main() 9 | { 10 | gl_Position = projection * view * model * vec4(position, 1.0f); 11 | } -------------------------------------------------------------------------------- /_assets/lighting/2.basic/lamp.frag: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | out vec4 color; 3 | 4 | void main() 5 | { 6 | color = vec4(1.0f); // Set alle 4 vector values to 1.0f 7 | } -------------------------------------------------------------------------------- /_assets/lighting/2.basic/lamp.vs: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | layout (location = 0) in vec3 position; 3 | 4 | uniform mat4 model; 5 | uniform mat4 view; 6 | uniform mat4 projection; 7 | 8 | void main() 9 | { 10 | gl_Position = projection * view * model * vec4(position, 1.0f); 11 | } -------------------------------------------------------------------------------- /_assets/lighting/2.basic/lighting.frag: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | out vec4 color; 3 | 4 | in vec3 FragPos; 5 | in vec3 Normal; 6 | 7 | uniform vec3 lightPos; 8 | uniform vec3 viewPos; 9 | uniform vec3 lightColor; 10 | uniform vec3 objectColor; 11 | 12 | void main() 13 | { 14 | // Ambient 15 | float ambientStrength = 0.1f; 16 | vec3 ambient = ambientStrength * lightColor; 17 | 18 | // Diffuse 19 | vec3 norm = normalize(Normal); 20 | vec3 lightDir = normalize(lightPos - FragPos); 21 | float diff = max(dot(norm, lightDir), 0.0); 22 | vec3 diffuse = diff * lightColor; 23 | 24 | // Specular 25 | float specularStrength = 0.5f; 26 | vec3 viewDir = normalize(viewPos - FragPos); 27 | vec3 reflectDir = reflect(-lightDir, norm); 28 | float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32); 29 | vec3 specular = specularStrength * spec * lightColor; 30 | 31 | vec3 result = (ambient + diffuse + specular) * objectColor; 32 | color = vec4(result, 1.0f); 33 | } -------------------------------------------------------------------------------- /_assets/lighting/2.basic/lighting.vs: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | layout (location = 0) in vec3 position; 3 | layout (location = 1) in vec3 normal; 4 | 5 | out vec3 Normal; 6 | out vec3 FragPos; 7 | 8 | uniform mat4 model; 9 | uniform mat4 view; 10 | uniform mat4 projection; 11 | 12 | void main() 13 | { 14 | gl_Position = projection * view * model * vec4(position, 1.0f); 15 | FragPos = vec3(model * vec4(position, 1.0f)); 16 | Normal = mat3(transpose(inverse(model))) * normal; 17 | } -------------------------------------------------------------------------------- /_assets/lighting/3.materials/lamp.frag: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | out vec4 color; 3 | 4 | void main() 5 | { 6 | color = vec4(1.0f); // Set alle 4 vector values to 1.0f 7 | } -------------------------------------------------------------------------------- /_assets/lighting/3.materials/lamp.vs: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | layout (location = 0) in vec3 position; 3 | 4 | uniform mat4 model; 5 | uniform mat4 view; 6 | uniform mat4 projection; 7 | 8 | void main() 9 | { 10 | gl_Position = projection * view * model * vec4(position, 1.0f); 11 | } -------------------------------------------------------------------------------- /_assets/lighting/3.materials/materials.frag: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | struct Material { 3 | vec3 ambient; 4 | vec3 diffuse; 5 | vec3 specular; 6 | float shininess; 7 | }; 8 | 9 | struct Light { 10 | vec3 position; 11 | 12 | vec3 ambient; 13 | vec3 diffuse; 14 | vec3 specular; 15 | }; 16 | 17 | in vec3 FragPos; 18 | in vec3 Normal; 19 | 20 | out vec4 color; 21 | 22 | uniform vec3 viewPos; 23 | uniform Material material; 24 | uniform Light light; 25 | 26 | void main() 27 | { 28 | // Ambient 29 | vec3 ambient = light.ambient * material.ambient; 30 | 31 | // Diffuse 32 | vec3 norm = normalize(Normal); 33 | vec3 lightDir = normalize(light.position - FragPos); 34 | float diff = max(dot(norm, lightDir), 0.0); 35 | vec3 diffuse = light.diffuse * (diff * material.diffuse); 36 | 37 | // Specular 38 | vec3 viewDir = normalize(viewPos - FragPos); 39 | vec3 reflectDir = reflect(-lightDir, norm); 40 | float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); 41 | vec3 specular = light.specular * (spec * material.specular); 42 | 43 | vec3 result = ambient + diffuse + specular; 44 | color = vec4(result, 1.0f); 45 | } -------------------------------------------------------------------------------- /_assets/lighting/3.materials/materials.vs: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | layout (location = 0) in vec3 position; 3 | layout (location = 1) in vec3 normal; 4 | 5 | out vec3 Normal; 6 | out vec3 FragPos; 7 | 8 | uniform mat4 model; 9 | uniform mat4 view; 10 | uniform mat4 projection; 11 | 12 | void main() 13 | { 14 | gl_Position = projection * view * model * vec4(position, 1.0f); 15 | FragPos = vec3(model * vec4(position, 1.0f)); 16 | Normal = mat3(transpose(inverse(model))) * normal; 17 | } -------------------------------------------------------------------------------- /_assets/model_loading/shader.frag: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | in vec2 TexCoords; 3 | out vec4 color; 4 | 5 | uniform sampler2D texture_diffuse1; 6 | 7 | void main() 8 | { 9 | color = texture(texture_diffuse1, TexCoords); 10 | } -------------------------------------------------------------------------------- /_assets/model_loading/shader.vs: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | layout (location = 0) in vec3 position; 3 | //layout (location = 1) in vec3 normal; 4 | layout (location = 2) in vec2 texCoords; 5 | 6 | 7 | out vec2 TexCoords; 8 | 9 | uniform mat4 model; 10 | uniform mat4 view; 11 | uniform mat4 projection; 12 | 13 | void main() 14 | { 15 | gl_Position = projection * view * model * vec4(position, 1.0f); 16 | TexCoords = texCoords; 17 | } -------------------------------------------------------------------------------- /_assets/objects/cyborg/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Slightly adapted version (by Joey de Vries) of Cyborg model. 2 | 3 | From: 3dregenerator 4 | Downloaded at: http://tf3dm.com/3d-model/cyborg-78.html 5 | 6 | For Personal Use Only. -------------------------------------------------------------------------------- /_assets/objects/cyborg/cyborg.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/cyborg/cyborg.blend -------------------------------------------------------------------------------- /_assets/objects/cyborg/cyborg.blend1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/cyborg/cyborg.blend1 -------------------------------------------------------------------------------- /_assets/objects/cyborg/cyborg.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'cyborg.blend' 2 | # Material Count: 1 3 | 4 | newmtl Cyborg 5 | Ns 92.156863 6 | Ka 0.000000 0.000000 0.000000 7 | Kd 0.512000 0.512000 0.512000 8 | Ks 0.000000 0.000000 0.000000 9 | Ni 1.000000 10 | d 1.000000 11 | illum 2 12 | map_Kd cyborg_diffuse.png 13 | map_Bump cyborg_normal.png 14 | map_Ks cyborg_specular.png 15 | -------------------------------------------------------------------------------- /_assets/objects/cyborg/cyborg_diffuse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/cyborg/cyborg_diffuse.png -------------------------------------------------------------------------------- /_assets/objects/cyborg/cyborg_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/cyborg/cyborg_normal.png -------------------------------------------------------------------------------- /_assets/objects/cyborg/cyborg_specular.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/cyborg/cyborg_specular.png -------------------------------------------------------------------------------- /_assets/objects/nanosuit/arm_dif.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/nanosuit/arm_dif.png -------------------------------------------------------------------------------- /_assets/objects/nanosuit/arm_showroom_ddn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/nanosuit/arm_showroom_ddn.png -------------------------------------------------------------------------------- /_assets/objects/nanosuit/arm_showroom_refl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/nanosuit/arm_showroom_refl.png -------------------------------------------------------------------------------- /_assets/objects/nanosuit/arm_showroom_spec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/nanosuit/arm_showroom_spec.png -------------------------------------------------------------------------------- /_assets/objects/nanosuit/back.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/nanosuit/back.jpg -------------------------------------------------------------------------------- /_assets/objects/nanosuit/body_dif.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/nanosuit/body_dif.png -------------------------------------------------------------------------------- /_assets/objects/nanosuit/body_showroom_ddn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/nanosuit/body_showroom_ddn.png -------------------------------------------------------------------------------- /_assets/objects/nanosuit/body_showroom_refl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/nanosuit/body_showroom_refl.png -------------------------------------------------------------------------------- /_assets/objects/nanosuit/body_showroom_spec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/nanosuit/body_showroom_spec.png -------------------------------------------------------------------------------- /_assets/objects/nanosuit/cell_arm_alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/nanosuit/cell_arm_alpha.png -------------------------------------------------------------------------------- /_assets/objects/nanosuit/cell_body_alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/nanosuit/cell_body_alpha.png -------------------------------------------------------------------------------- /_assets/objects/nanosuit/cell_ddn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/nanosuit/cell_ddn.png -------------------------------------------------------------------------------- /_assets/objects/nanosuit/cell_hand_alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/nanosuit/cell_hand_alpha.png -------------------------------------------------------------------------------- /_assets/objects/nanosuit/cell_helmet_alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/nanosuit/cell_helmet_alpha.png -------------------------------------------------------------------------------- /_assets/objects/nanosuit/cell_leg_alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/nanosuit/cell_leg_alpha.png -------------------------------------------------------------------------------- /_assets/objects/nanosuit/front.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/nanosuit/front.jpg -------------------------------------------------------------------------------- /_assets/objects/nanosuit/glass_ddn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/nanosuit/glass_ddn.png -------------------------------------------------------------------------------- /_assets/objects/nanosuit/glass_dif.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/nanosuit/glass_dif.png -------------------------------------------------------------------------------- /_assets/objects/nanosuit/glass_refl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/nanosuit/glass_refl.png -------------------------------------------------------------------------------- /_assets/objects/nanosuit/hand_dif.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/nanosuit/hand_dif.png -------------------------------------------------------------------------------- /_assets/objects/nanosuit/hand_showroom_ddn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/nanosuit/hand_showroom_ddn.png -------------------------------------------------------------------------------- /_assets/objects/nanosuit/hand_showroom_refl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/nanosuit/hand_showroom_refl.png -------------------------------------------------------------------------------- /_assets/objects/nanosuit/hand_showroom_spec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/nanosuit/hand_showroom_spec.png -------------------------------------------------------------------------------- /_assets/objects/nanosuit/helmet_diff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/nanosuit/helmet_diff.png -------------------------------------------------------------------------------- /_assets/objects/nanosuit/helmet_showroom_ddn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/nanosuit/helmet_showroom_ddn.png -------------------------------------------------------------------------------- /_assets/objects/nanosuit/helmet_showroom_refl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/nanosuit/helmet_showroom_refl.png -------------------------------------------------------------------------------- /_assets/objects/nanosuit/helmet_showroom_spec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/nanosuit/helmet_showroom_spec.png -------------------------------------------------------------------------------- /_assets/objects/nanosuit/leg_dif.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/nanosuit/leg_dif.png -------------------------------------------------------------------------------- /_assets/objects/nanosuit/leg_showroom_ddn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/nanosuit/leg_showroom_ddn.png -------------------------------------------------------------------------------- /_assets/objects/nanosuit/leg_showroom_refl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/nanosuit/leg_showroom_refl.png -------------------------------------------------------------------------------- /_assets/objects/nanosuit/leg_showroom_spec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/nanosuit/leg_showroom_spec.png -------------------------------------------------------------------------------- /_assets/objects/nanosuit/nanosuit.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'nanosuit.blend' 2 | # Material Count: 6 3 | 4 | newmtl Arm 5 | Ns 96.078431 6 | Ka 0.000000 0.000000 0.000000 7 | Kd 0.640000 0.640000 0.640000 8 | Ks 0.500000 0.500000 0.500000 9 | Ni 1.000000 10 | d 1.000000 11 | illum 2 12 | map_Bump arm_showroom_ddn.png 13 | map_Ka arm_showroom_refl.png 14 | map_Kd arm_dif.png 15 | map_Ks arm_showroom_spec.png 16 | 17 | newmtl Body 18 | Ns 96.078431 19 | Ka 0.000000 0.000000 0.000000 20 | Kd 0.640000 0.640000 0.640000 21 | Ks 0.500000 0.500000 0.500000 22 | Ni 1.000000 23 | d 1.000000 24 | illum 2 25 | map_Kd body_dif.png 26 | map_Bump body_showroom_ddn.png 27 | map_Ka body_showroom_refl.png 28 | map_Ks body_showroom_spec.png 29 | 30 | newmtl Glass 31 | Ns 96.078431 32 | Ka 0.000000 0.000000 0.000000 33 | Kd 0.640000 0.640000 0.640000 34 | Ks 0.500000 0.500000 0.500000 35 | Ni 1.000000 36 | d 1.000000 37 | illum 2 38 | map_Bump glass_ddn.png 39 | map_Ka glass_refl.png 40 | map_Kd glass_dif.png 41 | 42 | newmtl Hand 43 | Ns 96.078431 44 | Ka 0.000000 0.000000 0.000000 45 | Kd 0.640000 0.640000 0.640000 46 | Ks 0.500000 0.500000 0.500000 47 | Ni 1.000000 48 | d 1.000000 49 | illum 2 50 | map_Bump hand_showroom_ddn.png 51 | map_Ka hand_showroom_refl.png 52 | map_Kd hand_dif.png 53 | map_Ks hand_showroom_spec.png 54 | 55 | newmtl Helmet 56 | Ns 96.078431 57 | Ka 0.000000 0.000000 0.000000 58 | Kd 0.640000 0.640000 0.640000 59 | Ks 0.500000 0.500000 0.500000 60 | Ni 1.000000 61 | d 1.000000 62 | illum 2 63 | map_Bump helmet_showroom_ddn.png 64 | map_Ka helmet_showroom_refl.png 65 | map_Kd helmet_diff.png 66 | map_Ks helmet_showroom_spec.png 67 | 68 | newmtl Leg 69 | Ns 96.078431 70 | Ka 0.000000 0.000000 0.000000 71 | Kd 0.640000 0.640000 0.640000 72 | Ks 0.500000 0.500000 0.500000 73 | Ni 1.000000 74 | d 1.000000 75 | illum 2 76 | map_Bump leg_showroom_ddn.png 77 | map_Ka leg_showroom_refl.png 78 | map_Kd leg_dif.png 79 | map_Ks leg_showroom_spec.png 80 | -------------------------------------------------------------------------------- /_assets/objects/planet/planet.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL 2 | # Material Count: 1 3 | 4 | newmtl Material.001 5 | Ns 96.078431 6 | Ka 0.000000 0.000000 0.000000 7 | Kd 0.640000 0.640000 0.640000 8 | Ks 0.087302 0.087302 0.087302 9 | Ni 1.000000 10 | d 1.000000 11 | illum 2 12 | map_Kd planet_Quom1200.png 13 | map_Bump planet_Quom1200.png 14 | -------------------------------------------------------------------------------- /_assets/objects/planet/planet_Quom1200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/planet/planet_Quom1200.png -------------------------------------------------------------------------------- /_assets/objects/rock/rock.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'Rock1.blend' 2 | # Material Count: 1 3 | 4 | newmtl Material 5 | Ns 13.725490 6 | Ka 0.000000 0.000000 0.000000 7 | Kd 0.640000 0.640000 0.640000 8 | Ks 0.007937 0.007937 0.007937 9 | Ni 1.000000 10 | d 1.000000 11 | illum 2 12 | map_Kd rock.png 13 | map_Bump rock.png 14 | -------------------------------------------------------------------------------- /_assets/objects/rock/rock.obj: -------------------------------------------------------------------------------- 1 | # Blender v2.71 (sub 0) OBJ File: 'Rock1.blend' 2 | # www.blender.org 3 | mtllib rock.mtl 4 | o Cube 5 | v 0.896930 -0.116701 -1.078061 6 | v 0.736314 -0.076033 1.066762 7 | v -1.052088 -0.064600 0.954513 8 | v -0.692441 -0.114299 -0.835835 9 | v 1.303753 1.083753 -1.023542 10 | v 0.444005 1.032712 1.513821 11 | v -1.019775 1.174950 1.105961 12 | v -0.681862 1.180458 -1.481573 13 | v 1.045407 -0.157597 -0.147996 14 | v 0.067265 -0.072713 -0.783522 15 | v 1.200361 0.538245 -1.221685 16 | v -0.154563 -0.114500 1.228987 17 | v 1.155268 0.478039 1.381585 18 | v -1.094633 -0.254018 -0.118459 19 | v -1.648060 0.452009 0.853586 20 | v -1.185727 0.481559 -1.133555 21 | v 0.975431 1.246558 0.047895 22 | v 0.105258 1.126820 -1.585067 23 | v -0.344848 1.152380 1.730000 24 | v -1.177093 1.303243 0.009798 25 | v -0.015789 -0.312706 -0.060242 26 | v 0.046107 1.351565 -0.253730 27 | v 1.175182 0.692469 0.169032 28 | v 0.260077 0.452640 1.365451 29 | v -1.648881 0.429819 -0.064031 30 | v -0.199824 0.336820 -1.536424 31 | v 1.008866 -0.126459 0.470257 32 | v -0.321458 -0.060305 -0.702046 33 | v 1.385825 0.807576 -1.181814 34 | v -0.537873 -0.057997 1.154378 35 | v 0.936321 0.677546 1.426494 36 | v -0.862364 -0.219203 -0.537108 37 | v -1.281588 0.883991 1.218077 38 | v -0.974527 0.926074 -1.431442 39 | v 0.808457 1.346412 0.902078 40 | v -0.174992 1.147173 -1.801163 41 | v -0.610285 1.147948 1.327881 42 | v -1.356023 1.245036 -0.716849 43 | v 1.042022 -0.190494 -0.637866 44 | v 0.468949 -0.142859 -1.026806 45 | v 1.081272 0.175115 -1.287556 46 | v 0.243586 -0.141476 1.191072 47 | v 1.014587 0.183491 1.312948 48 | v -1.155731 -0.217847 0.459469 49 | v -1.571341 0.110279 0.770709 50 | v -1.063276 0.074521 -1.015607 51 | v 1.231954 1.216866 -0.594471 52 | v 0.770454 1.122192 -1.299703 53 | v -0.065279 1.102928 1.796044 54 | v -1.176430 1.281231 0.646380 55 | v -0.476225 -0.274043 -0.037390 56 | v 0.480423 -0.312115 -0.111060 57 | v 0.172793 -0.188473 -0.532460 58 | v -0.106274 -0.274351 0.595963 59 | v -0.198010 1.360380 0.630818 60 | v 0.062998 1.276304 -0.994314 61 | v 0.611501 1.352344 -0.290780 62 | v -0.603343 1.343584 -0.011276 63 | v 1.267461 0.630730 1.008356 64 | v 1.267107 0.600208 -0.689727 65 | v 1.268899 0.241091 -0.063884 66 | v 1.050912 1.068502 0.197512 67 | v -1.043570 0.402928 1.289593 68 | v 0.667029 0.439932 1.448684 69 | v -0.135120 0.156677 1.505020 70 | v -0.066870 0.652060 1.602193 71 | v -1.759897 0.319614 -0.724614 72 | v -1.646483 0.462612 0.459024 73 | v -1.548443 -0.153801 -0.255587 74 | v -1.483055 1.068517 0.045330 75 | v -0.775458 0.497559 -1.402503 76 | v 0.556317 0.449266 -1.496503 77 | v 0.153226 0.839249 -1.832230 78 | v -0.180515 0.060946 -1.233899 79 | v -0.630920 -0.226328 0.592326 80 | v -0.677921 1.329703 0.698183 81 | v 1.115930 1.067893 0.980967 82 | v -0.944509 0.743625 1.392342 83 | v -1.719440 0.916506 -0.699776 84 | v -0.751048 0.149059 -1.123006 85 | v -0.359688 -0.219676 -0.596748 86 | v 0.548058 -0.284113 -0.657622 87 | v 0.383454 -0.298149 0.533170 88 | v 0.342781 1.370886 0.863692 89 | v 0.801564 1.333314 -0.716665 90 | v -0.544178 1.290048 -0.889409 91 | v 1.347667 0.189763 0.746821 92 | v 1.323792 0.127379 -0.856060 93 | v 1.423543 0.897206 -0.707035 94 | v -0.706694 0.190636 1.346937 95 | v 0.494274 0.153436 1.399456 96 | v 0.524189 0.691410 1.410453 97 | v -1.346437 -0.078697 -0.808084 98 | v -1.550380 0.033513 0.487642 99 | v -1.434319 1.017100 0.746778 100 | v -0.263198 0.916780 -1.716774 101 | v 0.802037 0.850318 -1.528586 102 | v 0.512712 0.114694 -1.198383 103 | vt 0.058285 0.569867 104 | vt 0.082613 0.506661 105 | vt 0.152906 0.498683 106 | vt 0.206316 0.378186 107 | vt 0.155630 0.402329 108 | vt 0.099783 0.387655 109 | vt 0.854473 0.349296 110 | vt 0.794976 0.248970 111 | vt 0.870663 0.174892 112 | vt 0.944083 0.694636 113 | vt 0.905653 0.682602 114 | vt 0.916733 0.604517 115 | vt 0.336809 0.082005 116 | vt 0.369246 0.000842 117 | vt 0.489191 0.000000 118 | vt 0.512673 0.310590 119 | vt 0.481603 0.323059 120 | vt 0.447322 0.276247 121 | vt 0.276846 0.583529 122 | vt 0.215363 0.578539 123 | vt 0.223692 0.502410 124 | vt 0.288525 0.695621 125 | vt 0.226456 0.694739 126 | vt 0.220811 0.635843 127 | vt 0.149628 0.688747 128 | vt 0.060049 0.668982 129 | vt 0.053708 0.620010 130 | vt 0.115533 0.299946 131 | vt 0.042023 0.402498 132 | vt 0.011393 0.383384 133 | vt 0.133867 0.094672 134 | vt 0.226136 0.127633 135 | vt 0.165692 0.199396 136 | vt 0.273683 0.187557 137 | vt 0.335575 0.267841 138 | vt 0.258354 0.321530 139 | vt 0.422948 0.654063 140 | vt 0.520455 0.684734 141 | vt 0.477461 0.726331 142 | vt 0.422729 0.459207 143 | vt 0.529375 0.479105 144 | vt 0.539575 0.580737 145 | vt 0.744126 0.814485 146 | vt 0.672331 0.787452 147 | vt 0.683844 0.711964 148 | vt 0.016271 0.536299 149 | vt 0.006598 0.482318 150 | vt 0.054401 0.402498 151 | vt 0.855242 0.125920 152 | vt 0.818683 0.137473 153 | vt 0.786060 0.070157 154 | vt 0.829103 0.182611 155 | vt 0.720806 0.251159 156 | vt 0.693981 0.268226 157 | vt 0.348488 0.225548 158 | vt 0.431026 0.176751 159 | vt 0.821728 0.494375 160 | vt 0.758928 0.488146 161 | vt 0.747834 0.361119 162 | vt 0.853441 0.628842 163 | vt 0.844101 0.700647 164 | vt 0.766741 0.707183 165 | vt 0.554998 0.057463 166 | vt 0.491069 0.166304 167 | vt 0.661203 0.071636 168 | vt 0.642437 0.169965 169 | vt 0.565426 0.199969 170 | vt 0.619708 0.321108 171 | vt 0.560004 0.310321 172 | vt 0.556413 0.271543 173 | vt 0.137636 0.563411 174 | vt 0.140662 0.629249 175 | vt 0.155028 0.344089 176 | vt 0.206193 0.274302 177 | vt 0.896175 0.282885 178 | vt 0.907061 0.133559 179 | vt 0.622627 0.581780 180 | vt 0.617335 0.678426 181 | vt 0.662917 0.562066 182 | vt 0.672331 0.661064 183 | vt 0.949240 0.587705 184 | vt 0.869574 0.490922 185 | vt 0.791582 0.866218 186 | vt 0.744126 0.821215 187 | vt 0.752056 0.707183 188 | vt 0.999879 0.706758 189 | vt 0.460672 0.063535 190 | vt 0.766456 0.640000 191 | vt 0.672331 0.596657 192 | vt 0.677773 0.459778 193 | vt 0.674914 0.687648 194 | vt 0.485748 0.254952 195 | vt 0.336809 0.833560 196 | vt 0.336920 0.785916 197 | vt 0.384519 0.726331 198 | vt 0.506205 0.350977 199 | vt 0.448079 0.354288 200 | vt 0.559475 0.342029 201 | vt 0.266533 0.646047 202 | vt 0.609960 0.361119 203 | vt 0.278588 0.749240 204 | vt 0.320949 0.673747 205 | vt 0.218381 0.752553 206 | vt 0.143231 0.752483 207 | vt 0.069266 0.722735 208 | vt 0.808347 0.361119 209 | vt 0.116225 0.149680 210 | vt 0.046020 0.277128 211 | vt 0.000000 0.241327 212 | vt 0.056221 0.145884 213 | vt 0.187902 0.035191 214 | vt 0.085645 0.065345 215 | vt 0.273048 0.064123 216 | vt 0.316518 0.068429 217 | vt 0.336809 0.140426 218 | vt 0.340137 0.610197 219 | vt 0.404599 0.713241 220 | vt 0.339988 0.536299 221 | vt 0.439840 0.553878 222 | vt 0.429528 0.400325 223 | vt 0.336833 0.476818 224 | vt 0.517650 0.412671 225 | vt 0.604166 0.482239 226 | vt 0.586459 0.423461 227 | vt 0.646477 0.441109 228 | vt 0.670954 0.491413 229 | vt 0.090851 0.431859 230 | vt 0.000000 0.608449 231 | vt 0.694133 0.143704 232 | vt 0.012308 0.682984 233 | vt 0.019832 0.742597 234 | vt 0.857058 0.070133 235 | vt 0.758736 0.168010 236 | vt 0.408067 0.318081 237 | vt 0.232244 0.440506 238 | vt 0.291247 0.454530 239 | vt 0.270084 0.523882 240 | vt 0.685316 0.388716 241 | vt 0.130148 0.436240 242 | vt 0.834672 0.401576 243 | vt 0.563922 0.000091 244 | vt 0.582099 0.007382 245 | vt 0.608937 0.072162 246 | vt 0.207942 0.000000 247 | vt 0.293309 0.025246 248 | vt 0.579472 0.365264 249 | vt 0.477201 0.361119 250 | vt 0.628288 0.255903 251 | vt 0.693981 0.150197 252 | vt 0.693822 0.237100 253 | vt 0.668575 0.311882 254 | vt 0.731678 0.707183 255 | vt 0.934356 0.187628 256 | vt 0.939564 0.506329 257 | vt 0.791426 0.711743 258 | vt 1.000000 0.606532 259 | vt 0.387737 0.801509 260 | vt 0.324683 0.722893 261 | vt 0.116277 0.014773 262 | vt 0.336809 0.674909 263 | vt 0.353162 0.419686 264 | vt 0.736508 0.092307 265 | vt 0.913859 0.076969 266 | vt 0.867108 0.417288 267 | vt 0.639569 0.392860 268 | vn -0.233500 -0.819800 0.522800 269 | vn -0.341800 -0.625700 0.701200 270 | vn -0.276700 -0.937700 0.209800 271 | vn -0.424000 0.890700 0.163900 272 | vn -0.339200 0.818400 0.463900 273 | vn -0.460600 0.772900 0.436500 274 | vn 0.378500 0.884900 0.271500 275 | vn 0.471200 0.579600 0.664800 276 | vn 0.320600 0.158900 0.933800 277 | vn -0.646800 0.288800 0.705800 278 | vn -0.900700 0.371900 -0.224300 279 | vn -0.458400 0.862700 -0.213600 280 | vn -0.301000 0.819900 -0.486800 281 | vn 0.010700 -0.806900 -0.590500 282 | vn 0.230000 -0.694400 -0.681800 283 | vn -0.231200 -0.595000 -0.769700 284 | vn 0.016800 -0.846500 -0.532100 285 | vn -0.040300 -0.998600 -0.032900 286 | vn -0.122100 -0.991600 -0.041200 287 | vn -0.012200 -0.971900 -0.235000 288 | vn 0.122300 -0.992400 0.015000 289 | vn -0.071000 -0.993000 -0.094000 290 | vn 0.122200 -0.981400 0.148100 291 | vn 0.080500 -0.849300 0.521600 292 | vn -0.086200 -0.849400 0.520600 293 | vn -0.046700 0.996400 0.070500 294 | vn -0.217700 0.494400 0.841500 295 | vn -0.086400 0.146500 0.985400 296 | vn 0.178300 0.970700 -0.161300 297 | vn 0.007300 0.987200 -0.159100 298 | vn -0.027300 0.998100 -0.054800 299 | vn -0.044300 0.991500 -0.121900 300 | vn -0.344700 0.938400 0.022500 301 | vn 0.921600 -0.360400 0.143800 302 | vn 0.959300 0.222600 0.173800 303 | vn 0.648500 -0.032100 0.760500 304 | vn 0.919900 -0.291200 -0.262500 305 | vn 0.985400 -0.162400 0.050100 306 | vn 0.963400 0.267200 -0.018400 307 | vn 0.993300 0.035300 0.109500 308 | vn 0.638100 0.769000 0.038600 309 | vn 0.596700 0.799100 0.073100 310 | vn -0.326300 -0.473800 0.818000 311 | vn -0.434100 -0.329200 0.838600 312 | vn -0.913600 0.089800 0.396600 313 | vn 0.126700 -0.032600 0.991400 314 | vn -0.189100 -0.186900 0.964000 315 | vn -0.073600 -0.184200 0.980100 316 | vn 0.114700 -0.242200 0.963400 317 | vn -0.899000 -0.340400 -0.275600 318 | vn -0.479500 -0.331900 -0.812300 319 | vn -0.993700 0.107100 0.034300 320 | vn -0.999200 0.000100 0.039900 321 | vn -0.739400 -0.654700 -0.156500 322 | vn -0.824700 0.505000 0.254600 323 | vn -0.218100 -0.181700 -0.958800 324 | vn -0.432200 -0.296800 -0.851500 325 | vn 0.426900 0.149400 -0.891800 326 | vn 0.225900 -0.430300 -0.873900 327 | vn -0.117000 -0.587100 -0.801000 328 | vn -0.076900 -0.842600 -0.532900 329 | vn -0.211900 -0.938300 -0.273300 330 | vn -0.131600 -0.849400 -0.511000 331 | vn -0.085500 -0.979800 0.180600 332 | vn -0.055900 -0.987800 0.145500 333 | vn -0.093600 0.986700 0.133100 334 | vn -0.043400 0.998800 -0.021100 335 | vn 0.752400 0.571000 0.328300 336 | vn 0.940500 0.338300 0.030400 337 | vn -0.364600 -0.020200 0.930900 338 | vn -0.006300 -0.522900 0.852400 339 | vn -0.549100 0.086400 -0.831300 340 | vn -0.818900 0.564900 0.101300 341 | vn -0.109100 -0.775000 -0.622500 342 | vn -0.043500 -0.970400 -0.237300 343 | vn -0.216400 -0.916000 -0.337700 344 | vn 0.483000 -0.867200 -0.120600 345 | vn 0.586200 -0.808400 0.052800 346 | vn 0.453300 -0.878500 0.150900 347 | vn 0.302100 -0.888100 0.346500 348 | vn -0.011700 0.990200 0.139300 349 | vn 0.104700 0.994500 -0.006000 350 | vn 0.287400 0.799500 -0.527400 351 | vn 0.226500 0.797300 -0.559400 352 | vn 0.166900 0.398200 -0.901900 353 | vn 0.449900 -0.591100 0.669400 354 | vn 0.991200 -0.131900 -0.006400 355 | vn 0.421700 -0.247600 -0.872200 356 | vn 0.719900 -0.329000 -0.611100 357 | vn 0.873300 -0.027000 -0.486400 358 | vn 0.695900 0.658800 -0.285700 359 | vn -0.735800 -0.552500 0.391500 360 | vn 0.149300 -0.476900 0.866200 361 | vn -0.467200 -0.714600 -0.520600 362 | vn -0.791300 -0.591900 0.152900 363 | vn 0.150800 0.022200 -0.988300 364 | vn 0.072000 -0.564800 -0.822100 365 | vn 0.246700 -0.812300 -0.528500 366 | usemtl Material 367 | s 1 368 | f 30/1/1 3/2/2 44/3/3 369 | f 50/4/4 7/5/5 37/6/6 370 | f 35/7/7 6/8/8 31/9/9 371 | f 37/10/6 7/11/5 33/12/10 372 | f 79/13/11 38/14/12 8/15/13 373 | f 28/16/14 4/17/15 46/18/16 374 | f 81/19/17 51/20/18 14/21/19 375 | f 82/22/20 52/23/21 21/24/22 376 | f 83/25/23 42/26/24 12/27/25 377 | f 55/28/26 19/29/27 49/30/28 378 | f 85/31/29 56/32/30 22/33/31 379 | f 86/34/32 38/35/12 20/36/33 380 | f 87/37/34 59/38/35 13/39/36 381 | f 88/40/37 60/41/38 23/42/39 382 | f 89/43/40 47/44/41 17/45/42 383 | f 90/46/43 63/47/44 15/48/45 384 | f 64/49/46 24/50/47 65/51/48 385 | f 92/52/49 49/53/28 19/54/27 386 | f 67/55/50 16/56/51 46/18/16 387 | f 68/57/52 25/58/53 69/59/54 388 | f 95/60/55 50/61/4 20/62/33 389 | f 96/63/56 71/64/57 16/56/51 390 | f 97/65/58 72/66/59 26/67/60 391 | f 40/68/61 10/69/62 74/70/63 392 | f 75/71/64 44/3/3 14/21/19 393 | f 21/24/22 54/72/65 75/71/64 394 | f 12/27/25 30/1/1 75/71/64 395 | f 76/73/66 37/6/6 19/29/27 396 | f 22/33/31 58/74/67 76/73/66 397 | f 58/74/67 20/36/33 50/4/4 398 | f 77/75/68 31/9/9 13/76/36 399 | f 62/77/69 77/78/68 59/38/35 400 | f 17/79/42 35/80/7 77/78/68 401 | f 78/81/70 33/12/10 15/82/45 402 | f 24/83/47 66/84/71 78/85/70 403 | f 19/86/27 37/10/6 78/81/70 404 | f 67/55/50 79/13/11 34/87/72 405 | f 70/88/73 79/89/11 67/90/50 406 | f 20/62/33 38/91/12 79/89/11 407 | f 71/64/57 80/92/74 46/18/16 408 | f 74/70/63 80/92/74 71/64/57 409 | f 10/93/62 28/94/14 80/95/74 410 | f 28/16/14 81/96/17 32/97/75 411 | f 53/98/76 81/96/17 28/16/14 412 | f 53/99/76 21/24/22 51/20/18 413 | f 40/68/61 82/100/20 53/98/76 414 | f 39/101/77 82/22/20 40/102/61 415 | f 39/101/77 9/103/78 52/23/21 416 | f 52/23/21 83/25/23 54/72/65 417 | f 9/103/78 27/104/79 83/25/23 418 | f 27/104/79 2/105/80 42/26/24 419 | f 35/7/7 84/106/81 49/53/28 420 | f 57/107/82 84/108/81 35/109/7 421 | f 57/107/82 22/33/31 55/28/26 422 | f 85/31/29 57/107/82 17/110/42 423 | f 48/111/83 85/31/29 47/112/41 424 | f 18/113/84 56/32/30 85/31/29 425 | f 56/32/30 86/34/32 58/74/67 426 | f 36/114/85 86/34/32 56/32/30 427 | f 36/114/85 8/115/13 38/35/12 428 | f 27/116/79 87/37/34 43/117/86 429 | f 9/118/78 61/119/87 87/37/34 430 | f 61/119/87 23/42/39 59/38/35 431 | f 88/40/37 61/119/87 9/118/78 432 | f 41/120/88 88/40/37 39/121/77 433 | f 41/120/88 11/122/89 60/41/38 434 | f 60/41/38 89/123/40 62/77/69 435 | f 11/122/89 29/124/90 89/123/40 436 | f 29/124/90 5/125/91 47/126/41 437 | f 30/1/1 90/46/43 45/127/92 438 | f 12/27/25 65/128/48 90/46/43 439 | f 65/51/48 24/50/47 63/129/44 440 | f 91/130/93 65/128/48 12/27/25 441 | f 43/131/86 91/130/93 42/26/24 442 | f 13/76/36 64/49/46 91/132/93 443 | f 64/49/46 92/52/49 66/133/71 444 | f 13/76/36 31/9/9 92/52/49 445 | f 31/9/9 6/8/8 49/53/28 446 | f 93/134/94 46/18/16 4/17/15 447 | f 69/135/54 93/136/94 32/137/75 448 | f 25/58/53 67/90/50 93/138/94 449 | f 44/3/3 94/139/95 69/135/54 450 | f 3/2/2 45/127/92 94/139/95 451 | f 15/82/45 68/57/52 94/140/95 452 | f 95/60/55 70/88/73 25/58/53 453 | f 33/12/10 95/60/55 68/57/52 454 | f 33/12/10 7/11/5 50/61/4 455 | f 36/141/85 96/63/56 34/87/72 456 | f 18/142/84 73/143/96 96/63/56 457 | f 73/143/96 26/67/60 71/64/57 458 | f 48/111/83 97/144/58 73/145/96 459 | f 5/125/91 29/124/90 97/146/58 460 | f 29/124/90 11/122/89 72/147/59 461 | f 72/66/59 98/148/97 74/70/63 462 | f 11/149/89 41/150/88 98/148/97 463 | f 41/150/88 1/151/98 40/68/61 464 | f 75/71/64 30/1/1 44/3/3 465 | f 76/73/66 50/4/4 37/6/6 466 | f 77/75/68 35/7/7 31/9/9 467 | f 78/81/70 37/10/6 33/12/10 468 | f 34/87/72 79/13/11 8/15/13 469 | f 80/92/74 28/16/14 46/18/16 470 | f 32/137/75 81/19/17 14/21/19 471 | f 53/99/76 82/22/20 21/24/22 472 | f 54/72/65 83/25/23 12/27/25 473 | f 84/108/81 55/28/26 49/30/28 474 | f 57/107/82 85/31/29 22/33/31 475 | f 58/74/67 86/34/32 20/36/33 476 | f 43/117/86 87/37/34 13/39/36 477 | f 61/119/87 88/40/37 23/42/39 478 | f 62/152/69 89/43/40 17/45/42 479 | f 45/127/92 90/46/43 15/48/45 480 | f 91/132/93 64/49/46 65/51/48 481 | f 66/133/71 92/52/49 19/54/27 482 | f 93/134/94 67/55/50 46/18/16 483 | f 94/140/95 68/57/52 69/59/54 484 | f 70/88/73 95/60/55 20/62/33 485 | f 34/87/72 96/63/56 16/56/51 486 | f 73/143/96 97/65/58 26/67/60 487 | f 98/148/97 40/68/61 74/70/63 488 | f 51/20/18 75/71/64 14/21/19 489 | f 51/20/18 21/24/22 75/71/64 490 | f 54/72/65 12/27/25 75/71/64 491 | f 55/28/26 76/73/66 19/29/27 492 | f 55/28/26 22/33/31 76/73/66 493 | f 76/73/66 58/74/67 50/4/4 494 | f 59/153/35 77/75/68 13/76/36 495 | f 23/42/39 62/77/69 59/38/35 496 | f 62/77/69 17/79/42 77/78/68 497 | f 63/154/44 78/81/70 15/82/45 498 | f 63/155/44 24/83/47 78/85/70 499 | f 66/156/71 19/86/27 78/81/70 500 | f 16/56/51 67/55/50 34/87/72 501 | f 25/58/53 70/88/73 67/90/50 502 | f 70/88/73 20/62/33 79/89/11 503 | f 16/56/51 71/64/57 46/18/16 504 | f 26/67/60 74/70/63 71/64/57 505 | f 74/157/63 10/93/62 80/95/74 506 | f 4/17/15 28/16/14 32/97/75 507 | f 10/69/62 53/98/76 28/16/14 508 | f 81/19/17 53/99/76 51/20/18 509 | f 10/69/62 40/68/61 53/98/76 510 | f 1/158/98 39/101/77 40/102/61 511 | f 82/22/20 39/101/77 52/23/21 512 | f 21/24/22 52/23/21 54/72/65 513 | f 52/23/21 9/103/78 83/25/23 514 | f 83/25/23 27/104/79 42/26/24 515 | f 6/8/8 35/7/7 49/53/28 516 | f 17/110/42 57/107/82 35/109/7 517 | f 84/108/81 57/107/82 55/28/26 518 | f 47/112/41 85/31/29 17/110/42 519 | f 5/159/91 48/111/83 47/112/41 520 | f 48/111/83 18/113/84 85/31/29 521 | f 22/33/31 56/32/30 58/74/67 522 | f 18/113/84 36/114/85 56/32/30 523 | f 86/34/32 36/114/85 38/35/12 524 | f 2/160/80 27/116/79 43/117/86 525 | f 27/116/79 9/118/78 87/37/34 526 | f 87/37/34 61/119/87 59/38/35 527 | f 39/121/77 88/40/37 9/118/78 528 | f 1/161/98 41/120/88 39/121/77 529 | f 88/40/37 41/120/88 60/41/38 530 | f 23/42/39 60/41/38 62/77/69 531 | f 60/41/38 11/122/89 89/123/40 532 | f 89/123/40 29/124/90 47/126/41 533 | f 3/2/2 30/1/1 45/127/92 534 | f 30/1/1 12/27/25 90/46/43 535 | f 90/162/43 65/51/48 63/129/44 536 | f 42/26/24 91/130/93 12/27/25 537 | f 2/105/80 43/131/86 42/26/24 538 | f 43/163/86 13/76/36 91/132/93 539 | f 24/50/47 64/49/46 66/133/71 540 | f 64/49/46 13/76/36 92/52/49 541 | f 92/52/49 31/9/9 49/53/28 542 | f 32/97/75 93/134/94 4/17/15 543 | f 14/21/19 69/135/54 32/137/75 544 | f 69/59/54 25/58/53 93/138/94 545 | f 14/21/19 44/3/3 69/135/54 546 | f 44/3/3 3/2/2 94/139/95 547 | f 45/164/92 15/82/45 94/140/95 548 | f 68/57/52 95/60/55 25/58/53 549 | f 15/82/45 33/12/10 68/57/52 550 | f 95/60/55 33/12/10 50/61/4 551 | f 8/15/13 36/141/85 34/87/72 552 | f 36/141/85 18/142/84 96/63/56 553 | f 96/63/56 73/143/96 71/64/57 554 | f 18/113/84 48/111/83 73/145/96 555 | f 48/165/83 5/125/91 97/146/58 556 | f 97/146/58 29/124/90 72/147/59 557 | f 26/67/60 72/66/59 74/70/63 558 | f 72/66/59 11/149/89 98/148/97 559 | f 98/148/97 41/150/88 40/68/61 560 | -------------------------------------------------------------------------------- /_assets/objects/rock/rock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/objects/rock/rock.png -------------------------------------------------------------------------------- /_assets/textures/awesomeface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/textures/awesomeface.png -------------------------------------------------------------------------------- /_assets/textures/bricks2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/textures/bricks2.jpg -------------------------------------------------------------------------------- /_assets/textures/bricks2_disp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/textures/bricks2_disp.jpg -------------------------------------------------------------------------------- /_assets/textures/bricks2_normal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/textures/bricks2_normal.jpg -------------------------------------------------------------------------------- /_assets/textures/brickwall.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/textures/brickwall.jpg -------------------------------------------------------------------------------- /_assets/textures/brickwall_normal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/textures/brickwall_normal.jpg -------------------------------------------------------------------------------- /_assets/textures/container.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/textures/container.jpg -------------------------------------------------------------------------------- /_assets/textures/container2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/textures/container2.png -------------------------------------------------------------------------------- /_assets/textures/container2_specular.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/textures/container2_specular.png -------------------------------------------------------------------------------- /_assets/textures/grass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/textures/grass.png -------------------------------------------------------------------------------- /_assets/textures/marble.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/textures/marble.jpg -------------------------------------------------------------------------------- /_assets/textures/metal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/textures/metal.png -------------------------------------------------------------------------------- /_assets/textures/pbr/rusted_iron/albedo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/textures/pbr/rusted_iron/albedo.png -------------------------------------------------------------------------------- /_assets/textures/pbr/rusted_iron/ao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/textures/pbr/rusted_iron/ao.png -------------------------------------------------------------------------------- /_assets/textures/pbr/rusted_iron/metallic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/textures/pbr/rusted_iron/metallic.png -------------------------------------------------------------------------------- /_assets/textures/pbr/rusted_iron/normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/textures/pbr/rusted_iron/normal.png -------------------------------------------------------------------------------- /_assets/textures/pbr/rusted_iron/roughness.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/textures/pbr/rusted_iron/roughness.png -------------------------------------------------------------------------------- /_assets/textures/skybox/back.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/textures/skybox/back.jpg -------------------------------------------------------------------------------- /_assets/textures/skybox/bottom.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/textures/skybox/bottom.jpg -------------------------------------------------------------------------------- /_assets/textures/skybox/front.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/textures/skybox/front.jpg -------------------------------------------------------------------------------- /_assets/textures/skybox/left.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/textures/skybox/left.jpg -------------------------------------------------------------------------------- /_assets/textures/skybox/right.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/textures/skybox/right.jpg -------------------------------------------------------------------------------- /_assets/textures/skybox/top.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/textures/skybox/top.jpg -------------------------------------------------------------------------------- /_assets/textures/toy_box_diffuse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/textures/toy_box_diffuse.png -------------------------------------------------------------------------------- /_assets/textures/toy_box_disp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/textures/toy_box_disp.png -------------------------------------------------------------------------------- /_assets/textures/toy_box_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/textures/toy_box_normal.png -------------------------------------------------------------------------------- /_assets/textures/window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/textures/window.png -------------------------------------------------------------------------------- /_assets/textures/wood.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/_assets/textures/wood.png -------------------------------------------------------------------------------- /data/.gitignore: -------------------------------------------------------------------------------- 1 | # Unit test results 2 | # Ignore everything in this directory 3 | * 4 | # Except this file 5 | !.gitignore -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raedatoui/learn-opengl-golang/4076c38cd53ab75baa0327bc99da97a371c46504/screenshot.png -------------------------------------------------------------------------------- /sections/base.go: -------------------------------------------------------------------------------- 1 | package sections 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/go-gl/glfw/v3.2/glfw" 7 | "github.com/raedatoui/glutils" 8 | ) 9 | 10 | // WIDTH is the width of the window 11 | var WIDTH = 1280.0 12 | 13 | // HEIGHT is the height of the window 14 | var HEIGHT = 1024.0 15 | 16 | var Ratio = float32(WIDTH / HEIGHT) 17 | 18 | // Slide is the most basic slide. it has to setup, update, draw and close 19 | type Slide interface { 20 | Init(a ...interface{}) error 21 | InitGL() error 22 | Update() 23 | Draw() 24 | Close() 25 | GetHeader() string 26 | GetSubHeader() string 27 | SetName(s string) 28 | GetName() string 29 | GetColorHex() string 30 | HandleKeyboard(k glfw.Key, s int, a glfw.Action, m glfw.ModifierKey, keys map[glfw.Key]bool) 31 | HandleMousePosition(xpos, ypos float64) 32 | HandleScroll(xoff, yoff float64) 33 | HandleFiles(names []string) 34 | DrawText() bool 35 | } 36 | 37 | // BaseSlide is the base implementation of Slide with the min required fields 38 | type BaseSlide struct { 39 | Slide 40 | Name string 41 | Color glutils.Color 42 | Color32 glutils.Color32 43 | ColorHex string 44 | } 45 | 46 | func (s *BaseSlide) GetHeader() string { 47 | return s.Name 48 | } 49 | 50 | func (s *BaseSlide) GetSubHeader() string { 51 | return "" 52 | } 53 | 54 | func (s *BaseSlide) SetName(n string) { 55 | s.Name = n 56 | } 57 | 58 | func (s *BaseSlide) GetColorHex() string { 59 | return s.ColorHex 60 | } 61 | 62 | func (s *BaseSlide) InitGL() error { 63 | return nil 64 | } 65 | 66 | func (s *BaseSlide) Update() { 67 | 68 | } 69 | 70 | func (s *BaseSlide) Draw() { 71 | 72 | } 73 | 74 | func (s *BaseSlide) Close() { 75 | 76 | } 77 | 78 | func (s *BaseSlide) HandleKeyboard(k glfw.Key, sc int, a glfw.Action, mk glfw.ModifierKey, keys map[glfw.Key]bool) { 79 | 80 | } 81 | 82 | func (s *BaseSlide) HandleMousePosition(xpos, ypos float64) { 83 | 84 | } 85 | 86 | func (s *BaseSlide) HandleScroll(xoff, yoff float64) { 87 | 88 | } 89 | 90 | func (s *BaseSlide) HandleFiles(names []string) { 91 | 92 | } 93 | 94 | type BaseSketch struct { 95 | BaseSlide 96 | } 97 | 98 | func (b *BaseSketch) Init(a ...interface{}) error { 99 | c, ok := a[1].(glutils.Color) 100 | if ok == false { 101 | return errors.New("first argument isnt a color") 102 | } 103 | b.Color = c 104 | b.Color32 = c.To32() 105 | b.ColorHex = glutils.Rgb2Hex(c) 106 | return nil 107 | } 108 | 109 | func (b *BaseSketch) DrawText() bool { 110 | return true 111 | } 112 | 113 | // returns the index of an object within a slice. returns -1 if it doesnt exist. 114 | func SlidePosition(slice []Slide, value Slide) int { 115 | for p, v := range slice { 116 | if v == value { 117 | return p 118 | } 119 | } 120 | return -1 121 | } 122 | -------------------------------------------------------------------------------- /sections/getstarted/0.hellocube.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The go-gl Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package sketches represents each tutorial 6 | package getstarted 7 | 8 | import ( 9 | "github.com/go-gl/gl/v4.1-core/gl" 10 | "github.com/go-gl/glfw/v3.2/glfw" 11 | "github.com/go-gl/mathgl/mgl32" 12 | "github.com/raedatoui/glutils" 13 | "github.com/raedatoui/learn-opengl-golang/sections" 14 | _ "image/png" 15 | ) 16 | 17 | // HelloCube Renders a textured spinning cube using GLFW 3 and OpenGL 4.1 core forward-compatible profile. 18 | type HelloCube struct { 19 | sections.BaseSketch 20 | program uint32 21 | vao, vbo uint32 22 | texture uint32 23 | angle, previousTime float64 24 | model mgl32.Mat4 25 | modelUniform int32 26 | } 27 | 28 | // Setup is inherited 29 | func (hc *HelloCube) InitGL() error { 30 | hc.angle = 0.0 31 | hc.Name = "0. Test Cube From github.com/go-gl/examples" 32 | 33 | var cubeVertices = []float32{ 34 | // X, Y, Z, U, V 35 | // Bottom 36 | -1.0, -1.0, -1.0, 0.0, 0.0, 37 | 1.0, -1.0, -1.0, 1.0, 0.0, 38 | -1.0, -1.0, 1.0, 0.0, 1.0, 39 | 1.0, -1.0, -1.0, 1.0, 0.0, 40 | 1.0, -1.0, 1.0, 1.0, 1.0, 41 | -1.0, -1.0, 1.0, 0.0, 1.0, 42 | 43 | // Top 44 | -1.0, 1.0, -1.0, 0.0, 0.0, 45 | -1.0, 1.0, 1.0, 0.0, 1.0, 46 | 1.0, 1.0, -1.0, 1.0, 0.0, 47 | 1.0, 1.0, -1.0, 1.0, 0.0, 48 | -1.0, 1.0, 1.0, 0.0, 1.0, 49 | 1.0, 1.0, 1.0, 1.0, 1.0, 50 | 51 | // Front 52 | -1.0, -1.0, 1.0, 1.0, 0.0, 53 | 1.0, -1.0, 1.0, 0.0, 0.0, 54 | -1.0, 1.0, 1.0, 1.0, 1.0, 55 | 1.0, -1.0, 1.0, 0.0, 0.0, 56 | 1.0, 1.0, 1.0, 0.0, 1.0, 57 | -1.0, 1.0, 1.0, 1.0, 1.0, 58 | 59 | // Back 60 | -1.0, -1.0, -1.0, 0.0, 0.0, 61 | -1.0, 1.0, -1.0, 0.0, 1.0, 62 | 1.0, -1.0, -1.0, 1.0, 0.0, 63 | 1.0, -1.0, -1.0, 1.0, 0.0, 64 | -1.0, 1.0, -1.0, 0.0, 1.0, 65 | 1.0, 1.0, -1.0, 1.0, 1.0, 66 | 67 | // Left 68 | -1.0, -1.0, 1.0, 0.0, 1.0, 69 | -1.0, 1.0, -1.0, 1.0, 0.0, 70 | -1.0, -1.0, -1.0, 0.0, 0.0, 71 | -1.0, -1.0, 1.0, 0.0, 1.0, 72 | -1.0, 1.0, 1.0, 1.0, 1.0, 73 | -1.0, 1.0, -1.0, 1.0, 0.0, 74 | 75 | // Right 76 | 1.0, -1.0, 1.0, 1.0, 1.0, 77 | 1.0, -1.0, -1.0, 1.0, 0.0, 78 | 1.0, 1.0, -1.0, 0.0, 0.0, 79 | 1.0, -1.0, 1.0, 1.0, 1.0, 80 | 1.0, 1.0, -1.0, 0.0, 0.0, 81 | 1.0, 1.0, 1.0, 0.0, 1.0, 82 | } 83 | 84 | var vertexShader = ` 85 | #version 330 86 | 87 | uniform mat4 projection; 88 | uniform mat4 camera; 89 | uniform mat4 model; 90 | 91 | in vec3 vert; 92 | in vec2 vertTexCoord; 93 | 94 | out vec2 fragTexCoord; 95 | 96 | void main() { 97 | fragTexCoord = vertTexCoord; 98 | gl_Position = projection * camera * model * vec4(vert, 1); 99 | } 100 | ` + "\x00" 101 | 102 | var fragmentShader = ` 103 | #version 330 104 | 105 | uniform sampler2D tex; 106 | 107 | in vec2 fragTexCoord; 108 | 109 | out vec4 outputColor; 110 | 111 | void main() { 112 | outputColor = texture(tex, fragTexCoord); 113 | } 114 | ` + "\x00" 115 | // Configure the vertex and fragment shaders 116 | var err error 117 | hc.program, err = glutils.BasicProgram(vertexShader, fragmentShader) 118 | if err != nil { 119 | return err 120 | } 121 | 122 | gl.UseProgram(hc.program) 123 | 124 | projection := mgl32.Perspective(mgl32.DegToRad(45.0), sections.Ratio, 0.1, 10.0) 125 | projectionUniform := gl.GetUniformLocation(hc.program, gl.Str("projection\x00")) 126 | gl.UniformMatrix4fv(projectionUniform, 1, false, &projection[0]) 127 | 128 | camera := mgl32.LookAtV(mgl32.Vec3{3, 3, 3}, mgl32.Vec3{0, 0, 0}, mgl32.Vec3{0, 1, 0}) 129 | cameraUniform := gl.GetUniformLocation(hc.program, gl.Str("camera\x00")) 130 | gl.UniformMatrix4fv(cameraUniform, 1, false, &camera[0]) 131 | 132 | hc.model = mgl32.Ident4() 133 | hc.modelUniform = gl.GetUniformLocation(hc.program, gl.Str("model\x00")) 134 | gl.UniformMatrix4fv(hc.modelUniform, 1, false, &hc.model[0]) 135 | 136 | textureUniform := gl.GetUniformLocation(hc.program, gl.Str("tex\x00")) 137 | gl.Uniform1i(textureUniform, 0) 138 | 139 | gl.BindFragDataLocation(hc.program, 0, gl.Str("outputColor\x00")) 140 | 141 | // Load the texture 142 | hc.texture, err = glutils.NewTexture(gl.CLAMP_TO_EDGE, gl.CLAMP_TO_EDGE, gl.LINEAR, gl.LINEAR, "_assets/getting_started/0.cube/square.png") 143 | if err != nil { 144 | return err 145 | } 146 | 147 | // Configure the vertex data 148 | gl.GenVertexArrays(1, &hc.vao) 149 | gl.BindVertexArray(hc.vao) 150 | 151 | gl.GenBuffers(1, &hc.vbo) 152 | gl.BindBuffer(gl.ARRAY_BUFFER, hc.vbo) 153 | gl.BufferData(gl.ARRAY_BUFFER, len(cubeVertices)*4, gl.Ptr(cubeVertices), gl.STATIC_DRAW) 154 | 155 | vertAttrib := uint32(gl.GetAttribLocation(hc.program, gl.Str("vert\x00"))) 156 | gl.EnableVertexAttribArray(vertAttrib) 157 | gl.VertexAttribPointer(vertAttrib, 3, gl.FLOAT, false, 5*4, gl.PtrOffset(0)) 158 | 159 | texCoordAttrib := uint32(gl.GetAttribLocation(hc.program, gl.Str("vertTexCoord\x00"))) 160 | gl.EnableVertexAttribArray(texCoordAttrib) 161 | gl.VertexAttribPointer(texCoordAttrib, 2, gl.FLOAT, false, 5*4, gl.PtrOffset(3*4)) 162 | 163 | hc.previousTime = glfw.GetTime() 164 | 165 | return nil 166 | } 167 | 168 | // Update implements the update method 169 | func (hc *HelloCube) Update() { 170 | time := glfw.GetTime() 171 | elapsed := time - hc.previousTime 172 | hc.previousTime = time 173 | 174 | hc.angle += elapsed 175 | hc.model = mgl32.HomogRotate3D(float32(hc.angle), mgl32.Vec3{0, 1, 0}) 176 | } 177 | 178 | // Draw implements the draw method 179 | func (hc *HelloCube) Draw() { 180 | gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) 181 | gl.ClearColor(hc.Color32.R, hc.Color32.G, hc.Color32.B, hc.Color32.A) 182 | 183 | gl.UseProgram(hc.program) 184 | gl.UniformMatrix4fv(hc.modelUniform, 1, false, &hc.model[0]) 185 | 186 | gl.BindVertexArray(hc.vao) 187 | 188 | gl.ActiveTexture(gl.TEXTURE0) 189 | gl.BindTexture(gl.TEXTURE_2D, hc.texture) 190 | 191 | gl.DrawArrays(gl.TRIANGLES, 0, 6*2*3) 192 | 193 | } 194 | 195 | func (hc *HelloCube) Close() { 196 | gl.DeleteVertexArrays(1, &hc.vao) 197 | gl.DeleteBuffers(1, &hc.vbo) 198 | gl.DeleteBuffers(1, &hc.vao) 199 | gl.DeleteProgram(hc.program) 200 | } 201 | -------------------------------------------------------------------------------- /sections/getstarted/1.hellowindow.go: -------------------------------------------------------------------------------- 1 | package getstarted 2 | 3 | import ( 4 | "github.com/go-gl/gl/v4.1-core/gl" 5 | "github.com/raedatoui/learn-opengl-golang/sections" 6 | ) 7 | 8 | type HelloWindow struct { 9 | sections.BaseSketch 10 | } 11 | 12 | func (hw *HelloWindow) InitGL() error { 13 | hw.Name = "1. Hello Window" 14 | return nil 15 | } 16 | 17 | func (hw *HelloWindow) Draw() { 18 | gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) 19 | gl.ClearColor(hw.Color32.R, hw.Color32.G, hw.Color32.B, hw.Color32.A) 20 | } 21 | 22 | func (hw *HelloWindow) Close() { 23 | 24 | } 25 | -------------------------------------------------------------------------------- /sections/getstarted/2.hellotriangle.go: -------------------------------------------------------------------------------- 1 | package getstarted 2 | 3 | import ( 4 | "github.com/go-gl/gl/v4.1-core/gl" 5 | "github.com/raedatoui/glutils" 6 | "github.com/raedatoui/learn-opengl-golang/sections" 7 | ) 8 | 9 | type HelloTriangle struct { 10 | sections.BaseSketch 11 | program uint32 12 | vao, vbo uint32 13 | } 14 | 15 | func (ht *HelloTriangle) createBuffers(vertices []float32) (uint32, uint32) { 16 | var vao, vbo uint32 17 | gl.GenVertexArrays(1, &vao) 18 | gl.GenBuffers(1, &vbo) 19 | 20 | gl.BindVertexArray(vao) 21 | 22 | gl.BindBuffer(gl.ARRAY_BUFFER, vbo) 23 | gl.BufferData(gl.ARRAY_BUFFER, len(vertices)*glutils.GL_FLOAT32_SIZE, gl.Ptr(vertices), gl.STATIC_DRAW) 24 | 25 | //vertAttrib := uint32(gl.GetAttribLocation(ht.program, gl.Str("position\x00"))) 26 | // here we can skip computing the vertAttrib value and use 0 since our shader declares layout = 0 for 27 | // the uniform 28 | gl.VertexAttribPointer(0, 3, gl.FLOAT, false, 3*glutils.GL_FLOAT32_SIZE, gl.PtrOffset(0)) 29 | gl.EnableVertexAttribArray(0) 30 | 31 | gl.BindVertexArray(0) 32 | return vao, vbo 33 | } 34 | 35 | func (ht *HelloTriangle) InitGL() error { 36 | ht.Name = "2a. Hello Triangle" 37 | 38 | var vertexShader = ` 39 | #version 330 core 40 | layout (location = 0) in vec3 position; 41 | void main() { 42 | gl_Position = vec4(position.x, position.y, position.z, 1.0); 43 | }` + "\x00" 44 | 45 | var fragShader = ` 46 | #version 330 core 47 | out vec4 color; 48 | void main() { 49 | color = vec4(1.0f, 1.0f, 0.2f, 1.0f); 50 | }` + "\x00" 51 | 52 | var err error 53 | ht.program, err = glutils.BasicProgram(vertexShader, fragShader) 54 | if err != nil { 55 | return err 56 | } 57 | 58 | var vertices = []float32{ 59 | -0.5, -0.5, 0.0, // Left 60 | 0.5, -0.5, 0.0, // Right 61 | 0.0, 0.5, 0.0, // Top 62 | } 63 | ht.vao, ht.vbo = ht.createBuffers(vertices) 64 | return nil 65 | } 66 | 67 | func (ht *HelloTriangle) Draw() { 68 | gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) 69 | gl.ClearColor(ht.Color32.R, ht.Color32.G, ht.Color32.B, ht.Color32.A) 70 | 71 | // Draw our first triangle 72 | gl.UseProgram(ht.program) 73 | gl.BindVertexArray(ht.vao) 74 | gl.DrawArrays(gl.TRIANGLES, 0, 3) 75 | gl.BindVertexArray(0) 76 | } 77 | 78 | func (ht *HelloTriangle) Close() { 79 | gl.DeleteVertexArrays(1, &ht.vao) 80 | gl.DeleteBuffers(1, &ht.vbo) 81 | gl.DeleteProgram(ht.program) 82 | } 83 | 84 | type TriangleEx1 struct { 85 | HelloTriangle 86 | ebo uint32 87 | currentMode int32 88 | } 89 | 90 | func (hs *TriangleEx1) InitGL() error { 91 | hs.Name = "2b. Triangle Ex1" 92 | var vertexShader = ` 93 | #version 330 core 94 | in vec3 vert; 95 | void main() { 96 | gl_Position = vec4(vert.x, vert.y, vert.z, 1.0); 97 | }` + "\x00" 98 | 99 | var fragShader = ` 100 | #version 330 core 101 | out vec4 color; 102 | void main() { 103 | color = vec4(1.0f, 1.0f, 0.2f, 1.0f); 104 | }` + "\x00" 105 | 106 | var err error 107 | hs.program, err = glutils.BasicProgram(vertexShader, fragShader) 108 | if err != nil { 109 | return err 110 | } 111 | 112 | var vertices = []float32{ 113 | 0.5, 0.5, 0.0, // Top Right 114 | 0.5, -0.5, 0.0, // Bottom Right 115 | -0.5, -0.5, 0.0, // Bottom Left 116 | -0.5, 0.5, 0.0, // Top Left 117 | } 118 | 119 | var indices = []uint32{ 120 | 0, 1, 3, // First Triangle 121 | 1, 2, 3, // Second Triangle 122 | } 123 | 124 | gl.GenVertexArrays(1, &hs.vao) 125 | gl.BindVertexArray(hs.vao) 126 | 127 | gl.GenBuffers(1, &hs.vbo) 128 | gl.BindBuffer(gl.ARRAY_BUFFER, hs.vbo) 129 | gl.BufferData(gl.ARRAY_BUFFER, len(vertices)*glutils.GL_FLOAT32_SIZE, gl.Ptr(vertices), gl.STATIC_DRAW) 130 | 131 | gl.GenBuffers(1, &hs.ebo) 132 | gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, hs.ebo) 133 | // seems like 4 works best here for the size of uint32 134 | gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, len(indices)*4, gl.Ptr(indices), gl.STATIC_DRAW) 135 | 136 | vertAttrib := uint32(gl.GetAttribLocation(hs.program, gl.Str("vert\x00"))) 137 | gl.VertexAttribPointer(vertAttrib, 3, gl.FLOAT, false, 3*glutils.GL_FLOAT32_SIZE, gl.PtrOffset(0)) 138 | gl.EnableVertexAttribArray(vertAttrib) 139 | 140 | gl.BindVertexArray(0) 141 | 142 | return nil 143 | } 144 | 145 | func (hs *TriangleEx1) Draw() { 146 | gl.GetIntegerv(gl.POLYGON_MODE, &hs.currentMode) 147 | 148 | gl.PolygonMode(gl.FRONT_AND_BACK, gl.LINE) 149 | gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) 150 | gl.ClearColor(hs.Color32.R, hs.Color32.G, hs.Color32.B, hs.Color32.A) 151 | 152 | gl.UseProgram(hs.program) 153 | gl.BindVertexArray(hs.vao) 154 | gl.DrawElements(gl.TRIANGLES, 6, gl.UNSIGNED_INT, gl.PtrOffset(0)) 155 | gl.BindVertexArray(0) 156 | gl.PolygonMode(gl.FRONT_AND_BACK, uint32(hs.currentMode)) 157 | } 158 | 159 | func (hs *TriangleEx1) Close() { 160 | gl.DeleteVertexArrays(1, &hs.vao) 161 | gl.DeleteBuffers(1, &hs.vbo) 162 | gl.DeleteBuffers(1, &hs.ebo) 163 | gl.UseProgram(0) 164 | } 165 | 166 | func (hs *TriangleEx1) GetSubHeader() string { 167 | return "the square always uses GL_LINE for the polygon mode" 168 | } 169 | 170 | type TriangleEx2 struct { 171 | HelloTriangle 172 | program2 uint32 173 | vao2, vbo2 uint32 174 | } 175 | 176 | func (ht *TriangleEx2) InitGL() error { 177 | ht.Name = "2c. Triangle Ex2" 178 | 179 | var vertexShader = ` 180 | #version 330 core 181 | layout (location = 0) in vec3 position; 182 | void main() { 183 | gl_Position = vec4(position.x, position.y, position.z, 1.0); 184 | }` + "\x00" 185 | 186 | var fragShader = ` 187 | #version 330 core 188 | out vec4 color; 189 | void main() { 190 | color = vec4(1.0f, 1.0f, 0.2f, 0.9f); 191 | }` + "\x00" 192 | 193 | var vertexShader2 = ` 194 | #version 330 core 195 | layout (location = 0) in vec3 position; 196 | void main() { 197 | gl_Position = vec4(position.x/2.0, position.y/2.0, position.z/2.0, 1.0); 198 | }` + "\x00" 199 | 200 | var fragShader2 = ` 201 | #version 330 core 202 | out vec4 color; 203 | void main() { 204 | color = vec4(0.8f, 0.2f, 1.0f, 0.8f); 205 | }` + "\x00" 206 | 207 | var err error 208 | ht.program, err = glutils.BasicProgram(vertexShader, fragShader) 209 | if err != nil { 210 | return err 211 | } 212 | 213 | ht.program2, err = glutils.BasicProgram(vertexShader2, fragShader2) 214 | if err != nil { 215 | return err 216 | } 217 | 218 | var vertices = []float32{ 219 | 0.5, -0.5, 0.0, // Right 220 | -0.5, -0.5, 0.0, // Left 221 | 0.0, 0.5, 0.0, // Top 222 | } 223 | 224 | var vertices2 = []float32{ 225 | 1.0, -1.0, 0.0, // Left 226 | 1.0, 0.0, 0.0, // Right 227 | 0.0, -1.0, 0.0, // Top 228 | } 229 | 230 | ht.vao, ht.vbo = ht.createBuffers(vertices) 231 | ht.vao2, ht.vbo2 = ht.createBuffers(vertices2) 232 | 233 | return nil 234 | } 235 | 236 | func (ht *TriangleEx2) Draw() { 237 | gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) 238 | gl.ClearColor(ht.Color32.R, ht.Color32.G, ht.Color32.B, ht.Color32.A) 239 | 240 | // Draw our first triangle 241 | gl.UseProgram(ht.program) 242 | gl.BindVertexArray(ht.vao) 243 | gl.DrawArrays(gl.TRIANGLES, 0, 3) 244 | gl.BindVertexArray(0) 245 | 246 | gl.UseProgram(ht.program2) 247 | gl.BindVertexArray(ht.vao2) 248 | gl.DrawArrays(gl.TRIANGLES, 0, 3) 249 | gl.BindVertexArray(0) 250 | } 251 | -------------------------------------------------------------------------------- /sections/getstarted/3.shaders.go: -------------------------------------------------------------------------------- 1 | package getstarted 2 | 3 | import ( 4 | "github.com/go-gl/gl/v4.1-core/gl" 5 | "github.com/go-gl/glfw/v3.2/glfw" 6 | "github.com/raedatoui/glutils" 7 | "github.com/raedatoui/learn-opengl-golang/sections" 8 | "math" 9 | ) 10 | 11 | type HelloShaders struct { 12 | sections.BaseSketch 13 | shader glutils.Shader 14 | va glutils.VertexArray 15 | } 16 | 17 | func (hs *HelloShaders) createShader(v, f string) error { 18 | var err error 19 | hs.shader, err = glutils.NewShader(v, f, "") 20 | 21 | if err != nil { 22 | return err 23 | } 24 | return nil 25 | } 26 | 27 | func (hs *HelloShaders) createBuffers() { 28 | var vertices = []float32{ 29 | // Positions // Colors 30 | 0.5, -0.5, 0.0, 1.0, 0.0, 0.0, // Bottom Right 31 | -0.5, -0.5, 0.0, 0.0, 1.0, 0.0, // Bottom Left 32 | 0.0, 0.5, 0.0, 0.0, 0.0, 1.0, // Top 33 | } 34 | attr := make(glutils.AttributesMap) 35 | attr[hs.shader.Attributes["position"]] = [2]int{3, 0} 36 | attr[hs.shader.Attributes["color"]] = [2]int{3, 3} 37 | 38 | hs.va = glutils.VertexArray{ 39 | Data: vertices, 40 | Stride: 6, 41 | Normalized: false, 42 | DrawMode: gl.STATIC_DRAW, 43 | Attributes: attr, 44 | } 45 | 46 | hs.va.Setup() 47 | } 48 | 49 | func (hs *HelloShaders) InitGL() error { 50 | hs.Name = "3a. Shaders" 51 | 52 | if err := hs.createShader( 53 | "_assets/getting_started/3.shaders/basic.vs", 54 | "_assets/getting_started/3.shaders/basic.frag"); err != nil { 55 | return err 56 | } 57 | 58 | hs.createBuffers() 59 | 60 | return nil 61 | } 62 | 63 | func (hs *HelloShaders) Draw() { 64 | gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) 65 | gl.ClearColor(hs.Color32.R, hs.Color32.G, hs.Color32.B, hs.Color32.A) 66 | 67 | // Draw the triangle 68 | gl.UseProgram(hs.shader.Program) 69 | gl.BindVertexArray(hs.va.Vao) 70 | gl.DrawArrays(gl.TRIANGLES, 0, 3) 71 | gl.BindVertexArray(0) 72 | } 73 | 74 | func (hs *HelloShaders) Close() { 75 | hs.shader.Delete() 76 | hs.va.Delete() 77 | } 78 | 79 | type ShaderEx1 struct { 80 | HelloShaders 81 | timeValue float64 82 | greenValue float32 83 | vertexColorLocation int32 84 | } 85 | 86 | func (hs *ShaderEx1) InitGL() error { 87 | hs.Name = "3b. Shaders Ex1" 88 | if err := hs.createShader( 89 | "_assets/getting_started/3.shaders/basic.vs", 90 | "_assets/getting_started/3.shaders/uniform.frag"); err != nil { 91 | return err 92 | } 93 | 94 | hs.createBuffers() 95 | return nil 96 | } 97 | 98 | func (hs *ShaderEx1) Update() { 99 | hs.timeValue = glfw.GetTime() 100 | hs.greenValue = float32(math.Sin(hs.timeValue)/2) + 0.5 101 | } 102 | 103 | func (hs *ShaderEx1) Draw() { 104 | gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) 105 | gl.ClearColor(hs.Color32.R, hs.Color32.G, hs.Color32.B, hs.Color32.A) 106 | 107 | // Draw the triangle 108 | gl.UseProgram(hs.shader.Program) 109 | gl.Uniform4f(hs.shader.Uniforms["ourColor"], 0.0, hs.greenValue, 0.0, 1.0) 110 | gl.BindVertexArray(hs.va.Vao) 111 | gl.DrawArrays(gl.TRIANGLES, 0, 3) 112 | gl.BindVertexArray(0) 113 | } 114 | 115 | func (hs *ShaderEx1) GetSubHeader() string { 116 | return "with a uniform updated by gl.Uniform4f" 117 | } 118 | 119 | type ShaderEx2 struct { 120 | HelloShaders 121 | } 122 | 123 | func (hs *ShaderEx2) InitGL() error { 124 | hs.Name = "3c. Shaders Ex2" 125 | if err := hs.createShader( 126 | "_assets/getting_started/3.shaders/reverse.vs", 127 | "_assets/getting_started/3.shaders/basic.frag"); err != nil { 128 | return err 129 | } 130 | 131 | hs.createBuffers() 132 | 133 | return nil 134 | } 135 | 136 | type ShaderEx3 struct { 137 | HelloShaders 138 | } 139 | 140 | func (hs *ShaderEx3) InitGL() error { 141 | hs.Name = "3b. Shaders Ex3" 142 | if err := hs.createShader( 143 | "_assets/getting_started/3.shaders/offset.vs", 144 | "_assets/getting_started/3.shaders/basic.frag"); err != nil { 145 | return err 146 | } 147 | 148 | hs.createBuffers() 149 | 150 | gl.UseProgram(hs.shader.Program) 151 | gl.Uniform1f(hs.shader.Uniforms["xOffset"], 0.5) 152 | 153 | return nil 154 | } 155 | 156 | type ShaderEx4 struct { 157 | HelloShaders 158 | } 159 | 160 | func (hs *ShaderEx4) InitGL() error { 161 | hs.Name = "3c. Shaders Ex4" 162 | if err := hs.createShader( 163 | "_assets/getting_started/3.shaders/ex4.vs", 164 | "_assets/getting_started/3.shaders/ex4.frag"); err != nil { 165 | return err 166 | } 167 | 168 | hs.createBuffers() 169 | 170 | return nil 171 | } 172 | 173 | func (hs *ShaderEx4) createBuffers() { 174 | var vertices = []float32{ 175 | // Positions // Colors 176 | 0.5, -0.5, 0.0, 1.0, 0.0, 0.0, // Bottom Right 177 | -0.5, -0.5, 0.0, 0.0, 1.0, 0.0, // Bottom Left 178 | 0.0, 0.5, 0.0, 0.0, 0.0, 1.0, // Top 179 | } 180 | attr := glutils.NewAttributesMap() 181 | attr.Add(hs.shader.Attributes["position"], 3, 0) 182 | 183 | hs.va = glutils.VertexArray{ 184 | Data: vertices, 185 | Stride: 6, 186 | Normalized: false, 187 | DrawMode: gl.STATIC_DRAW, 188 | Attributes: attr, 189 | } 190 | 191 | hs.va.Setup() 192 | } -------------------------------------------------------------------------------- /sections/getstarted/4.textures.go: -------------------------------------------------------------------------------- 1 | package getstarted 2 | 3 | import ( 4 | "github.com/go-gl/gl/v4.1-core/gl" 5 | "github.com/go-gl/glfw/v3.2/glfw" 6 | "github.com/raedatoui/glutils" 7 | "github.com/raedatoui/learn-opengl-golang/sections" 8 | ) 9 | 10 | type HelloTextures struct { 11 | sections.BaseSketch 12 | shader glutils.Shader 13 | va glutils.VertexArray 14 | texture1, texture2 uint32 15 | } 16 | 17 | func (ht *HelloTextures) getShaders() []string { 18 | return []string{"_assets/getting_started/4.textures/texture.vs", 19 | "_assets/getting_started/4.textures/texture.frag"} 20 | } 21 | func (ht *HelloTextures) getVertices() []float32 { 22 | return []float32{ 23 | // Positions // Colors // Texture Coords 24 | 0.5, 0.5, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, // Top Right 25 | 0.5, -0.5, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, // Bottom Right 26 | -0.5, -0.5, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, // Bottom Left 27 | -0.5, 0.5, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, // Top Left 28 | } 29 | } 30 | func (ht *HelloTextures) createBuffers(vertices []float32) { 31 | indices := []uint32{ // Note that we start from 0! 32 | 0, 1, 3, // First Triangle 33 | 1, 2, 3, // Second Triangle 34 | } 35 | attr := glutils.NewAttributesMap() 36 | attr.Add(ht.shader.Attributes["position"], 3, 0) 37 | attr.Add(ht.shader.Attributes["color"], 3, 2) 38 | attr.Add(ht.shader.Attributes["texCoord"], 2, 6) 39 | 40 | ht.va = glutils.VertexArray{ 41 | Data: vertices, 42 | Indices: indices, 43 | Stride: 8, 44 | Normalized: false, 45 | DrawMode: gl.STATIC_DRAW, 46 | Attributes: attr, 47 | } 48 | ht.va.Setup() 49 | } 50 | func (ht *HelloTextures) InitGL() error { 51 | ht.Name = "4. Textures" 52 | 53 | var err error 54 | shaders := ht.getShaders() 55 | ht.shader, err = glutils.NewShader(shaders[0], shaders[1], "") 56 | if err != nil { 57 | return err 58 | } 59 | 60 | ht.createBuffers(ht.getVertices()) 61 | 62 | // ==================== 63 | // Texture 1 64 | // ==================== 65 | if tex, err := glutils.NewTexture(gl.REPEAT, gl.REPEAT, gl.LINEAR, gl.LINEAR, "_assets/images/container.png"); err != nil { 66 | return err 67 | } else { 68 | ht.texture1 = tex 69 | } 70 | 71 | // ==================== 72 | // Texture 2 73 | // ==================== 74 | if tex, err := glutils.NewTexture(gl.REPEAT, gl.REPEAT, gl.LINEAR, gl.LINEAR, "_assets/images/awesomeface.png"); err != nil { 75 | return err 76 | } else { 77 | ht.texture2 = tex 78 | } 79 | 80 | return nil 81 | } 82 | 83 | func (ht *HelloTextures) Draw() { 84 | gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) 85 | gl.ClearColor(ht.Color32.R, ht.Color32.G, ht.Color32.B, ht.Color32.A) 86 | 87 | // Bind Textures using texture units 88 | gl.ActiveTexture(gl.TEXTURE0) 89 | gl.BindTexture(gl.TEXTURE_2D, ht.texture1) 90 | gl.Uniform1i(ht.shader.Uniforms["ourTexture1"], 0) 91 | 92 | gl.ActiveTexture(gl.TEXTURE1) 93 | gl.BindTexture(gl.TEXTURE_2D, ht.texture2) 94 | gl.Uniform1i(ht.shader.Uniforms["ourTexture2"], 1) 95 | 96 | // Activate shader 97 | gl.UseProgram(ht.shader.Program) 98 | 99 | // Draw container 100 | gl.BindVertexArray(ht.va.Vao) 101 | gl.DrawElements(gl.TRIANGLES, 6, gl.UNSIGNED_INT, gl.PtrOffset(0)) 102 | gl.BindVertexArray(0) 103 | } 104 | 105 | func (ht *HelloTextures) Close() { 106 | ht.shader.Delete() 107 | ht.va.Delete() 108 | } 109 | 110 | type TexturesEx1 struct { 111 | HelloTextures 112 | } 113 | 114 | func (ht *TexturesEx1) getShaders() []string { 115 | return []string{"_assets/getting_started/4.textures/texture.vs", 116 | "_assets/getting_started/4.textures/textureex1.frag"} 117 | } 118 | func (ht *TexturesEx1) InitGL() error { 119 | ht.Name = "4a. Textures Ex1" 120 | 121 | var err error 122 | shaders := ht.getShaders() 123 | ht.shader, err = glutils.NewShader(shaders[0], shaders[1], "") 124 | if err != nil { 125 | return err 126 | } 127 | 128 | ht.createBuffers(ht.getVertices()) 129 | 130 | // ==================== 131 | // Texture 1 132 | // ==================== 133 | if tex, err := glutils.NewTexture(gl.REPEAT, gl.REPEAT, gl.LINEAR, gl.LINEAR, "_assets/images/container.png"); err != nil { 134 | return err 135 | } else { 136 | ht.texture1 = tex 137 | } 138 | 139 | // ==================== 140 | // Texture 2 141 | // ==================== 142 | if tex, err := glutils.NewTexture(gl.REPEAT, gl.REPEAT, gl.LINEAR, gl.LINEAR, "_assets/images/awesomeface.png"); err != nil { 143 | return err 144 | } else { 145 | ht.texture2 = tex 146 | } 147 | 148 | return nil 149 | } 150 | 151 | func (ht *TexturesEx1) GetSubHeader() string { 152 | return "flip the happy face in the frag shader" 153 | } 154 | 155 | type TexturesEx2 struct { 156 | TexturesEx1 157 | } 158 | 159 | func (ht *TexturesEx2) getVertices() []float32 { 160 | return []float32{ 161 | // Positions // Colors // Texture Coords 162 | 0.5, 0.5, 0.0, 1.0, 0.0, 0.0, 2.0, 2.0, // Top Right 163 | 0.5, -0.5, 0.0, 0.0, 1.0, 0.0, 2.0, 0.0, // Bottom Right 164 | -0.5, -0.5, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, // Bottom Left 165 | -0.5, 0.5, 0.0, 1.0, 1.0, 0.0, 0.0, 2.0, // Top Left 166 | } 167 | } 168 | func (ht *TexturesEx2) InitGL() error { 169 | ht.Name = "4b. Textures Ex2" 170 | 171 | var err error 172 | shaders := ht.getShaders() 173 | ht.shader, err = glutils.NewShader(shaders[0], shaders[1], "") 174 | if err != nil { 175 | return err 176 | } 177 | 178 | ht.createBuffers(ht.getVertices()) 179 | 180 | // ==================== 181 | // Texture 1 182 | // ==================== 183 | if tex, err := glutils.NewTexture(gl.CLAMP_TO_EDGE, gl.CLAMP_TO_EDGE, gl.NEAREST, gl.NEAREST, "_assets/images/container.png"); err != nil { 184 | return err 185 | } else { 186 | ht.texture1 = tex 187 | } 188 | 189 | // ==================== 190 | // Texture 2 191 | // ==================== 192 | if tex, err := glutils.NewTexture(gl.REPEAT, gl.REPEAT, gl.NEAREST, gl.NEAREST, "_assets/images/awesomeface.png"); err != nil { 193 | return err 194 | } else { 195 | ht.texture2 = tex 196 | } 197 | 198 | return nil 199 | } 200 | 201 | func (ht *TexturesEx2) GetSubHeader() string { 202 | return "scale tex coord by 2 and set nearest filter on tex to see individual pixels" 203 | } 204 | 205 | type TexturesEx3 struct { 206 | TexturesEx1 207 | } 208 | 209 | func (ht *TexturesEx3) getVertices() []float32 { 210 | return []float32{ 211 | // Positions // Colors // Texture Coords 212 | 0.5, 0.5, 0.0, 1.0, 0.0, 0.0, 0.55, 0.55, // Top Right 213 | 0.5, -0.5, 0.0, 0.0, 1.0, 0.0, 0.55, 0.45, // Bottom Right 214 | -0.5, -0.5, 0.0, 0.0, 0.0, 1.0, 0.45, 0.45, // Bottom Left 215 | -0.5, 0.5, 0.0, 1.0, 1.0, 0.0, 0.45, 0.55, // Top Left 216 | } 217 | } 218 | func (ht *TexturesEx3) InitGL() error { 219 | ht.Name = "4c. Textures Ex3" 220 | 221 | var err error 222 | shaders := ht.getShaders() 223 | ht.shader, err = glutils.NewShader(shaders[0], shaders[1], "") 224 | if err != nil { 225 | return err 226 | } 227 | ht.createBuffers(ht.getVertices()) 228 | 229 | // Texture 1 230 | if tex, err := glutils.NewTexture(gl.REPEAT, gl.REPEAT, gl.NEAREST, gl.NEAREST, "_assets/images/container.png"); err != nil { 231 | return err 232 | } else { 233 | ht.texture1 = tex 234 | } 235 | 236 | // Texture 2 237 | if tex, err := glutils.NewTexture(gl.REPEAT, gl.REPEAT, gl.NEAREST, gl.NEAREST, "_assets/images/awesomeface.png"); err != nil { 238 | return err 239 | } else { 240 | ht.texture2 = tex 241 | } 242 | 243 | // mixvalue uniform 244 | return nil 245 | } 246 | 247 | type TexturesEx4 struct { 248 | HelloTextures 249 | mixValue float32 250 | } 251 | 252 | func (ht *TexturesEx3) GetSubHeader() string { 253 | return "scale tex down and test various wrapping" 254 | } 255 | 256 | func (ht *TexturesEx4) getShaders() []string { 257 | return []string{"_assets/getting_started/4.textures/texture.vs", 258 | "_assets/getting_started/4.textures/textureex4.frag"} 259 | } 260 | func (ht *TexturesEx4) InitGL() error { 261 | ht.Name = "4d. Textures Ex4" 262 | 263 | var err error 264 | shaders := ht.getShaders() 265 | ht.shader, err = glutils.NewShader(shaders[0], shaders[1], "") 266 | if err != nil { 267 | return err 268 | } 269 | ht.createBuffers(ht.getVertices()) 270 | 271 | // Texture 1 272 | if tex, err := glutils.NewTexture(gl.REPEAT, gl.REPEAT, gl.NEAREST, gl.NEAREST, "_assets/images/container.png"); err != nil { 273 | return err 274 | } else { 275 | ht.texture1 = tex 276 | } 277 | 278 | // Texture 2 279 | if tex, err := glutils.NewTexture(gl.REPEAT, gl.REPEAT, gl.NEAREST, gl.NEAREST, "_assets/images/awesomeface.png"); err != nil { 280 | return err 281 | } else { 282 | ht.texture2 = tex 283 | } 284 | 285 | return nil 286 | } 287 | 288 | func (ht *TexturesEx4) HandleKeyboard(k glfw.Key, s int, a glfw.Action, mk glfw.ModifierKey, keys map[glfw.Key]bool) { 289 | if keys[glfw.KeyUp] { 290 | ht.mixValue += 0.1 291 | if ht.mixValue >= 1.0 { 292 | ht.mixValue = 1.0 293 | } 294 | } 295 | if keys[glfw.KeyDown] { 296 | ht.mixValue -= 0.1 297 | if ht.mixValue <= 0.0 { 298 | ht.mixValue = 0.0 299 | } 300 | } 301 | } 302 | 303 | func (ht *TexturesEx4) Draw() { 304 | gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) 305 | gl.ClearColor(ht.Color32.R, ht.Color32.G, ht.Color32.B, ht.Color32.A) 306 | 307 | // Activate shader 308 | gl.UseProgram(ht.shader.Program) 309 | 310 | // Bind Textures using texture units 311 | gl.ActiveTexture(gl.TEXTURE0) 312 | gl.BindTexture(gl.TEXTURE_2D, ht.texture1) 313 | gl.Uniform1i(ht.shader.Uniforms["ourTexture1"], 0) 314 | 315 | gl.ActiveTexture(gl.TEXTURE1) 316 | gl.BindTexture(gl.TEXTURE_2D, ht.texture2) 317 | gl.Uniform1i(ht.shader.Uniforms["ourTexture2"], 1) 318 | 319 | gl.Uniform1f(ht.shader.Uniforms["mixValue"], ht.mixValue) 320 | 321 | // Draw container 322 | gl.BindVertexArray(ht.va.Vao) 323 | gl.DrawElements(gl.TRIANGLES, 6, gl.UNSIGNED_INT, gl.PtrOffset(0)) 324 | gl.BindVertexArray(0) 325 | } 326 | 327 | func (ht *TexturesEx4) GetSubHeader() string { 328 | return "cross fade tex using up/dwn arrows, setting opacity as frag uniform " 329 | } 330 | -------------------------------------------------------------------------------- /sections/getstarted/5.transformations.go: -------------------------------------------------------------------------------- 1 | package getstarted 2 | 3 | import ( 4 | "math" 5 | 6 | "github.com/go-gl/gl/v4.1-core/gl" 7 | "github.com/go-gl/glfw/v3.2/glfw" 8 | "github.com/go-gl/mathgl/mgl32" 9 | "github.com/raedatoui/glutils" 10 | "github.com/raedatoui/learn-opengl-golang/sections" 11 | ) 12 | 13 | type HelloTransformations struct { 14 | sections.BaseSketch 15 | shader glutils.Shader 16 | va glutils.VertexArray 17 | texture1, texture2 uint32 18 | translationMat mgl32.Mat4 19 | rotationAxis mgl32.Vec3 20 | } 21 | 22 | func (ht *HelloTransformations) GetHeader() string { 23 | return "5. Transformations" 24 | } 25 | 26 | func (ht *HelloTransformations) InitGL() error { 27 | ht.translationMat = mgl32.Translate3D(0.5, -0.5, 0.0) 28 | ht.rotationAxis = mgl32.Vec3{0.0, 0.0, 1.0}.Normalize() 29 | 30 | var err error 31 | ht.shader, err = glutils.NewShader( 32 | "_assets/getting_started/5.transformations/transform.vs", 33 | "_assets/getting_started/5.transformations/transform.frag", "") 34 | if err != nil { 35 | return err 36 | } 37 | 38 | vertices := []float32{ 39 | // Positions // Colors // Texture Coords 40 | 0.5, 0.5, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, // Top Right 41 | 0.5, -0.5, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, // Bottom Right 42 | -0.5, -0.5, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, // Bottom Left 43 | -0.5, 0.5, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, // Top Left 44 | } 45 | 46 | attr := glutils.NewAttributesMap() 47 | attr.Add(ht.shader.Attributes["position"], 3, 0) 48 | attr.Add(ht.shader.Attributes["texCoord"], 2, 6) 49 | 50 | indices := []uint32{ // Note that we start from 0! 51 | 0, 1, 3, // First Triangle 52 | 1, 2, 3, // Second Triangle 53 | } 54 | ht.va = glutils.VertexArray{ 55 | Data: vertices, 56 | Indices: indices, 57 | DrawMode: gl.STATIC_DRAW, 58 | Normalized: false, 59 | Stride: 8, 60 | Attributes: attr, 61 | } 62 | ht.va.Setup() 63 | 64 | // Texture 1 65 | if tex, err := glutils.NewTexture(gl.REPEAT, gl.REPEAT, gl.LINEAR, gl.LINEAR, "_assets/images/container.png"); err != nil { 66 | return err 67 | } else { 68 | ht.texture1 = tex 69 | } 70 | 71 | // Texture 2 72 | if tex, err := glutils.NewTexture(gl.REPEAT, gl.REPEAT, gl.LINEAR, gl.LINEAR, "_assets/images/awesomeface.png"); err != nil { 73 | return err 74 | } else { 75 | ht.texture2 = tex 76 | } 77 | 78 | return nil 79 | } 80 | 81 | func (ht *HelloTransformations) getTransform() mgl32.Mat4 { 82 | // rotate 83 | transform := ht.translationMat.Mul4(mgl32.HomogRotate3D(float32(glfw.GetTime()), ht.rotationAxis)) 84 | return transform 85 | } 86 | 87 | func (ht *HelloTransformations) Draw() { 88 | gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) 89 | gl.ClearColor(ht.Color32.R, ht.Color32.G, ht.Color32.B, ht.Color32.A) 90 | 91 | // Activate shader 92 | gl.UseProgram(ht.shader.Program) 93 | 94 | // Bind Textures using texture units 95 | gl.ActiveTexture(gl.TEXTURE0) 96 | gl.BindTexture(gl.TEXTURE_2D, ht.texture1) 97 | gl.Uniform1i(ht.shader.Uniforms["ourTexture1"], 0) 98 | 99 | gl.ActiveTexture(gl.TEXTURE1) 100 | gl.BindTexture(gl.TEXTURE_2D, ht.texture2) 101 | gl.Uniform1i(ht.shader.Uniforms["ourTexture2"], 1) 102 | 103 | transform := ht.getTransform() 104 | // here we create a pointer from the first element of the matrix? 105 | // read up and update this comm 106 | gl.UniformMatrix4fv(ht.shader.Uniforms["transform"], 1, false, &transform[0]) 107 | 108 | // Draw container 109 | gl.BindVertexArray(ht.va.Vao) 110 | gl.DrawElements(gl.TRIANGLES, 6, gl.UNSIGNED_INT, gl.PtrOffset(0)) 111 | gl.BindVertexArray(0) 112 | } 113 | 114 | func (ht *HelloTransformations) Close() { 115 | ht.shader.Delete() 116 | ht.va.Delete() 117 | } 118 | 119 | type TransformationEx1 struct { 120 | HelloTransformations 121 | } 122 | 123 | func (ht *TransformationEx1) GetHeader() string { 124 | return "5a. Transformations Ex1" 125 | } 126 | 127 | func (ht *TransformationEx1) GetSubHeader() string { 128 | return "Rotate then translate" 129 | } 130 | 131 | func (ht *TransformationEx1) getTransform() mgl32.Mat4 { 132 | // rotate 133 | transform := mgl32.HomogRotate3D(float32(glfw.GetTime()), ht.rotationAxis).Mul4(ht.translationMat) 134 | return transform 135 | } 136 | 137 | func (ht *TransformationEx1) Draw() { 138 | gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) 139 | gl.ClearColor(ht.Color32.R, ht.Color32.G, ht.Color32.B, ht.Color32.A) 140 | 141 | // Activate shader 142 | gl.UseProgram(ht.shader.Program) 143 | 144 | // Bind Textures using texture units 145 | gl.ActiveTexture(gl.TEXTURE0) 146 | gl.BindTexture(gl.TEXTURE_2D, ht.texture1) 147 | gl.Uniform1i(ht.shader.Uniforms["ourTexture1"], 0) 148 | 149 | gl.ActiveTexture(gl.TEXTURE1) 150 | gl.BindTexture(gl.TEXTURE_2D, ht.texture2) 151 | gl.Uniform1i(ht.shader.Uniforms["ourTexture2"], 1) 152 | 153 | transform := ht.getTransform() 154 | // here we create a pointer from the first element of the matrix? 155 | // read up and update this comm 156 | gl.UniformMatrix4fv(ht.shader.Uniforms["transform"], 1, false, &transform[0]) 157 | 158 | // Draw container 159 | gl.BindVertexArray(ht.va.Vao) 160 | gl.DrawElements(gl.TRIANGLES, 6, gl.UNSIGNED_INT, gl.PtrOffset(0)) 161 | gl.BindVertexArray(0) 162 | } 163 | 164 | type TransformationEx2 struct { 165 | HelloTransformations 166 | } 167 | 168 | func (ht *TransformationEx2) Draw() { 169 | gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) 170 | gl.ClearColor(ht.Color32.R, ht.Color32.G, ht.Color32.B, ht.Color32.A) 171 | 172 | // Activate shader 173 | gl.UseProgram(ht.shader.Program) 174 | 175 | // Bind Textures using texture units 176 | gl.ActiveTexture(gl.TEXTURE0) 177 | gl.BindTexture(gl.TEXTURE_2D, ht.texture1) 178 | gl.Uniform1i(ht.shader.Uniforms["ourTexture1"], 0) 179 | 180 | gl.ActiveTexture(gl.TEXTURE1) 181 | gl.BindTexture(gl.TEXTURE_2D, ht.texture2) 182 | gl.Uniform1i(ht.shader.Uniforms["ourTexture2"], 1) 183 | 184 | // Draw container 185 | gl.BindVertexArray(ht.va.Vao) 186 | transform := ht.translationMat.Mul4(mgl32.HomogRotate3D(float32(glfw.GetTime()), ht.rotationAxis)) 187 | // here we create a pointer from the first element of the matrix? 188 | // read up and update this comm 189 | gl.UniformMatrix4fv(ht.shader.Uniforms["transform"], 1, false, &transform[0]) 190 | gl.DrawElements(gl.TRIANGLES, 6, gl.UNSIGNED_INT, gl.PtrOffset(0)) 191 | 192 | scaleAmount := float32(math.Sin(glfw.GetTime())) 193 | transform = mgl32.Translate3D(-0.5, 0.5, 0.0).Mul4(mgl32.Scale3D(scaleAmount, scaleAmount, scaleAmount)) 194 | gl.UniformMatrix4fv(ht.shader.Uniforms["transform"], 1, false, &transform[0]) 195 | gl.DrawElements(gl.TRIANGLES, 6, gl.UNSIGNED_INT, gl.PtrOffset(0)) 196 | 197 | gl.BindVertexArray(0) 198 | } 199 | -------------------------------------------------------------------------------- /sections/getstarted/6.coordinates.go: -------------------------------------------------------------------------------- 1 | package getstarted 2 | 3 | import ( 4 | "github.com/go-gl/gl/v4.1-core/gl" 5 | "github.com/go-gl/glfw/v3.2/glfw" 6 | "github.com/go-gl/mathgl/mgl32" 7 | "github.com/raedatoui/glutils" 8 | "github.com/raedatoui/learn-opengl-golang/sections" 9 | ) 10 | 11 | type HelloCoordinates struct { 12 | sections.BaseSketch 13 | shader glutils.Shader 14 | va glutils.VertexArray 15 | texture1, texture2 uint32 16 | transform mgl32.Mat4 17 | cubePositions []mgl32.Mat4 18 | rotationAxis mgl32.Vec3 19 | } 20 | 21 | func (hc *HelloCoordinates) GetHeader() string { 22 | return "6. Coordinate Systems" 23 | } 24 | 25 | func (hc *HelloCoordinates) createShader() error { 26 | var err error 27 | hc.shader, err = glutils.NewShader( 28 | "_assets/getting_started/6.coordinates/coordinate.vs", 29 | "_assets/getting_started/6.coordinates/coordinate.frag", "") 30 | if err != nil { 31 | return err 32 | } 33 | return nil 34 | } 35 | func (hc *HelloCoordinates) createBuffers() error { 36 | vertices := []float32{ 37 | -0.5, -0.5, -0.5, 0.0, 0.0, 38 | 0.5, -0.5, -0.5, 1.0, 0.0, 39 | 0.5, 0.5, -0.5, 1.0, 1.0, 40 | 0.5, 0.5, -0.5, 1.0, 1.0, 41 | -0.5, 0.5, -0.5, 0.0, 1.0, 42 | -0.5, -0.5, -0.5, 0.0, 0.0, 43 | 44 | -0.5, -0.5, 0.5, 0.0, 0.0, 45 | 0.5, -0.5, 0.5, 1.0, 0.0, 46 | 0.5, 0.5, 0.5, 1.0, 1.0, 47 | 0.5, 0.5, 0.5, 1.0, 1.0, 48 | -0.5, 0.5, 0.5, 0.0, 1.0, 49 | -0.5, -0.5, 0.5, 0.0, 0.0, 50 | 51 | -0.5, 0.5, 0.5, 1.0, 0.0, 52 | -0.5, 0.5, -0.5, 1.0, 1.0, 53 | -0.5, -0.5, -0.5, 0.0, 1.0, 54 | -0.5, -0.5, -0.5, 0.0, 1.0, 55 | -0.5, -0.5, 0.5, 0.0, 0.0, 56 | -0.5, 0.5, 0.5, 1.0, 0.0, 57 | 58 | 0.5, 0.5, 0.5, 1.0, 0.0, 59 | 0.5, 0.5, -0.5, 1.0, 1.0, 60 | 0.5, -0.5, -0.5, 0.0, 1.0, 61 | 0.5, -0.5, -0.5, 0.0, 1.0, 62 | 0.5, -0.5, 0.5, 0.0, 0.0, 63 | 0.5, 0.5, 0.5, 1.0, 0.0, 64 | 65 | -0.5, -0.5, -0.5, 0.0, 1.0, 66 | 0.5, -0.5, -0.5, 1.0, 1.0, 67 | 0.5, -0.5, 0.5, 1.0, 0.0, 68 | 0.5, -0.5, 0.5, 1.0, 0.0, 69 | -0.5, -0.5, 0.5, 0.0, 0.0, 70 | -0.5, -0.5, -0.5, 0.0, 1.0, 71 | 72 | -0.5, 0.5, -0.5, 0.0, 1.0, 73 | 0.5, 0.5, -0.5, 1.0, 1.0, 74 | 0.5, 0.5, 0.5, 1.0, 0.0, 75 | 0.5, 0.5, 0.5, 1.0, 0.0, 76 | -0.5, 0.5, 0.5, 0.0, 0.0, 77 | -0.5, 0.5, -0.5, 0.0, 1.0, 78 | } 79 | 80 | attr := glutils.NewAttributesMap() 81 | attr.Add(hc.shader.Attributes["position"], 3, 0) 82 | attr.Add(hc.shader.Attributes["texCoord"], 2, 3) 83 | 84 | hc.va = glutils.VertexArray{ 85 | Data: vertices, 86 | Stride: 5, 87 | DrawMode: gl.STATIC_DRAW, 88 | Normalized: false, 89 | Attributes: attr, 90 | } 91 | hc.va.Setup() 92 | 93 | hc.rotationAxis = mgl32.Vec3{1.0, 0.3, 0.5}.Normalize() 94 | 95 | hc.cubePositions = []mgl32.Mat4{ 96 | mgl32.Translate3D(0.0, 0.0, 0.0), 97 | mgl32.Translate3D(2.0, 5.0, -15.0), 98 | mgl32.Translate3D(-1.5, -2.2, -2.5), 99 | mgl32.Translate3D(-3.8, -2.0, -12.3), 100 | mgl32.Translate3D(2.4, -0.4, -3.5), 101 | mgl32.Translate3D(-1.7, 3.0, -7.5), 102 | mgl32.Translate3D(1.3, -2.0, -2.5), 103 | mgl32.Translate3D(1.5, 2.0, -2.5), 104 | mgl32.Translate3D(1.5, 0.2, -1.5), 105 | mgl32.Translate3D(-1.3, 1.0, -1.5), 106 | } 107 | return nil 108 | } 109 | func (hc *HelloCoordinates) createTextures() error { 110 | // Texture 1 111 | if tex, err := glutils.NewTexture(gl.REPEAT, gl.REPEAT, gl.LINEAR, gl.LINEAR, "_assets/images/container.png"); err != nil { 112 | return err 113 | } else { 114 | hc.texture1 = tex 115 | } 116 | 117 | // Texture 2 118 | if tex, err := glutils.NewTexture(gl.REPEAT, gl.REPEAT, gl.LINEAR, gl.LINEAR, "_assets/images/awesomeface.png"); err != nil { 119 | return err 120 | } else { 121 | hc.texture2 = tex 122 | } 123 | return nil 124 | } 125 | func (hc *HelloCoordinates) InitGL() error { 126 | if err := hc.createShader(); err != nil { 127 | return err 128 | } 129 | if err := hc.createBuffers(); err != nil { 130 | return err 131 | } 132 | if err := hc.createTextures(); err != nil { 133 | return err 134 | } 135 | return nil 136 | } 137 | 138 | func (hc *HelloCoordinates) clear() { 139 | gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) 140 | gl.ClearColor(hc.Color32.R, hc.Color32.G, hc.Color32.B, hc.Color32.A) 141 | } 142 | func (hc *HelloCoordinates) setTextures() { 143 | // Bind Textures using texture units 144 | gl.ActiveTexture(gl.TEXTURE0) 145 | gl.BindTexture(gl.TEXTURE_2D, hc.texture1) 146 | gl.Uniform1i(hc.shader.Uniforms["ourTexture1"], 0) 147 | 148 | gl.ActiveTexture(gl.TEXTURE1) 149 | gl.BindTexture(gl.TEXTURE_2D, hc.texture2) 150 | gl.Uniform1i(hc.shader.Uniforms["ourTexture2"], 1) 151 | } 152 | func (hc *HelloCoordinates) setTransformations() { 153 | // Create transformations 154 | view := mgl32.Translate3D(0.0, 0.0, -3.0) 155 | projection := mgl32.Perspective(45.0, sections.Ratio, 0.1, 100.0) 156 | // Pass the matrices to the shader 157 | gl.UniformMatrix4fv(hc.shader.Uniforms["view"], 1, false, &view[0]) 158 | // Note: currently we set the projection matrix each frame, 159 | // but since the projection matrix rarely changes it's often best practice to set it outside the main loop only once. 160 | gl.UniformMatrix4fv(hc.shader.Uniforms["projection"], 1, false, &projection[0]) 161 | } 162 | func (hc *HelloCoordinates) renderVertexArray() { 163 | // Draw container 164 | gl.BindVertexArray(hc.va.Vao) 165 | for i := 0; i < 10; i++ { 166 | // Calculate the model matrix for each object and pass it to shader before drawing 167 | model := hc.cubePositions[i] 168 | 169 | angle := float32(glfw.GetTime()) * float32(i+1) 170 | 171 | model = model.Mul4(mgl32.HomogRotate3D(angle, hc.rotationAxis)) 172 | gl.UniformMatrix4fv(hc.shader.Uniforms["model"], 1, false, &model[0]) 173 | gl.DrawArrays(gl.TRIANGLES, 0, 36) 174 | } 175 | gl.BindVertexArray(0) 176 | } 177 | func (hc *HelloCoordinates) Draw() { 178 | hc.clear() 179 | // Activate shader 180 | gl.UseProgram(hc.shader.Program) 181 | hc.setTextures() 182 | hc.setTransformations() 183 | hc.renderVertexArray() 184 | } 185 | 186 | func (hc *HelloCoordinates) Close() { 187 | hc.shader.Delete() 188 | hc.va.Delete() 189 | } 190 | -------------------------------------------------------------------------------- /sections/getstarted/7.camera.go: -------------------------------------------------------------------------------- 1 | package getstarted 2 | 3 | import ( 4 | "github.com/go-gl/gl/v4.1-core/gl" 5 | "github.com/go-gl/glfw/v3.2/glfw" 6 | "github.com/go-gl/mathgl/mgl32" 7 | "github.com/raedatoui/glutils" 8 | "github.com/raedatoui/learn-opengl-golang/sections" 9 | ) 10 | 11 | type HelloCamera struct { 12 | HelloCoordinates 13 | camera glutils.Camera 14 | deltaTime, lastFrame float64 15 | w, a, s, d bool 16 | lastX, lastY float64 17 | firstMouse bool 18 | } 19 | 20 | func (hc *HelloCamera) GetHeader() string { 21 | return "7. Camera (use WSDA and mouse)" 22 | } 23 | 24 | func (hc *HelloCamera) InitGL() error { 25 | hc.camera = glutils.NewCamera( 26 | mgl32.Vec3{0.0, 0.0, 3.0}, 27 | mgl32.Vec3{0.0, 1.0, 3.0}, 28 | glutils.YAW, glutils.PITCH, 29 | ) 30 | hc.lastX = sections.WIDTH / 2 31 | hc.lastY = sections.HEIGHT / 2 32 | hc.firstMouse = true 33 | 34 | if err := hc.createShader(); err != nil { 35 | return err 36 | } 37 | if err := hc.createBuffers(); err != nil { 38 | return err 39 | } 40 | if err := hc.createTextures(); err != nil { 41 | return err 42 | } 43 | 44 | return nil 45 | } 46 | 47 | func (hc *HelloCamera) Update() { 48 | // Set frame time 49 | currentFrame := glfw.GetTime() 50 | hc.deltaTime = currentFrame - hc.lastFrame 51 | hc.lastFrame = currentFrame 52 | if hc.w { 53 | hc.camera.ProcessKeyboard(glutils.FORWARD, hc.deltaTime) 54 | } 55 | if hc.s { 56 | hc.camera.ProcessKeyboard(glutils.BACKWARD, hc.deltaTime) 57 | } 58 | if hc.a { 59 | hc.camera.ProcessKeyboard(glutils.LEFT, hc.deltaTime) 60 | } 61 | if hc.d { 62 | hc.camera.ProcessKeyboard(glutils.RIGHT, hc.deltaTime) 63 | } 64 | } 65 | 66 | func (hc *HelloCamera) setTransformations() { 67 | // Create transformations 68 | view := hc.camera.GetViewMatrix() 69 | projection := mgl32.Perspective(float32(hc.camera.Zoom), sections.Ratio, 0.1, 1000.0) 70 | 71 | // Pass the matrices to the shader 72 | gl.UniformMatrix4fv(hc.shader.Uniforms["view"], 1, false, &view[0]) 73 | // Note: currently we set the projection matrix each frame, 74 | // but since the projection matrix rarely changes it's often best practice to set it outside the main loop only once. 75 | gl.UniformMatrix4fv(hc.shader.Uniforms["projection"], 1, false, &projection[0]) 76 | } 77 | 78 | func (hc *HelloCamera) Draw() { 79 | hc.clear() 80 | // Activate shader 81 | gl.UseProgram(hc.shader.Program) 82 | hc.setTextures() 83 | hc.setTransformations() 84 | hc.renderVertexArray() 85 | } 86 | 87 | func (hc *HelloCamera) HandleKeyboard(k glfw.Key, s int, a glfw.Action, mk glfw.ModifierKey, keys map[glfw.Key]bool) { 88 | hc.w = keys[glfw.KeyW] 89 | hc.a = keys[glfw.KeyA] 90 | hc.s = keys[glfw.KeyS] 91 | hc.d = keys[glfw.KeyD] 92 | } 93 | 94 | func (hc *HelloCamera) HandleMousePosition(xpos, ypos float64) { 95 | if hc.firstMouse { 96 | hc.lastX = xpos 97 | hc.lastY = ypos 98 | hc.firstMouse = false 99 | } 100 | 101 | xoffset := xpos - hc.lastX 102 | yoffset := hc.lastY - ypos // Reversed since y-coordinates go from bottom to left 103 | 104 | hc.lastX = xpos 105 | hc.lastY = ypos 106 | 107 | hc.camera.ProcessMouseMovement(xoffset, yoffset, true) 108 | } 109 | 110 | func (hc *HelloCamera) HandleScroll(xoff, yoff float64) { 111 | hc.camera.ProcessMouseScroll(yoff) 112 | } 113 | -------------------------------------------------------------------------------- /sections/lighting/1.colors.go: -------------------------------------------------------------------------------- 1 | package lighting 2 | 3 | import ( 4 | "github.com/go-gl/gl/v4.1-core/gl" 5 | "github.com/go-gl/glfw/v3.2/glfw" 6 | "github.com/go-gl/mathgl/mgl32" 7 | "github.com/raedatoui/glutils" 8 | "github.com/raedatoui/learn-opengl-golang/sections" 9 | ) 10 | 11 | type LightingColors struct { 12 | sections.BaseSketch 13 | lightingShader, lampShader glutils.Shader 14 | containerVa, lightVa glutils.VertexArray 15 | lastX float64 16 | lastY float64 17 | firstMouse bool 18 | deltaTime, lastFrame float64 19 | camera glutils.Camera 20 | lightPos mgl32.Vec3 21 | w, a, s, d bool 22 | rotationAxis mgl32.Vec3 23 | translationMat mgl32.Mat4 24 | lightPositionMat mgl32.Mat4 25 | scaleMat mgl32.Mat4 26 | } 27 | 28 | func (lc *LightingColors) GetHeader() string { 29 | return "1. Colors" 30 | } 31 | 32 | func (lc *LightingColors) initShaders(v1, f1, v2, f2 string) error { 33 | if sh, err := glutils.NewShader(v1, f1, ""); err != nil { 34 | return err 35 | } else { 36 | lc.lightingShader = sh 37 | } 38 | if sh, err := glutils.NewShader(v2, f2, ""); err != nil { 39 | return err 40 | } else { 41 | lc.lampShader = sh 42 | } 43 | return nil 44 | } 45 | func (lc *LightingColors) initCamera() { 46 | // Camera 47 | lc.camera = glutils.NewCamera( 48 | mgl32.Vec3{0.0, 0.0, 3.0}, 49 | mgl32.Vec3{0.0, 1.0, 3.0}, 50 | glutils.YAW, glutils.PITCH, 51 | ) 52 | lc.lastX = sections.WIDTH / 2.0 53 | lc.lastY = sections.HEIGHT / 2.0 54 | 55 | // Light attributes 56 | lc.lightPos = mgl32.Vec3{1.2, 1.0, 2.0} 57 | lc.lightPositionMat = mgl32.Translate3D(lc.lightPos[0], lc.lightPos[1], lc.lightPos[2]) 58 | 59 | // Deltatime 60 | lc.deltaTime = 0.0 // Time between current frame and last frame 61 | lc.lastFrame = 0.0 // Time of last frame 62 | 63 | lc.translationMat = mgl32.Translate3D(0, 0, 0.0) 64 | lc.scaleMat = mgl32.Scale3D(0.2, 0.2, 0.2) 65 | lc.rotationAxis = mgl32.Vec3{1.0, 0.3, 0.5}.Normalize() 66 | } 67 | func (lc *LightingColors) getVertices() []float32 { 68 | return []float32{ 69 | -0.5, -0.5, -0.5, 70 | 0.5, -0.5, -0.5, 71 | 0.5, 0.5, -0.5, 72 | 0.5, 0.5, -0.5, 73 | -0.5, 0.5, -0.5, 74 | -0.5, -0.5, -0.5, 75 | 76 | -0.5, -0.5, 0.5, 77 | 0.5, -0.5, 0.5, 78 | 0.5, 0.5, 0.5, 79 | 0.5, 0.5, 0.5, 80 | -0.5, 0.5, 0.5, 81 | -0.5, -0.5, 0.5, 82 | 83 | -0.5, 0.5, 0.5, 84 | -0.5, 0.5, -0.5, 85 | -0.5, -0.5, -0.5, 86 | -0.5, -0.5, -0.5, 87 | -0.5, -0.5, 0.5, 88 | -0.5, 0.5, 0.5, 89 | 90 | 0.5, 0.5, 0.5, 91 | 0.5, 0.5, -0.5, 92 | 0.5, -0.5, -0.5, 93 | 0.5, -0.5, -0.5, 94 | 0.5, -0.5, 0.5, 95 | 0.5, 0.5, 0.5, 96 | 97 | -0.5, -0.5, -0.5, 98 | 0.5, -0.5, -0.5, 99 | 0.5, -0.5, 0.5, 100 | 0.5, -0.5, 0.5, 101 | -0.5, -0.5, 0.5, 102 | -0.5, -0.5, -0.5, 103 | 104 | -0.5, 0.5, -0.5, 105 | 0.5, 0.5, -0.5, 106 | 0.5, 0.5, 0.5, 107 | 0.5, 0.5, 0.5, 108 | -0.5, 0.5, 0.5, 109 | -0.5, 0.5, -0.5, 110 | } 111 | } 112 | func (lc *LightingColors) initContainers(vertices []float32) { 113 | 114 | attr := glutils.NewAttributesMap() 115 | attr.Add(lc.lightingShader.Attributes["position"], 3, 0) 116 | lc.containerVa = glutils.VertexArray{ 117 | Data: vertices, 118 | Stride: 3, 119 | DrawMode: gl.STATIC_DRAW, 120 | Normalized: false, 121 | Attributes: attr, 122 | } 123 | lc.containerVa.Setup() 124 | 125 | attr2 := glutils.NewAttributesMap() 126 | attr2.Add(lc.lampShader.Attributes["position"], 3, 0) 127 | lc.lightVa = glutils.VertexArray{ 128 | Vbo: lc.containerVa.Vbo, 129 | Attributes: attr2, 130 | DrawMode: gl.STATIC_DRAW, 131 | Normalized: false, 132 | Stride: 3, 133 | } 134 | lc.lightVa.Setup() 135 | } 136 | func (lc *LightingColors) InitGL() error { 137 | lc.initCamera() 138 | if err := lc.initShaders( 139 | "_assets/lighting/1.colors/colors.vs", 140 | "_assets/lighting/1.colors/colors.frag", 141 | "_assets/lighting/1.colors/lamp.vs", 142 | "_assets/lighting/1.colors/lamp.frag", 143 | ); err != nil { 144 | return err 145 | } 146 | vertices := lc.getVertices() 147 | lc.initContainers(vertices) 148 | return nil 149 | } 150 | 151 | func (lc *LightingColors) Update() { 152 | // Set frame time 153 | currentFrame := glfw.GetTime() 154 | lc.deltaTime = currentFrame - lc.lastFrame 155 | lc.lastFrame = currentFrame 156 | if lc.w { 157 | lc.camera.ProcessKeyboard(glutils.FORWARD, lc.deltaTime) 158 | } 159 | if lc.s { 160 | lc.camera.ProcessKeyboard(glutils.BACKWARD, lc.deltaTime) 161 | } 162 | if lc.a { 163 | lc.camera.ProcessKeyboard(glutils.LEFT, lc.deltaTime) 164 | } 165 | if lc.d { 166 | lc.camera.ProcessKeyboard(glutils.RIGHT, lc.deltaTime) 167 | } 168 | } 169 | 170 | func (lc *LightingColors) clear() { 171 | // Clear the colorbuffer 172 | gl.ClearColor(lc.Color32.R, lc.Color32.G, lc.Color32.B, lc.Color32.A) 173 | gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) 174 | } 175 | func (lc *LightingColors) setLightingUniforms() { 176 | // Use corresponding shader when setting uniforms/drawing objects 177 | gl.Uniform3f(lc.lightingShader.Uniforms["objectColor"], 1.0, 0.5, 0.31) 178 | gl.Uniform3f(lc.lightingShader.Uniforms["lightColor"], 1.0, 0.5, 1.0) 179 | } 180 | func (lc *LightingColors) getCameraTransforms() (mgl32.Mat4, mgl32.Mat4) { 181 | // Create camera transformations 182 | view := lc.camera.GetViewMatrix() 183 | projection := mgl32.Perspective(float32(lc.camera.Zoom), sections.Ratio, 0.1, 100.0) 184 | return view, projection 185 | } 186 | func (lc *LightingColors) transformShader(shader glutils.Shader, view, projection mgl32.Mat4) { 187 | // Pass the matrices to the shader 188 | gl.UniformMatrix4fv(shader.Uniforms["view"], 1, false, &view[0]) 189 | gl.UniformMatrix4fv(shader.Uniforms["projection"], 1, false, &projection[0]) 190 | } 191 | func (lc *LightingColors) drawContainer() { 192 | // Draw the container (using container's vertex attributes) 193 | angle := float32(glfw.GetTime()) 194 | model := lc.translationMat.Mul4(mgl32.HomogRotate3D(angle, lc.rotationAxis)) 195 | gl.UniformMatrix4fv(lc.lightingShader.Uniforms["model"], 1, false, &model[0]) 196 | 197 | gl.BindVertexArray(lc.containerVa.Vao) 198 | gl.DrawArrays(gl.TRIANGLES, 0, 36) 199 | gl.BindVertexArray(0) 200 | } 201 | func (lc *LightingColors) drawLamp() { 202 | //model2 = model2.Mul4(mgl32.Translate3D(lc.lightPos[0], lc.lightPos[1], lc.lightPos[2])) 203 | model := lc.lightPositionMat.Mul4(lc.scaleMat) // Make it a smaller cube 204 | gl.UniformMatrix4fv(lc.lampShader.Uniforms["model"], 1, false, &model[0]) 205 | // Draw the light object (using light's vertex attributes) 206 | gl.BindVertexArray(lc.lightVa.Vao) 207 | gl.DrawArrays(gl.TRIANGLES, 0, 36) 208 | gl.BindVertexArray(0) 209 | } 210 | func (lc *LightingColors) Draw() { 211 | lc.clear() 212 | gl.UseProgram(lc.lightingShader.Program) 213 | lc.setLightingUniforms() 214 | v, p := lc.getCameraTransforms() 215 | lc.transformShader(lc.lightingShader, v, p) 216 | lc.drawContainer() 217 | 218 | // Also draw the lamp object, again binding the appropriate shader 219 | gl.UseProgram(lc.lampShader.Program) 220 | // Set matrices 221 | lc.transformShader(lc.lampShader, v, p) 222 | 223 | lc.drawLamp() 224 | } 225 | 226 | func (lc *LightingColors) Close() { 227 | lc.lampShader.Delete() 228 | lc.lightingShader.Delete() 229 | lc.lightVa.Delete() 230 | lc.containerVa.Delete() 231 | } 232 | 233 | func (lc *LightingColors) HandleKeyboard(k glfw.Key, s int, a glfw.Action, mk glfw.ModifierKey, keys map[glfw.Key]bool) { 234 | lc.w = keys[glfw.KeyW] 235 | lc.a = keys[glfw.KeyA] 236 | lc.s = keys[glfw.KeyS] 237 | lc.d = keys[glfw.KeyD] 238 | } 239 | 240 | func (lc *LightingColors) HandleMousePosition(xpos, ypos float64) { 241 | if lc.firstMouse { 242 | lc.lastX = xpos 243 | lc.lastY = ypos 244 | lc.firstMouse = false 245 | } 246 | 247 | xoffset := xpos - lc.lastX 248 | yoffset := lc.lastY - ypos // Reversed since y-coordinates go from bottom to left 249 | 250 | lc.lastX = xpos 251 | lc.lastY = ypos 252 | 253 | lc.camera.ProcessMouseMovement(xoffset, yoffset, true) 254 | } 255 | 256 | func (lc *LightingColors) HandleScroll(xoff, yoff float64) { 257 | lc.camera.ProcessMouseScroll(yoff) 258 | } 259 | -------------------------------------------------------------------------------- /sections/lighting/2.basic.go: -------------------------------------------------------------------------------- 1 | package lighting 2 | 3 | import ( 4 | "github.com/go-gl/gl/v4.1-core/gl" 5 | "github.com/raedatoui/glutils" 6 | ) 7 | 8 | type BasicSpecular struct { 9 | LightingColors 10 | } 11 | 12 | func (bc *BasicSpecular) GetHeader() string { 13 | return "2. Basic Specular Lighting" 14 | } 15 | 16 | func (lc *BasicSpecular) getVertices() []float32 { 17 | return []float32{ 18 | -0.5, -0.5, -0.5, 0.0, 0.0, -1.0, 19 | 0.5, -0.5, -0.5, 0.0, 0.0, -1.0, 20 | 0.5, 0.5, -0.5, 0.0, 0.0, -1.0, 21 | 0.5, 0.5, -0.5, 0.0, 0.0, -1.0, 22 | -0.5, 0.5, -0.5, 0.0, 0.0, -1.0, 23 | -0.5, -0.5, -0.5, 0.0, 0.0, -1.0, 24 | 25 | -0.5, -0.5, 0.5, 0.0, 0.0, 1.0, 26 | 0.5, -0.5, 0.5, 0.0, 0.0, 1.0, 27 | 0.5, 0.5, 0.5, 0.0, 0.0, 1.0, 28 | 0.5, 0.5, 0.5, 0.0, 0.0, 1.0, 29 | -0.5, 0.5, 0.5, 0.0, 0.0, 1.0, 30 | -0.5, -0.5, 0.5, 0.0, 0.0, 1.0, 31 | 32 | -0.5, 0.5, 0.5, -1.0, 0.0, 0.0, 33 | -0.5, 0.5, -0.5, -1.0, 0.0, 0.0, 34 | -0.5, -0.5, -0.5, -1.0, 0.0, 0.0, 35 | -0.5, -0.5, -0.5, -1.0, 0.0, 0.0, 36 | -0.5, -0.5, 0.5, -1.0, 0.0, 0.0, 37 | -0.5, 0.5, 0.5, -1.0, 0.0, 0.0, 38 | 39 | 0.5, 0.5, 0.5, 1.0, 0.0, 0.0, 40 | 0.5, 0.5, -0.5, 1.0, 0.0, 0.0, 41 | 0.5, -0.5, -0.5, 1.0, 0.0, 0.0, 42 | 0.5, -0.5, -0.5, 1.0, 0.0, 0.0, 43 | 0.5, -0.5, 0.5, 1.0, 0.0, 0.0, 44 | 0.5, 0.5, 0.5, 1.0, 0.0, 0.0, 45 | 46 | -0.5, -0.5, -0.5, 0.0, -1.0, 0.0, 47 | 0.5, -0.5, -0.5, 0.0, -1.0, 0.0, 48 | 0.5, -0.5, 0.5, 0.0, -1.0, 0.0, 49 | 0.5, -0.5, 0.5, 0.0, -1.0, 0.0, 50 | -0.5, -0.5, 0.5, 0.0, -1.0, 0.0, 51 | -0.5, -0.5, -0.5, 0.0, -1.0, 0.0, 52 | 53 | -0.5, 0.5, -0.5, 0.0, 1.0, 0.0, 54 | 0.5, 0.5, -0.5, 0.0, 1.0, 0.0, 55 | 0.5, 0.5, 0.5, 0.0, 1.0, 0.0, 56 | 0.5, 0.5, 0.5, 0.0, 1.0, 0.0, 57 | -0.5, 0.5, 0.5, 0.0, 1.0, 0.0, 58 | -0.5, 0.5, -0.5, 0.0, 1.0, 0.0, 59 | } 60 | } 61 | func (bc *BasicSpecular) initContainers(vertices []float32) { 62 | 63 | attr := glutils.NewAttributesMap() 64 | attr.Add(bc.lightingShader.Attributes["position"], 3, 0) 65 | attr.Add(bc.lightingShader.Attributes["normal"], 3, 3) 66 | bc.containerVa = glutils.VertexArray{ 67 | Data: vertices, 68 | Stride: 6, 69 | DrawMode: gl.STATIC_DRAW, 70 | Normalized: false, 71 | Attributes: attr, 72 | } 73 | bc.containerVa.Setup() 74 | 75 | attr2 := glutils.NewAttributesMap() 76 | attr2.Add(bc.lampShader.Attributes["position"], 3, 0) 77 | bc.lightVa = glutils.VertexArray{ 78 | Vbo: bc.containerVa.Vbo, 79 | Attributes: attr2, 80 | DrawMode: gl.STATIC_DRAW, 81 | Normalized: false, 82 | Stride: 6, 83 | } 84 | bc.lightVa.Setup() 85 | } 86 | 87 | func (bc *BasicSpecular) setLightingUniforms() { 88 | gl.Uniform3f(bc.lightingShader.Uniforms["objectColor"], 1.0, 0.5, 0.31) 89 | gl.Uniform3f(bc.lightingShader.Uniforms["lightColor"], 1.0, 0.5, 1.0) 90 | gl.Uniform3f(bc.lightingShader.Uniforms["lightPos"], bc.lightPos[0], bc.lightPos[1], bc.lightPos[2]) 91 | gl.Uniform3f(bc.lightingShader.Uniforms["viewPos"], bc.camera.Position[0], bc.camera.Position[1], bc.camera.Position[2]) 92 | } 93 | func (bc *BasicSpecular) InitGL() error { 94 | bc.initCamera() 95 | if err := bc.initShaders( 96 | "_assets/lighting/2.basic/lighting.vs", 97 | "_assets/lighting/2.basic/lighting.frag", 98 | "_assets/lighting/2.basic/lamp.vs", 99 | "_assets/lighting/2.basic/lamp.frag", 100 | ); err != nil { 101 | return err 102 | } 103 | bc.initContainers(bc.getVertices()) 104 | return nil 105 | } 106 | 107 | func (bc *BasicSpecular) Draw() { 108 | bc.clear() 109 | gl.UseProgram(bc.lightingShader.Program) 110 | bc.setLightingUniforms() 111 | v, p := bc.getCameraTransforms() 112 | bc.transformShader(bc.lightingShader, v, p) 113 | bc.drawContainer() 114 | 115 | // Also draw the lamp object, again binding the appropriate shader 116 | gl.UseProgram(bc.lampShader.Program) 117 | // Set matrices 118 | bc.transformShader(bc.lampShader, v, p) 119 | bc.drawLamp() 120 | } 121 | 122 | //func (bc *BasicSpecular) Draw() { 123 | // // Clear the colorbuffer 124 | // gl.ClearColor(bc.Color32.R, bc.Color32.G, bc.Color32.B, bc.Color32.A) 125 | // gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) 126 | // 127 | // // Use corresponding shader when setting uniforms/drawing objects 128 | // gl.UseProgram(bc.lightingShader) 129 | // objectColorLoc := gl.GetUniformLocation(bc.lightingShader, gl.Str("objectColor\x00")) 130 | // lightColorLoc := gl.GetUniformLocation(bc.lightingShader, gl.Str("lightColor\x00")) 131 | // lightPosLoc := gl.GetUniformLocation(bc.lightingShader, gl.Str("lightPos\x00")) 132 | // viewPosLoc := gl.GetUniformLocation(bc.lightingShader, gl.Str("viewPos\x00")) 133 | // gl.Uniform3f(objectColorLoc, 1.0, 0.5, 0.31) 134 | // gl.Uniform3f(lightColorLoc, 1.0, 0.5, 1.0) 135 | // gl.Uniform3f(lightPosLoc, bc.lightPos[0], bc.lightPos[1], bc.lightPos[2]) 136 | // gl.Uniform3f(viewPosLoc, bc.camera.Position[0], bc.camera.Position[1], bc.camera.Position[2]) 137 | // 138 | // // Create camera transformations 139 | // view := bc.camera.GetViewMatrix() 140 | // projection := mgl32.Perspective(float32(bc.camera.Zoom), sections.RATIO, 0.1, 100.0) 141 | // // Get the uniform locations 142 | // modelLoc := gl.GetUniformLocation(bc.lightingShader, gl.Str("model\x00")) 143 | // viewLoc := gl.GetUniformLocation(bc.lightingShader, gl.Str("view\x00")) 144 | // projLoc := gl.GetUniformLocation(bc.lightingShader, gl.Str("projection\x00")) 145 | // // Pass the matrices to the shader 146 | // gl.UniformMatrix4fv(viewLoc, 1, false, &view[0]) 147 | // gl.UniformMatrix4fv(projLoc, 1, false, &projection[0]) 148 | // 149 | // // Draw the container (using container's vertex attributes) 150 | // gl.BindVertexArray(bc.containerVAO) 151 | // model := mgl32.Translate3D(0, 0, 0.0) 152 | // angle := float32(glfw.GetTime()) 153 | // model = model.Mul4(mgl32.HomogRotate3D(angle, bc.rotationAxis)) 154 | // gl.UniformMatrix4fv(modelLoc, 1, false, &model[0]) 155 | // gl.DrawArrays(gl.TRIANGLES, 0, 36) 156 | // gl.BindVertexArray(0) 157 | // 158 | // // Also draw the lamp object, again binding the appropriate shader 159 | // gl.UseProgram(bc.lampShader) 160 | // // Get location objects for the matrices on the lamp shader (these could be different on a different shader) 161 | // modelLoc = gl.GetUniformLocation(bc.lampShader, gl.Str("model\x00")) 162 | // viewLoc = gl.GetUniformLocation(bc.lampShader, gl.Str("view\x00")) 163 | // projLoc = gl.GetUniformLocation(bc.lampShader, gl.Str("projection\x00")) 164 | // // Set matrices 165 | // gl.UniformMatrix4fv(viewLoc, 1, false, &view[0]) 166 | // gl.UniformMatrix4fv(projLoc, 1, false, &projection[0]) 167 | // 168 | // // Get location objects for the matrices on the lamp shader (these could be different on a different shader) 169 | // model2 := bc.lightPositionMat.Mul4(mgl32.Scale3D(0.2, 0.2, 0.2)) // Make it a smaller cube 170 | // gl.UniformMatrix4fv(modelLoc, 1, false, &model2[0]) 171 | // // Draw the light object (using light's vertex attributes) 172 | // gl.BindVertexArray(bc.lightVAO) 173 | // gl.DrawArrays(gl.TRIANGLES, 0, 36) 174 | // gl.BindVertexArray(0) 175 | //} 176 | -------------------------------------------------------------------------------- /sections/lighting/3.materials.go: -------------------------------------------------------------------------------- 1 | package lighting 2 | 3 | import ( 4 | "math" 5 | 6 | "github.com/go-gl/gl/v4.1-core/gl" 7 | "github.com/go-gl/glfw/v3.2/glfw" 8 | "github.com/go-gl/mathgl/mgl32" 9 | ) 10 | 11 | type Materials struct { 12 | BasicSpecular 13 | } 14 | 15 | func (m *Materials) GetHeader() string { 16 | return "2. Basic Specular Lighting" 17 | } 18 | 19 | func (m *Materials) setLightingUniforms() { 20 | gl.Uniform3f(m.lightingShader.Uniforms["light.position"], m.lightPos.X(), m.lightPos.Y(), m.lightPos.Z()) 21 | gl.Uniform3f(m.lightingShader.Uniforms["viewPos"], m.camera.Position.X(), m.camera.Position.Y(), m.camera.Position.Z()) 22 | 23 | // Set lights properties 24 | lightColor := mgl32.Vec3{ 25 | float32(math.Sin(glfw.GetTime() * 2.0)), 26 | float32(math.Sin(glfw.GetTime() * 0.7)), 27 | float32(math.Sin(glfw.GetTime() * 1.3)), 28 | } 29 | 30 | // Decrease the influence 31 | diffuseColor := mgl32.Vec3{ 32 | lightColor.X() * 0.5, 33 | lightColor.Y() * 0.5, 34 | lightColor.Z() * 0.5, 35 | } 36 | // Low influence 37 | ambientColor := mgl32.Vec3{ 38 | diffuseColor.X() * 0.2, 39 | diffuseColor.Y() * 0.2, 40 | diffuseColor.Z() * 0.2, 41 | } 42 | 43 | gl.Uniform3f(m.lightingShader.Uniforms["light.ambient"], ambientColor.X(), ambientColor.Y(), ambientColor.Z()) 44 | gl.Uniform3f(m.lightingShader.Uniforms["light.diffuse"], diffuseColor.X(), diffuseColor.Y(), diffuseColor.Z()) 45 | gl.Uniform3f(m.lightingShader.Uniforms["light.specular"], 1.0, 1.0, 1.0) 46 | // Set material properties 47 | gl.Uniform3f(m.lightingShader.Uniforms["material.ambient"], 1.0, 0.5, 0.31) 48 | gl.Uniform3f(m.lightingShader.Uniforms["material.diffuse"], 1.0, 0.5, 0.31) 49 | gl.Uniform3f(m.lightingShader.Uniforms["material.specular"], 0.5, 0.5, 0.5) // Specular doesn't have full effect on this object's material 50 | gl.Uniform1f(m.lightingShader.Uniforms["material.shininess"], 32.0) 51 | } 52 | func (m *Materials) InitGL() error { 53 | m.initCamera() 54 | if err := m.initShaders( 55 | "_assets/lighting/3.materials/materials.vs", 56 | "_assets/lighting/3.materials/materials.frag", 57 | "_assets/lighting/3.materials/lamp.vs", 58 | "_assets/lighting/3.materials/lamp.frag", 59 | ); err != nil { 60 | return err 61 | } 62 | m.initContainers(m.getVertices()) 63 | return nil 64 | } 65 | 66 | func (m *Materials) Draw() { 67 | m.clear() 68 | gl.UseProgram(m.lightingShader.Program) 69 | m.setLightingUniforms() 70 | v, p := m.getCameraTransforms() 71 | m.transformShader(m.lightingShader, v, p) 72 | m.drawContainer() 73 | 74 | // Also draw the lamp object, again binding the appropriate shader 75 | gl.UseProgram(m.lampShader.Program) 76 | // Set matrices 77 | m.transformShader(m.lampShader, v, p) 78 | m.drawLamp() 79 | } 80 | -------------------------------------------------------------------------------- /sections/modelloading/1.model_loading.go: -------------------------------------------------------------------------------- 1 | package modelloading 2 | 3 | import ( 4 | "github.com/go-gl/gl/v4.1-core/gl" 5 | "github.com/go-gl/glfw/v3.2/glfw" 6 | "github.com/go-gl/mathgl/mgl32" 7 | "github.com/raedatoui/glutils" 8 | "github.com/raedatoui/learn-opengl-golang/sections" 9 | "path" 10 | "fmt" 11 | ) 12 | 13 | type ModelLoading struct { 14 | sections.BaseSketch 15 | shader glutils.Shader 16 | model glutils.Model 17 | camera glutils.Camera 18 | deltaTime, lastFrame float64 19 | lastX, lastY float64 20 | firstMouse bool 21 | w, a, s, d bool 22 | } 23 | 24 | func (ml *ModelLoading) InitGL() error { 25 | ml.firstMouse = false 26 | ml.camera = glutils.NewCamera( 27 | mgl32.Vec3{0.0, 0.0, 3.0}, 28 | mgl32.Vec3{0.0, 1.0, 3.0}, 29 | glutils.YAW, glutils.PITCH, 30 | ) 31 | ml.Name = "3. Model Loading" 32 | // Setup and compile our shaders 33 | ml.shader, _ = glutils.NewShader("_assets/model_loading/shader.vs", 34 | "_assets/model_loading/shader.frag", "") 35 | // Load models 36 | ml.model, _ = glutils.NewModel("_assets/objects/nanosuit/", "nanosuit.obj", false) 37 | gl.PolygonMode(gl.FRONT_AND_BACK, gl.LINE) 38 | return nil 39 | } 40 | 41 | func (ml *ModelLoading) Update() { 42 | // Set frame time 43 | currentFrame := glfw.GetTime() 44 | ml.deltaTime = currentFrame - ml.lastFrame 45 | ml.lastFrame = currentFrame 46 | if ml.w { 47 | ml.camera.ProcessKeyboard(glutils.FORWARD, ml.deltaTime) 48 | } 49 | if ml.s { 50 | ml.camera.ProcessKeyboard(glutils.BACKWARD, ml.deltaTime) 51 | } 52 | if ml.a { 53 | ml.camera.ProcessKeyboard(glutils.LEFT, ml.deltaTime) 54 | } 55 | if ml.d { 56 | ml.camera.ProcessKeyboard(glutils.RIGHT, ml.deltaTime) 57 | } 58 | } 59 | 60 | func (ml *ModelLoading) Draw() { 61 | gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) 62 | gl.ClearColor(ml.Color32.R, ml.Color32.G, ml.Color32.B, ml.Color32.A) 63 | 64 | gl.UseProgram(ml.shader.Program) 65 | 66 | // Transformation matrices 67 | projection := mgl32.Perspective(float32(ml.camera.Zoom), sections.Ratio, 0.1, 100.0) 68 | view := ml.camera.GetViewMatrix() 69 | 70 | gl.UniformMatrix4fv(ml.shader.Uniforms["view"], 1, false, &view[0]) 71 | gl.UniformMatrix4fv(ml.shader.Uniforms["projection"], 1, false, &projection[0]) 72 | 73 | // Draw the loaded model 74 | model := mgl32.Translate3D(0, -1.75, 0.0) // Translate it down a bit so it's at the center of the scene 75 | model = model.Mul4(mgl32.Scale3D(0.2, 0.2, 0.2)) // It's a bit too big for our scene, so scale it down 76 | 77 | gl.UniformMatrix4fv(ml.shader.Uniforms["model"], 1, false, &model[0]) 78 | ml.model.Draw(ml.shader.Program) 79 | } 80 | 81 | func (lc *ModelLoading) HandleMousePosition(xpos, ypos float64) { 82 | if lc.firstMouse { 83 | lc.lastX = xpos 84 | lc.lastY = ypos 85 | lc.firstMouse = false 86 | } 87 | 88 | xoffset := xpos - lc.lastX 89 | yoffset := lc.lastY - ypos // Reversed since y-coordinates go from bottom to left 90 | 91 | lc.lastX = xpos 92 | lc.lastY = ypos 93 | 94 | lc.camera.ProcessMouseMovement(xoffset, yoffset, true) 95 | } 96 | 97 | func (ml *ModelLoading) HandleKeyboard(k glfw.Key, s int, a glfw.Action, mk glfw.ModifierKey, keys map[glfw.Key]bool) { 98 | ml.w = keys[glfw.KeyW] 99 | ml.a = keys[glfw.KeyA] 100 | ml.s = keys[glfw.KeyS] 101 | ml.d = keys[glfw.KeyD] 102 | } 103 | 104 | func (ml *ModelLoading) HandleScroll(xoff, yoff float64) { 105 | ml.camera.ProcessMouseScroll(yoff) 106 | } 107 | 108 | func (ml *ModelLoading) HandleFiles(names []string) { 109 | f := path.Base(names[0]) 110 | dir := path.Dir(names[0]) + "/" 111 | fmt.Println(f, dir) 112 | ml.model.Dispose() 113 | ml.model, _ = glutils.NewModel(dir, f, false) 114 | //gl.PolygonMode(gl.FRONT_AND_BACK, gl.LINE) 115 | } 116 | 117 | func (ml *ModelLoading) Close() { 118 | ml.model.Dispose() 119 | gl.UseProgram(0) 120 | } 121 | -------------------------------------------------------------------------------- /sections/title_slide.go: -------------------------------------------------------------------------------- 1 | package sections 2 | 3 | import ( 4 | "errors" 5 | "github.com/go-gl/gl/v4.1-core/gl" 6 | "github.com/raedatoui/glfont" 7 | "github.com/raedatoui/glutils" 8 | "strings" 9 | ) 10 | 11 | type TitleSlide struct { 12 | BaseSlide 13 | font *glfont.Font 14 | lines []string 15 | } 16 | 17 | func (s *TitleSlide) Init(a ...interface{}) error { 18 | f, ok := a[0].(*glfont.Font) 19 | if ok == false { 20 | return errors.New("first argument isnt a font") 21 | } 22 | s.font = f 23 | 24 | c, ok := a[1].(glutils.Color) 25 | if ok == false { 26 | return errors.New("second argument isnt a ColorA") 27 | } 28 | s.Color = c 29 | s.Color32 = c.To32() 30 | s.ColorHex = glutils.Rgb2Hex(c) 31 | 32 | n, ok := a[2].(string) 33 | if ok == false { 34 | return errors.New("third argument isnt a string") 35 | } 36 | s.Name = n 37 | 38 | if strings.Contains(s.Name, "\n") { 39 | s.lines = strings.Split(s.Name, "\n") 40 | } else { 41 | s.lines = []string{s.Name} 42 | } 43 | 44 | return nil 45 | } 46 | 47 | func (s *TitleSlide) Draw() { 48 | gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) 49 | gl.ClearColor(s.Color32.R, s.Color32.G, s.Color32.B, s.Color32.A) 50 | 51 | s.font.SetColor(1.0, 1.0, 1.0, 1.0) 52 | for i := 0; i < len(s.lines); i++ { 53 | s.font.Printf(30, 100+60*float32(i), 0.85, s.lines[i]) 54 | } 55 | } 56 | 57 | func (b *TitleSlide) DrawText() bool { 58 | return false 59 | } 60 | -------------------------------------------------------------------------------- /tutorial.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | _ "image/png" 6 | "log" 7 | "os" 8 | "runtime" 9 | "strconv" 10 | 11 | "github.com/go-gl/gl/v4.1-core/gl" 12 | "github.com/go-gl/glfw/v3.2/glfw" 13 | "github.com/raedatoui/glfont" 14 | "github.com/raedatoui/glutils" 15 | "github.com/raedatoui/learn-opengl-golang/sections" 16 | "github.com/raedatoui/learn-opengl-golang/sections/getstarted" 17 | "github.com/raedatoui/learn-opengl-golang/sections/lighting" 18 | "github.com/raedatoui/learn-opengl-golang/sections/modelloading" 19 | ) 20 | 21 | var ( 22 | currentSlide sections.Slide 23 | slides []sections.Slide 24 | covers map[int]sections.Slide 25 | slideIndex = 0 26 | window *glfw.Window 27 | font *glfont.Font 28 | keys map[glfw.Key]bool 29 | wireframe int32 30 | ) 31 | 32 | func init() { 33 | // This is needed to arrange that main() runs on main thread. 34 | // See documentation for functions that are only allowed to be called from the main thread. 35 | runtime.LockOSThread() 36 | } 37 | 38 | func init() { 39 | dir, err := glutils.ImportPathToDir("github.com/raedatoui/learn-opengl-golang") 40 | if err != nil { 41 | log.Fatalln("Unable to find Go package in your GOPATH, it's needed to load assets:", err) 42 | } 43 | if err := os.Chdir(dir); err != nil { 44 | log.Panicln("os.Chdir:", err) 45 | } 46 | } 47 | 48 | func keyCallBack(w *glfw.Window, k glfw.Key, s int, a glfw.Action, mk glfw.ModifierKey) { 49 | if a == glfw.Press { 50 | if k == glfw.KeyEscape { 51 | window.SetShouldClose(true) 52 | } 53 | if k == glfw.KeySpace { 54 | gl.GetIntegerv(gl.POLYGON_MODE, &wireframe) 55 | switch wireframe { 56 | case gl.FILL: 57 | gl.PolygonMode(gl.FRONT_AND_BACK, gl.LINE) 58 | case gl.LINE: 59 | gl.PolygonMode(gl.FRONT_AND_BACK, gl.POINT) 60 | gl.PointSize(20.0) 61 | case gl.POINT: 62 | gl.PolygonMode(gl.FRONT_AND_BACK, gl.FILL) 63 | } 64 | } 65 | 66 | if k >= glfw.Key0 && k <= glfw.Key9 { 67 | c := int(k) - 48 68 | if c < len(covers) { 69 | slideIndex = sections.SlidePosition(slides, covers[c]) 70 | currentSlide.Close() 71 | currentSlide = slides[slideIndex] 72 | if err := currentSlide.InitGL(); err != nil { 73 | log.Fatalf("slide failed %v: ", err) 74 | } 75 | return 76 | } 77 | } 78 | 79 | newIndex := slideIndex 80 | if s == 124 { 81 | newIndex = slideIndex + 1 82 | if newIndex > len(slides)-1 { 83 | newIndex = len(slides) - 1 84 | } 85 | } 86 | if s == 123 { 87 | newIndex = slideIndex - 1 88 | if newIndex < 0 { 89 | newIndex = 0 90 | } 91 | } 92 | if newIndex != slideIndex { 93 | slideIndex = newIndex 94 | currentSlide.Close() 95 | currentSlide = slides[newIndex] 96 | if err := currentSlide.InitGL(); err != nil { 97 | log.Fatalf("slide failed %v: ", err) 98 | } 99 | return 100 | } 101 | keys[k] = true 102 | 103 | } else if a == glfw.Release { 104 | keys[k] = false 105 | } 106 | 107 | if currentSlide != nil { 108 | currentSlide.HandleKeyboard(k, s, a, mk, keys) 109 | } 110 | 111 | } 112 | 113 | func mouseCallback(w *glfw.Window, xpos float64, ypos float64) { 114 | if currentSlide != nil { 115 | currentSlide.HandleMousePosition(xpos, ypos) 116 | } 117 | } 118 | 119 | func scrollCallback(w *glfw.Window, xoff float64, yoff float64) { 120 | if currentSlide != nil { 121 | currentSlide.HandleScroll(xoff, yoff) 122 | } 123 | } 124 | 125 | func resizeCallback(w *glfw.Window, width int, height int) { 126 | sections.WIDTH = float64(width) 127 | sections.HEIGHT = float64(height) 128 | sections.Ratio = float32(sections.WIDTH / sections.HEIGHT) 129 | font.Resize(sections.WIDTH, sections.HEIGHT) 130 | gl.Viewport(0, 0, int32(width), int32(height)) 131 | } 132 | 133 | func fileDropCallback(w *glfw.Window, names []string) { 134 | if currentSlide != nil { 135 | currentSlide.HandleFiles(names) 136 | } 137 | } 138 | 139 | func setup() (*glfw.Window, error) { 140 | glfw.WindowHint(glfw.Resizable, glfw.True) 141 | glfw.WindowHint(glfw.ContextVersionMajor, 4) 142 | glfw.WindowHint(glfw.ContextVersionMinor, 1) 143 | glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile) 144 | glfw.WindowHint(glfw.OpenGLForwardCompatible, gl.TRUE) 145 | 146 | window, err := glfw.CreateWindow(int(sections.WIDTH), int(sections.HEIGHT), "learnopengl.com in Golang", nil, nil) 147 | if err != nil { 148 | return nil, err 149 | } 150 | window.MakeContextCurrent() 151 | 152 | // Initialize Glow - this is the equivalent of glew 153 | if err := gl.Init(); err != nil { 154 | return nil, err 155 | } 156 | 157 | // Resize Callback 158 | window.SetFramebufferSizeCallback(resizeCallback) 159 | 160 | //Keyboard Callback 161 | window.SetKeyCallback(keyCallBack) 162 | window.SetCursorPosCallback(mouseCallback) 163 | window.SetScrollCallback(scrollCallback) 164 | 165 | // File Drag n Drop 166 | window.SetDropCallback(fileDropCallback) 167 | version := gl.GoStr(gl.GetString(gl.VERSION)) 168 | glsl := gl.GoStr(gl.GetString(gl.SHADING_LANGUAGE_VERSION)) 169 | fmt.Println("OpenGL version", version, glsl) 170 | 171 | width, height := window.GetFramebufferSize() 172 | gl.Viewport(0, 0, int32(width), int32(height)) 173 | 174 | return window, nil 175 | } 176 | 177 | func setupSlides() []sections.Slide { 178 | // make a slice of pointers to sketch instances 179 | return []sections.Slide{ 180 | new(sections.TitleSlide), 181 | new(getstarted.HelloCube), 182 | new(sections.TitleSlide), 183 | new(getstarted.HelloWindow), 184 | 185 | new(getstarted.HelloTriangle), 186 | new(getstarted.TriangleEx1), 187 | new(getstarted.TriangleEx2), 188 | 189 | new(getstarted.HelloShaders), 190 | new(getstarted.ShaderEx1), 191 | new(getstarted.ShaderEx2), 192 | new(getstarted.ShaderEx3), 193 | new(getstarted.ShaderEx4), 194 | 195 | new(getstarted.HelloTextures), 196 | new(getstarted.TexturesEx1), 197 | new(getstarted.TexturesEx2), 198 | new(getstarted.TexturesEx3), 199 | new(getstarted.TexturesEx4), 200 | 201 | new(getstarted.HelloTransformations), 202 | new(getstarted.TransformationEx1), 203 | new(getstarted.TransformationEx2), 204 | 205 | new(getstarted.HelloCoordinates), 206 | new(getstarted.HelloCamera), 207 | 208 | new(sections.TitleSlide), 209 | new(lighting.LightingColors), 210 | new(lighting.BasicSpecular), 211 | new(lighting.Materials), 212 | 213 | new(sections.TitleSlide), 214 | new(modelloading.ModelLoading), 215 | 216 | new(sections.TitleSlide), 217 | new(sections.TitleSlide), 218 | new(sections.TitleSlide), 219 | new(sections.TitleSlide), 220 | } 221 | } 222 | 223 | func main() { 224 | // init GLFW 225 | if err := glfw.Init(); err != nil { 226 | log.Fatalln("failed to initialize glfw:", err) 227 | } 228 | defer glfw.Terminate() 229 | 230 | keys = make(map[glfw.Key]bool) 231 | 232 | // create window 233 | w, err := setup() 234 | if err != nil { 235 | log.Fatalf("cant create window %v", err) 236 | } 237 | window = w 238 | 239 | //load font (fontfile, font scale, window width, window height 240 | f, err := glfont.LoadFont("_assets/fonts/huge_agb_v5.ttf", int32(52), sections.WIDTH, sections.HEIGHT) 241 | if err != nil { 242 | log.Fatalf("LoadFont: %v", err) 243 | } 244 | font = f 245 | c := glutils.White.To32() 246 | font.SetColor(c.R, c.G, c.B, 1.0) 247 | 248 | slides = setupSlides() 249 | l := len(slides) 250 | covers = make(map[int]sections.Slide) 251 | titles := []string{ 252 | "LearnOpenGL in Go\n \n" + 253 | "0. Test installation using go-gl\n" + 254 | "1. Getting Started\n" + 255 | "2. Lighting\n" + 256 | "3. Model Loading\n" + 257 | "4. Advanced OpenGL\n" + 258 | "5. Advanced Lighting\n" + 259 | "6. PBR\n" + 260 | "7. In Practice", 261 | "Section 1: Getting Started", 262 | "Section 2: Lighting", 263 | "Section 3: Model Loading", 264 | "Section 4: Advanced OpenGL", 265 | "Section 5: Advanced Lighting", 266 | "Section 6: PBR", 267 | "Section 7: In Practice", 268 | } 269 | count := 0 270 | titleSlideType := §ions.TitleSlide{} 271 | for x, slide := range slides { 272 | c := glutils.StepColor(glutils.Magenta, glutils.Black, l, x) 273 | 274 | if glutils.IsType(slide, titleSlideType) { 275 | covers[count] = slide 276 | if err := slide.Init(f, c, titles[count]); err != nil { 277 | log.Fatalf("Failed setting up sketch: %v", err) 278 | } 279 | count += 1 280 | } else { 281 | if err := slide.Init(f, c); err != nil { 282 | log.Fatalf("Failed setting up sketch: %v", err) 283 | } 284 | } 285 | } 286 | 287 | currentSlide = slides[0] 288 | 289 | if err := currentSlide.InitGL(); err != nil { 290 | log.Fatalf("Failed initializing GL for slide: %v", err) 291 | } 292 | 293 | // TODO: do we always need to enabled the depth test? 294 | gl.Enable(gl.DEPTH_TEST) 295 | //gl.DepthFunc(gl.LESS) 296 | 297 | // TODO: how to effectively blend shapes that use a frag shader with 298 | // TODO: transparency 299 | gl.Enable(gl.BLEND) 300 | gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) 301 | 302 | var maxAttrib int32 303 | gl.GetIntegerv(gl.MAX_VERTEX_ATTRIBS, &maxAttrib) 304 | 305 | glutils.InitFPS() 306 | 307 | // loop 308 | for !window.ShouldClose() { 309 | 310 | // Update 311 | currentSlide.Update() 312 | 313 | //Render 314 | currentSlide.Draw() 315 | if currentSlide.DrawText() { 316 | font.Printf(30, 30, 0.5, currentSlide.GetHeader()) 317 | if currentSlide.GetSubHeader() != "" { 318 | font.Printf(30, 50, 0.3, currentSlide.GetSubHeader()) 319 | } 320 | } 321 | 322 | font.Printf(30, float32(sections.HEIGHT)-20, 0.2, currentSlide.GetColorHex()) 323 | fps := "FPS: " + strconv.FormatFloat(glutils.CalcFPS(1.0), 'f', 2, 64) 324 | font.Printf(float32(sections.WIDTH)-80, float32(sections.HEIGHT)-20, 0.25, fps) 325 | 326 | window.SwapBuffers() 327 | // Poll Events 328 | glfw.PollEvents() 329 | } 330 | currentSlide.Close() 331 | 332 | } 333 | --------------------------------------------------------------------------------