Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
236 lines (184 sloc) 5.47 KB
package main
import (
"fmt"
"math"
"runtime"
"strings"
"github.com/go-gl/gl/v3.3-core/gl"
"github.com/go-gl/glfw/v3.1/glfw"
"github.com/go-gl/mathgl/mgl32"
)
const windowWidth = 800
const windowHeight = 600
const period = 2.0
var vertexShader = `
#version 330
uniform mat4 projection;
uniform mat4 camera;
uniform mat4 model;
in vec3 vert;
void main() {
gl_Position = projection * camera * model * vec4(vert, 1);
}
` + "\x00"
var fragmentShader = `
#version 330
out vec4 fc;
void main() {
fc = vec4(0.0, 0.71, 0.98, 1.0);
}
` + "\x00"
func init() {
// This is needed to arrange that main() runs on main thread.
// See documentation for functions that are only allowed to be called from the main thread.
runtime.LockOSThread()
}
func main() {
// init glfw
if err := glfw.Init(); err != nil {
panic(err)
}
defer glfw.Terminate()
glfw.WindowHint(glfw.Resizable, glfw.False)
glfw.WindowHint(glfw.ContextVersionMajor, 4)
glfw.WindowHint(glfw.ContextVersionMinor, 1)
glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile)
glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True)
// make an application window
window, err := glfw.CreateWindow(windowWidth, windowHeight, "Transform", nil, nil)
if err != nil {
panic(err)
}
window.MakeContextCurrent()
// init gl
if err := gl.Init(); err != nil {
panic(err)
}
fmt.Println("OpenGL version", gl.GoStr(gl.GetString(gl.VERSION)))
// create vertex & fragment shader
program, err := newProgram(vertexShader, fragmentShader)
if err != nil {
panic(err)
}
gl.UseProgram(program)
projection := mgl32.Perspective(mgl32.DegToRad(45.0), float32(windowWidth)/windowHeight, 0.1, 10.0)
projectionUniform := gl.GetUniformLocation(program, gl.Str("projection\x00"))
gl.UniformMatrix4fv(projectionUniform, 1, false, &projection[0])
camera := mgl32.LookAtV(
mgl32.Vec3{3, 3, 3},
mgl32.Vec3{0, 0, 0},
mgl32.Vec3{0, 1, 0},
)
cameraUniform := gl.GetUniformLocation(program, gl.Str("camera\x00"))
gl.UniformMatrix4fv(cameraUniform, 1, false, &camera[0])
model := mgl32.Ident4()
modelUniform := gl.GetUniformLocation(program, gl.Str("model\x00"))
gl.UniformMatrix4fv(modelUniform, 1, false, &model[0])
gl.BindFragDataLocation(program, 0, gl.Str("vert\x00"))
points := []float32{
-0.9, -0.9, -0.9,
0.9, -0.9, -0.9,
0.9, -0.9, 0.9,
-0.9, -0.9, 0.9,
-0.9, 0.9, -0.9,
0.9, 0.9, -0.9,
0.9, 0.9, 0.9,
-0.9, 0.9, 0.9,
}
vertices := []uint32{
0, 1,
1, 2,
2, 3,
3, 0,
0, 4,
1, 5,
2, 6,
3, 7,
4, 5,
5, 6,
6, 7,
7, 4,
}
// configure the vertex data
var vao uint32
gl.GenVertexArrays(1, &vao)
gl.BindVertexArray(vao)
defer gl.BindVertexArray(0)
var vbo uint32
gl.GenBuffers(1, &vbo)
gl.BindBuffer(gl.ARRAY_BUFFER, vbo)
gl.BufferData(gl.ARRAY_BUFFER, len(points)*4, gl.Ptr(points), gl.STATIC_DRAW)
var ibo uint32
gl.GenBuffers(1, &ibo)
gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo)
gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, len(vertices)*4, gl.Ptr(vertices), gl.STATIC_DRAW)
vertAttrib := uint32(gl.GetAttribLocation(program, gl.Str("vert\x00")))
gl.EnableVertexAttribArray(vertAttrib)
gl.VertexAttribPointer(vertAttrib, 3, gl.FLOAT, false, 3*4, gl.PtrOffset(0))
// global settings
gl.Enable(gl.DEPTH_TEST)
gl.DepthFunc(gl.LESS)
gl.ClearColor(0.0, 0.0, 0.0, 1.0)
angleX := 0.0
angleY := 0.0
angleZ := 0.0
previousTime := glfw.GetTime()
for !window.ShouldClose() {
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
time := glfw.GetTime()
elapsed := time - previousTime
previousTime = time
angleX += math.Sin((elapsed / period) * math.Pi * 2.0)
angleY += math.Sin((elapsed / period) / 6.0 * math.Pi * 2.0)
angleZ += math.Sin((elapsed / period) / 3.0 * math.Pi * 2.0)
model = mgl32.HomogRotate3DY(float32(angleY)).Mul4(mgl32.HomogRotate3DX(float32(angleX))).Mul4(mgl32.HomogRotate3DZ(float32(angleZ)))
gl.UseProgram(program)
gl.UniformMatrix4fv(modelUniform, 1, false, &model[0])
gl.BindVertexArray(vao)
gl.DrawElements(gl.LINES, int32(len(vertices)), gl.UNSIGNED_INT, gl.PtrOffset(0))
window.SwapBuffers()
glfw.PollEvents()
}
}
func newProgram(vertexShaderSource, fragmentShaderSource string) (uint32, error) {
vertexShader, err := compileShader(vertexShaderSource, gl.VERTEX_SHADER)
if err != nil {
return 0, err
}
fragmentShader, err := compileShader(fragmentShaderSource, gl.FRAGMENT_SHADER)
if err != nil {
return 0, err
}
program := gl.CreateProgram()
gl.AttachShader(program, vertexShader)
gl.AttachShader(program, fragmentShader)
gl.LinkProgram(program)
var status int32
gl.GetProgramiv(program, gl.LINK_STATUS, &status)
if status == gl.FALSE {
var logLength int32
gl.GetProgramiv(program, gl.INFO_LOG_LENGTH, &logLength)
log := strings.Repeat("\x00", int(logLength+1))
gl.GetProgramInfoLog(program, logLength, nil, gl.Str(log))
return 0, fmt.Errorf("failed to link program: %v", log)
}
gl.DeleteShader(vertexShader)
gl.DeleteShader(fragmentShader)
return program, nil
}
func compileShader(source string, shaderType uint32) (uint32, error) {
shader := gl.CreateShader(shaderType)
csource := gl.Str(source)
gl.ShaderSource(shader, 1, &csource, nil)
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
}