Add Texture.native

This commit is contained in:
Hajime Hoshi 2013-10-19 18:47:34 +09:00
parent 78755c9b09
commit ec83c0ad5f
3 changed files with 88 additions and 55 deletions

View File

@ -15,21 +15,23 @@ 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[C.GLuint]*Texture textures map[graphics.TextureID]*Texture
currentOffscreen *Texture renderTargets map[graphics.RenderTargetID]*RenderTarget
mainFramebufferTexture *Texture currentOffscreen *RenderTarget
mainFramebufferTexture *RenderTarget
} }
func newContext(screenWidth, screenHeight, screenScale int) *Context { func newContext(screenWidth, screenHeight, screenScale int) *Context {
context := &Context{ context := &Context{
screenWidth: screenWidth, screenWidth: screenWidth,
screenHeight: screenHeight, screenHeight: screenHeight,
screenScale: screenScale, screenScale: screenScale,
textures: map[C.GLuint]*Texture{}, textures: map[graphics.TextureID]*Texture{},
renderTargets: map[graphics.RenderTargetID]*RenderTarget{},
} }
return context return context
} }
@ -49,11 +51,12 @@ func (context *Context) Init() {
screenID := context.NewRenderTarget( screenID := context.NewRenderTarget(
context.screenWidth, context.screenHeight) context.screenWidth, context.screenHeight)
context.screen = context.textures[C.GLuint(screenID)] context.screen = context.renderTargets[screenID]
} }
func (context *Context) ToTexture(renderTargetID graphics.RenderTargetID) graphics.TextureID { func (context *Context) ToTexture(renderTargetID graphics.RenderTargetID) graphics.TextureID {
return graphics.TextureID(renderTargetID) renderTarget := context.renderTargets[renderTargetID]
return renderTarget.texture.ID()
} }
func (context *Context) Clear() { func (context *Context) Clear() {
@ -73,8 +76,10 @@ func (context *Context) Fill(r, g, b uint8) {
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[C.GLuint(textureID)] texture, ok := context.textures[textureID]
if !ok {
panic("invalid texture ID")
}
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}}
context.DrawTextureParts(textureID, locations, context.DrawTextureParts(textureID, locations,
@ -84,13 +89,14 @@ 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[C.GLuint(textureID)]
if texture == nil { texture, ok := context.textures[textureID]
if !ok {
panic("invalid texture ID") panic("invalid texture ID")
} }
shaderProgram := context.setShaderProgram(geometryMatrix, colorMatrix) shaderProgram := context.setShaderProgram(geometryMatrix, colorMatrix)
C.glBindTexture(C.GL_TEXTURE_2D, texture.id) C.glBindTexture(C.GL_TEXTURE_2D, texture.native)
vertexAttrLocation := getAttributeLocation(shaderProgram, "vertex") vertexAttrLocation := getAttributeLocation(shaderProgram, "vertex")
textureAttrLocation := getAttributeLocation(shaderProgram, "texture") textureAttrLocation := getAttributeLocation(shaderProgram, "texture")
@ -142,11 +148,11 @@ func (context *Context) ResetOffscreen() {
} }
func (context *Context) SetOffscreen(renderTargetID graphics.RenderTargetID) { func (context *Context) SetOffscreen(renderTargetID graphics.RenderTargetID) {
renderTarget := context.textures[C.GLuint(renderTargetID)] renderTarget := context.renderTargets[renderTargetID]
context.setOffscreen(renderTarget) context.setOffscreen(renderTarget)
} }
func (context *Context) setOffscreen(renderTarget *Texture) { func (context *Context) setOffscreen(renderTarget *RenderTarget) {
context.currentOffscreen = renderTarget context.currentOffscreen = renderTarget
C.glFlush() C.glFlush()
@ -161,8 +167,8 @@ func (context *Context) setOffscreen(renderTarget *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(renderTarget.textureWidth), C.glViewport(0, 0, C.GLsizei(renderTarget.texture.textureWidth),
C.GLsizei(renderTarget.textureHeight)) C.GLsizei(renderTarget.texture.textureHeight))
} }
func (context *Context) setMainFramebufferOffscreen() { func (context *Context) setMainFramebufferOffscreen() {
@ -174,16 +180,16 @@ func (context *Context) flush() {
} }
func (context *Context) projectionMatrix() [16]float32 { func (context *Context) projectionMatrix() [16]float32 {
texture := context.currentOffscreen texture := context.currentOffscreen.texture
e11 := float32(2) / float32(texture.textureWidth) e11 := float32(2) / float32(texture.textureWidth)
e22 := float32(2) / float32(texture.textureHeight) e22 := float32(2) / float32(texture.textureHeight)
e41 := float32(-1) e41 := float32(-1)
e42 := float32(-1) e42 := float32(-1)
if texture == context.mainFramebufferTexture { if context.currentOffscreen.ID() == context.mainFramebufferTexture.ID() {
e22 *= -1 e22 *= -1
e42 += float32(texture.height)/float32(texture.textureHeight)*2 e42 += float32(texture.height) / float32(texture.textureHeight) * 2
} }
return [...]float32{ return [...]float32{
@ -258,13 +264,14 @@ func (context *Context) setShaderProgram(
func (context *Context) NewRenderTarget(width, height int) graphics.RenderTargetID { func (context *Context) NewRenderTarget(width, height int) graphics.RenderTargetID {
renderTarget := newRenderTarget(width, height) renderTarget := newRenderTarget(width, height)
context.textures[renderTarget.id] = (*Texture)(renderTarget) context.renderTargets[renderTarget.ID()] = renderTarget
context.textures[renderTarget.texture.ID()] = renderTarget.texture
context.setOffscreen((*Texture)(renderTarget)) context.setOffscreen(renderTarget)
context.Clear() context.Clear()
context.setMainFramebufferOffscreen() context.setMainFramebufferOffscreen()
return graphics.RenderTargetID(renderTarget.id) return renderTarget.ID()
} }
func (context *Context) NewTextureFromImage(img image.Image) ( func (context *Context) NewTextureFromImage(img image.Image) (
@ -273,6 +280,6 @@ func (context *Context) NewTextureFromImage(img image.Image) (
if err != nil { if err != nil {
return 0, err return 0, err
} }
context.textures[texture.id] = texture context.textures[texture.ID()] = texture
return texture.ID(), nil return texture.ID(), nil
} }

View File

@ -53,7 +53,7 @@ func (device *Device) Update(draw func(graphics.Context)) {
{0, scale, 0}, {0, scale, 0},
}, },
} }
context.DrawTexture(graphics.TextureID(context.screen.id), context.DrawTexture(context.ToTexture(context.screen.ID()),
geometryMatrix, matrix.IdentityColor()) geometryMatrix, matrix.IdentityColor())
context.flush() context.flush()
} }

View File

@ -38,24 +38,22 @@ func adjustPixels(width, height int, pixels []uint8) []uint8 {
} }
type Texture struct { type Texture struct {
id C.GLuint id graphics.TextureID
native C.GLuint
width int width int
height int height int
textureWidth int textureWidth int
textureHeight int textureHeight int
framebuffer C.GLuint }
type RenderTarget struct {
id graphics.RenderTargetID
texture *Texture
framebuffer C.GLuint
} }
func (texture *Texture) ID() graphics.TextureID { func (texture *Texture) ID() graphics.TextureID {
return graphics.TextureID(texture.id) return texture.id
}
func (texture *Texture) Width() int {
return texture.width
}
func (texture *Texture) Height() int {
return texture.height
} }
func createTexture(width, height int, pixels []uint8) *Texture { func createTexture(width, height int, pixels []uint8) *Texture {
@ -72,13 +70,13 @@ func createTexture(width, height int, pixels []uint8) *Texture {
textureHeight: textureHeight, textureHeight: textureHeight,
} }
textureID := C.GLuint(0) nativeTexture := C.GLuint(0)
C.glGenTextures(1, (*C.GLuint)(&textureID)) C.glGenTextures(1, (*C.GLuint)(&nativeTexture))
if textureID < 0 { if nativeTexture < 0 {
panic("glGenTexture failed") panic("glGenTexture failed")
} }
C.glPixelStorei(C.GL_UNPACK_ALIGNMENT, 4) C.glPixelStorei(C.GL_UNPACK_ALIGNMENT, 4)
C.glBindTexture(C.GL_TEXTURE_2D, C.GLuint(textureID)) C.glBindTexture(C.GL_TEXTURE_2D, C.GLuint(nativeTexture))
ptr := unsafe.Pointer(nil) ptr := unsafe.Pointer(nil)
if pixels != nil { if pixels != nil {
@ -92,23 +90,37 @@ func createTexture(width, height int, pixels []uint8) *Texture {
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MIN_FILTER, C.GL_LINEAR) C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MIN_FILTER, C.GL_LINEAR)
C.glBindTexture(C.GL_TEXTURE_2D, 0) C.glBindTexture(C.GL_TEXTURE_2D, 0)
texture.id = textureID texture.native = nativeTexture
texture.id = graphics.TextureID(<-newID)
return texture return texture
} }
func newRenderTarget(width, height int) *RenderTarget {
texture := createTexture(width, height, nil)
framebuffer := createFramebuffer(texture.native)
return &RenderTarget{
id: graphics.RenderTargetID(<-newID),
texture: texture,
framebuffer: framebuffer,
}
}
func (renderTarget *RenderTarget) ID() graphics.RenderTargetID {
return renderTarget.id
}
func (renderTarget *RenderTarget) Texture() *Texture {
return renderTarget.texture
}
type textureError string type textureError string
func (err textureError) Error() string { func (err textureError) Error() string {
return "Texture Error: " + string(err) return "Texture Error: " + string(err)
} }
func newRenderTarget(width, height int) *Texture {
texture := createTexture(width, height, nil)
texture.framebuffer = createFramebuffer(texture.id)
return texture
}
func newTextureFromImage(img image.Image) (*Texture, error) { func newTextureFromImage(img image.Image) (*Texture, error) {
var pix []uint8 var pix []uint8
switch img.(type) { switch img.(type) {
@ -124,18 +136,21 @@ func newTextureFromImage(img image.Image) (*Texture, error) {
} }
func newRenderTargetWithFramebuffer(width, height int, func newRenderTargetWithFramebuffer(width, height int,
framebuffer C.GLuint) *Texture { framebuffer C.GLuint) *RenderTarget {
return &Texture{ texture := &Texture{
id: 0, id: graphics.TextureID(<-newID),
width: width, width: width,
height: height, height: height,
textureWidth: int(nextPowerOf2(uint64(width))), textureWidth: int(nextPowerOf2(uint64(width))),
textureHeight: int(nextPowerOf2(uint64(height))), textureHeight: int(nextPowerOf2(uint64(height))),
framebuffer: framebuffer, }
return &RenderTarget{
texture: texture,
framebuffer: framebuffer,
} }
} }
func createFramebuffer(textureID C.GLuint) C.GLuint { func createFramebuffer(nativeTexture C.GLuint) C.GLuint {
framebuffer := C.GLuint(0) framebuffer := C.GLuint(0)
C.glGenFramebuffers(1, &framebuffer) C.glGenFramebuffers(1, &framebuffer)
@ -143,7 +158,7 @@ func createFramebuffer(textureID C.GLuint) C.GLuint {
C.glGetIntegerv(C.GL_FRAMEBUFFER_BINDING, &origFramebuffer) C.glGetIntegerv(C.GL_FRAMEBUFFER_BINDING, &origFramebuffer)
C.glBindFramebuffer(C.GL_FRAMEBUFFER, framebuffer) C.glBindFramebuffer(C.GL_FRAMEBUFFER, framebuffer)
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, nativeTexture, 0)
C.glBindFramebuffer(C.GL_FRAMEBUFFER, C.GLuint(origFramebuffer)) C.glBindFramebuffer(C.GL_FRAMEBUFFER, C.GLuint(origFramebuffer))
if C.glCheckFramebufferStatus(C.GL_FRAMEBUFFER) != if C.glCheckFramebufferStatus(C.GL_FRAMEBUFFER) !=
C.GL_FRAMEBUFFER_COMPLETE { C.GL_FRAMEBUFFER_COMPLETE {
@ -152,3 +167,14 @@ func createFramebuffer(textureID C.GLuint) C.GLuint {
return framebuffer return framebuffer
} }
var newID chan int
func init() {
newID = make(chan int)
go func() {
for i := 0; ; i++ {
newID <- i
}
}()
}