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 {
|
type Rects struct {
|
||||||
rectTexture graphics.Texture
|
rectTexture graphics.RenderTarget
|
||||||
rectTextureInited bool
|
rectTextureInited bool
|
||||||
offscreen graphics.Texture
|
offscreen graphics.RenderTarget
|
||||||
offscreenInited bool
|
offscreenInited bool
|
||||||
rectBounds *graphics.Rect
|
rectBounds *graphics.Rect
|
||||||
rectColor *color.RGBA
|
rectColor *color.RGBA
|
||||||
@ -49,8 +49,8 @@ func New() *Rects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (game *Rects) Init(tf graphics.TextureFactory) {
|
func (game *Rects) Init(tf graphics.TextureFactory) {
|
||||||
game.rectTexture = tf.NewTexture(16, 16)
|
game.rectTexture = tf.NewRenderTarget(16, 16)
|
||||||
game.offscreen = tf.NewTexture(256, 240)
|
game.offscreen = tf.NewRenderTarget(256, 240)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (game *Rects) Update(context ebiten.GameContext) {
|
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})
|
g.Fill(&color.RGBA{0, 0, 0, 255})
|
||||||
game.offscreenInited = true
|
game.offscreenInited = true
|
||||||
}
|
}
|
||||||
g.DrawTexture(game.rectTexture.ID(),
|
g.DrawTexture(game.rectTexture.Texture().ID(),
|
||||||
game.rectGeometryMatrix(),
|
game.rectGeometryMatrix(),
|
||||||
game.rectColorMatrix())
|
game.rectColorMatrix())
|
||||||
|
|
||||||
g.SetOffscreen(g.Screen().ID())
|
g.SetOffscreen(g.Screen().ID())
|
||||||
g.DrawTexture(game.offscreen.ID(),
|
g.DrawTexture(game.offscreen.Texture().ID(),
|
||||||
matrix.IdentityGeometry(),
|
matrix.IdentityGeometry(),
|
||||||
matrix.IdentityColor())
|
matrix.IdentityColor())
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ type TexturePart struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Context interface {
|
type Context interface {
|
||||||
Screen() Texture
|
Screen() RenderTarget
|
||||||
Clear()
|
Clear()
|
||||||
Fill(clr color.Color)
|
Fill(clr color.Color)
|
||||||
DrawTexture(textureID TextureID,
|
DrawTexture(textureID TextureID,
|
||||||
@ -50,11 +50,11 @@ type Context interface {
|
|||||||
parts []TexturePart,
|
parts []TexturePart,
|
||||||
geometryMatrix matrix.Geometry,
|
geometryMatrix matrix.Geometry,
|
||||||
colorMatrix matrix.Color)
|
colorMatrix matrix.Color)
|
||||||
SetOffscreen(textureID TextureID)
|
SetOffscreen(renderTargetID RenderTargetID)
|
||||||
}
|
}
|
||||||
|
|
||||||
type TextureFactory interface {
|
type TextureFactory interface {
|
||||||
NewTexture(width, height int) Texture
|
NewRenderTarget(width, height int) RenderTarget
|
||||||
NewTextureFromImage(img image.Image) (Texture, error)
|
NewTextureFromImage(img image.Image) (Texture, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,3 +65,13 @@ type Texture interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type TextureID int
|
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 {
|
type Context struct {
|
||||||
screen *Texture
|
screen *RenderTarget
|
||||||
screenWidth int
|
screenWidth int
|
||||||
screenHeight int
|
screenHeight int
|
||||||
screenScale int
|
screenScale int
|
||||||
textures map[graphics.TextureID]*Texture
|
textures map[C.GLuint]*Texture
|
||||||
currentOffscreen *Texture
|
currentOffscreen *RenderTarget
|
||||||
mainFramebufferTexture *Texture
|
mainFramebufferTexture *RenderTarget
|
||||||
}
|
}
|
||||||
|
|
||||||
func newContext(screenWidth, screenHeight, screenScale int) *Context {
|
func newContext(screenWidth, screenHeight, screenScale int) *Context {
|
||||||
@ -50,28 +50,29 @@ func newContext(screenWidth, screenHeight, screenScale int) *Context {
|
|||||||
screenWidth: screenWidth,
|
screenWidth: screenWidth,
|
||||||
screenHeight: screenHeight,
|
screenHeight: screenHeight,
|
||||||
screenScale: screenScale,
|
screenScale: screenScale,
|
||||||
textures: map[graphics.TextureID]*Texture{},
|
textures: map[C.GLuint]*Texture{},
|
||||||
}
|
}
|
||||||
return context
|
return context
|
||||||
}
|
}
|
||||||
|
|
||||||
func (context *Context) Init() {
|
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)
|
mainFramebuffer := C.GLint(0)
|
||||||
C.glGetIntegerv(C.GL_FRAMEBUFFER_BINDING, &mainFramebuffer)
|
C.glGetIntegerv(C.GL_FRAMEBUFFER_BINDING, &mainFramebuffer)
|
||||||
|
|
||||||
context.mainFramebufferTexture = newVirtualTexture(
|
context.mainFramebufferTexture = newRenderTargetWithFramebuffer(
|
||||||
context.screenWidth*context.screenScale,
|
context.screenWidth*context.screenScale,
|
||||||
context.screenHeight*context.screenScale)
|
context.screenHeight*context.screenScale,
|
||||||
context.mainFramebufferTexture.framebuffer = C.GLuint(mainFramebuffer)
|
C.GLuint(mainFramebuffer))
|
||||||
|
|
||||||
initializeShaders()
|
initializeShaders()
|
||||||
|
|
||||||
context.screen =
|
context.screen = context.NewRenderTarget(
|
||||||
context.NewTexture(context.screenWidth, context.screenHeight).(*Texture)
|
context.screenWidth, context.screenHeight).(*RenderTarget)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (context *Context) Screen() graphics.Texture {
|
func (context *Context) Screen() graphics.RenderTarget {
|
||||||
return context.screen
|
return context.screen
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +83,7 @@ func (context *Context) Clear() {
|
|||||||
|
|
||||||
func (context *Context) Fill(clr color.Color) {
|
func (context *Context) Fill(clr color.Color) {
|
||||||
r, g, b, a := clr.RGBA()
|
r, g, b, a := clr.RGBA()
|
||||||
max := float64(math.MaxUint16)
|
const max = float64(math.MaxUint16)
|
||||||
C.glClearColor(
|
C.glClearColor(
|
||||||
C.GLclampf(float64(r)/max),
|
C.GLclampf(float64(r)/max),
|
||||||
C.GLclampf(float64(g)/max),
|
C.GLclampf(float64(g)/max),
|
||||||
@ -94,7 +95,7 @@ func (context *Context) Fill(clr color.Color) {
|
|||||||
func (context *Context) DrawTexture(
|
func (context *Context) DrawTexture(
|
||||||
textureID graphics.TextureID,
|
textureID graphics.TextureID,
|
||||||
geometryMatrix matrix.Geometry, colorMatrix matrix.Color) {
|
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}
|
source := graphics.Rect{0, 0, texture.width, texture.height}
|
||||||
locations := []graphics.TexturePart{{0, 0, source}}
|
locations := []graphics.TexturePart{{0, 0, source}}
|
||||||
@ -105,7 +106,7 @@ func (context *Context) DrawTexture(
|
|||||||
func (context *Context) DrawTextureParts(
|
func (context *Context) DrawTextureParts(
|
||||||
textureID graphics.TextureID, parts []graphics.TexturePart,
|
textureID graphics.TextureID, parts []graphics.TexturePart,
|
||||||
geometryMatrix matrix.Geometry, colorMatrix matrix.Color) {
|
geometryMatrix matrix.Geometry, colorMatrix matrix.Color) {
|
||||||
texture := context.textures[textureID]
|
texture := context.textures[C.GLuint(textureID)]
|
||||||
if texture == nil {
|
if texture == nil {
|
||||||
panic("invalid texture ID")
|
panic("invalid texture ID")
|
||||||
}
|
}
|
||||||
@ -144,9 +145,11 @@ func (context *Context) DrawTextureParts(
|
|||||||
tu1, tv2,
|
tu1, tv2,
|
||||||
tu2, 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]))
|
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]))
|
0, unsafe.Pointer(&texCoord[0]))
|
||||||
C.glDrawArrays(C.GL_TRIANGLE_STRIP, 0, 4)
|
C.glDrawArrays(C.GL_TRIANGLE_STRIP, 0, 4)
|
||||||
}
|
}
|
||||||
@ -163,21 +166,23 @@ func abs(x int) int {
|
|||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
|
||||||
func (context *Context) SetOffscreen(textureID graphics.TextureID) {
|
func (context *Context) SetOffscreen(renderTargetID graphics.RenderTargetID) {
|
||||||
texture := context.textures[textureID]
|
renderTarget :=
|
||||||
if texture.framebuffer == 0 {
|
(*RenderTarget)(context.textures[C.GLuint(renderTargetID)])
|
||||||
texture.framebuffer = createFramebuffer(texture.id)
|
if renderTarget.framebuffer == 0 {
|
||||||
|
renderTarget.framebuffer = createFramebuffer(renderTarget.id)
|
||||||
}
|
}
|
||||||
context.setOffscreen(texture)
|
context.setOffscreen(renderTarget)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (context *Context) setOffscreen(texture *Texture) {
|
func (context *Context) setOffscreen(renderTarget *RenderTarget) {
|
||||||
context.currentOffscreen = texture
|
context.currentOffscreen = renderTarget
|
||||||
|
|
||||||
C.glFlush()
|
C.glFlush()
|
||||||
|
|
||||||
C.glBindFramebuffer(C.GL_FRAMEBUFFER, texture.framebuffer)
|
C.glBindFramebuffer(C.GL_FRAMEBUFFER, renderTarget.framebuffer)
|
||||||
if err := C.glCheckFramebufferStatus(C.GL_FRAMEBUFFER); err != C.GL_FRAMEBUFFER_COMPLETE {
|
err := C.glCheckFramebufferStatus(C.GL_FRAMEBUFFER)
|
||||||
|
if err != C.GL_FRAMEBUFFER_COMPLETE {
|
||||||
panic(fmt.Sprintf("glBindFramebuffer failed: %d", err))
|
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.glBlendFuncSeparate(C.GL_SRC_ALPHA, C.GL_ONE_MINUS_SRC_ALPHA,
|
||||||
C.GL_ZERO, C.GL_ONE)
|
C.GL_ZERO, C.GL_ONE)
|
||||||
|
|
||||||
C.glViewport(0, 0, C.GLsizei(abs(texture.textureWidth)),
|
C.glViewport(0, 0, C.GLsizei(abs(renderTarget.textureWidth)),
|
||||||
C.GLsizei(abs(texture.textureHeight)))
|
C.GLsizei(abs(renderTarget.textureHeight)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (context *Context) resetOffscreen() {
|
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.glFramebufferTexture2D(C.GL_FRAMEBUFFER, C.GL_COLOR_ATTACHMENT0,
|
||||||
C.GL_TEXTURE_2D, textureID, 0)
|
C.GL_TEXTURE_2D, textureID, 0)
|
||||||
C.glBindFramebuffer(C.GL_FRAMEBUFFER, C.GLuint(origFramebuffer))
|
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")
|
panic("creating framebuffer failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
return framebuffer
|
return framebuffer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (context *Context) NewTexture(width, height int) graphics.Texture {
|
func (context *Context) NewRenderTarget(width, height int) (
|
||||||
texture := newTexture(width, height)
|
graphics.RenderTarget) {
|
||||||
id := graphics.TextureID(texture.id)
|
renderTarget := newRenderTarget(width, height)
|
||||||
context.textures[id] = texture
|
context.textures[renderTarget.id] = (*Texture)(renderTarget)
|
||||||
|
|
||||||
context.SetOffscreen(texture.ID())
|
context.SetOffscreen(renderTarget.ID())
|
||||||
context.Clear()
|
context.Clear()
|
||||||
context.resetOffscreen()
|
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)
|
texture, err := newTextureFromImage(img)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
id := graphics.TextureID(texture.id)
|
context.textures[texture.id] = texture
|
||||||
context.textures[id] = texture
|
|
||||||
return texture, nil
|
return texture, nil
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ func (device *Device) Update(draw func(graphics.Context)) {
|
|||||||
{0, scale, 0},
|
{0, scale, 0},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
context.DrawTexture(context.Screen().ID(),
|
context.DrawTexture(context.Screen().Texture().ID(),
|
||||||
geometryMatrix, matrix.IdentityColor())
|
geometryMatrix, matrix.IdentityColor())
|
||||||
context.flush()
|
context.flush()
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,6 @@ type Texture struct {
|
|||||||
textureWidth int
|
textureWidth int
|
||||||
textureHeight int
|
textureHeight int
|
||||||
framebuffer C.GLuint
|
framebuffer C.GLuint
|
||||||
isVirtual bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (texture *Texture) ID() graphics.TextureID {
|
func (texture *Texture) ID() graphics.TextureID {
|
||||||
@ -91,7 +90,6 @@ func createTexture(width, height int, pixels []uint8) *Texture {
|
|||||||
height: height,
|
height: height,
|
||||||
textureWidth: textureWidth,
|
textureWidth: textureWidth,
|
||||||
textureHeight: textureHeight,
|
textureHeight: textureHeight,
|
||||||
isVirtual: false,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
textureID := C.GLuint(0)
|
textureID := C.GLuint(0)
|
||||||
@ -125,8 +123,9 @@ func (err textureError) Error() string {
|
|||||||
return "Texture Error: " + string(err)
|
return "Texture Error: " + string(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTexture(width, height int) *Texture {
|
func newRenderTarget(width, height int) *RenderTarget {
|
||||||
return createTexture(width, height, nil)
|
renderTarget := createTexture(width, height, nil)
|
||||||
|
return (*RenderTarget)(renderTarget)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTextureFromImage(img image.Image) (*Texture, error) {
|
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
|
return createTexture(size.X, size.Y, pix), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newVirtualTexture(width, height int) *Texture {
|
func newRenderTargetWithFramebuffer(width, height int,
|
||||||
return &Texture{
|
framebuffer C.GLuint) *RenderTarget {
|
||||||
|
texture := &Texture{
|
||||||
id: 0,
|
id: 0,
|
||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
textureWidth: int(clp2(uint64(width))),
|
textureWidth: int(clp2(uint64(width))),
|
||||||
textureHeight: int(clp2(uint64(height))),
|
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