mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-28 12:48:54 +01:00
111 lines
3.1 KiB
Go
111 lines
3.1 KiB
Go
package offscreen
|
|
|
|
// #cgo LDFLAGS: -framework OpenGL
|
|
//
|
|
// #include <stdlib.h>
|
|
// #include <OpenGL/gl.h>
|
|
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"
|
|
gtexture "github.com/hajimehoshi/go-ebiten/graphics/texture"
|
|
)
|
|
|
|
type Offscreen struct {
|
|
screenHeight int
|
|
screenScale int
|
|
mainFramebufferTexture *gtexture.RenderTarget
|
|
projectionMatrix [16]float32
|
|
}
|
|
|
|
func New(screenWidth, screenHeight, screenScale int) *Offscreen {
|
|
offscreen := &Offscreen{
|
|
screenHeight: screenHeight,
|
|
screenScale: screenScale,
|
|
}
|
|
|
|
mainFramebuffer := C.GLint(0)
|
|
C.glGetIntegerv(C.GL_FRAMEBUFFER_BINDING, &mainFramebuffer)
|
|
|
|
var err error
|
|
offscreen.mainFramebufferTexture, err = rendertarget.CreateWithFramebuffer(
|
|
screenWidth*screenScale,
|
|
screenHeight*screenScale,
|
|
rendertarget.Framebuffer(mainFramebuffer))
|
|
if err != nil {
|
|
panic("creating main framebuffer failed: " + err.Error())
|
|
}
|
|
|
|
return offscreen
|
|
}
|
|
|
|
func (o *Offscreen) Set(rt *gtexture.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) {
|
|
texture.Draw(&drawable{o, geometryMatrix, colorMatrix})
|
|
}
|
|
|
|
func (o *Offscreen) DrawTextureParts(texture *gtexture.Texture,
|
|
parts []graphics.TexturePart,
|
|
geometryMatrix matrix.Geometry, colorMatrix matrix.Color) {
|
|
texture.DrawParts(parts, &drawable{o, geometryMatrix, colorMatrix})
|
|
}
|
|
|
|
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)
|
|
}
|