mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 04:57:26 +01:00
Add graphics.RenderTarget
This commit is contained in:
parent
e6680eeda9
commit
86eb30c650
@ -31,9 +31,9 @@ import (
|
||||
)
|
||||
|
||||
type Rects struct {
|
||||
rectTexture graphics.Texture
|
||||
rectTexture graphics.RenderTarget
|
||||
rectTextureInited bool
|
||||
offscreen graphics.Texture
|
||||
offscreen graphics.RenderTarget
|
||||
offscreenInited bool
|
||||
rectBounds *graphics.Rect
|
||||
rectColor *color.RGBA
|
||||
@ -49,8 +49,8 @@ func New() *Rects {
|
||||
}
|
||||
|
||||
func (game *Rects) Init(tf graphics.TextureFactory) {
|
||||
game.rectTexture = tf.NewTexture(16, 16)
|
||||
game.offscreen = tf.NewTexture(256, 240)
|
||||
game.rectTexture = tf.NewRenderTarget(16, 16)
|
||||
game.offscreen = tf.NewRenderTarget(256, 240)
|
||||
}
|
||||
|
||||
func (game *Rects) Update(context ebiten.GameContext) {
|
||||
@ -104,12 +104,12 @@ func (game *Rects) Draw(g graphics.Context) {
|
||||
g.Fill(&color.RGBA{0, 0, 0, 255})
|
||||
game.offscreenInited = true
|
||||
}
|
||||
g.DrawTexture(game.rectTexture.ID(),
|
||||
g.DrawTexture(game.rectTexture.Texture().ID(),
|
||||
game.rectGeometryMatrix(),
|
||||
game.rectColorMatrix())
|
||||
|
||||
g.SetOffscreen(g.Screen().ID())
|
||||
g.DrawTexture(game.offscreen.ID(),
|
||||
g.DrawTexture(game.offscreen.Texture().ID(),
|
||||
matrix.IdentityGeometry(),
|
||||
matrix.IdentityColor())
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ type TexturePart struct {
|
||||
}
|
||||
|
||||
type Context interface {
|
||||
Screen() Texture
|
||||
Screen() RenderTarget
|
||||
Clear()
|
||||
Fill(clr color.Color)
|
||||
DrawTexture(textureID TextureID,
|
||||
@ -50,11 +50,11 @@ type Context interface {
|
||||
parts []TexturePart,
|
||||
geometryMatrix matrix.Geometry,
|
||||
colorMatrix matrix.Color)
|
||||
SetOffscreen(textureID TextureID)
|
||||
SetOffscreen(renderTargetID RenderTargetID)
|
||||
}
|
||||
|
||||
type TextureFactory interface {
|
||||
NewTexture(width, height int) Texture
|
||||
NewRenderTarget(width, height int) RenderTarget
|
||||
NewTextureFromImage(img image.Image) (Texture, error)
|
||||
}
|
||||
|
||||
@ -65,3 +65,13 @@ type Texture interface {
|
||||
}
|
||||
|
||||
type TextureID int
|
||||
|
||||
type RenderTarget interface {
|
||||
Texture() Texture
|
||||
ID() RenderTargetID
|
||||
Width() int
|
||||
Height() int
|
||||
}
|
||||
|
||||
type RenderTargetID int
|
||||
|
||||
|
@ -36,13 +36,13 @@ import (
|
||||
)
|
||||
|
||||
type Context struct {
|
||||
screen *Texture
|
||||
screen *RenderTarget
|
||||
screenWidth int
|
||||
screenHeight int
|
||||
screenScale int
|
||||
textures map[graphics.TextureID]*Texture
|
||||
currentOffscreen *Texture
|
||||
mainFramebufferTexture *Texture
|
||||
textures map[C.GLuint]*Texture
|
||||
currentOffscreen *RenderTarget
|
||||
mainFramebufferTexture *RenderTarget
|
||||
}
|
||||
|
||||
func newContext(screenWidth, screenHeight, screenScale int) *Context {
|
||||
@ -50,28 +50,29 @@ func newContext(screenWidth, screenHeight, screenScale int) *Context {
|
||||
screenWidth: screenWidth,
|
||||
screenHeight: screenHeight,
|
||||
screenScale: screenScale,
|
||||
textures: map[graphics.TextureID]*Texture{},
|
||||
textures: map[C.GLuint]*Texture{},
|
||||
}
|
||||
return context
|
||||
}
|
||||
|
||||
func (context *Context) Init() {
|
||||
// main framebuffer should be created sooner than any other framebuffers!
|
||||
// The main framebuffer should be created sooner than any other
|
||||
// framebuffers!
|
||||
mainFramebuffer := C.GLint(0)
|
||||
C.glGetIntegerv(C.GL_FRAMEBUFFER_BINDING, &mainFramebuffer)
|
||||
|
||||
context.mainFramebufferTexture = newVirtualTexture(
|
||||
context.mainFramebufferTexture = newRenderTargetWithFramebuffer(
|
||||
context.screenWidth*context.screenScale,
|
||||
context.screenHeight*context.screenScale)
|
||||
context.mainFramebufferTexture.framebuffer = C.GLuint(mainFramebuffer)
|
||||
context.screenHeight*context.screenScale,
|
||||
C.GLuint(mainFramebuffer))
|
||||
|
||||
initializeShaders()
|
||||
|
||||
context.screen =
|
||||
context.NewTexture(context.screenWidth, context.screenHeight).(*Texture)
|
||||
context.screen = context.NewRenderTarget(
|
||||
context.screenWidth, context.screenHeight).(*RenderTarget)
|
||||
}
|
||||
|
||||
func (context *Context) Screen() graphics.Texture {
|
||||
func (context *Context) Screen() graphics.RenderTarget {
|
||||
return context.screen
|
||||
}
|
||||
|
||||
@ -82,7 +83,7 @@ func (context *Context) Clear() {
|
||||
|
||||
func (context *Context) Fill(clr color.Color) {
|
||||
r, g, b, a := clr.RGBA()
|
||||
max := float64(math.MaxUint16)
|
||||
const max = float64(math.MaxUint16)
|
||||
C.glClearColor(
|
||||
C.GLclampf(float64(r)/max),
|
||||
C.GLclampf(float64(g)/max),
|
||||
@ -94,7 +95,7 @@ func (context *Context) Fill(clr color.Color) {
|
||||
func (context *Context) DrawTexture(
|
||||
textureID graphics.TextureID,
|
||||
geometryMatrix matrix.Geometry, colorMatrix matrix.Color) {
|
||||
texture := context.textures[textureID]
|
||||
texture := context.textures[C.GLuint(textureID)]
|
||||
|
||||
source := graphics.Rect{0, 0, texture.width, texture.height}
|
||||
locations := []graphics.TexturePart{{0, 0, source}}
|
||||
@ -105,7 +106,7 @@ func (context *Context) DrawTexture(
|
||||
func (context *Context) DrawTextureParts(
|
||||
textureID graphics.TextureID, parts []graphics.TexturePart,
|
||||
geometryMatrix matrix.Geometry, colorMatrix matrix.Color) {
|
||||
texture := context.textures[textureID]
|
||||
texture := context.textures[C.GLuint(textureID)]
|
||||
if texture == nil {
|
||||
panic("invalid texture ID")
|
||||
}
|
||||
@ -144,9 +145,11 @@ func (context *Context) DrawTextureParts(
|
||||
tu1, tv2,
|
||||
tu2, tv2,
|
||||
}
|
||||
C.glVertexAttribPointer(C.GLuint(vertexAttrLocation), 2, C.GL_FLOAT, C.GL_FALSE,
|
||||
C.glVertexAttribPointer(C.GLuint(vertexAttrLocation), 2,
|
||||
C.GL_FLOAT, C.GL_FALSE,
|
||||
0, unsafe.Pointer(&vertex[0]))
|
||||
C.glVertexAttribPointer(C.GLuint(textureAttrLocation), 2, C.GL_FLOAT, C.GL_FALSE,
|
||||
C.glVertexAttribPointer(C.GLuint(textureAttrLocation), 2,
|
||||
C.GL_FLOAT, C.GL_FALSE,
|
||||
0, unsafe.Pointer(&texCoord[0]))
|
||||
C.glDrawArrays(C.GL_TRIANGLE_STRIP, 0, 4)
|
||||
}
|
||||
@ -163,21 +166,23 @@ func abs(x int) int {
|
||||
return x
|
||||
}
|
||||
|
||||
func (context *Context) SetOffscreen(textureID graphics.TextureID) {
|
||||
texture := context.textures[textureID]
|
||||
if texture.framebuffer == 0 {
|
||||
texture.framebuffer = createFramebuffer(texture.id)
|
||||
func (context *Context) SetOffscreen(renderTargetID graphics.RenderTargetID) {
|
||||
renderTarget :=
|
||||
(*RenderTarget)(context.textures[C.GLuint(renderTargetID)])
|
||||
if renderTarget.framebuffer == 0 {
|
||||
renderTarget.framebuffer = createFramebuffer(renderTarget.id)
|
||||
}
|
||||
context.setOffscreen(texture)
|
||||
context.setOffscreen(renderTarget)
|
||||
}
|
||||
|
||||
func (context *Context) setOffscreen(texture *Texture) {
|
||||
context.currentOffscreen = texture
|
||||
func (context *Context) setOffscreen(renderTarget *RenderTarget) {
|
||||
context.currentOffscreen = renderTarget
|
||||
|
||||
C.glFlush()
|
||||
|
||||
C.glBindFramebuffer(C.GL_FRAMEBUFFER, texture.framebuffer)
|
||||
if err := C.glCheckFramebufferStatus(C.GL_FRAMEBUFFER); err != C.GL_FRAMEBUFFER_COMPLETE {
|
||||
C.glBindFramebuffer(C.GL_FRAMEBUFFER, renderTarget.framebuffer)
|
||||
err := C.glCheckFramebufferStatus(C.GL_FRAMEBUFFER)
|
||||
if err != C.GL_FRAMEBUFFER_COMPLETE {
|
||||
panic(fmt.Sprintf("glBindFramebuffer failed: %d", err))
|
||||
}
|
||||
|
||||
@ -185,8 +190,8 @@ func (context *Context) setOffscreen(texture *Texture) {
|
||||
C.glBlendFuncSeparate(C.GL_SRC_ALPHA, C.GL_ONE_MINUS_SRC_ALPHA,
|
||||
C.GL_ZERO, C.GL_ONE)
|
||||
|
||||
C.glViewport(0, 0, C.GLsizei(abs(texture.textureWidth)),
|
||||
C.GLsizei(abs(texture.textureHeight)))
|
||||
C.glViewport(0, 0, C.GLsizei(abs(renderTarget.textureWidth)),
|
||||
C.GLsizei(abs(renderTarget.textureHeight)))
|
||||
}
|
||||
|
||||
func (context *Context) resetOffscreen() {
|
||||
@ -294,31 +299,32 @@ func createFramebuffer(textureID C.GLuint) C.GLuint {
|
||||
C.glFramebufferTexture2D(C.GL_FRAMEBUFFER, C.GL_COLOR_ATTACHMENT0,
|
||||
C.GL_TEXTURE_2D, textureID, 0)
|
||||
C.glBindFramebuffer(C.GL_FRAMEBUFFER, C.GLuint(origFramebuffer))
|
||||
if C.glCheckFramebufferStatus(C.GL_FRAMEBUFFER) != C.GL_FRAMEBUFFER_COMPLETE {
|
||||
if C.glCheckFramebufferStatus(C.GL_FRAMEBUFFER) !=
|
||||
C.GL_FRAMEBUFFER_COMPLETE {
|
||||
panic("creating framebuffer failed")
|
||||
}
|
||||
|
||||
return framebuffer
|
||||
}
|
||||
|
||||
func (context *Context) NewTexture(width, height int) graphics.Texture {
|
||||
texture := newTexture(width, height)
|
||||
id := graphics.TextureID(texture.id)
|
||||
context.textures[id] = texture
|
||||
func (context *Context) NewRenderTarget(width, height int) (
|
||||
graphics.RenderTarget) {
|
||||
renderTarget := newRenderTarget(width, height)
|
||||
context.textures[renderTarget.id] = (*Texture)(renderTarget)
|
||||
|
||||
context.SetOffscreen(texture.ID())
|
||||
context.SetOffscreen(renderTarget.ID())
|
||||
context.Clear()
|
||||
context.resetOffscreen()
|
||||
|
||||
return texture
|
||||
return renderTarget
|
||||
}
|
||||
|
||||
func (context *Context) NewTextureFromImage(img image.Image) (graphics.Texture, error) {
|
||||
func (context *Context) NewTextureFromImage(img image.Image) (
|
||||
graphics.Texture, error) {
|
||||
texture, err := newTextureFromImage(img)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
id := graphics.TextureID(texture.id)
|
||||
context.textures[id] = texture
|
||||
context.textures[texture.id] = texture
|
||||
return texture, nil
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ func (device *Device) Update(draw func(graphics.Context)) {
|
||||
{0, scale, 0},
|
||||
},
|
||||
}
|
||||
context.DrawTexture(context.Screen().ID(),
|
||||
context.DrawTexture(context.Screen().Texture().ID(),
|
||||
geometryMatrix, matrix.IdentityColor())
|
||||
context.flush()
|
||||
}
|
||||
|
@ -64,7 +64,6 @@ type Texture struct {
|
||||
textureWidth int
|
||||
textureHeight int
|
||||
framebuffer C.GLuint
|
||||
isVirtual bool
|
||||
}
|
||||
|
||||
func (texture *Texture) ID() graphics.TextureID {
|
||||
@ -91,7 +90,6 @@ func createTexture(width, height int, pixels []uint8) *Texture {
|
||||
height: height,
|
||||
textureWidth: textureWidth,
|
||||
textureHeight: textureHeight,
|
||||
isVirtual: false,
|
||||
}
|
||||
|
||||
textureID := C.GLuint(0)
|
||||
@ -125,8 +123,9 @@ func (err textureError) Error() string {
|
||||
return "Texture Error: " + string(err)
|
||||
}
|
||||
|
||||
func newTexture(width, height int) *Texture {
|
||||
return createTexture(width, height, nil)
|
||||
func newRenderTarget(width, height int) *RenderTarget {
|
||||
renderTarget := createTexture(width, height, nil)
|
||||
return (*RenderTarget)(renderTarget)
|
||||
}
|
||||
|
||||
func newTextureFromImage(img image.Image) (*Texture, error) {
|
||||
@ -143,13 +142,33 @@ func newTextureFromImage(img image.Image) (*Texture, error) {
|
||||
return createTexture(size.X, size.Y, pix), nil
|
||||
}
|
||||
|
||||
func newVirtualTexture(width, height int) *Texture {
|
||||
return &Texture{
|
||||
func newRenderTargetWithFramebuffer(width, height int,
|
||||
framebuffer C.GLuint) *RenderTarget {
|
||||
texture := &Texture{
|
||||
id: 0,
|
||||
width: width,
|
||||
height: height,
|
||||
textureWidth: int(clp2(uint64(width))),
|
||||
textureHeight: int(clp2(uint64(height))),
|
||||
isVirtual: true,
|
||||
framebuffer: framebuffer,
|
||||
}
|
||||
return (*RenderTarget)(texture)
|
||||
}
|
||||
|
||||
type RenderTarget Texture
|
||||
|
||||
func (renderTarget *RenderTarget) Texture() graphics.Texture {
|
||||
return (*Texture)(renderTarget)
|
||||
}
|
||||
|
||||
func (renderTarget *RenderTarget) ID() graphics.RenderTargetID {
|
||||
return graphics.RenderTargetID(renderTarget.id)
|
||||
}
|
||||
|
||||
func (renderTarget *RenderTarget) Width() int {
|
||||
return renderTarget.width
|
||||
}
|
||||
|
||||
func (renderTarget *RenderTarget) Height() int {
|
||||
return renderTarget.height
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user