From a28443b2d9fb8caa21c002e720345d91978c3edb Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Sat, 26 Oct 2013 21:29:48 +0900 Subject: [PATCH] Move drawing function to shader package --- graphics/opengl/context.go | 75 ++----------------- graphics/opengl/shader/shader.go | 123 ++++++++++++++++++++----------- 2 files changed, 89 insertions(+), 109 deletions(-) diff --git a/graphics/opengl/context.go b/graphics/opengl/context.go index 1212debb6..0f8254513 100644 --- a/graphics/opengl/context.go +++ b/graphics/opengl/context.go @@ -14,7 +14,6 @@ import ( "github.com/hajimehoshi/go-ebiten/graphics/texture" "image" "math" - "unsafe" ) type Context struct { @@ -57,7 +56,7 @@ func (context *Context) Init() { panic("creating main framebuffer failed: " + err.Error()) } - shader.Initialize() + shader.Init() context.screenId, err = context.NewRenderTarget( context.screenWidth, context.screenHeight) @@ -85,68 +84,13 @@ func (context *Context) Fill(r, g, b uint8) { } type TextureDrawing struct { - context *Context - geometryMatrix matrix.Geometry - colorMatrix matrix.Color + projectionMatrix [16]float32 + geometryMatrix matrix.Geometry + colorMatrix matrix.Color } func (t *TextureDrawing) Draw(native interface{}, quads []texture.Quad) { - if len(quads) == 0 { - return - } - shaderProgram := t.context.setShaderProgram(t.geometryMatrix, t.colorMatrix) - C.glBindTexture(C.GL_TEXTURE_2D, native.(C.GLuint)) - - vertexAttrLocation := shader.GetAttributeLocation(shaderProgram, "vertex") - textureAttrLocation := shader.GetAttributeLocation(shaderProgram, "texture") - - C.glEnableClientState(C.GL_VERTEX_ARRAY) - C.glEnableClientState(C.GL_TEXTURE_COORD_ARRAY) - C.glEnableVertexAttribArray(C.GLuint(vertexAttrLocation)) - C.glEnableVertexAttribArray(C.GLuint(textureAttrLocation)) - vertices := []float32{} - texCoords := []float32{} - indicies := []uint32{} - // TODO: Check len(parts) and GL_MAX_ELEMENTS_INDICES - for i, quad := range quads { - x1 := quad.VertexX1 - x2 := quad.VertexX2 - y1 := quad.VertexY1 - y2 := quad.VertexY2 - vertices = append(vertices, - x1, y1, - x2, y1, - x1, y2, - x2, y2, - ) - u1 := quad.TextureCoordU1 - u2 := quad.TextureCoordU2 - v1 := quad.TextureCoordV1 - v2 := quad.TextureCoordV2 - texCoords = append(texCoords, - u1, v1, - u2, v1, - u1, v2, - u2, v2, - ) - base := uint32(i * 4) - indicies = append(indicies, - base, base+1, base+2, - base+1, base+2, base+3, - ) - } - C.glVertexAttribPointer(C.GLuint(vertexAttrLocation), 2, - C.GL_FLOAT, C.GL_FALSE, - 0, unsafe.Pointer(&vertices[0])) - C.glVertexAttribPointer(C.GLuint(textureAttrLocation), 2, - C.GL_FLOAT, C.GL_FALSE, - 0, unsafe.Pointer(&texCoords[0])) - C.glDrawElements(C.GL_TRIANGLES, C.GLsizei(len(indicies)), - C.GL_UNSIGNED_INT, unsafe.Pointer(&indicies[0])) - C.glDisableVertexAttribArray(C.GLuint(textureAttrLocation)) - C.glDisableVertexAttribArray(C.GLuint(vertexAttrLocation)) - C.glDisableClientState(C.GL_TEXTURE_COORD_ARRAY) - C.glDisableClientState(C.GL_VERTEX_ARRAY) + shader.DrawTexture(uint(native.(C.GLuint)), t.projectionMatrix, quads, t.geometryMatrix, t.colorMatrix) } func (context *Context) DrawTexture( @@ -156,7 +100,7 @@ func (context *Context) DrawTexture( if !ok { panic("invalid texture ID") } - drawing := &TextureDrawing{context, geometryMatrix, colorMatrix} + drawing := &TextureDrawing{context.projectionMatrix, geometryMatrix, colorMatrix} texture.Draw(drawing.Draw) } @@ -167,7 +111,7 @@ func (context *Context) DrawTextureParts( if !ok { panic("invalid texture ID") } - drawing := &TextureDrawing{context, geometryMatrix, colorMatrix} + drawing := &TextureDrawing{context.projectionMatrix, geometryMatrix, colorMatrix} texture.DrawParts(parts, drawing.Draw) } @@ -238,11 +182,6 @@ func (context *Context) flush() { C.glFlush() } -func (context *Context) setShaderProgram( - geometryMatrix matrix.Geometry, colorMatrix matrix.Color) (program shader.Program) { - return shader.Use(context.projectionMatrix, geometryMatrix, colorMatrix) -} - func (context *Context) NewRenderTarget(width, height int) ( graphics.RenderTargetId, error) { renderTarget, err := newRenderTarget(width, height) diff --git a/graphics/opengl/shader/shader.go b/graphics/opengl/shader/shader.go index 53448052f..83755b31e 100644 --- a/graphics/opengl/shader/shader.go +++ b/graphics/opengl/shader/shader.go @@ -7,16 +7,10 @@ package shader import "C" import ( "github.com/hajimehoshi/go-ebiten/graphics/matrix" + "github.com/hajimehoshi/go-ebiten/graphics/texture" "unsafe" ) -type Program int - -const ( - ProgramRegular Program = iota - ProgramColorMatrix -) - type Location int type shader struct { @@ -72,8 +66,8 @@ void main(void) { ) var ( - regularShaderProgram = C.GLuint(0) - colorMatrixShaderProgram = C.GLuint(0) + programRegular = C.GLuint(0) + programColorMatrix = C.GLuint(0) ) func (s *shader) compile() { @@ -120,7 +114,7 @@ func createProgram(shaders ...*shader) C.GLuint { return program } -func Initialize() { +func Init() { // TODO: when should this function be called? vertexShader.id = C.glCreateShader(C.GL_VERTEX_SHADER) if vertexShader.id == 0 { @@ -139,8 +133,8 @@ func Initialize() { fragmentShader.compile() colorMatrixShader.compile() - regularShaderProgram = createProgram(vertexShader, fragmentShader) - colorMatrixShaderProgram = createProgram(vertexShader, colorMatrixShader) + programRegular = createProgram(vertexShader, fragmentShader) + programColorMatrix = createProgram(vertexShader, colorMatrixShader) C.glDeleteShader(vertexShader.id) C.glDeleteShader(fragmentShader.id) @@ -159,34 +153,21 @@ var ( } ) -func toInnerProgram(program Program) C.GLuint { - switch program { - case ProgramRegular: - return regularShaderProgram - case ProgramColorMatrix: - return colorMatrixShaderProgram - default: - panic("no reach") - } - return C.GLuint(0) -} - -func getLocation(program Program, name string, qualifierVariableType int) int { +func getLocation(program C.GLuint, name string, qualifierVariableType int) C.GLint { if location, ok := shaderLocationCache[qualifierVariableType][name]; ok { - return int(location) + return location } locationName := C.CString(name) defer C.free(unsafe.Pointer(locationName)) location := C.GLint(-1) - innerProgram := toInnerProgram(program) switch qualifierVariableType { case qualifierVariableTypeAttribute: - location = C.glGetAttribLocation(innerProgram, (*C.GLchar)(locationName)) + location = C.glGetAttribLocation(program, (*C.GLchar)(locationName)) case qualifierVariableTypeUniform: - location = C.glGetUniformLocation(innerProgram, (*C.GLchar)(locationName)) + location = C.glGetUniformLocation(program, (*C.GLchar)(locationName)) default: panic("no reach") } @@ -195,23 +176,23 @@ func getLocation(program Program, name string, qualifierVariableType int) int { } shaderLocationCache[qualifierVariableType][name] = location - return int(location) + return location } -func GetAttributeLocation(program Program, name string) int { +func getAttributeLocation(program C.GLuint, name string) C.GLint { return getLocation(program, name, qualifierVariableTypeAttribute) } -func getUniformLocation(program Program, name string) int { +func getUniformLocation(program C.GLuint, name string) C.GLint { return getLocation(program, name, qualifierVariableTypeUniform) } -func Use(projectionMatrix [16]float32, geometryMatrix matrix.Geometry, colorMatrix matrix.Color) Program { - program := ProgramRegular +func use(projectionMatrix [16]float32, geometryMatrix matrix.Geometry, colorMatrix matrix.Color) C.GLuint { + program := programRegular if !colorMatrix.IsIdentity() { - program = ProgramColorMatrix + program = programColorMatrix } - C.glUseProgram(toInnerProgram(program)) + C.glUseProgram(program) C.glUniformMatrix4fv(C.GLint(getUniformLocation(program, "projection_matrix")), 1, C.GL_FALSE, (*C.GLfloat)(&projectionMatrix[0])) @@ -228,13 +209,13 @@ func Use(projectionMatrix [16]float32, geometryMatrix matrix.Geometry, colorMatr 0, 0, 1, 0, tx, ty, 0, 1, } - C.glUniformMatrix4fv(C.GLint(getUniformLocation(program, "modelview_matrix")), + C.glUniformMatrix4fv(getUniformLocation(program, "modelview_matrix"), 1, C.GL_FALSE, (*C.GLfloat)(&glModelviewMatrix[0])) - C.glUniform1i(C.GLint(getUniformLocation(program, "texture")), 0) + C.glUniform1i(getUniformLocation(program, "texture"), 0) - if program != ProgramColorMatrix { + if program != programColorMatrix { return program } @@ -251,14 +232,74 @@ func Use(projectionMatrix [16]float32, geometryMatrix matrix.Geometry, colorMatr e[0][2], e[1][2], e[2][2], e[3][2], e[0][3], e[1][3], e[2][3], e[3][3], } - C.glUniformMatrix4fv(C.GLint(getUniformLocation(program, "color_matrix")), + C.glUniformMatrix4fv(getUniformLocation(program, "color_matrix"), 1, C.GL_FALSE, (*C.GLfloat)(&glColorMatrix[0])) glColorMatrixTranslation := [...]float32{ e[0][4], e[1][4], e[2][4], e[3][4], } - C.glUniform4fv(C.GLint(getUniformLocation(program, "color_matrix_translation")), + C.glUniform4fv(getUniformLocation(program, "color_matrix_translation"), 1, (*C.GLfloat)(&glColorMatrixTranslation[0])) return program } + +func DrawTexture(native uint, projectionMatrix [16]float32, quads []texture.Quad, + geometryMatrix matrix.Geometry, colorMatrix matrix.Color) { + if len(quads) == 0 { + return + } + shaderProgram := use(projectionMatrix, geometryMatrix, colorMatrix) + C.glBindTexture(C.GL_TEXTURE_2D, C.GLuint(native)) + + vertexAttrLocation := getAttributeLocation(shaderProgram, "vertex") + textureAttrLocation := getAttributeLocation(shaderProgram, "texture") + + C.glEnableClientState(C.GL_VERTEX_ARRAY) + C.glEnableClientState(C.GL_TEXTURE_COORD_ARRAY) + C.glEnableVertexAttribArray(C.GLuint(vertexAttrLocation)) + C.glEnableVertexAttribArray(C.GLuint(textureAttrLocation)) + vertices := []float32{} + texCoords := []float32{} + indicies := []uint32{} + // TODO: Check len(parts) and GL_MAX_ELEMENTS_INDICES + for i, quad := range quads { + x1 := quad.VertexX1 + x2 := quad.VertexX2 + y1 := quad.VertexY1 + y2 := quad.VertexY2 + vertices = append(vertices, + x1, y1, + x2, y1, + x1, y2, + x2, y2, + ) + u1 := quad.TextureCoordU1 + u2 := quad.TextureCoordU2 + v1 := quad.TextureCoordV1 + v2 := quad.TextureCoordV2 + texCoords = append(texCoords, + u1, v1, + u2, v1, + u1, v2, + u2, v2, + ) + base := uint32(i * 4) + indicies = append(indicies, + base, base+1, base+2, + base+1, base+2, base+3, + ) + } + C.glVertexAttribPointer(C.GLuint(vertexAttrLocation), 2, + C.GL_FLOAT, C.GL_FALSE, + 0, unsafe.Pointer(&vertices[0])) + C.glVertexAttribPointer(C.GLuint(textureAttrLocation), 2, + C.GL_FLOAT, C.GL_FALSE, + 0, unsafe.Pointer(&texCoords[0])) + C.glDrawElements(C.GL_TRIANGLES, C.GLsizei(len(indicies)), + C.GL_UNSIGNED_INT, unsafe.Pointer(&indicies[0])) + C.glDisableVertexAttribArray(C.GLuint(textureAttrLocation)) + C.glDisableVertexAttribArray(C.GLuint(vertexAttrLocation)) + C.glDisableClientState(C.GL_TEXTURE_COORD_ARRAY) + C.glDisableClientState(C.GL_VERTEX_ARRAY) +}