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
currentOffscreen *RenderTarget
mainFramebufferTexture *RenderTarget
projectionMatrix [16]float32
}
func newContext(screenWidth, screenHeight, screenScale int) *Context {
@ -96,11 +97,11 @@ func (context *Context) DrawTextureParts(
texture, ok := context.textures[textureId]
if !ok {
panic("invalid texture Id")
panic("invalid texture ID")
}
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")
textureAttrLocation := getAttributeLocation(shaderProgram, "texture")
@ -123,10 +124,10 @@ func (context *Context) DrawTextureParts(
}
src := part.Source
tu1 := float32(src.X) / float32(texture.textureWidth)
tu2 := float32(src.X+src.Width) / float32(texture.textureWidth)
tv1 := float32(src.Y) / float32(texture.textureHeight)
tv2 := float32(src.Y+src.Height) / float32(texture.textureHeight)
tu1 := float32(texture.U(src.X))
tu2 := float32(texture.U(src.X + src.Width))
tv1 := float32(texture.V(src.Y))
tv2 := float32(texture.V(src.Y + src.Height))
texCoord := [...]float32{
tu1, 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.GL_ZERO, C.GL_ONE)
C.glViewport(0, 0, C.GLsizei(renderTarget.texture.textureWidth),
C.GLsizei(renderTarget.texture.textureHeight))
context.currentOffscreen.SetAsViewport(context)
}
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() {
@ -183,27 +217,6 @@ func (context *Context) flush() {
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(
geometryMatrix matrix.Geometry, colorMatrix matrix.Color) (program C.GLuint) {
if colorMatrix.IsIdentity() {
@ -214,10 +227,9 @@ func (context *Context) setShaderProgram(
// TODO: cache and skip?
C.glUseProgram(program)
projectionMatrix := context.projectionMatrix()
C.glUniformMatrix4fv(getUniformLocation(program, "projection_matrix"),
1, C.GL_FALSE,
(*C.GLfloat)(&projectionMatrix[0]))
(*C.GLfloat)(&context.projectionMatrix[0]))
a := float32(geometryMatrix.Elements[0][0])
b := float32(geometryMatrix.Elements[0][1])
@ -280,6 +292,7 @@ func (context *Context) NewRenderTarget(width, height int) (
context.setOffscreen(renderTarget)
context.Clear()
// TODO: Is it OK to revert he main framebuffer?
context.setMainFramebufferOffscreen()
return renderTargetId, nil

View File

@ -22,11 +22,29 @@ func nextPowerOf2(x uint64) uint64 {
}
type Texture struct {
native C.GLuint
native interface{}
width 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 {
@ -34,6 +52,14 @@ type RenderTarget struct {
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 {
nativeTexture := C.GLuint(0)
@ -56,20 +82,17 @@ func createNativeTexture(textureWidth, textureHeight int, pixels unsafe.Pointer)
}
func createTexture(width, height int) *Texture {
textureWidth := int(nextPowerOf2(uint64(width)))
textureHeight := int(nextPowerOf2(uint64(height)))
return &Texture{
texture := &Texture{
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) {
texture := createTexture(width, height)
framebuffer := createFramebuffer(texture.native)
framebuffer := createFramebuffer(texture.Native().(C.GLuint))
return &RenderTarget{
texture: texture,
framebuffer: framebuffer,
@ -80,12 +103,14 @@ func newTextureFromImage(img image.Image) (*Texture, error) {
size := img.Bounds().Size()
width, height := size.X, size.Y
textureWidth := int(nextPowerOf2(uint64(width)))
textureHeight := int(nextPowerOf2(uint64(height)))
texture := &Texture{
width: width,
height: height,
}
adjustedImageBound := image.Rectangle{
image.ZP,
image.Point{textureWidth, textureHeight},
image.Point{texture.textureWidth(), texture.textureHeight()},
}
adjustedImage := image.NewNRGBA(adjustedImageBound)
dstBound := image.Rectangle{
@ -94,15 +119,9 @@ func newTextureFromImage(img image.Image) (*Texture, error) {
}
draw.Draw(adjustedImage, dstBound, img, image.ZP, draw.Src)
pixelsPtr := unsafe.Pointer(&adjustedImage.Pix[0])
nativeTexture := createNativeTexture(textureWidth, textureHeight, pixelsPtr)
return &Texture{
width: width,
height: height,
textureWidth: textureWidth,
textureHeight: textureHeight,
native: nativeTexture,
}, nil
texture.native = createNativeTexture(
texture.textureWidth(), texture.textureHeight(), pixelsPtr)
return texture, nil
}
func newRenderTargetWithFramebuffer(width, height int,
@ -110,8 +129,6 @@ func newRenderTargetWithFramebuffer(width, height int,
texture := &Texture{
width: width,
height: height,
textureWidth: int(nextPowerOf2(uint64(width))),
textureHeight: int(nextPowerOf2(uint64(height))),
}
return &RenderTarget{
texture: texture,