summaryrefslogtreecommitdiff
path: root/graphics.go
diff options
context:
space:
mode:
Diffstat (limited to 'graphics.go')
-rw-r--r--graphics.go151
1 files changed, 151 insertions, 0 deletions
diff --git a/graphics.go b/graphics.go
new file mode 100644
index 0000000..812be3a
--- /dev/null
+++ b/graphics.go
@@ -0,0 +1,151 @@
+// vim: shiftwidth=4 tabstop=4 noexpandtab
+
+package main
+
+import (
+ "fmt"
+ "log"
+ "strings"
+
+ "github.com/go-gl/gl/v4.6-core/gl"
+ "github.com/go-gl/glfw/v3.3/glfw"
+)
+
+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 (
+ WINDOW_WIDTH = 500
+ WINDOW_HEIGHT = 500
+ WINDOW_TITLE = "stlscope"
+
+ // 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"
+)
+
+func initGlfw() *glfw.Window {
+ log.Println("GLFW init")
+
+ if err := glfw.Init(); err != nil {
+ panic(err)
+ }
+
+ glfw.WindowHint(glfw.Resizable, glfw.False)
+ glfw.WindowHint(glfw.ContextVersionMajor, 4)
+ glfw.WindowHint(glfw.ContextVersionMinor, 6)
+ glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile)
+ glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True)
+ glfw.WindowHint(glfw.Samples, 16) // anti-aliasing
+
+ window, err := glfw.CreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE, nil, nil)
+ if err != nil {
+ panic(err)
+ }
+ window.MakeContextCurrent()
+
+ return window
+}
+
+// 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, window *glfw.Window, 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))
+
+ glfw.PollEvents()
+ window.SwapBuffers()
+}
+
+// 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
+}