diff options
Diffstat (limited to 'graphics.go')
-rw-r--r-- | graphics.go | 151 |
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 +} |