diff --git a/graphics/opengl/context.go b/graphics/opengl/context.go index e46a039d1..6b975ee5d 100644 --- a/graphics/opengl/context.go +++ b/graphics/opengl/context.go @@ -8,23 +8,24 @@ import "C" import ( "github.com/hajimehoshi/go-ebiten/graphics" "github.com/hajimehoshi/go-ebiten/graphics/matrix" - "github.com/hajimehoshi/go-ebiten/graphics/opengl/rendertarget" - "github.com/hajimehoshi/go-ebiten/graphics/opengl/shader" + "github.com/hajimehoshi/go-ebiten/graphics/opengl/offscreen" + // "github.com/hajimehoshi/go-ebiten/graphics/opengl/shader" "github.com/hajimehoshi/go-ebiten/graphics/opengl/texture" grendertarget "github.com/hajimehoshi/go-ebiten/graphics/rendertarget" - gtexture "github.com/hajimehoshi/go-ebiten/graphics/texture" + // gtexture "github.com/hajimehoshi/go-ebiten/graphics/texture" "image" "math" ) type Context struct { - screenId graphics.RenderTargetId - screenWidth int - screenHeight int - screenScale int - ids *ids - mainFramebufferTexture *grendertarget.RenderTarget - projectionMatrix [16]float32 + screenId graphics.RenderTargetId + screenWidth int + screenHeight int + screenScale int + ids *ids + //mainFramebufferTexture *grendertarget.RenderTarget + //projectionMatrix [16]float32 + offscreen *offscreen.Offscreen } func newContext(screenWidth, screenHeight, screenScale int) *Context { @@ -33,22 +34,10 @@ func newContext(screenWidth, screenHeight, screenScale int) *Context { screenHeight: screenHeight, screenScale: screenScale, ids: newIds(), + offscreen: offscreen.New(screenWidth, screenHeight, screenScale), } - // The main framebuffer should be created sooner than any other - // framebuffers! - mainFramebuffer := C.GLint(0) - C.glGetIntegerv(C.GL_FRAMEBUFFER_BINDING, &mainFramebuffer) - var err error - context.mainFramebufferTexture, err = rendertarget.NewWithFramebuffer( - context.screenWidth*context.screenScale, - context.screenHeight*context.screenScale, - rendertarget.Framebuffer(mainFramebuffer)) - if err != nil { - panic("creating main framebuffer failed: " + err.Error()) - } - context.screenId, err = context.createRenderTarget( context.screenWidth, context.screenHeight, texture.FilterNearest) if err != nil { @@ -82,22 +71,14 @@ func (context *Context) DrawTexture( textureId graphics.TextureId, geometryMatrix matrix.Geometry, colorMatrix matrix.Color) { tex := context.ids.TextureAt(textureId) - tex.Draw(func(native interface{}, quads []gtexture.Quad) { - shader.DrawTexture(native.(texture.Native), - context.projectionMatrix, quads, - geometryMatrix, colorMatrix) - }) + context.offscreen.DrawTexture(tex, geometryMatrix, colorMatrix) } func (context *Context) DrawTextureParts( textureId graphics.TextureId, parts []graphics.TexturePart, geometryMatrix matrix.Geometry, colorMatrix matrix.Color) { tex := context.ids.TextureAt(textureId) - tex.DrawParts(parts, func(native interface{}, quads []gtexture.Quad) { - shader.DrawTexture(native.(texture.Native), - context.projectionMatrix, quads, - geometryMatrix, colorMatrix) - }) + context.offscreen.DrawTextureParts(tex, parts, geometryMatrix, colorMatrix) } func (context *Context) Init() { @@ -115,19 +96,16 @@ func (context *Context) SetOffscreen(renderTargetId graphics.RenderTargetId) { } func (context *Context) setOffscreen(rt *grendertarget.RenderTarget) { - C.glFlush() + /*C.glFlush() - setter := &OffscreenSetter{ - context.screenHeight, - context.screenScale, - rt == context.mainFramebufferTexture, - &context.projectionMatrix, - } - rt.SetAsOffscreen(setter) + rt.SetAsOffscreen(context.offscreen) + context.projectionMatrix = setter.projectionMatrix*/ + context.offscreen.Set(rt) } func (context *Context) setMainFramebufferOffscreen() { - context.setOffscreen(context.mainFramebufferTexture) + //context.setOffscreen(context.mainFramebufferTexture) + context.offscreen.SetMainFramebuffer() } func (context *Context) flush() { diff --git a/graphics/opengl/offscreen.go b/graphics/opengl/offscreen.go deleted file mode 100644 index 7672ab36c..000000000 --- a/graphics/opengl/offscreen.go +++ /dev/null @@ -1,48 +0,0 @@ -package opengl - -// #cgo LDFLAGS: -framework OpenGL -// -// #include -// #include -import "C" -import ( - "fmt" - "github.com/hajimehoshi/go-ebiten/graphics" - "github.com/hajimehoshi/go-ebiten/graphics/opengl/rendertarget" -) - -type OffscreenSetter struct { - screenHeight int - screenScale int - usingMainFramebuffer bool - projectionMatrix *[16]float32 -} - -func (s *OffscreenSetter) Set(framebuffer interface{}, x, y, width, height int) { - f := framebuffer.(rendertarget.Framebuffer) - C.glBindFramebuffer(C.GL_FRAMEBUFFER, C.GLuint(f)) - err := C.glCheckFramebufferStatus(C.GL_FRAMEBUFFER) - if err != C.GL_FRAMEBUFFER_COMPLETE { - panic(fmt.Sprintf("glBindFramebuffer failed: %d", err)) - } - - C.glBlendFuncSeparate(C.GL_SRC_ALPHA, C.GL_ONE_MINUS_SRC_ALPHA, - C.GL_ZERO, C.GL_ONE) - - C.glViewport(C.GLint(x), C.GLint(y), - C.GLsizei(width), C.GLsizei(height)) - - matrix := graphics.OrthoProjectionMatrix(x, width, y, height) - if s.usingMainFramebuffer { - actualScreenHeight := s.screenHeight * s.screenScale - // Flip Y and move to fit with the top of the window. - matrix[1][1] *= -1 - matrix[1][3] += float64(actualScreenHeight) / float64(height) * 2 - } - - for j := 0; j < 4; j++ { - for i := 0; i < 4; i++ { - s.projectionMatrix[i+j*4] = float32(matrix[i][j]) - } - } -} diff --git a/graphics/opengl/offscreen/offscreen.go b/graphics/opengl/offscreen/offscreen.go new file mode 100644 index 000000000..cf8db39d5 --- /dev/null +++ b/graphics/opengl/offscreen/offscreen.go @@ -0,0 +1,115 @@ +package offscreen + +// #cgo LDFLAGS: -framework OpenGL +// +// #include +// #include +import "C" +import ( + "fmt" + "github.com/hajimehoshi/go-ebiten/graphics" + "github.com/hajimehoshi/go-ebiten/graphics/matrix" + "github.com/hajimehoshi/go-ebiten/graphics/opengl/rendertarget" + "github.com/hajimehoshi/go-ebiten/graphics/opengl/shader" + "github.com/hajimehoshi/go-ebiten/graphics/opengl/texture" + grendertarget "github.com/hajimehoshi/go-ebiten/graphics/rendertarget" + gtexture "github.com/hajimehoshi/go-ebiten/graphics/texture" +) + +type Offscreen struct { + screenHeight int + screenScale int + mainFramebufferTexture *grendertarget.RenderTarget + projectionMatrix [16]float32 +} + +func New(screenWidth, screenHeight, screenScale int) *Offscreen { + offscreen := &Offscreen{ + screenHeight: screenHeight, + screenScale: screenScale, + } + + // The main framebuffer should be created sooner than any other + // framebuffers! + mainFramebuffer := C.GLint(0) + C.glGetIntegerv(C.GL_FRAMEBUFFER_BINDING, &mainFramebuffer) + + var err error + offscreen.mainFramebufferTexture, err = rendertarget.NewWithFramebuffer( + screenWidth*screenScale, + screenHeight*screenScale, + rendertarget.Framebuffer(mainFramebuffer)) + if err != nil { + panic("creating main framebuffer failed: " + err.Error()) + } + + return offscreen +} + +func (o *Offscreen) Set(rt *grendertarget.RenderTarget) { + C.glFlush() + rt.SetAsOffscreen(&setter{o, rt == o.mainFramebufferTexture}) +} + +func (o *Offscreen) SetMainFramebuffer() { + o.Set(o.mainFramebufferTexture) +} + +func (o *Offscreen) DrawTexture(texture *gtexture.Texture, + geometryMatrix matrix.Geometry, colorMatrix matrix.Color) { + d := &drawable{o, geometryMatrix, colorMatrix} + texture.Draw(d.Draw) +} + +func (o *Offscreen) DrawTextureParts(texture *gtexture.Texture, + parts []graphics.TexturePart, + geometryMatrix matrix.Geometry, colorMatrix matrix.Color) { + d := &drawable{o, geometryMatrix, colorMatrix} + texture.DrawParts(parts, d.Draw) +} + +type setter struct { + offscreen *Offscreen + usingMainFramebuffer bool +} + +func (s *setter) Set(framebuffer interface{}, x, y, width, height int) { + f := framebuffer.(rendertarget.Framebuffer) + C.glBindFramebuffer(C.GL_FRAMEBUFFER, C.GLuint(f)) + err := C.glCheckFramebufferStatus(C.GL_FRAMEBUFFER) + if err != C.GL_FRAMEBUFFER_COMPLETE { + panic(fmt.Sprintf("glBindFramebuffer failed: %d", err)) + } + + C.glBlendFuncSeparate(C.GL_SRC_ALPHA, C.GL_ONE_MINUS_SRC_ALPHA, + C.GL_ZERO, C.GL_ONE) + + C.glViewport(C.GLint(x), C.GLint(y), + C.GLsizei(width), C.GLsizei(height)) + + matrix := graphics.OrthoProjectionMatrix(x, width, y, height) + if s.usingMainFramebuffer { + actualScreenHeight := s.offscreen.screenHeight * s.offscreen.screenScale + // Flip Y and move to fit with the top of the window. + matrix[1][1] *= -1 + matrix[1][3] += float64(actualScreenHeight) / float64(height) * 2 + } + + for j := 0; j < 4; j++ { + for i := 0; i < 4; i++ { + s.offscreen.projectionMatrix[i+j*4] = float32(matrix[i][j]) + } + } +} + +type drawable struct { + offscreen *Offscreen + geometryMatrix matrix.Geometry + colorMatrix matrix.Color +} + +func (d *drawable) Draw(native interface{}, quads []gtexture.Quad) { + shader.DrawTexture(native.(texture.Native), + d.offscreen.projectionMatrix, quads, + d.geometryMatrix, d.colorMatrix) +} diff --git a/ui/cocoa/cocoa.go b/ui/cocoa/cocoa.go index 7bdcea369..f3900eb4e 100644 --- a/ui/cocoa/cocoa.go +++ b/ui/cocoa/cocoa.go @@ -80,14 +80,14 @@ func New(screenWidth, screenHeight, screenScale int, title string) *UI { C.StartApplication() context := C.CreateGLContext(unsafe.Pointer(nil)) - C.SetCurrentGLContext(context); + C.SetCurrentGLContext(context) ui.graphicsDevice = opengl.NewDevice( ui.screenWidth, ui.screenHeight, ui.screenScale) - ui.window = C.CreateWindow(C.size_t(ui.screenWidth * ui.screenScale), - C.size_t(ui.screenHeight * ui.screenScale), + ui.window = C.CreateWindow(C.size_t(ui.screenWidth*ui.screenScale), + C.size_t(ui.screenHeight*ui.screenScale), cTitle, context) currentUI = ui