diff --git a/internal/graphics/draw.go b/internal/graphics/draw.go index e7a52aab2..4f9dad101 100644 --- a/internal/graphics/draw.go +++ b/internal/graphics/draw.go @@ -55,8 +55,16 @@ func drawTexture(c *opengl.Context, texture opengl.Texture, projectionMatrix *[4 return errors.New(fmt.Sprintf("len(quads) must be equal to or less than %d", quadsMaxNum)) } - f := useProgramForTexture(c, glMatrix(projectionMatrix), texture, geo, color) - defer f.FinishProgram() + p := programContext{ + program: programTexture, + context: c, + projectionMatrix: glMatrix(projectionMatrix), + texture: texture, + geoM: geo, + colorM: color, + } + p.begin() + defer p.end() vertices := vertices[0:0] num := 0 diff --git a/internal/graphics/program.go b/internal/graphics/program.go index bf24072af..3993d4ff4 100644 --- a/internal/graphics/program.go +++ b/internal/graphics/program.go @@ -99,38 +99,40 @@ var ( lastColorMatrix []float32 ) -type programFinisher func() - -func (p programFinisher) FinishProgram() { - p() +type programContext struct { + program opengl.Program + context *opengl.Context + projectionMatrix []float32 + texture opengl.Texture + geoM Matrix + colorM Matrix } -func useProgramForTexture(c *opengl.Context, projectionMatrix []float32, texture opengl.Texture, geo Matrix, color Matrix) programFinisher { - if !lastProgram.Equals(programTexture) { - c.UseProgram(programTexture) +func (p *programContext) begin() { + c := p.context + if !lastProgram.Equals(p.program) { + c.UseProgram(p.program) lastProgram = programTexture lastProjectionMatrix = nil lastModelviewMatrix = nil lastColorMatrix = nil } - program := programTexture - c.BindElementArrayBuffer(indexBufferQuads) - if !areSameFloat32Array(lastProjectionMatrix, projectionMatrix) { - c.UniformFloats(program, "projection_matrix", projectionMatrix) + if !areSameFloat32Array(lastProjectionMatrix, p.projectionMatrix) { + c.UniformFloats(p.program, "projection_matrix", p.projectionMatrix) if lastProjectionMatrix == nil { lastProjectionMatrix = make([]float32, 16) } - copy(lastProjectionMatrix, projectionMatrix) + copy(lastProjectionMatrix, p.projectionMatrix) } - ma := float32(geo.Element(0, 0)) - mb := float32(geo.Element(0, 1)) - mc := float32(geo.Element(1, 0)) - md := float32(geo.Element(1, 1)) - tx := float32(geo.Element(0, 2)) - ty := float32(geo.Element(1, 2)) + ma := float32(p.geoM.Element(0, 0)) + mb := float32(p.geoM.Element(0, 1)) + mc := float32(p.geoM.Element(1, 0)) + md := float32(p.geoM.Element(1, 1)) + tx := float32(p.geoM.Element(0, 2)) + ty := float32(p.geoM.Element(1, 2)) modelviewMatrix := []float32{ ma, mc, 0, 0, mb, md, 0, 0, @@ -138,19 +140,19 @@ func useProgramForTexture(c *opengl.Context, projectionMatrix []float32, texture tx, ty, 0, 1, } if !areSameFloat32Array(lastModelviewMatrix, modelviewMatrix) { - c.UniformFloats(program, "modelview_matrix", modelviewMatrix) + c.UniformFloats(p.program, "modelview_matrix", modelviewMatrix) if lastModelviewMatrix == nil { lastModelviewMatrix = make([]float32, 16) } copy(lastModelviewMatrix, modelviewMatrix) } - c.UniformInt(program, "texture", 0) + c.UniformInt(p.program, "texture", 0) e := [4][5]float32{} for i := 0; i < 4; i++ { for j := 0; j < 5; j++ { - e[i][j] = float32(color.Element(i, j)) + e[i][j] = float32(p.colorM.Element(i, j)) } } @@ -161,7 +163,7 @@ func useProgramForTexture(c *opengl.Context, projectionMatrix []float32, texture e[0][3], e[1][3], e[2][3], e[3][3], } if !areSameFloat32Array(lastColorMatrix, colorMatrix) { - c.UniformFloats(program, "color_matrix", colorMatrix) + c.UniformFloats(p.program, "color_matrix", colorMatrix) if lastColorMatrix == nil { lastColorMatrix = make([]float32, 16) } @@ -170,20 +172,21 @@ func useProgramForTexture(c *opengl.Context, projectionMatrix []float32, texture colorMatrixTranslation := []float32{ e[0][4], e[1][4], e[2][4], e[3][4], } - c.UniformFloats(program, "color_matrix_translation", colorMatrixTranslation) + c.UniformFloats(p.program, "color_matrix_translation", colorMatrixTranslation) // We don't have to call gl.ActiveTexture here: GL_TEXTURE0 is the default active texture // See also: https://www.opengl.org/sdk/docs/man2/xhtml/glActiveTexture.xml - c.BindTexture(texture) + c.BindTexture(p.texture) - c.EnableVertexAttribArray(program, "vertex") - c.EnableVertexAttribArray(program, "tex_coord") + c.EnableVertexAttribArray(p.program, "vertex") + c.EnableVertexAttribArray(p.program, "tex_coord") - c.VertexAttribPointer(program, "vertex", true, false, int16Size*4, 2, int16Size*0) - c.VertexAttribPointer(program, "tex_coord", true, true, int16Size*4, 2, int16Size*2) - - return func() { - c.DisableVertexAttribArray(program, "tex_coord") - c.DisableVertexAttribArray(program, "vertex") - } + c.VertexAttribPointer(p.program, "vertex", true, false, int16Size*4, 2, int16Size*0) + c.VertexAttribPointer(p.program, "tex_coord", true, true, int16Size*4, 2, int16Size*2) +} + +func (p *programContext) end() { + c := p.context + c.DisableVertexAttribArray(p.program, "tex_coord") + c.DisableVertexAttribArray(p.program, "vertex") }