Refactoring

This commit is contained in:
Hajime Hoshi 2013-10-23 01:08:01 +09:00
parent a0f17a4971
commit 9aded38cc2
3 changed files with 92 additions and 62 deletions

View File

@ -24,6 +24,7 @@ type Context struct {
renderTargetToTexture map[graphics.RenderTargetId]graphics.TextureId renderTargetToTexture map[graphics.RenderTargetId]graphics.TextureId
currentOffscreen *RenderTarget currentOffscreen *RenderTarget
mainFramebufferTexture *RenderTarget mainFramebufferTexture *RenderTarget
projectionMatrix [16]float32
} }
func newContext(screenWidth, screenHeight, screenScale int) *Context { func newContext(screenWidth, screenHeight, screenScale int) *Context {
@ -96,11 +97,11 @@ func (context *Context) DrawTextureParts(
texture, ok := context.textures[textureId] texture, ok := context.textures[textureId]
if !ok { 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.native) C.glBindTexture(C.GL_TEXTURE_2D, texture.Native().(C.GLuint))
vertexAttrLocation := getAttributeLocation(shaderProgram, "vertex") vertexAttrLocation := getAttributeLocation(shaderProgram, "vertex")
textureAttrLocation := getAttributeLocation(shaderProgram, "texture") textureAttrLocation := getAttributeLocation(shaderProgram, "texture")
@ -123,10 +124,10 @@ func (context *Context) DrawTextureParts(
} }
src := part.Source src := part.Source
tu1 := float32(src.X) / float32(texture.textureWidth) tu1 := float32(texture.U(src.X))
tu2 := float32(src.X+src.Width) / float32(texture.textureWidth) tu2 := float32(texture.U(src.X + src.Width))
tv1 := float32(src.Y) / float32(texture.textureHeight) tv1 := float32(texture.V(src.Y))
tv2 := float32(src.Y+src.Height) / float32(texture.textureHeight) tv2 := float32(texture.V(src.Y + src.Height))
texCoord := [...]float32{ texCoord := [...]float32{
tu1, tv1, tu1, tv1,
tu2, tv1, tu2, tv1,
@ -171,8 +172,41 @@ func (context *Context) setOffscreen(renderTarget *RenderTarget) {
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.texture.textureWidth), context.currentOffscreen.SetAsViewport(context)
C.GLsizei(renderTarget.texture.textureHeight)) }
func orthoProjectionMatrix(left, right, bottom, top int) [4][4]float64 {
e11 := float64(2) / float64(right-left)
e22 := float64(2) / float64(top-bottom)
e14 := -1 * float64(right+left) / float64(right-left)
e24 := -1 * float64(top+bottom) / float64(top-bottom)
return [4][4]float64{
{e11, 0, 0, e14},
{0, e22, 0, e24},
{0, 0, 1, 0},
{0, 0, 0, 1},
}
}
func (context *Context) SetViewport(x, y, width, height int) {
C.glViewport(C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height))
matrix := orthoProjectionMatrix(x, width, y, height)
if context.currentOffscreen == context.mainFramebufferTexture {
// Flip Y and translate
matrix[1][1] *= -1
actualHeight := context.screenHeight * context.screenScale
matrix[1][3] += float64(actualHeight) / float64(height) * 2
}
for j := 0; j < 4; j++ {
for i := 0; i < 4; i++ {
context.projectionMatrix[i+j*4] = float32(matrix[i][j])
}
}
// TODO: call 'setShaderProgram' here?
} }
func (context *Context) setMainFramebufferOffscreen() { func (context *Context) setMainFramebufferOffscreen() {
@ -183,27 +217,6 @@ func (context *Context) flush() {
C.glFlush() C.glFlush()
} }
func (context *Context) projectionMatrix() [16]float32 {
texture := context.currentOffscreen.texture
e11 := float32(2) / float32(texture.textureWidth)
e22 := float32(2) / float32(texture.textureHeight)
e41 := float32(-1)
e42 := float32(-1)
if context.currentOffscreen == context.mainFramebufferTexture {
e22 *= -1
e42 += float32(texture.height) / float32(texture.textureHeight) * 2
}
return [...]float32{
e11, 0, 0, 0,
0, e22, 0, 0,
0, 0, 1, 0,
e41, e42, 0, 1,
}
}
func (context *Context) setShaderProgram( func (context *Context) setShaderProgram(
geometryMatrix matrix.Geometry, colorMatrix matrix.Color) (program C.GLuint) { geometryMatrix matrix.Geometry, colorMatrix matrix.Color) (program C.GLuint) {
if colorMatrix.IsIdentity() { if colorMatrix.IsIdentity() {
@ -214,10 +227,9 @@ func (context *Context) setShaderProgram(
// TODO: cache and skip? // TODO: cache and skip?
C.glUseProgram(program) C.glUseProgram(program)
projectionMatrix := context.projectionMatrix()
C.glUniformMatrix4fv(getUniformLocation(program, "projection_matrix"), C.glUniformMatrix4fv(getUniformLocation(program, "projection_matrix"),
1, C.GL_FALSE, 1, C.GL_FALSE,
(*C.GLfloat)(&projectionMatrix[0])) (*C.GLfloat)(&context.projectionMatrix[0]))
a := float32(geometryMatrix.Elements[0][0]) a := float32(geometryMatrix.Elements[0][0])
b := float32(geometryMatrix.Elements[0][1]) b := float32(geometryMatrix.Elements[0][1])
@ -280,6 +292,7 @@ func (context *Context) NewRenderTarget(width, height int) (
context.setOffscreen(renderTarget) context.setOffscreen(renderTarget)
context.Clear() context.Clear()
// TODO: Is it OK to revert he main framebuffer?
context.setMainFramebufferOffscreen() context.setMainFramebufferOffscreen()
return renderTargetId, nil return renderTargetId, nil

View File

@ -22,11 +22,29 @@ func nextPowerOf2(x uint64) uint64 {
} }
type Texture struct { type Texture struct {
native C.GLuint native interface{}
width int width int
height int height int
textureWidth int }
textureHeight int
func (texture *Texture) Native() interface{} {
return texture.native
}
func (texture *Texture) textureWidth() int {
return int(nextPowerOf2(uint64(texture.width)))
}
func (texture *Texture) textureHeight() int {
return int(nextPowerOf2(uint64(texture.height)))
}
func (texture *Texture) U(x int) float64 {
return float64(x) / float64(texture.textureWidth())
}
func (texture *Texture) V(y int) float64 {
return float64(y) / float64(texture.textureHeight())
} }
type RenderTarget struct { type RenderTarget struct {
@ -34,6 +52,14 @@ type RenderTarget struct {
framebuffer C.GLuint framebuffer C.GLuint
} }
func (renderTarget *RenderTarget) SetAsViewport(setter interface{
SetViewport(x, y, width, height int)
}) {
texture := renderTarget.texture
x, y, width, height := 0, 0, texture.textureWidth(), texture.textureHeight()
setter.SetViewport(x, y, width, height)
}
func createNativeTexture(textureWidth, textureHeight int, pixels unsafe.Pointer) C.GLuint { func createNativeTexture(textureWidth, textureHeight int, pixels unsafe.Pointer) C.GLuint {
nativeTexture := C.GLuint(0) nativeTexture := C.GLuint(0)
@ -56,20 +82,17 @@ func createNativeTexture(textureWidth, textureHeight int, pixels unsafe.Pointer)
} }
func createTexture(width, height int) *Texture { func createTexture(width, height int) *Texture {
textureWidth := int(nextPowerOf2(uint64(width))) texture := &Texture{
textureHeight := int(nextPowerOf2(uint64(height))) width: width,
return &Texture{ height: height,
width: width,
height: height,
textureWidth: textureWidth,
textureHeight: textureHeight,
native: createNativeTexture(textureWidth, textureHeight, nil),
} }
texture.native = createNativeTexture(texture.textureWidth(), texture.textureHeight(), nil)
return texture
} }
func newRenderTarget(width, height int) (*RenderTarget, error) { func newRenderTarget(width, height int) (*RenderTarget, error) {
texture := createTexture(width, height) texture := createTexture(width, height)
framebuffer := createFramebuffer(texture.native) framebuffer := createFramebuffer(texture.Native().(C.GLuint))
return &RenderTarget{ return &RenderTarget{
texture: texture, texture: texture,
framebuffer: framebuffer, framebuffer: framebuffer,
@ -80,12 +103,14 @@ func newTextureFromImage(img image.Image) (*Texture, error) {
size := img.Bounds().Size() size := img.Bounds().Size()
width, height := size.X, size.Y width, height := size.X, size.Y
textureWidth := int(nextPowerOf2(uint64(width))) texture := &Texture{
textureHeight := int(nextPowerOf2(uint64(height))) width: width,
height: height,
}
adjustedImageBound := image.Rectangle{ adjustedImageBound := image.Rectangle{
image.ZP, image.ZP,
image.Point{textureWidth, textureHeight}, image.Point{texture.textureWidth(), texture.textureHeight()},
} }
adjustedImage := image.NewNRGBA(adjustedImageBound) adjustedImage := image.NewNRGBA(adjustedImageBound)
dstBound := image.Rectangle{ dstBound := image.Rectangle{
@ -94,24 +119,16 @@ func newTextureFromImage(img image.Image) (*Texture, error) {
} }
draw.Draw(adjustedImage, dstBound, img, image.ZP, draw.Src) draw.Draw(adjustedImage, dstBound, img, image.ZP, draw.Src)
pixelsPtr := unsafe.Pointer(&adjustedImage.Pix[0]) pixelsPtr := unsafe.Pointer(&adjustedImage.Pix[0])
nativeTexture := createNativeTexture(textureWidth, textureHeight, pixelsPtr) texture.native = createNativeTexture(
texture.textureWidth(), texture.textureHeight(), pixelsPtr)
return &Texture{ return texture, nil
width: width,
height: height,
textureWidth: textureWidth,
textureHeight: textureHeight,
native: nativeTexture,
}, nil
} }
func newRenderTargetWithFramebuffer(width, height int, func newRenderTargetWithFramebuffer(width, height int,
framebuffer C.GLuint) *RenderTarget { framebuffer C.GLuint) *RenderTarget {
texture := &Texture{ texture := &Texture{
width: width, width: width,
height: height, height: height,
textureWidth: int(nextPowerOf2(uint64(width))),
textureHeight: int(nextPowerOf2(uint64(height))),
} }
return &RenderTarget{ return &RenderTarget{
texture: texture, texture: texture,