Created
September 15, 2015 14:24
-
-
Save noonat/c36e4e017af071f67da5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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