├── .github └── workflows │ ├── golangci-lint.yaml │ └── main.yml ├── .golangci.yml ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── gl21-cube ├── README.md ├── Screenshot.png ├── cube.go └── square.png ├── gl41core-cube ├── README.md ├── Screenshot.png ├── cube.go └── square.png ├── go.mod └── go.sum /.github/workflows/golangci-lint.yaml: -------------------------------------------------------------------------------- 1 | name: golangci-lint 2 | on: [push, pull_request] 3 | jobs: 4 | golangci: 5 | name: lint 6 | runs-on: ubuntu-latest 7 | steps: 8 | - uses: actions/checkout@v2 9 | - name: Install libraries 10 | run: | 11 | sudo apt-get update 12 | sudo apt-get install -y mesa-utils mesa-common-dev libx11-dev libxcursor-dev libxrandr-dev libxinerama-dev libxi-dev libgl1-mesa-dev libxxf86vm-dev libglfw3-dev 13 | 14 | - name: golangci-lint 15 | uses: golangci/golangci-lint-action@v2.5.2 16 | with: 17 | version: v1.39.0 18 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Main 2 | on: [push, pull_request] 3 | jobs: 4 | 5 | tests: 6 | name: ${{matrix.go-version}} ${{matrix.os}} 7 | runs-on: ${{ matrix.os }} 8 | strategy: 9 | matrix: 10 | go-version: [1.14, 1.16] 11 | os: [macos-latest, windows-latest, ubuntu-latest] 12 | steps: 13 | - name: Install dependencies (linux) 14 | if: ${{ matrix.os == 'ubuntu-latest' }} 15 | run: | 16 | sudo apt-get update 17 | sudo apt-get install -y mesa-utils mesa-common-dev libx11-dev libxcursor-dev libxrandr-dev libxinerama-dev libxi-dev libgl1-mesa-dev libxxf86vm-dev libglfw3-dev 18 | - name: Set up Go 19 | uses: actions/setup-go@v1 20 | with: 21 | go-version: ${{matrix.go-version}} 22 | - name: Print go version 23 | run: go version 24 | - name: Check out module 25 | uses: actions/checkout@v1 26 | with: 27 | fetch-depth: 1 28 | - name: Run tests 29 | run: go test -v -race ./... 30 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | run: 2 | deadline: 5m 3 | 4 | issues: 5 | exclude-use-default: false # disable filtering of defaults for better zero-issue policy 6 | max-per-linter: 0 # disable limit; report all issues of a linter 7 | max-same-issues: 0 # disable limit; report all issues of the same issue 8 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributing to go-gl/example 2 | ============================= 3 | 4 | We appreciate your help! 5 | 6 | Contributing to existing examples 7 | --------------------------------- 8 | 9 | Feel free to create PRs with suggested improvements for review. 10 | 11 | Contributing new examples 12 | ------------------------- 13 | 14 | We want to ensure the examples here are high quality, well maintained, few and well organized. The goal is to be helpful to people who are interested in examples. 15 | 16 | We will accept new examples if those criteria are met and if it's reasonable to expect that the contributed examples will be maintained. 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2012 go-gl authors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # go-gl Examples [![Build Status](https://github.com/go-gl/example/actions/workflows/main.yml/badge.svg)](https://github.com/go-gl/example/actions/workflows/main.yml) 2 | 3 | Basic Usage 4 | ----------- 5 | 6 | These examples demonstrate initialization and basic usage. They have the bare minimum code needed. 7 | 8 | - [`gl41core-cube`](gl41core-cube) - Renders a textured spinning cube using GLFW 3 and OpenGL 4.1 core forward-compatible profile. 9 | - [`gl21-cube`](gl21-cube) - Renders a textured spinning cube using GLFW 3 and OpenGL 2.1. 10 | -------------------------------------------------------------------------------- /gl21-cube/README.md: -------------------------------------------------------------------------------- 1 | Cube 2 | ==== 3 | 4 | Renders a textured spinning cube using GLFW 3 and OpenGL 2.1. 5 | 6 | ``` 7 | go get -u github.com/go-gl/example/gl21-cube 8 | ``` 9 | 10 | ![Screenshot](Screenshot.png) 11 | -------------------------------------------------------------------------------- /gl21-cube/Screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-gl/example/d71b0d9f823d97c3b5ac2a79fdcdb56ca1677eba/gl21-cube/Screenshot.png -------------------------------------------------------------------------------- /gl21-cube/cube.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 | // Renders a textured spinning cube using GLFW 3 and OpenGL 2.1. 6 | package main // import "github.com/go-gl/example/gl21-cube" 7 | 8 | import ( 9 | "go/build" 10 | "image" 11 | "image/draw" 12 | _ "image/png" 13 | "log" 14 | "os" 15 | "runtime" 16 | 17 | "github.com/go-gl/gl/v2.1/gl" 18 | "github.com/go-gl/glfw/v3.3/glfw" 19 | ) 20 | 21 | var ( 22 | texture uint32 23 | rotationX float32 24 | rotationY float32 25 | ) 26 | 27 | const width, height = 800, 600 28 | 29 | func init() { 30 | // GLFW event handling must run on the main OS thread 31 | runtime.LockOSThread() 32 | } 33 | 34 | func main() { 35 | if err := glfw.Init(); err != nil { 36 | log.Fatalln("failed to initialize glfw:", err) 37 | } 38 | defer glfw.Terminate() 39 | 40 | glfw.WindowHint(glfw.Resizable, glfw.False) 41 | glfw.WindowHint(glfw.ContextVersionMajor, 2) 42 | glfw.WindowHint(glfw.ContextVersionMinor, 1) 43 | window, err := glfw.CreateWindow(width, height, "Cube", nil, nil) 44 | if err != nil { 45 | panic(err) 46 | } 47 | window.MakeContextCurrent() 48 | 49 | if err := gl.Init(); err != nil { 50 | panic(err) 51 | } 52 | 53 | texture = newTexture("square.png") 54 | defer gl.DeleteTextures(1, &texture) 55 | 56 | setupScene() 57 | for !window.ShouldClose() { 58 | drawScene() 59 | window.SwapBuffers() 60 | glfw.PollEvents() 61 | } 62 | } 63 | 64 | func newTexture(file string) uint32 { 65 | imgFile, err := os.Open(file) 66 | if err != nil { 67 | log.Fatalf("texture %q not found on disk: %v\n", file, err) 68 | } 69 | img, _, err := image.Decode(imgFile) 70 | if err != nil { 71 | panic(err) 72 | } 73 | 74 | rgba := image.NewRGBA(img.Bounds()) 75 | if rgba.Stride != rgba.Rect.Size().X*4 { 76 | panic("unsupported stride") 77 | } 78 | draw.Draw(rgba, rgba.Bounds(), img, image.Point{0, 0}, draw.Src) 79 | 80 | var texture uint32 81 | gl.Enable(gl.TEXTURE_2D) 82 | gl.GenTextures(1, &texture) 83 | gl.BindTexture(gl.TEXTURE_2D, texture) 84 | gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) 85 | gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) 86 | gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) 87 | gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) 88 | gl.TexImage2D( 89 | gl.TEXTURE_2D, 90 | 0, 91 | gl.RGBA, 92 | int32(rgba.Rect.Size().X), 93 | int32(rgba.Rect.Size().Y), 94 | 0, 95 | gl.RGBA, 96 | gl.UNSIGNED_BYTE, 97 | gl.Ptr(rgba.Pix)) 98 | 99 | return texture 100 | } 101 | 102 | func setupScene() { 103 | gl.Enable(gl.DEPTH_TEST) 104 | gl.Enable(gl.LIGHTING) 105 | 106 | gl.ClearColor(0.5, 0.5, 0.5, 0.0) 107 | gl.ClearDepth(1) 108 | gl.DepthFunc(gl.LEQUAL) 109 | 110 | ambient := []float32{0.5, 0.5, 0.5, 1} 111 | diffuse := []float32{1, 1, 1, 1} 112 | lightPosition := []float32{-5, 5, 10, 0} 113 | gl.Lightfv(gl.LIGHT0, gl.AMBIENT, &ambient[0]) 114 | gl.Lightfv(gl.LIGHT0, gl.DIFFUSE, &diffuse[0]) 115 | gl.Lightfv(gl.LIGHT0, gl.POSITION, &lightPosition[0]) 116 | gl.Enable(gl.LIGHT0) 117 | 118 | gl.MatrixMode(gl.PROJECTION) 119 | gl.LoadIdentity() 120 | f := float64(width)/height - 1 121 | gl.Frustum(-1-f, 1+f, -1, 1, 1.0, 10.0) 122 | gl.MatrixMode(gl.MODELVIEW) 123 | gl.LoadIdentity() 124 | } 125 | 126 | func drawScene() { 127 | gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) 128 | 129 | gl.MatrixMode(gl.MODELVIEW) 130 | gl.LoadIdentity() 131 | gl.Translatef(0, 0, -3.0) 132 | gl.Rotatef(rotationX, 1, 0, 0) 133 | gl.Rotatef(rotationY, 0, 1, 0) 134 | 135 | rotationX += 0.5 136 | rotationY += 0.5 137 | 138 | gl.BindTexture(gl.TEXTURE_2D, texture) 139 | 140 | gl.Color4f(1, 1, 1, 1) 141 | 142 | gl.Begin(gl.QUADS) 143 | 144 | gl.Normal3f(0, 0, 1) 145 | gl.TexCoord2f(0, 0) 146 | gl.Vertex3f(-1, -1, 1) 147 | gl.TexCoord2f(1, 0) 148 | gl.Vertex3f(1, -1, 1) 149 | gl.TexCoord2f(1, 1) 150 | gl.Vertex3f(1, 1, 1) 151 | gl.TexCoord2f(0, 1) 152 | gl.Vertex3f(-1, 1, 1) 153 | 154 | gl.Normal3f(0, 0, -1) 155 | gl.TexCoord2f(1, 0) 156 | gl.Vertex3f(-1, -1, -1) 157 | gl.TexCoord2f(1, 1) 158 | gl.Vertex3f(-1, 1, -1) 159 | gl.TexCoord2f(0, 1) 160 | gl.Vertex3f(1, 1, -1) 161 | gl.TexCoord2f(0, 0) 162 | gl.Vertex3f(1, -1, -1) 163 | 164 | gl.Normal3f(0, 1, 0) 165 | gl.TexCoord2f(0, 1) 166 | gl.Vertex3f(-1, 1, -1) 167 | gl.TexCoord2f(0, 0) 168 | gl.Vertex3f(-1, 1, 1) 169 | gl.TexCoord2f(1, 0) 170 | gl.Vertex3f(1, 1, 1) 171 | gl.TexCoord2f(1, 1) 172 | gl.Vertex3f(1, 1, -1) 173 | 174 | gl.Normal3f(0, -1, 0) 175 | gl.TexCoord2f(1, 1) 176 | gl.Vertex3f(-1, -1, -1) 177 | gl.TexCoord2f(0, 1) 178 | gl.Vertex3f(1, -1, -1) 179 | gl.TexCoord2f(0, 0) 180 | gl.Vertex3f(1, -1, 1) 181 | gl.TexCoord2f(1, 0) 182 | gl.Vertex3f(-1, -1, 1) 183 | 184 | gl.Normal3f(1, 0, 0) 185 | gl.TexCoord2f(1, 0) 186 | gl.Vertex3f(1, -1, -1) 187 | gl.TexCoord2f(1, 1) 188 | gl.Vertex3f(1, 1, -1) 189 | gl.TexCoord2f(0, 1) 190 | gl.Vertex3f(1, 1, 1) 191 | gl.TexCoord2f(0, 0) 192 | gl.Vertex3f(1, -1, 1) 193 | 194 | gl.Normal3f(-1, 0, 0) 195 | gl.TexCoord2f(0, 0) 196 | gl.Vertex3f(-1, -1, -1) 197 | gl.TexCoord2f(1, 0) 198 | gl.Vertex3f(-1, -1, 1) 199 | gl.TexCoord2f(1, 1) 200 | gl.Vertex3f(-1, 1, 1) 201 | gl.TexCoord2f(0, 1) 202 | gl.Vertex3f(-1, 1, -1) 203 | 204 | gl.End() 205 | } 206 | 207 | // Set the working directory to the root of Go package, so that its assets can be accessed. 208 | func init() { 209 | dir, err := importPathToDir("github.com/go-gl/example/gl21-cube") 210 | if err != nil { 211 | log.Fatalln("Unable to find Go package in your GOPATH, it's needed to load assets:", err) 212 | } 213 | err = os.Chdir(dir) 214 | if err != nil { 215 | log.Panicln("os.Chdir:", err) 216 | } 217 | } 218 | 219 | // importPathToDir resolves the absolute path from importPath. 220 | // There doesn't need to be a valid Go package inside that import path, 221 | // but the directory must exist. 222 | func importPathToDir(importPath string) (string, error) { 223 | p, err := build.Import(importPath, "", build.FindOnly) 224 | if err != nil { 225 | return "", err 226 | } 227 | return p.Dir, nil 228 | } 229 | -------------------------------------------------------------------------------- /gl21-cube/square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-gl/example/d71b0d9f823d97c3b5ac2a79fdcdb56ca1677eba/gl21-cube/square.png -------------------------------------------------------------------------------- /gl41core-cube/README.md: -------------------------------------------------------------------------------- 1 | Cube 2 | ==== 3 | 4 | Renders a textured spinning cube using GLFW 3 and OpenGL 4.1 core forward-compatible profile. 5 | 6 | ``` 7 | go get -u github.com/go-gl/example/gl41core-cube 8 | ``` 9 | 10 | ![Screenshot](Screenshot.png) 11 | -------------------------------------------------------------------------------- /gl41core-cube/Screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-gl/example/d71b0d9f823d97c3b5ac2a79fdcdb56ca1677eba/gl41core-cube/Screenshot.png -------------------------------------------------------------------------------- /gl41core-cube/cube.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 | // Renders a textured spinning cube using GLFW 3 and OpenGL 4.1 core forward-compatible profile. 6 | package main // import "github.com/go-gl/example/gl41core-cube" 7 | 8 | import ( 9 | "fmt" 10 | "go/build" 11 | "image" 12 | "image/draw" 13 | _ "image/png" 14 | "log" 15 | "os" 16 | "runtime" 17 | "strings" 18 | 19 | "github.com/go-gl/gl/v4.1-core/gl" 20 | "github.com/go-gl/glfw/v3.3/glfw" 21 | "github.com/go-gl/mathgl/mgl32" 22 | ) 23 | 24 | const windowWidth = 800 25 | const windowHeight = 600 26 | 27 | func init() { 28 | // GLFW event handling must run on the main OS thread 29 | runtime.LockOSThread() 30 | } 31 | 32 | func main() { 33 | if err := glfw.Init(); err != nil { 34 | log.Fatalln("failed to initialize glfw:", err) 35 | } 36 | defer glfw.Terminate() 37 | 38 | glfw.WindowHint(glfw.Resizable, glfw.False) 39 | glfw.WindowHint(glfw.ContextVersionMajor, 4) 40 | glfw.WindowHint(glfw.ContextVersionMinor, 1) 41 | glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile) 42 | glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True) 43 | window, err := glfw.CreateWindow(windowWidth, windowHeight, "Cube", nil, nil) 44 | if err != nil { 45 | panic(err) 46 | } 47 | window.MakeContextCurrent() 48 | 49 | // Initialize Glow 50 | if err := gl.Init(); err != nil { 51 | panic(err) 52 | } 53 | 54 | version := gl.GoStr(gl.GetString(gl.VERSION)) 55 | fmt.Println("OpenGL version", version) 56 | 57 | // Configure the vertex and fragment shaders 58 | program, err := newProgram(vertexShader, fragmentShader) 59 | if err != nil { 60 | panic(err) 61 | } 62 | 63 | gl.UseProgram(program) 64 | 65 | projection := mgl32.Perspective(mgl32.DegToRad(45.0), float32(windowWidth)/windowHeight, 0.1, 10.0) 66 | projectionUniform := gl.GetUniformLocation(program, gl.Str("projection\x00")) 67 | gl.UniformMatrix4fv(projectionUniform, 1, false, &projection[0]) 68 | 69 | camera := mgl32.LookAtV(mgl32.Vec3{3, 3, 3}, mgl32.Vec3{0, 0, 0}, mgl32.Vec3{0, 1, 0}) 70 | cameraUniform := gl.GetUniformLocation(program, gl.Str("camera\x00")) 71 | gl.UniformMatrix4fv(cameraUniform, 1, false, &camera[0]) 72 | 73 | model := mgl32.Ident4() 74 | modelUniform := gl.GetUniformLocation(program, gl.Str("model\x00")) 75 | gl.UniformMatrix4fv(modelUniform, 1, false, &model[0]) 76 | 77 | textureUniform := gl.GetUniformLocation(program, gl.Str("tex\x00")) 78 | gl.Uniform1i(textureUniform, 0) 79 | 80 | gl.BindFragDataLocation(program, 0, gl.Str("outputColor\x00")) 81 | 82 | // Load the texture 83 | texture, err := newTexture("square.png") 84 | if err != nil { 85 | log.Fatalln(err) 86 | } 87 | 88 | // Configure the vertex data 89 | var vao uint32 90 | gl.GenVertexArrays(1, &vao) 91 | gl.BindVertexArray(vao) 92 | 93 | var vbo uint32 94 | gl.GenBuffers(1, &vbo) 95 | gl.BindBuffer(gl.ARRAY_BUFFER, vbo) 96 | gl.BufferData(gl.ARRAY_BUFFER, len(cubeVertices)*4, gl.Ptr(cubeVertices), gl.STATIC_DRAW) 97 | 98 | vertAttrib := uint32(gl.GetAttribLocation(program, gl.Str("vert\x00"))) 99 | gl.EnableVertexAttribArray(vertAttrib) 100 | gl.VertexAttribPointerWithOffset(vertAttrib, 3, gl.FLOAT, false, 5*4, 0) 101 | 102 | texCoordAttrib := uint32(gl.GetAttribLocation(program, gl.Str("vertTexCoord\x00"))) 103 | gl.EnableVertexAttribArray(texCoordAttrib) 104 | gl.VertexAttribPointerWithOffset(texCoordAttrib, 2, gl.FLOAT, false, 5*4, 3*4) 105 | 106 | // Configure global settings 107 | gl.Enable(gl.DEPTH_TEST) 108 | gl.DepthFunc(gl.LESS) 109 | gl.ClearColor(1.0, 1.0, 1.0, 1.0) 110 | 111 | angle := 0.0 112 | previousTime := glfw.GetTime() 113 | 114 | for !window.ShouldClose() { 115 | gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) 116 | 117 | // Update 118 | time := glfw.GetTime() 119 | elapsed := time - previousTime 120 | previousTime = time 121 | 122 | angle += elapsed 123 | model = mgl32.HomogRotate3D(float32(angle), mgl32.Vec3{0, 1, 0}) 124 | 125 | // Render 126 | gl.UseProgram(program) 127 | gl.UniformMatrix4fv(modelUniform, 1, false, &model[0]) 128 | 129 | gl.BindVertexArray(vao) 130 | 131 | gl.ActiveTexture(gl.TEXTURE0) 132 | gl.BindTexture(gl.TEXTURE_2D, texture) 133 | 134 | gl.DrawArrays(gl.TRIANGLES, 0, 6*2*3) 135 | 136 | // Maintenance 137 | window.SwapBuffers() 138 | glfw.PollEvents() 139 | } 140 | } 141 | 142 | func newProgram(vertexShaderSource, fragmentShaderSource string) (uint32, error) { 143 | vertexShader, err := compileShader(vertexShaderSource, gl.VERTEX_SHADER) 144 | if err != nil { 145 | return 0, err 146 | } 147 | 148 | fragmentShader, err := compileShader(fragmentShaderSource, gl.FRAGMENT_SHADER) 149 | if err != nil { 150 | return 0, err 151 | } 152 | 153 | program := gl.CreateProgram() 154 | 155 | gl.AttachShader(program, vertexShader) 156 | gl.AttachShader(program, fragmentShader) 157 | gl.LinkProgram(program) 158 | 159 | var status int32 160 | gl.GetProgramiv(program, gl.LINK_STATUS, &status) 161 | if status == gl.FALSE { 162 | var logLength int32 163 | gl.GetProgramiv(program, gl.INFO_LOG_LENGTH, &logLength) 164 | 165 | log := strings.Repeat("\x00", int(logLength+1)) 166 | gl.GetProgramInfoLog(program, logLength, nil, gl.Str(log)) 167 | 168 | return 0, fmt.Errorf("failed to link program: %v", log) 169 | } 170 | 171 | gl.DeleteShader(vertexShader) 172 | gl.DeleteShader(fragmentShader) 173 | 174 | return program, nil 175 | } 176 | 177 | func compileShader(source string, shaderType uint32) (uint32, error) { 178 | shader := gl.CreateShader(shaderType) 179 | 180 | csources, free := gl.Strs(source) 181 | gl.ShaderSource(shader, 1, csources, nil) 182 | free() 183 | gl.CompileShader(shader) 184 | 185 | var status int32 186 | gl.GetShaderiv(shader, gl.COMPILE_STATUS, &status) 187 | if status == gl.FALSE { 188 | var logLength int32 189 | gl.GetShaderiv(shader, gl.INFO_LOG_LENGTH, &logLength) 190 | 191 | log := strings.Repeat("\x00", int(logLength+1)) 192 | gl.GetShaderInfoLog(shader, logLength, nil, gl.Str(log)) 193 | 194 | return 0, fmt.Errorf("failed to compile %v: %v", source, log) 195 | } 196 | 197 | return shader, nil 198 | } 199 | 200 | func newTexture(file string) (uint32, error) { 201 | imgFile, err := os.Open(file) 202 | if err != nil { 203 | return 0, fmt.Errorf("texture %q not found on disk: %v", file, err) 204 | } 205 | img, _, err := image.Decode(imgFile) 206 | if err != nil { 207 | return 0, err 208 | } 209 | 210 | rgba := image.NewRGBA(img.Bounds()) 211 | if rgba.Stride != rgba.Rect.Size().X*4 { 212 | return 0, fmt.Errorf("unsupported stride") 213 | } 214 | draw.Draw(rgba, rgba.Bounds(), img, image.Point{0, 0}, draw.Src) 215 | 216 | var texture uint32 217 | gl.GenTextures(1, &texture) 218 | gl.ActiveTexture(gl.TEXTURE0) 219 | gl.BindTexture(gl.TEXTURE_2D, texture) 220 | gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) 221 | gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) 222 | gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) 223 | gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) 224 | gl.TexImage2D( 225 | gl.TEXTURE_2D, 226 | 0, 227 | gl.RGBA, 228 | int32(rgba.Rect.Size().X), 229 | int32(rgba.Rect.Size().Y), 230 | 0, 231 | gl.RGBA, 232 | gl.UNSIGNED_BYTE, 233 | gl.Ptr(rgba.Pix)) 234 | 235 | return texture, nil 236 | } 237 | 238 | var vertexShader = ` 239 | #version 330 240 | 241 | uniform mat4 projection; 242 | uniform mat4 camera; 243 | uniform mat4 model; 244 | 245 | in vec3 vert; 246 | in vec2 vertTexCoord; 247 | 248 | out vec2 fragTexCoord; 249 | 250 | void main() { 251 | fragTexCoord = vertTexCoord; 252 | gl_Position = projection * camera * model * vec4(vert, 1); 253 | } 254 | ` + "\x00" 255 | 256 | var fragmentShader = ` 257 | #version 330 258 | 259 | uniform sampler2D tex; 260 | 261 | in vec2 fragTexCoord; 262 | 263 | out vec4 outputColor; 264 | 265 | void main() { 266 | outputColor = texture(tex, fragTexCoord); 267 | } 268 | ` + "\x00" 269 | 270 | var cubeVertices = []float32{ 271 | // X, Y, Z, U, V 272 | // Bottom 273 | -1.0, -1.0, -1.0, 0.0, 0.0, 274 | 1.0, -1.0, -1.0, 1.0, 0.0, 275 | -1.0, -1.0, 1.0, 0.0, 1.0, 276 | 1.0, -1.0, -1.0, 1.0, 0.0, 277 | 1.0, -1.0, 1.0, 1.0, 1.0, 278 | -1.0, -1.0, 1.0, 0.0, 1.0, 279 | 280 | // Top 281 | -1.0, 1.0, -1.0, 0.0, 0.0, 282 | -1.0, 1.0, 1.0, 0.0, 1.0, 283 | 1.0, 1.0, -1.0, 1.0, 0.0, 284 | 1.0, 1.0, -1.0, 1.0, 0.0, 285 | -1.0, 1.0, 1.0, 0.0, 1.0, 286 | 1.0, 1.0, 1.0, 1.0, 1.0, 287 | 288 | // Front 289 | -1.0, -1.0, 1.0, 1.0, 0.0, 290 | 1.0, -1.0, 1.0, 0.0, 0.0, 291 | -1.0, 1.0, 1.0, 1.0, 1.0, 292 | 1.0, -1.0, 1.0, 0.0, 0.0, 293 | 1.0, 1.0, 1.0, 0.0, 1.0, 294 | -1.0, 1.0, 1.0, 1.0, 1.0, 295 | 296 | // Back 297 | -1.0, -1.0, -1.0, 0.0, 0.0, 298 | -1.0, 1.0, -1.0, 0.0, 1.0, 299 | 1.0, -1.0, -1.0, 1.0, 0.0, 300 | 1.0, -1.0, -1.0, 1.0, 0.0, 301 | -1.0, 1.0, -1.0, 0.0, 1.0, 302 | 1.0, 1.0, -1.0, 1.0, 1.0, 303 | 304 | // Left 305 | -1.0, -1.0, 1.0, 0.0, 1.0, 306 | -1.0, 1.0, -1.0, 1.0, 0.0, 307 | -1.0, -1.0, -1.0, 0.0, 0.0, 308 | -1.0, -1.0, 1.0, 0.0, 1.0, 309 | -1.0, 1.0, 1.0, 1.0, 1.0, 310 | -1.0, 1.0, -1.0, 1.0, 0.0, 311 | 312 | // Right 313 | 1.0, -1.0, 1.0, 1.0, 1.0, 314 | 1.0, -1.0, -1.0, 1.0, 0.0, 315 | 1.0, 1.0, -1.0, 0.0, 0.0, 316 | 1.0, -1.0, 1.0, 1.0, 1.0, 317 | 1.0, 1.0, -1.0, 0.0, 0.0, 318 | 1.0, 1.0, 1.0, 0.0, 1.0, 319 | } 320 | 321 | // Set the working directory to the root of Go package, so that its assets can be accessed. 322 | func init() { 323 | dir, err := importPathToDir("github.com/go-gl/example/gl41core-cube") 324 | if err != nil { 325 | log.Fatalln("Unable to find Go package in your GOPATH, it's needed to load assets:", err) 326 | } 327 | err = os.Chdir(dir) 328 | if err != nil { 329 | log.Panicln("os.Chdir:", err) 330 | } 331 | } 332 | 333 | // importPathToDir resolves the absolute path from importPath. 334 | // There doesn't need to be a valid Go package inside that import path, 335 | // but the directory must exist. 336 | func importPathToDir(importPath string) (string, error) { 337 | p, err := build.Import(importPath, "", build.FindOnly) 338 | if err != nil { 339 | return "", err 340 | } 341 | return p.Dir, nil 342 | } 343 | -------------------------------------------------------------------------------- /gl41core-cube/square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-gl/example/d71b0d9f823d97c3b5ac2a79fdcdb56ca1677eba/gl41core-cube/square.png -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/go-gl/example 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/go-gl/gl v0.0.0-20210426225639-a3bfa832c8aa 7 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20210410170116-ea3d685f79fb 8 | github.com/go-gl/mathgl v1.0.0 9 | golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb // indirect 10 | ) 11 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/go-gl/gl v0.0.0-20210426225639-a3bfa832c8aa h1:yiL6tST9ZuWBXiymIdM0j6yeLwMVGXDoybpXqnbJpCk= 2 | github.com/go-gl/gl v0.0.0-20210426225639-a3bfa832c8aa/go.mod h1:wjpnOv6ONl2SuJSxqCPVaPZibGFdSci9HFocT9qtVYM= 3 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20210410170116-ea3d685f79fb h1:T6gaWBvRzJjuOrdCtg8fXXjKai2xSDqWTcKFUPuw8Tw= 4 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20210410170116-ea3d685f79fb/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 5 | github.com/go-gl/mathgl v1.0.0 h1:t9DznWJlXxxjeeKLIdovCOVJQk/GzDEL7h/h+Ro2B68= 6 | github.com/go-gl/mathgl v1.0.0/go.mod h1:yhpkQzEiH9yPyxDUGzkmgScbaBVlhC06qodikEM0ZwQ= 7 | golang.org/x/image v0.0.0-20190321063152-3fc05d484e9f/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= 8 | golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb h1:fqpd0EBDzlHRCjiphRR5Zo/RSWWQlWv34418dnEixWk= 9 | golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 10 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 11 | --------------------------------------------------------------------------------