Add graphics.RenderTarget

This commit is contained in:
Hajime Hoshi 2013-10-12 01:29:19 +09:00
parent e6680eeda9
commit 86eb30c650
5 changed files with 90 additions and 55 deletions

View File

@ -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())
}

View File

@ -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

View File

@ -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
}

View File

@ -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()
}

View File

@ -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
}