func (buf *TextureFramebuffer) StartSample(ctx gl.Context) { buf.fbo.Bind(ctx, buf.withtex) ctx.GetIntegerv(int32v4, gl.VIEWPORT) ctx.Viewport(0, 0, buf.w, buf.h) ctx.ClearColor(0, 0, 0, 0) ctx.Clear(gl.COLOR_BUFFER_BIT) }
func onPaint(glctx gl.Context, sz size.Event) { glctx.Viewport(0, 0, sz.WidthPx, sz.HeightPx) glctx.ClearColor(0.5, 0.5, 0.5, 1) glctx.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) glctx.UseProgram(program) projectionMtx = mgl32.Perspective(45, float32(width)/float32(height), 0.1, 100) arcBallMtx := arcball.getMtx() glctx.UniformMatrix4fv(projection, projectionMtx[:]) glctx.UniformMatrix4fv(view, arcBallMtx[:]) glctx.BindBuffer(gl.ARRAY_BUFFER, triBuf) glctx.EnableVertexAttribArray(position) glctx.EnableVertexAttribArray(color) glctx.EnableVertexAttribArray(normals) vertSize := 4 * (coordsPerVertex + colorPerVertex + normalsPerVertex) glctx.VertexAttribPointer(position, coordsPerVertex, gl.FLOAT, false, vertSize, 0) glctx.VertexAttribPointer(color, colorPerVertex, gl.FLOAT, false, vertSize, 4*coordsPerVertex) glctx.VertexAttribPointer(normals, normalsPerVertex, gl.FLOAT, false, vertSize, 4*(coordsPerVertex+colorPerVertex)) glctx.DepthMask(true) glctx.Uniform3fv(lightPos, light.Pos[:]) glctx.Uniform3fv(lightIntensity, light.Intensities[:]) for _, k := range piano.Keys { glctx.Uniform4fv(tint, k.Color[:]) mtx := k.GetMtx() normMat := mtx.Mat3().Inv().Transpose() glctx.UniformMatrix3fv(normalMatrix, normMat[:]) glctx.UniformMatrix4fv(model, mtx[:]) glctx.DrawArrays(gl.TRIANGLES, 0, len(triangleData)/vertSize) } modelMtx := mgl32.Ident4() modelMtx = modelMtx.Mul4(mgl32.Translate3D(worldPos.X(), worldPos.Y(), worldPos.Z())) modelMtx = modelMtx.Mul4(mgl32.Scale3D(0.5, 0.5, 0.5)) /* glctx.Uniform4fv(tint, red[:]) // Disable depthmask so we dont get the pixel depth of the cursor cube glctx.DepthMask(false) glctx.UniformMatrix4fv(model, modelMtx[:]) glctx.DepthMask(true) */ glctx.DisableVertexAttribArray(position) glctx.DisableVertexAttribArray(color) glctx.DisableVertexAttribArray(normals) fps.Draw(sz) }
func (buf *TextureFramebuffer) StopSample(ctx gl.Context) { ctx.Viewport(int(int32v4[0]), int(int32v4[1]), int(int32v4[2]), int(int32v4[3])) // TODO Unbind should maybe take options too? buf.fbo.Unbind(ctx) // sbuf.tex.Unbind(ctx) }
func main() { app.Main(func(a app.App) { var glctx gl.Context visible, sz := false, size.Event{} for e := range a.Events() { switch e := a.Filter(e).(type) { case lifecycle.Event: switch e.Crosses(lifecycle.StageVisible) { case lifecycle.CrossOn: visible = true glctx, _ = e.DrawContext.(gl.Context) onStart(glctx) case lifecycle.CrossOff: visible = false onStop(glctx) } case size.Event: sz = e width = sz.WidthPx height = sz.HeightPx touchX = float32(sz.WidthPx / 2) touchY = float32(sz.HeightPx / 2) if glctx != nil { glctx.Viewport(0, 0, sz.WidthPx, sz.HeightPx) } case paint.Event: onPaint(glctx, sz) a.Publish() if visible { n := time.Now() piano.update(n.Sub(lastUpdate)) lastUpdate = n // Drive the animation by preparing to paint the next frame // after this one is shown. // // TODO: is paint.Event the right thing to send? Should we // have a dedicated publish.Event type? Should App.Publish // take an optional event sender and send a publish.Event? a.Send(paint.Event{}) } case touch.Event: touchX = e.X touchY = e.Y worldRayStart, worldRayEnd := unproject(glctx, e.X, e.Y) if !piano.HandleTouch(worldRayStart, worldRayEnd, e) && !beganOnPiano { if e.Type == touch.TypeMove { arcball.move(int(e.X), int(e.Y)) } else if e.Type == touch.TypeBegin { arcball.begin(int(e.X), int(e.Y)) } else { arcball.end() } } else if e.Type == touch.TypeBegin { beganOnPiano = true } else if e.Type == touch.TypeEnd { beganOnPiano = false } case key.Event: if e.Code == key.CodeEscape { visible = false onStop(glctx) os.Exit(0) } } } }) }