1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
// vim: shiftwidth=4 tabstop=4 noexpandtab
package main
import (
"fmt"
"log"
"strings"
"github.com/go-gl/gl/v4.6-core/gl"
)
var (
// a single triangle
triangle = []float32{
0.0, 0.5, 0.0,
-0.5, -0.5, 0.0,
0.5, -0.5, 0.0,
}
)
const (
// vertex shader to draw points
VERTEX_SHADER = `
#version 410
in vec3 vp;
void main() {
gl_Position = vec4(vp, 1.0);
}
` + "\x00"
// fragment shader to draw surfaces
FRAGMENT_SHADER = `
#version 410
out vec4 frag_colour;
void main() {
frag_colour = vec4(0, 0, 1, 1); // RGBA color format
}
` + "\x00"
)
// initOpenGL initializes OpenGL and returns an intiialized program
func initOpenGL() uint32 {
log.Println("OpenGL init")
if err := gl.Init(); err != nil {
panic(err)
}
version := gl.GoStr(gl.GetString(gl.VERSION))
log.Println("OpenGL version", version)
vertexShader, err := compileShader(VERTEX_SHADER, gl.VERTEX_SHADER)
if err != nil {
panic(err)
}
fragmentShader, err := compileShader(FRAGMENT_SHADER, gl.FRAGMENT_SHADER)
if err != nil {
panic(err)
}
prog := gl.CreateProgram()
gl.AttachShader(prog, vertexShader)
gl.AttachShader(prog, fragmentShader)
gl.LinkProgram(prog)
return prog
}
func draw(vao uint32, program uint32) {
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
gl.UseProgram(program)
gl.BindVertexArray(vao)
gl.DrawArrays(gl.TRIANGLES, 0, int32(len(triangle)/3))
}
// makeVao initializes and returns a vertex array from the points provided.
func makeVao(points []float32) uint32 {
log.Println("Creating VAO")
// start with vertex buffer object (VBO):
var vbo uint32 // VBO ID
gl.GenBuffers(1, &vbo)
gl.BindBuffer(gl.ARRAY_BUFFER, vbo)
gl.BufferData(gl.ARRAY_BUFFER, 4*len(points), gl.Ptr(points), gl.STATIC_DRAW)
// vertex array objects (VAO) are a feature of newer GL implementations:
var vao uint32 // VAO ID
gl.GenVertexArrays(1, &vao)
gl.BindVertexArray(vao)
gl.EnableVertexAttribArray(0)
gl.BindBuffer(gl.ARRAY_BUFFER, vbo)
gl.VertexAttribPointer(0, 3, gl.FLOAT, false, 0, nil) // tell GL to use 3D float vectors
return vao
}
func compileShader(source string, shaderType uint32) (uint32, error) {
log.Println("Compiling shader")
shader := gl.CreateShader(shaderType)
csources, free := gl.Strs(source)
gl.ShaderSource(shader, 1, csources, nil)
free()
gl.CompileShader(shader)
var status int32
gl.GetShaderiv(shader, gl.COMPILE_STATUS, &status)
if status == gl.FALSE {
var logLength int32
gl.GetShaderiv(shader, gl.INFO_LOG_LENGTH, &logLength)
log := strings.Repeat("\x00", int(logLength+1))
gl.GetShaderInfoLog(shader, logLength, nil, gl.Str(log))
return 0, fmt.Errorf("failed to compile %v: %v", source, log)
}
return shader, nil
}
|