func (c *Context) NewFramebuffer(texture Texture) (Framebuffer, error) { var framebuffer Framebuffer var f uint32 if err := c.runOnContextThread(func() error { gl.GenFramebuffers(1, &f) // TODO: Use gl.IsFramebuffer if f <= 0 { return errors.New("opengl: creating framebuffer failed: gl.IsFramebuffer returns false") } return nil }); err != nil { return 0, err } if err := c.bindFramebuffer(Framebuffer(f)); err != nil { return 0, err } if err := c.runOnContextThread(func() error { gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, uint32(texture), 0) s := gl.CheckFramebufferStatus(gl.FRAMEBUFFER) if s != gl.FRAMEBUFFER_COMPLETE { if s != 0 { return fmt.Errorf("opengl: creating framebuffer failed: %v", s) } if e := gl.GetError(); e != gl.NO_ERROR { return fmt.Errorf("opengl: creating framebuffer failed: (glGetError) %d", e) } return fmt.Errorf("opengl: creating framebuffer failed: unknown error") } framebuffer = Framebuffer(f) return nil }); err != nil { return 0, err } return framebuffer, nil }
// checkGLError returns an opengl error if one exists. func checkGLError() error { errno := gl.GetError() if errno == gl.NO_ERROR { return nil } return fmt.Errorf("GL error: %d", errno) }
func (c *Context) SetViewport(f Framebuffer, width, height int) error { gl.Flush() gl.BindFramebuffer(gl.FRAMEBUFFER, uint32(f)) if err := gl.CheckFramebufferStatus(gl.FRAMEBUFFER); err != gl.FRAMEBUFFER_COMPLETE { if e := gl.GetError(); e != 0 { return errors.New(fmt.Sprintf("glBindFramebuffer failed: %d", e)) } return errors.New("glBindFramebuffer failed: the context is different?") } gl.Viewport(0, 0, int32(width), int32(height)) return nil }
func (c *Context) FramebufferPixels(f Framebuffer, width, height int) ([]uint8, error) { gl.Flush() gl.BindFramebuffer(gl.FRAMEBUFFER, uint32(f)) pixels := make([]uint8, 4*width*height) gl.ReadPixels(0, 0, int32(width), int32(height), gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(pixels)) if e := gl.GetError(); e != gl.NO_ERROR { return nil, errors.New(fmt.Sprintf("glReadPixels: %d", e)) } return pixels, nil }
func loadShader(shaderType uint32, source string) uint32 { shader := gl.CreateShader(shaderType) if err := gl.GetError(); err != gl.NO_ERROR { panic(fmt.Errorf("gl error: %v", err)) } 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.TRUE { //log := shader.GetInfoLog() panic(fmt.Errorf("Failed to compile shader: shader: %v", source)) } return shader }
func (atlas *FontAtlas) upload() { if !atlas.Dirty { return } atlas.Dirty = false gl.Enable(gl.TEXTURE_2D) if atlas.Texture != 0 { gl.DeleteTextures(1, &atlas.Texture) atlas.Texture = 0 } gl.GenTextures(1, &atlas.Texture) gl.BindTexture(gl.TEXTURE_2D, atlas.Texture) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) gl.TexImage2D( gl.TEXTURE_2D, 0, gl.RGBA, int32(atlas.Image.Rect.Size().X), int32(atlas.Image.Rect.Size().Y), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(atlas.Image.Pix)) if err := gl.GetError(); err != 0 { log.Println(err) } gl.Disable(gl.TEXTURE_2D) }
func (c *Context) FramebufferPixels(f Framebuffer, width, height int) ([]uint8, error) { var pixels []uint8 if err := c.runOnContextThread(func() error { gl.Flush() return nil }); err != nil { return nil, err } if err := c.bindFramebuffer(f); err != nil { return nil, err } if err := c.runOnContextThread(func() error { pixels = make([]uint8, 4*width*height) gl.ReadPixels(0, 0, int32(width), int32(height), gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(pixels)) if e := gl.GetError(); e != gl.NO_ERROR { pixels = nil return fmt.Errorf("opengl: glReadPixels: %d", e) } return nil }); err != nil { return nil, err } return pixels, nil }
// GetError returns the next error. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetError.xhtml func GetError() Enum { return Enum(gl.GetError()) }
func (c *Context) Check() { if e := gl.GetError(); e != gl.NO_ERROR { panic(fmt.Sprintf("check failed: %d", e)) } }
func main() { flag.Parse() go func() { http.ListenAndServe("localhost:6060", nil) }() go func() { for { runtime.GC() time.Sleep(1) } }() if err := glfw.Init(); err != nil { log.Fatalln("failed to initialize glfw:", err) } defer glfw.Terminate() glfw.WindowHint(glfw.Resizable, glfw.True) glfw.WindowHint(glfw.Visible, glfw.False) // do not steal focus glfw.WindowHint(glfw.Samples, 4) glfw.WindowHint(glfw.ContextVersionMajor, 2) glfw.WindowHint(glfw.ContextVersionMinor, 1) window, err := glfw.CreateWindow(800, 600, "Spector", nil, nil) if err != nil { panic(err) } window.MakeContextCurrent() window.Restore() window.SetPos(32, 64) if err := gl.Init(); err != nil { panic(err) } if err := gl.GetError(); err != 0 { fmt.Println("INIT", err) } startnano := time.Now().UnixNano() DrawList := draw.NewList() for !window.ShouldClose() { start := qpc.Now() if window.GetKey(glfw.KeyEscape) == glfw.Press { return } now := float64(time.Now().UnixNano()-startnano) / 1e9 width, height := window.GetSize() { // reset window gl.MatrixMode(gl.MODELVIEW) gl.LoadIdentity() gl.Viewport(0, 0, int32(width), int32(height)) gl.Ortho(0, float64(width), float64(height), 0, 30, -30) gl.ClearColor(1, 1, 1, 1) gl.Clear(gl.COLOR_BUFFER_BIT) } DrawList.Reset() DrawList.AddRectFill(&draw.Rectangle{ draw.Vector{10, 10}, draw.Vector{50, 50}, }, draw.Red) CircleRadius := float32(50.0 * math.Sin(now*1.3)) DrawList.AddCircle( draw.Vector{100, 100}, CircleRadius, draw.Red) DrawList.AddArc( draw.Vector{200, 100}, CircleRadius/2+50, float32(now), float32(math.Sin(now)*10), draw.ColorHSL(float32(math.Sin(now*0.3)), 0.8, 0.5)) LineWidth := float32(math.Sin(now*2.1)*5 + 5) LineCount := int(width / 8) line := make([]draw.Vector, LineCount) for i := range line { r := float64(i) / float64(LineCount-1) line[i].X = float32(r) * float32(width) line[i].Y = float32(height)*0.5 + float32(math.Sin(r*11.8+now)*100) } DrawList.AddLine(line[:], LineWidth, draw.ColorHSL(float32(math.Sin(now*0.3)), 0.6, 0.6)) CircleCount := int(width / 8) circle := make([]draw.Vector, CircleCount) for i := range circle { p := float64(i) / float64(CircleCount) a := now + p*math.Pi*2 w := math.Sin(p*62)*20.0 + 100.0 circle[i].X = float32(width)*0.5 + float32(math.Cos(a)*w) circle[i].Y = float32(height)*0.5 + float32(math.Sin(a)*w) } // DrawList.PushClip(draw.Rect(0, 0, float32(width)/2, float32(height)/2)) DrawList.AddClosedLine(circle[:], LineWidth, draw.Green) // DrawList.PopClip() render.List(width, height, DrawList) if err := gl.GetError(); err != 0 { fmt.Println(err) } stop := qpc.Now() window.SwapBuffers() runtime.GC() glfw.PollEvents() fmt.Printf("%-10.3f\n", stop.Sub(start).Duration().Seconds()*1000) } }
func (c *Context) GetError() int { return int(gl.GetError()) }
func CheckGLError() { errorCode := gl.GetError() if errorCode != 0 { log.Panicln("GL Error:", errorCode) } }