Skip to content

Instantly share code, notes, and snippets.

@noonat
Created September 15, 2015 14:24
Show Gist options
  • Save noonat/c36e4e017af071f67da5 to your computer and use it in GitHub Desktop.
Save noonat/c36e4e017af071f67da5 to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"math"
"github.com/go-gl/mathgl/mgl32"
"github.com/gopherjs/gopherjs/js"
"github.com/gopherjs/webgl"
)
const fragmentShaderSource = `
precision mediump float;
varying vec4 outVertexColor;
void main(void) {
gl_FragColor = outVertexColor;
}
`
const vertexShaderSource = `
attribute vec3 inVertexPosition;
attribute vec3 inVertexColor;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform mat4 modelViewProjectionMatrix;
varying vec4 outVertexColor;
void main(void) {
gl_Position = projectionMatrix * modelViewMatrix * vec4(inVertexPosition, 1.0);
outVertexColor = vec4(inVertexColor, 1.0);
}
`
var vertexPositionData = []float32{
// near face
-1.0, -1.0, 1.0,
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
1.0, -1.0, 1.0,
// left face
-1.0, -1.0, -1.0,
-1.0, 1.0, -1.0,
-1.0, 1.0, 1.0,
-1.0, -1.0, 1.0,
// far face
1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
-1.0, 1.0, -1.0,
-1.0, -1.0, -1.0,
// right face
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
1.0, 1.0, -1.0,
1.0, -1.0, -1.0,
// top face
-1.0, 1.0, 1.0,
-1.0, 1.0, -1.0,
1.0, 1.0, -1.0,
1.0, 1.0, 1.0,
// bottom face
-1.0, -1.0, -1.0,
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, -1.0, -1.0,
}
var vertexColorData = []float32{
// near face
1.0, 0.0, 0.0,
1.0, 0.0, 0.0,
1.0, 0.0, 0.0,
1.0, 0.0, 0.0,
// left face
0.0, 1.0, 0.0,
0.0, 1.0, 0.0,
0.0, 1.0, 0.0,
0.0, 1.0, 0.0,
// far face
0.0, 0.0, 1.0,
0.0, 0.0, 1.0,
0.0, 0.0, 1.0,
0.0, 0.0, 1.0,
// right face
1.0, 1.0, 0.0,
1.0, 1.0, 0.0,
1.0, 1.0, 0.0,
1.0, 1.0, 0.0,
// top face
1.0, 0.0, 1.0,
1.0, 0.0, 1.0,
1.0, 0.0, 1.0,
1.0, 0.0, 1.0,
// bottom face
0.0, 1.0, 1.0,
0.0, 1.0, 1.0,
0.0, 1.0, 1.0,
0.0, 1.0, 1.0,
}
var indexData = []uint16{
0, 1, 2,
0, 2, 3,
4, 5, 6,
4, 6, 7,
8, 9, 10,
8, 10, 11,
12, 13, 14,
12, 14, 15,
16, 17, 18,
16, 18, 19,
20, 21, 22,
20, 22, 23,
}
const viewportWidth float32 = 500
const viewportHeight float32 = 500
func printError(message string) {
js.Global.Call("alert", "Error: "+message)
}
func cancelAnimationFrame(id int) {
js.Global.Call("cancelAnimationFrame")
}
func requestAnimationFrame(callback func(float32)) int {
return js.Global.Call("requestAnimationFrame", callback).Int()
}
func degToRad(degrees float32) float32 {
return float32(degrees * float32(math.Pi) / 180.0)
}
func main() {
document := js.Global.Get("document")
canvas := document.Call("createElement", "canvas")
canvas.Set("id", "canvas")
canvas.Set("width", viewportWidth)
canvas.Set("height", viewportHeight)
document.Get("body").Call("appendChild", canvas)
textCanvas := document.Call("createElement", "canvas")
textCanvas.Set("id", "text-canvas")
textCanvas.Set("width", viewportWidth*2)
textCanvas.Set("height", viewportHeight*2)
textCanvas.Get("style").Set("width", fmt.Sprintf("%dpx", int(viewportWidth)))
textCanvas.Get("style").Set("height", fmt.Sprintf("%dpx", int(viewportHeight)))
document.Get("body").Call("appendChild", textCanvas)
textContext := textCanvas.Call("getContext", "2d")
textContext.Call("setTransform", 2, 0, 0, 2, 0, 0)
attrs := webgl.DefaultAttributes()
attrs.Alpha = false
gl, err := webgl.NewContext(canvas, attrs)
if err != nil {
printError(err.Error())
return
}
fragmentShader := gl.CreateShader(gl.FRAGMENT_SHADER)
gl.ShaderSource(fragmentShader, fragmentShaderSource)
gl.CompileShader(fragmentShader)
if !gl.GetShaderParameterb(fragmentShader, gl.COMPILE_STATUS) {
printError(gl.GetShaderInfoLog(fragmentShader))
return
}
vertexShader := gl.CreateShader(gl.VERTEX_SHADER)
gl.ShaderSource(vertexShader, vertexShaderSource)
gl.CompileShader(vertexShader)
if !gl.GetShaderParameterb(vertexShader, gl.COMPILE_STATUS) {
printError(gl.GetShaderInfoLog(vertexShader))
return
}
program := gl.CreateProgram()
gl.AttachShader(program, vertexShader)
gl.AttachShader(program, fragmentShader)
gl.LinkProgram(program)
if !gl.GetProgramParameterb(program, gl.LINK_STATUS) {
printError(gl.GetProgramInfoLog(program))
return
}
gl.UseProgram(program)
inVertexPositionLocation := gl.GetAttribLocation(program, "inVertexPosition")
inVertexColorLocation := gl.GetAttribLocation(program, "inVertexColor")
modelViewMatrixLocation := gl.GetUniformLocation(program, "modelViewMatrix")
projectionMatrixLocation := gl.GetUniformLocation(program, "projectionMatrix")
gl.EnableVertexAttribArray(inVertexPositionLocation)
gl.EnableVertexAttribArray(inVertexColorLocation)
vertexPositionBuffer := gl.CreateBuffer()
gl.BindBuffer(gl.ARRAY_BUFFER, vertexPositionBuffer)
gl.BufferData(gl.ARRAY_BUFFER, vertexPositionData, gl.STATIC_DRAW)
vertexColorBuffer := gl.CreateBuffer()
gl.BindBuffer(gl.ARRAY_BUFFER, vertexColorBuffer)
gl.BufferData(gl.ARRAY_BUFFER, vertexColorData, gl.STATIC_DRAW)
indexBuffer := gl.CreateBuffer()
gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer)
gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, indexData, gl.STATIC_DRAW)
gl.Viewport(0, 0, int(viewportWidth), int(viewportHeight))
var pitch float32 = 0.0
var yaw float32 = 0.0
var tweenTime float32 = 0.0
var tick func(float32)
tick = func(timeMs float32) {
textContext.Call("clearRect", 0, 0, viewportWidth, viewportHeight)
textContext.Set("font", "12px sans-serif")
textContext.Set("fillStyle", "rgb(255, 255, 255)")
textContext.Call("fillText", "Hello, world!", 10, 20)
time := timeMs / 1000
if tweenTime == 0.0 {
tweenTime = time + 1.0
}
for tweenTime < time {
tweenTime += 1.0
pitch = float32(math.Mod(float64(pitch)+60.0, 360.0))
yaw = float32(math.Mod(float64(yaw)+40.0, 360.0))
}
factor := tweenTime - time
if factor < 0.0 {
factor = 0.0
} else if factor > 1.0 {
factor = 1.0
}
factor = 1.0 - float32(math.Pow(float64(factor), 4.0))
tweenPitch := pitch + (60.0 * factor)
tweenYaw := yaw + (40.0 * factor)
gl.ClearColor(0, 0, 0, 1)
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
gl.Enable(gl.CULL_FACE)
gl.FrontFace(gl.CW)
modelViewMatrix := mgl32.Ident4().
Mul4(mgl32.Translate3D(0, 0, -3)).
Mul4(mgl32.HomogRotate3DX(degToRad(tweenPitch))).
Mul4(mgl32.HomogRotate3DY(degToRad(tweenYaw)))
gl.UniformMatrix4fv(modelViewMatrixLocation, false, modelViewMatrix[:])
projectionMatrix := mgl32.Perspective(55, viewportWidth/viewportHeight, 0.1, 2048)
gl.UniformMatrix4fv(projectionMatrixLocation, false, projectionMatrix[:])
gl.BindBuffer(gl.ARRAY_BUFFER, vertexPositionBuffer)
gl.VertexAttribPointer(inVertexPositionLocation, 3, gl.FLOAT, false, 0, 0)
gl.BindBuffer(gl.ARRAY_BUFFER, vertexColorBuffer)
gl.VertexAttribPointer(inVertexColorLocation, 3, gl.FLOAT, false, 0, 0)
gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer)
gl.DrawElements(gl.TRIANGLES, len(indexData), gl.UNSIGNED_SHORT, 0)
requestAnimationFrame(tick)
}
requestAnimationFrame(tick)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment