Move drawing function to shader package

This commit is contained in:
Hajime Hoshi 2013-10-26 21:29:48 +09:00
parent c5f8738ae9
commit a28443b2d9
2 changed files with 89 additions and 109 deletions

View File

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

View File

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