mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-01-24 01:42:05 +01:00
Move drawing function to shader package
This commit is contained in:
parent
c5f8738ae9
commit
a28443b2d9
@ -14,7 +14,6 @@ import (
|
|||||||
"github.com/hajimehoshi/go-ebiten/graphics/texture"
|
"github.com/hajimehoshi/go-ebiten/graphics/texture"
|
||||||
"image"
|
"image"
|
||||||
"math"
|
"math"
|
||||||
"unsafe"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Context struct {
|
type Context struct {
|
||||||
@ -57,7 +56,7 @@ func (context *Context) Init() {
|
|||||||
panic("creating main framebuffer failed: " + err.Error())
|
panic("creating main framebuffer failed: " + err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
shader.Initialize()
|
shader.Init()
|
||||||
|
|
||||||
context.screenId, err = context.NewRenderTarget(
|
context.screenId, err = context.NewRenderTarget(
|
||||||
context.screenWidth, context.screenHeight)
|
context.screenWidth, context.screenHeight)
|
||||||
@ -85,68 +84,13 @@ func (context *Context) Fill(r, g, b uint8) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type TextureDrawing struct {
|
type TextureDrawing struct {
|
||||||
context *Context
|
projectionMatrix [16]float32
|
||||||
geometryMatrix matrix.Geometry
|
geometryMatrix matrix.Geometry
|
||||||
colorMatrix matrix.Color
|
colorMatrix matrix.Color
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TextureDrawing) Draw(native interface{}, quads []texture.Quad) {
|
func (t *TextureDrawing) Draw(native interface{}, quads []texture.Quad) {
|
||||||
if len(quads) == 0 {
|
shader.DrawTexture(uint(native.(C.GLuint)), t.projectionMatrix, quads, t.geometryMatrix, t.colorMatrix)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (context *Context) DrawTexture(
|
func (context *Context) DrawTexture(
|
||||||
@ -156,7 +100,7 @@ func (context *Context) DrawTexture(
|
|||||||
if !ok {
|
if !ok {
|
||||||
panic("invalid texture ID")
|
panic("invalid texture ID")
|
||||||
}
|
}
|
||||||
drawing := &TextureDrawing{context, geometryMatrix, colorMatrix}
|
drawing := &TextureDrawing{context.projectionMatrix, geometryMatrix, colorMatrix}
|
||||||
texture.Draw(drawing.Draw)
|
texture.Draw(drawing.Draw)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,7 +111,7 @@ func (context *Context) DrawTextureParts(
|
|||||||
if !ok {
|
if !ok {
|
||||||
panic("invalid texture ID")
|
panic("invalid texture ID")
|
||||||
}
|
}
|
||||||
drawing := &TextureDrawing{context, geometryMatrix, colorMatrix}
|
drawing := &TextureDrawing{context.projectionMatrix, geometryMatrix, colorMatrix}
|
||||||
texture.DrawParts(parts, drawing.Draw)
|
texture.DrawParts(parts, drawing.Draw)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,11 +182,6 @@ func (context *Context) flush() {
|
|||||||
C.glFlush()
|
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) (
|
func (context *Context) NewRenderTarget(width, height int) (
|
||||||
graphics.RenderTargetId, error) {
|
graphics.RenderTargetId, error) {
|
||||||
renderTarget, err := newRenderTarget(width, height)
|
renderTarget, err := newRenderTarget(width, height)
|
||||||
|
@ -7,16 +7,10 @@ package shader
|
|||||||
import "C"
|
import "C"
|
||||||
import (
|
import (
|
||||||
"github.com/hajimehoshi/go-ebiten/graphics/matrix"
|
"github.com/hajimehoshi/go-ebiten/graphics/matrix"
|
||||||
|
"github.com/hajimehoshi/go-ebiten/graphics/texture"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Program int
|
|
||||||
|
|
||||||
const (
|
|
||||||
ProgramRegular Program = iota
|
|
||||||
ProgramColorMatrix
|
|
||||||
)
|
|
||||||
|
|
||||||
type Location int
|
type Location int
|
||||||
|
|
||||||
type shader struct {
|
type shader struct {
|
||||||
@ -72,8 +66,8 @@ void main(void) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
regularShaderProgram = C.GLuint(0)
|
programRegular = C.GLuint(0)
|
||||||
colorMatrixShaderProgram = C.GLuint(0)
|
programColorMatrix = C.GLuint(0)
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *shader) compile() {
|
func (s *shader) compile() {
|
||||||
@ -120,7 +114,7 @@ func createProgram(shaders ...*shader) C.GLuint {
|
|||||||
return program
|
return program
|
||||||
}
|
}
|
||||||
|
|
||||||
func Initialize() {
|
func Init() {
|
||||||
// TODO: when should this function be called?
|
// TODO: when should this function be called?
|
||||||
vertexShader.id = C.glCreateShader(C.GL_VERTEX_SHADER)
|
vertexShader.id = C.glCreateShader(C.GL_VERTEX_SHADER)
|
||||||
if vertexShader.id == 0 {
|
if vertexShader.id == 0 {
|
||||||
@ -139,8 +133,8 @@ func Initialize() {
|
|||||||
fragmentShader.compile()
|
fragmentShader.compile()
|
||||||
colorMatrixShader.compile()
|
colorMatrixShader.compile()
|
||||||
|
|
||||||
regularShaderProgram = createProgram(vertexShader, fragmentShader)
|
programRegular = createProgram(vertexShader, fragmentShader)
|
||||||
colorMatrixShaderProgram = createProgram(vertexShader, colorMatrixShader)
|
programColorMatrix = createProgram(vertexShader, colorMatrixShader)
|
||||||
|
|
||||||
C.glDeleteShader(vertexShader.id)
|
C.glDeleteShader(vertexShader.id)
|
||||||
C.glDeleteShader(fragmentShader.id)
|
C.glDeleteShader(fragmentShader.id)
|
||||||
@ -159,34 +153,21 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func toInnerProgram(program Program) C.GLuint {
|
func getLocation(program C.GLuint, name string, qualifierVariableType int) C.GLint {
|
||||||
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 {
|
|
||||||
if location, ok := shaderLocationCache[qualifierVariableType][name]; ok {
|
if location, ok := shaderLocationCache[qualifierVariableType][name]; ok {
|
||||||
return int(location)
|
return location
|
||||||
}
|
}
|
||||||
|
|
||||||
locationName := C.CString(name)
|
locationName := C.CString(name)
|
||||||
defer C.free(unsafe.Pointer(locationName))
|
defer C.free(unsafe.Pointer(locationName))
|
||||||
|
|
||||||
location := C.GLint(-1)
|
location := C.GLint(-1)
|
||||||
innerProgram := toInnerProgram(program)
|
|
||||||
|
|
||||||
switch qualifierVariableType {
|
switch qualifierVariableType {
|
||||||
case qualifierVariableTypeAttribute:
|
case qualifierVariableTypeAttribute:
|
||||||
location = C.glGetAttribLocation(innerProgram, (*C.GLchar)(locationName))
|
location = C.glGetAttribLocation(program, (*C.GLchar)(locationName))
|
||||||
case qualifierVariableTypeUniform:
|
case qualifierVariableTypeUniform:
|
||||||
location = C.glGetUniformLocation(innerProgram, (*C.GLchar)(locationName))
|
location = C.glGetUniformLocation(program, (*C.GLchar)(locationName))
|
||||||
default:
|
default:
|
||||||
panic("no reach")
|
panic("no reach")
|
||||||
}
|
}
|
||||||
@ -195,23 +176,23 @@ func getLocation(program Program, name string, qualifierVariableType int) int {
|
|||||||
}
|
}
|
||||||
shaderLocationCache[qualifierVariableType][name] = location
|
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)
|
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)
|
return getLocation(program, name, qualifierVariableTypeUniform)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Use(projectionMatrix [16]float32, geometryMatrix matrix.Geometry, colorMatrix matrix.Color) Program {
|
func use(projectionMatrix [16]float32, geometryMatrix matrix.Geometry, colorMatrix matrix.Color) C.GLuint {
|
||||||
program := ProgramRegular
|
program := programRegular
|
||||||
if !colorMatrix.IsIdentity() {
|
if !colorMatrix.IsIdentity() {
|
||||||
program = ProgramColorMatrix
|
program = programColorMatrix
|
||||||
}
|
}
|
||||||
C.glUseProgram(toInnerProgram(program))
|
C.glUseProgram(program)
|
||||||
|
|
||||||
C.glUniformMatrix4fv(C.GLint(getUniformLocation(program, "projection_matrix")),
|
C.glUniformMatrix4fv(C.GLint(getUniformLocation(program, "projection_matrix")),
|
||||||
1, C.GL_FALSE, (*C.GLfloat)(&projectionMatrix[0]))
|
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,
|
0, 0, 1, 0,
|
||||||
tx, ty, 0, 1,
|
tx, ty, 0, 1,
|
||||||
}
|
}
|
||||||
C.glUniformMatrix4fv(C.GLint(getUniformLocation(program, "modelview_matrix")),
|
C.glUniformMatrix4fv(getUniformLocation(program, "modelview_matrix"),
|
||||||
1, C.GL_FALSE,
|
1, C.GL_FALSE,
|
||||||
(*C.GLfloat)(&glModelviewMatrix[0]))
|
(*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
|
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][2], e[1][2], e[2][2], e[3][2],
|
||||||
e[0][3], e[1][3], e[2][3], e[3][3],
|
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]))
|
1, C.GL_FALSE, (*C.GLfloat)(&glColorMatrix[0]))
|
||||||
|
|
||||||
glColorMatrixTranslation := [...]float32{
|
glColorMatrixTranslation := [...]float32{
|
||||||
e[0][4], e[1][4], e[2][4], e[3][4],
|
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]))
|
1, (*C.GLfloat)(&glColorMatrixTranslation[0]))
|
||||||
|
|
||||||
return program
|
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)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user