diff --git a/image.go b/image.go index 00b8b07e4..d631afe15 100644 --- a/image.go +++ b/image.go @@ -147,7 +147,7 @@ func (i *Image) At(x, y int) color.Color { if i.pixels == nil { ui.Use(func(c *opengl.Context) { var err error - i.pixels, err = i.texture.Pixels(c) + i.pixels, err = i.framebuffer.Pixels(c) if err != nil { panic(err) } diff --git a/image_test.go b/image_test.go index e81cc0f08..a9bd1a133 100644 --- a/image_test.go +++ b/image_test.go @@ -168,7 +168,7 @@ func TestImageDotByDotInversion(t *testing.T) { c0 := img0.At(i, j).(color.RGBA) c1 := img1.At(w-i-1, h-j-1).(color.RGBA) if c0 != c1 { - t.Errorf("c0 should equal to c1 but not: c0: %v, c1: %v", c0, c1) + t.Errorf("img0.At(%[1]d, %[2]d) should equal to img1.At(%[1]d, %[2]d) but not: %[3]v vs %[4]v", i, j, c0, c1) } } } diff --git a/internal/graphics/framebuffer.go b/internal/graphics/framebuffer.go index d648f1a95..b61da912b 100644 --- a/internal/graphics/framebuffer.go +++ b/internal/graphics/framebuffer.go @@ -141,3 +141,9 @@ func (f *Framebuffer) FillRects(c *opengl.Context, rects Rects) error { p := f.projectionMatrix() return shader.FillRects(c, p, rects) } + +func (f *Framebuffer) Pixels(c *opengl.Context) ([]uint8, error) { + w, h := f.Size() + w, h = internal.NextPowerOf2Int(w), internal.NextPowerOf2Int(h) + return c.FramebufferPixels(f.native, w, h) +} diff --git a/internal/graphics/texture.go b/internal/graphics/texture.go index 31e3e48a6..93cc69df3 100644 --- a/internal/graphics/texture.go +++ b/internal/graphics/texture.go @@ -90,8 +90,3 @@ func NewTextureFromImage(c *opengl.Context, img image.Image, filter opengl.Filte func (t *Texture) Dispose(c *opengl.Context) { c.DeleteTexture(t.native) } - -func (t *Texture) Pixels(c *opengl.Context) ([]uint8, error) { - w, h := internal.NextPowerOf2Int(t.width), internal.NextPowerOf2Int(t.height) - return c.TexturePixels(t.native, w, h) -} diff --git a/internal/opengl/context.go b/internal/opengl/context.go index 23b2916dd..1111d0bc2 100644 --- a/internal/opengl/context.go +++ b/internal/opengl/context.go @@ -84,12 +84,13 @@ func (c *Context) NewTexture(width, height int, pixels []uint8, filter Filter) ( return Texture(t), nil } -func (c *Context) TexturePixels(t Texture, width, height int) ([]uint8, error) { +func (c *Context) FramebufferPixels(f Framebuffer, width, height int) ([]uint8, error) { gl.Flush() - // TODO: Use glGetTexLevelParameteri and GL_TEXTURE_WIDTH? + + gl.Framebuffer(f).Bind() + pixels := make([]uint8, 4*width*height) - gl.Texture(t).Bind(gl.TEXTURE_2D) - gl.GetTexImage(gl.TEXTURE_2D, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels) + gl.ReadPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels) if e := gl.GetError(); e != gl.NO_ERROR { return nil, errors.New(fmt.Sprintf("gl error: %d", e)) } diff --git a/internal/opengl/context_js.go b/internal/opengl/context_js.go index 581da7d1e..4e93c0955 100644 --- a/internal/opengl/context_js.go +++ b/internal/opengl/context_js.go @@ -64,6 +64,8 @@ type context struct { gl *webgl.Context } +var lastFramebuffer Framebuffer + func NewContext(gl *webgl.Context) *Context { c := &Context{ Nearest: Filter(gl.NEAREST), @@ -113,12 +115,14 @@ func (c *Context) NewTexture(width, height int, pixels []uint8, filter Filter) ( return Texture{t}, nil } -func (c *Context) TexturePixels(t Texture, width, height int) ([]uint8, error) { +func (c *Context) FramebufferPixels(f Framebuffer, width, height int) ([]uint8, error) { gl := c.gl gl.Flush() - // TODO: Use glGetTexLevelParameteri and GL_TEXTURE_WIDTH? + + lastFramebuffer = Framebuffer{nil} + gl.BindFramebuffer(gl.FRAMEBUFFER, f.Object) + pixels := js.Global.Get("Uint8Array").New(4 * width * height) - gl.BindTexture(gl.TEXTURE_2D, t.Object) gl.ReadPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels) if e := gl.GetError(); e != gl.NO_ERROR { return nil, errors.New(fmt.Sprintf("gl error: %d", e)) @@ -148,6 +152,7 @@ func (c *Context) GlslHighpSupported() bool { func (c *Context) NewFramebuffer(t Texture) (Framebuffer, error) { gl := c.gl f := gl.CreateFramebuffer() + lastFramebuffer = Framebuffer{nil} gl.BindFramebuffer(gl.FRAMEBUFFER, f) gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, t.Object, 0) @@ -158,8 +163,6 @@ func (c *Context) NewFramebuffer(t Texture) (Framebuffer, error) { return Framebuffer{f}, nil } -var lastFramebuffer Framebuffer - func (c *Context) SetViewport(f Framebuffer, width, height int) error { gl := c.gl // TODO: Fix this after the GopherJS bug was fixed (#159)