func main() { if err := glfw.Init(); err != nil { fmt.Fprintf(os.Stderr, "[e] %v\n", err) return } defer glfw.Terminate() if err := glfw.OpenWindow(appWidth, appHeight, 8, 8, 8, 8, 24, 8, glfw.Windowed); err != nil { fmt.Fprintf(os.Stderr, "[e] %v\n", err) return } defer glfw.CloseWindow() if err := gl.Init(); err != 0 { fmt.Fprintf(os.Stderr, "[e] %v\n", err) return } glfw.SetWindowTitle(title) fps := fps.NewFPS(glfw.Time()) blocks.Init(appWidth, appHeight) for glfw.WindowParam(glfw.Opened) == 1 { blocks.Tick() fps.Tick(glfw.Time()) if glfw.WindowParam(glfw.Active) == 1 { glfw.Sleep(0.001) } else { glfw.Sleep(0.05) } } }
func StartEngine() { runtime.GOMAXPROCS(runtime.NumCPU()) runtime.LockOSThread() fmt.Println("Enginge started!") var err error if err = glfw.Init(); err != nil { panic(err) } fmt.Println("GLFW Initialized!") glfw.OpenWindowHint(glfw.Accelerated, 1) if err = glfw.OpenWindow(Width, Height, 8, 8, 8, 8, 8, 8, glfw.Windowed); err != nil { panic(err) } glfw.SetSwapInterval(1) //0 to disable vsync, 1 to enable it glfw.SetWindowTitle(windowTitle) glfw.SetWindowSizeCallback(onResize) glfw.SetKeyCallback(input.OnKey) glfw.SetCharCallback(input.OnChar) glfw.SetMouseButtonCallback(input.ButtonPress) glfw.SetMouseWheel(0) glfw.SetMouseWheelCallback(input.MouseWheelCallback) input.MouseWheelPosition = glfw.MouseWheel input.MousePosition = glfw.MousePos if err = initGL(); err != nil { panic(err) } fmt.Println("Opengl Initialized!") TextureMaterial = NewBasicMaterial(spriteVertexShader, spriteFragmentShader) err = TextureMaterial.Load() if err != nil { fmt.Println(err) } SDFMaterial = NewBasicMaterial(sdfVertexShader, sdfFragmentShader) err = SDFMaterial.Load() if err != nil { fmt.Println(err) } internalMaterial = NewBasicMaterial(spriteVertexShader, spriteFragmentShader) err = internalMaterial.Load() if err != nil { fmt.Println(err) } initDefaultPlane() glfw.SwapBuffers() gameTime = time.Time{} lastTime = time.Now() dl = glfw.Time() }
func (me *TimingStats) end() { if Stats.enabled { if me.thisTime = glfw.Time() - me.measureStartTime; me.thisTime > me.max { me.max = me.thisTime } me.measuredCounter++ me.totalAccum += me.thisTime } }
func main() { var err error if err = glfw.Init(); err != nil { log.Fatalf("%v\n", err) return } defer glfw.Terminate() // Open window with FSAA samples (if possible). glfw.OpenWindowHint(glfw.FsaaSamples, 4) if err = glfw.OpenWindow(400, 400, 0, 0, 0, 0, 0, 0, glfw.Windowed); err != nil { log.Fatalf("%v\n", err) return } defer glfw.CloseWindow() glfw.SetWindowTitle("Aliasing Detector") glfw.SetSwapInterval(1) if samples := glfw.WindowParam(glfw.FsaaSamples); samples != 0 { fmt.Printf("Context reports FSAA is supported with %d samples\n", samples) } else { fmt.Printf("Context reports FSAA is unsupported\n") } gl.MatrixMode(gl.PROJECTION) glu.Perspective(0, 1, 0, 1) for glfw.WindowParam(glfw.Opened) == 1 { time := float32(glfw.Time()) gl.Clear(gl.COLOR_BUFFER_BIT) gl.LoadIdentity() gl.Translatef(0.5, 0, 0) gl.Rotatef(time, 0, 0, 1) gl.Enable(GL_MULTISAMPLE_ARB) gl.Color3f(1, 1, 1) gl.Rectf(-0.25, -0.25, 0.25, 0.25) gl.LoadIdentity() gl.Translatef(-0.5, 0, 0) gl.Rotatef(time, 0, 0, 1) gl.Disable(GL_MULTISAMPLE_ARB) gl.Color3f(1, 1, 1) gl.Rectf(-0.25, -0.25, 0.25, 0.25) glfw.SwapBuffers() } }
func Tick() { timer = float32(glfw.Time()) gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) program.Use() camera.Tick() modelViewMatrixUniform.UniformMatrix4fv(camera.modelViewMatrix[:]) projectionMatrixUniform.UniformMatrix4fv(camera.projectionMatrix[:]) timerUniform.Uniform1f(timer) positionAttrib.EnableArray() texcoordAttrib.EnableArray() gl.ActiveTexture(gl.TEXTURE0) textures[0].Bind(gl.TEXTURE_2D) textureUniforms[0].Uniform1i(0) gl.ActiveTexture(gl.TEXTURE1) textures[1].Bind(gl.TEXTURE_2D) textureUniforms[1].Uniform1i(1) sizeOfVertex := int(unsafe.Sizeof(Vertex{})) posoffset := uintptr(0) texoffset := unsafe.Offsetof(Vertex{}.texcoord) for _, renderObject := range renderObjects { renderObject.vertexBuffer.Bind(gl.ARRAY_BUFFER) positionAttrib.AttribPointer(3, gl.FLOAT, false, sizeOfVertex, posoffset) texcoordAttrib.AttribPointer(2, gl.FLOAT, false, sizeOfVertex, texoffset) gl.DrawArrays(gl.TRIANGLES, 0, renderObject.numVerticies) } positionAttrib.DisableArray() texcoordAttrib.DisableArray() gl.ProgramUnuse() glfw.SwapBuffers() }
// Since go has multiple return values, I just went ahead and made it return the view and perspective matrices (in that order) rather than messing with getter methods func (c *Camera) ComputeViewPerspective() (mathgl.Mat4f, mathgl.Mat4f) { if mathgl.FloatEqual(-1.0, c.time) { c.time = glfw.Time() } currTime := glfw.Time() deltaT := currTime - c.time xPos, yPos := glfw.MousePos() glfw.SetMousePos(width/2.0, height/2.0) c.hAngle += mouseSpeed * ((width / 2.0) - float64(xPos)) c.vAngle += mouseSpeed * ((height / 2.0) - float64(yPos)) dir := mathgl.Vec3f{ float32(math.Cos(c.vAngle) * math.Sin(c.hAngle)), float32(math.Sin(c.vAngle)), float32(math.Cos(c.vAngle) * math.Cos(c.hAngle))} right := mathgl.Vec3f{ float32(math.Sin(c.hAngle - math.Pi/2.0)), 0.0, float32(math.Cos(c.hAngle - math.Pi/2.0))} up := right.Cross(dir) if glfw.Key(glfw.KeyUp) == glfw.KeyPress || glfw.Key('W') == glfw.KeyPress { c.pos = c.pos.Add(dir.Mul(float32(deltaT * speed))) } if glfw.Key(glfw.KeyDown) == glfw.KeyPress || glfw.Key('S') == glfw.KeyPress { c.pos = c.pos.Sub(dir.Mul(float32(deltaT * speed))) } if glfw.Key(glfw.KeyRight) == glfw.KeyPress || glfw.Key('D') == glfw.KeyPress { c.pos = c.pos.Add(right.Mul(float32(deltaT * speed))) } if glfw.Key(glfw.KeyLeft) == glfw.KeyPress || glfw.Key('A') == glfw.KeyPress { c.pos = c.pos.Sub(right.Mul(float32(deltaT * speed))) } // Adding to the original tutorial, Space goes up if glfw.Key(glfw.KeySpace) == glfw.KeyPress { c.pos = c.pos.Add(up.Mul(float32(deltaT * speed))) } // Adding to the original tutorial, left control goes down if glfw.Key(glfw.KeyLctrl) == glfw.KeyPress { c.pos = c.pos.Sub(up.Mul(float32(deltaT * speed))) } fov := initialFOV - 5.0*float64(glfw.MouseWheel()) proj := mathgl.Perspective(fov, 4.0/3.0, 0.1, 100.0) view := mathgl.LookAtV(c.pos, c.pos.Add(dir), up) c.time = currTime return view, proj }
func main() { sys := Make() sys.Startup() defer sys.Shutdown() // InitQueue() sys.CreateWindow(1024, 768, "Gexic") gl.ClearColor(1, 1, 1, 0.) initGL() prevSelectPos = []int{0, 0, 0} // PurgeQueue() // genHexMap() hexMap2 = GenHexMap() // for matches := checkHexMap(); len(matches) > 0; matches = checkHexMap() { // removeHexAndGenNew(matches) // } glfw.SetMouseButtonCallback(MouseButtonCallback) glfw.SetCharCallback(charCallback) glfw.SetMousePosCallback(MousePosCallback) currExX = -1 currExY = -1 for sys.CheckExitMainLoop() { start := glfw.Time() wait := float64(1) / float64(30) gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) gl.Enable(gl.TEXTURE_2D) gl.Enable(gl.BLEND) gl.Disable(gl.DEPTH_TEST) // renderHexMap() wallpaper.Bind(gl.TEXTURE_2D) gl.TexEnvf(gl.TEXTURE_ENV, gl.TEXTURE_ENV_MODE, gl.REPLACE) gl.Begin(gl.QUADS) gl.TexCoord2f(0, 0) gl.Vertex2i(0, 0) gl.TexCoord2f(0, 1) gl.Vertex2i(0, 768) gl.TexCoord2f(1, 1) gl.Vertex2i(1024, 768) gl.TexCoord2f(1, 0) gl.Vertex2i(1024, 0) gl.End() hexMap2.Render() hexRotate.AnimateAndExecute() hexShrink.AnimateAndExecute() hexFall.AnimateAndExecute() if !mouse.locked { x, y := mouse.GetXY() hexMap2.CalcClosestCenter(x, y) } gl.Flush() gl.Disable(gl.TEXTURE_2D) gl.Disable(gl.BLEND) sys.Refresh() diff := glfw.Time() - start if diff < wait { glfw.Sleep(wait - diff) } } }
// Returns the number of seconds expired ever since Loop.Run() was last called. func (_ *NgLoop) Time() float64 { return glfw.Time() }
// Initiates a rendering loop. This method returns only when the loop is stopped for whatever reason. // // (Before entering the loop, this method performs a one-off GC invokation.) func (_ *NgLoop) Run() { var ( secTick int runGc = Options.Loop.GcEvery.Frame ) if !Loop.Running { Loop.Running = true glfw.SetTime(0) Loop.Tick.Now = glfw.Time() Core.copyAppToPrep() Core.copyPrepToRend() Loop.Tick.Prev = Loop.Tick.Now Loop.Tick.Now = glfw.Time() Loop.Tick.PrevSec, Loop.Tick.Delta = int(Loop.Tick.Now), Loop.Tick.Now-Loop.Tick.Prev Stats.reset() runtime.GC() Diag.LogMisc("Enter loop...") Loop.Running = glfw.WindowParam(glfw.Opened) == 1 for Loop.Running { // STEP 0. Fire off the prep thread (for next frame) and app thread (for next-after-next frame). thrPrep.Lock() go Loop.onThreadPrep() thrApp.Lock() go Loop.onThreadApp() // STEP 1. Fill the GPU command queue with rendering commands (batched together by the previous prep thread) Stats.FrameRenderCpu.begin() Core.onRender() Stats.FrameRenderCpu.end() // STEP 2. While the GL driver processes its command queue and other CPU cores work on // app and prep threads, this CPU core can now perform some other minor duties Stats.fpsCounter++ Stats.fpsAll++ // This branch runs at most and at least 1x per second if secTick = int(Loop.Tick.Now); secTick != Loop.Tick.PrevSec { Stats.FrameOnSec.begin() Stats.FpsLastSec, Loop.Tick.PrevSec = Stats.fpsCounter, secTick Stats.fpsCounter = 0 if Diag.LogGLErrorsInLoopOnSec { Diag.LogIfGlErr("onSec") } Loop.On.EverySec() runGc = Options.Loop.GcEvery.Sec Stats.FrameOnSec.end() Stats.enable() // the first few frames were warm-ups that don't count towards the stats } // Wait for threads -- waits until both app and prep threads are done and copies stage states around Loop.onWaitForThreads() // Call On.WinThread() -- for main-thread user code (mostly input polling) without affecting On.AppThread Loop.onThreadWin() // Must do this here so that current-tick won't change half-way through OnAppTread(), // and then we'd also like this frame's On.WinThread() to have the same current-tick. Loop.Tick.Prev, Loop.Tick.Now = Loop.Tick.Now, glfw.Time() Stats.Frame.measureStartTime, Loop.Tick.Delta = Loop.Tick.Prev, Loop.Tick.Now-Loop.Tick.Prev Stats.Frame.end() // GC stops-the-world so do it after go-routines have finished. Now is a good time, as the GPU // is likely still busy processing commands from step 1 and won't be interrupted by Go's GC -- // the subsequent buffer-swap step block-waits for the GPU anyway. if runGc { runGc = Options.Loop.GcEvery.Frame Loop.onGC() } // STEP 3. Swap buffers -- this waits for the GPU/GL to finish processing its command // queue filled in Step 1, swap buffers and for V-sync (if any) Loop.onSwap() // Check for resize before next render if (UserIO.Window.lastResize > 0) && ((Loop.Tick.Now - UserIO.Window.lastResize) > UserIO.Window.ResizeMinDelay) { UserIO.Window.lastResize = 0 Core.onResizeWindow(UserIO.Window.width, UserIO.Window.height) } Stats.FrameRenderBoth.combine(&Stats.FrameRenderCpu, &Stats.FrameRenderGpu) if Loop.Delay > 0 { time.Sleep(Loop.Delay) } if Loop.MaxIterations > 0 && Stats.fpsAll >= Loop.MaxIterations { Loop.Running = false } } Loop.Running = false Diag.LogMisc("Exited loop.") Diag.LogIfGlErr("ngine.PostLoop") if false { for rbi, rbe := range Core.Render.Canvases[1].Views[0].Technique_Scene().thrRend.batch.all { println(strf("%d\t==>\tP:%v\tT:%v\tB:%v\tD:%v", rbi, rbe.prog, rbe.texes, Core.Libs.Meshes[rbe.mesh].meshBuffer.glIbo.GlHandle, rbe.dist)) } } } }
func Run() { timeNow := time.Now() gameTime = gameTime.Add(timeNow.Sub(lastTime)) //deltaTime = float64(timeNow.Sub(lastTime).Nanoseconds()) / float64(time.Second) lastTime = timeNow before := timeNow dn := glfw.Time() dd = dn - dl dl = dn deltaTime = dd timer := NewTimer() timer.Start() CurrentCamera().Clear() var destroyDelta, startDelta, fixedUpdateDelta, physicsDelta, updateDelta, lateUpdateDelta, drawDelta, coroutinesDelta, stepDelta, behaviorDelta, startPhysicsDelta, endPhysicsDelta time.Duration if mainScene != nil { d := deltaTime if d > maxPhysicsTime { d = maxPhysicsTime } fixedTime += d sd := mainScene.SceneBase() arr := &sd.gameObjects timer.StartCustom("Destory routines") iter(arr, destoyGameObject) destroyDelta = timer.StopCustom("Destory routines") //Better to not do it every frame. mainScene.SceneBase().cleanNil() timer.StartCustom("Start routines") iter(arr, startGameObject) startDelta = timer.StopCustom("Start routines") // timer.StartCustom("Physics time") if EnablePhysics { timer.StartCustom("Physics step time") for fixedTime >= stepTime { timer.StartCustom("FixedUpdate routines") iter(arr, fixedUdpateGameObject) fixedUpdateDelta = timer.StopCustom("FixedUpdate routines") timer.StartCustom("PreStep Physics Delta") iter(arr, preStepGameObject) startPhysicsDelta = timer.StopCustom("PreStep Physics Delta") Space.Step(vect.Float(stepTime)) fixedTime -= stepTime _ = timer.StopCustom("Physics step time") timer.StartCustom("PostStep Physics Delta") iter(arr, postStepGameObject) endPhysicsDelta = timer.StopCustom("PostStep Physics Delta") } if fixedTime > 0 && fixedTime < stepTime { iter(arr, interpolateGameObject) } } physicsDelta = timer.StopCustom("Physics time") timer.StartCustom("Update routines") internalFPSObject.Update() iter(arr, udpateGameObject) updateDelta = timer.StopCustom("Update routines") timer.StartCustom("LateUpdate routines") iter(arr, lateudpateGameObject) lateUpdateDelta = timer.StopCustom("LateUpdate routines") timer.StartCustom("Draw routines") depthMap.Iter(drawGameObject) drawDelta = timer.StopCustom("Draw routines") timer.StartCustom("coroutines") cr.Run() coroutinesDelta = timer.StopCustom("coroutines") timer.StartCustom("BehaviorTree") bt.Run(BehaviorTicks) behaviorDelta = timer.StopCustom("BehaviorTree") input.UpdateInput() stepDelta = timer.Stop() } timer.StartCustom("SwapBuffers") glfw.SwapBuffers() swapBuffersDelta := timer.StopCustom("SwapBuffers") now := time.Now() deltaDur := now.Sub(before) if Debug { fmt.Println() fmt.Println("##################") if InternalFPS < 20 { fmt.Println("FPS is lower than 20. FPS:", InternalFPS) } else if InternalFPS < 30 { fmt.Println("FPS is lower than 30. FPS:", InternalFPS) } else if InternalFPS < 40 { fmt.Println("FPS is lower than 40. FPS:", InternalFPS) } if stepDelta > 17*time.Millisecond { fmt.Println("StepDelta time is lower than normal") } fmt.Println("Debugging Times:") if (deltaDur.Nanoseconds() / int64(time.Millisecond)) != 0 { fmt.Println("Expected FPS", 1000/(deltaDur.Nanoseconds()/int64(time.Millisecond))) } fmt.Println("Step time", stepDelta) fmt.Println("Destroy time", destroyDelta) fmt.Println("Start time", startDelta) fmt.Println("FixedUpdate time", fixedUpdateDelta) fmt.Println("Update time", updateDelta) fmt.Println("LateUpdate time", lateUpdateDelta) fmt.Println("Draw time", drawDelta) fmt.Println("Delta time", deltaDur, deltaTime) fmt.Println("SwapBuffers time", swapBuffersDelta) fmt.Println("Coroutines time", coroutinesDelta) fmt.Println("BehaviorTree time", behaviorDelta) fmt.Println("------------------") fmt.Println("Physics time:", physicsDelta) fmt.Println("PreStepDelta time", startPhysicsDelta) fmt.Println("PostStepDelta time", endPhysicsDelta) fmt.Println("StepTime time", Space.StepTime) fmt.Println("ApplyImpulse time", Space.ApplyImpulsesTime) fmt.Println("ReindexQueryTime time", Space.ReindexQueryTime) fmt.Println("Arbiters", len(Space.Arbiters)) fmt.Println("##################") fmt.Println() } }
// Returns the average number of frames-per-second since Loop.Loop() was last called. func (_ *NgStats) AverageFps() float64 { return Stats.fpsAll / glfw.Time() }
func (me *TimingStats) begin() { if Stats.enabled { me.measureStartTime = glfw.Time() } }
func main() { if err := glfw.Init(); err != nil { fmt.Fprintf(os.Stderr, "%s\n", err.Error()) return } defer glfw.Terminate() glfw.OpenWindowHint(glfw.FsaaSamples, 4) glfw.OpenWindowHint(glfw.OpenGLVersionMajor, 3) glfw.OpenWindowHint(glfw.OpenGLVersionMinor, 3) glfw.OpenWindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile) if err := glfw.OpenWindow(1024, 768, 0, 0, 0, 0, 32, 0, glfw.Windowed); err != nil { fmt.Fprintf(os.Stderr, "%s\n", err.Error()) return } glfw.SetSwapInterval(0) //gl.GlewExperimental(true) gl.Init() // Can't find gl.GLEW_OK or any variation, not sure how to check if this worked gl.GetError() // ignore error, since we're telling it to use CoreProfile above, we get "invalid enumerant" (GLError 1280) which freaks the OpenGLSentinel out glfw.SetWindowTitle("Tutorial 09") glfw.Enable(glfw.StickyKeys) glfw.Disable(glfw.MouseCursor) // Not in the original tutorial, but IMO it SHOULD be there glfw.SetMousePos(1024.0/2.0, 768.0/2.0) gl.ClearColor(0., 0., 0.4, 0.) gl.Enable(gl.DEPTH_TEST) gl.DepthFunc(gl.LESS) gl.Enable(gl.CULL_FACE) camera := input.NewCamera() vertexArray := gl.GenVertexArray() defer vertexArray.Delete() vertexArray.Bind() prog := helper.MakeProgram("StandardShading.vertexshader", "StandardShading.fragmentshader") defer prog.Delete() matrixID := prog.GetUniformLocation("MVP") viewMatrixID := prog.GetUniformLocation("V") modelMatrixID := prog.GetUniformLocation("M") texture := helper.MakeTextureFromTGA("uvmap.tga") // Had to convert to tga, go-gl is missing the texture method for DDS right now defer texture.Delete() texSampler := prog.GetUniformLocation("myTextureSampler") meshObj := objloader.LoadObject("suzanne.obj") indices, indexedVertices, indexedUVs, indexedNormals := indexer.IndexVBO(meshObj.Vertices, meshObj.UVs, meshObj.Normals) vertexBuffer := gl.GenBuffer() defer vertexBuffer.Delete() vertexBuffer.Bind(gl.ARRAY_BUFFER) gl.BufferData(gl.ARRAY_BUFFER, len(indexedVertices)*3*4, indexedVertices, gl.STATIC_DRAW) uvBuffer := gl.GenBuffer() defer uvBuffer.Delete() uvBuffer.Bind(gl.ARRAY_BUFFER) // And yet, the weird length stuff doesn't seem to matter for UV or normal gl.BufferData(gl.ARRAY_BUFFER, len(indexedUVs)*2*4, indexedUVs, gl.STATIC_DRAW) normBuffer := gl.GenBuffer() defer normBuffer.Delete() normBuffer.Bind(gl.ARRAY_BUFFER) gl.BufferData(gl.ARRAY_BUFFER, len(indexedNormals)*3*4, indexedNormals, gl.STATIC_DRAW) elementBuffer := gl.GenBuffer() defer elementBuffer.Delete() elementBuffer.Bind(gl.ELEMENT_ARRAY_BUFFER) gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, len(indices)*2, indices, gl.STATIC_DRAW) // NOTE: a GL_UNSIGNED_SHORT is 16-bits lightID := prog.GetUniformLocation("LightPosition_worldspace") lastTime := glfw.Time() nbFrames := 0 // Equivalent to a do... while for ok := true; ok; ok = (glfw.Key(glfw.KeyEsc) != glfw.KeyPress && glfw.WindowParam(glfw.Opened) == gl.TRUE && glfw.Key('Q') != glfw.KeyPress) { currTime := glfw.Time() nbFrames++ if currTime-lastTime >= 1.0 { fmt.Printf("%f ms/frame\n", 1000.0/float64(nbFrames)) nbFrames = 0 lastTime += 1.0 } func() { gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) prog.Use() defer gl.ProgramUnuse() view, proj := camera.ComputeViewPerspective() model := mathgl.Ident4f() MVP := proj.Mul4(view).Mul4(model) //mvpArray := mvp.AsCMOArray(mathgl.FLOAT32).([16]float32) //vArray := view.AsCMOArray(mathgl.FLOAT32).([16]float32) //mArray := model.AsCMOArray(mathgl.FLOAT32).([16]float32) matrixID.UniformMatrix4fv(false, MVP) viewMatrixID.UniformMatrix4fv(false, view) modelMatrixID.UniformMatrix4fv(false, model) lightID.Uniform3f(4., 4., 4.) gl.ActiveTexture(gl.TEXTURE0) texture.Bind(gl.TEXTURE_2D) defer texture.Unbind(gl.TEXTURE_2D) texSampler.Uniform1i(0) vertexAttrib := gl.AttribLocation(0) vertexAttrib.EnableArray() defer vertexAttrib.DisableArray() vertexBuffer.Bind(gl.ARRAY_BUFFER) defer vertexBuffer.Unbind(gl.ARRAY_BUFFER) vertexAttrib.AttribPointer(3, gl.FLOAT, false, 0, nil) uvAttrib := gl.AttribLocation(1) uvAttrib.EnableArray() defer uvAttrib.DisableArray() uvBuffer.Bind(gl.ARRAY_BUFFER) defer uvBuffer.Unbind(gl.ARRAY_BUFFER) uvAttrib.AttribPointer(2, gl.FLOAT, false, 0, nil) normAttrib := gl.AttribLocation(2) normAttrib.EnableArray() defer normAttrib.DisableArray() normBuffer.Bind(gl.ARRAY_BUFFER) defer normBuffer.Unbind(gl.ARRAY_BUFFER) normAttrib.AttribPointer(3, gl.FLOAT, false, 0, nil) elementBuffer.Bind(gl.ELEMENT_ARRAY_BUFFER) defer elementBuffer.Unbind(gl.ELEMENT_ARRAY_BUFFER) gl.DrawElements(gl.TRIANGLES, len(indices), gl.UNSIGNED_SHORT, nil) glfw.SwapBuffers() }() // Defers unbinds and disables to here, end of the loop } }
func (me *context) Time() float64 { return glfw.Time() }