2013-10-26 18:56:58 +02:00
|
|
|
package shader
|
|
|
|
|
|
|
|
import (
|
2014-12-06 07:47:48 +01:00
|
|
|
"github.com/go-gl/gl"
|
2014-12-05 14:16:58 +01:00
|
|
|
"github.com/hajimehoshi/ebiten/graphics/matrix"
|
2013-10-26 18:56:58 +02:00
|
|
|
)
|
|
|
|
|
2013-12-12 16:31:00 +01:00
|
|
|
type program struct {
|
2014-12-06 07:47:48 +01:00
|
|
|
native gl.Program
|
2013-12-12 16:31:00 +01:00
|
|
|
shaderIds []shaderId
|
|
|
|
}
|
|
|
|
|
|
|
|
type programId int
|
|
|
|
|
|
|
|
const (
|
|
|
|
programRegular programId = iota
|
|
|
|
programColorMatrix
|
|
|
|
)
|
|
|
|
|
|
|
|
var programs = map[programId]*program{
|
2014-05-11 12:44:36 +02:00
|
|
|
// TODO: programRegular is not used for now. Remove this.
|
2013-12-12 16:31:00 +01:00
|
|
|
programRegular: &program{
|
|
|
|
shaderIds: []shaderId{shaderVertex, shaderFragment},
|
|
|
|
},
|
|
|
|
programColorMatrix: &program{
|
|
|
|
shaderIds: []shaderId{shaderVertex, shaderColorMatrix},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *program) create() {
|
2014-12-06 07:47:48 +01:00
|
|
|
p.native = gl.CreateProgram()
|
2013-12-12 16:31:00 +01:00
|
|
|
if p.native == 0 {
|
|
|
|
panic("glCreateProgram failed")
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, shaderId := range p.shaderIds {
|
2014-12-06 07:47:48 +01:00
|
|
|
p.native.AttachShader(shaders[shaderId].native)
|
2013-10-26 18:56:58 +02:00
|
|
|
}
|
2014-12-06 07:47:48 +01:00
|
|
|
p.native.Link()
|
|
|
|
if p.native.Get(gl.LINK_STATUS) == gl.FALSE {
|
2013-10-26 18:56:58 +02:00
|
|
|
panic("program error")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func initialize() {
|
2013-12-12 16:31:00 +01:00
|
|
|
for _, shader := range shaders {
|
|
|
|
shader.compile()
|
2013-10-26 18:56:58 +02:00
|
|
|
}
|
2013-12-12 16:31:00 +01:00
|
|
|
defer func() {
|
|
|
|
for _, shader := range shaders {
|
|
|
|
shader.delete()
|
|
|
|
}
|
|
|
|
}()
|
2013-10-26 18:56:58 +02:00
|
|
|
|
2013-12-12 16:31:00 +01:00
|
|
|
for _, program := range programs {
|
|
|
|
program.create()
|
|
|
|
}
|
2013-10-26 18:56:58 +02:00
|
|
|
}
|
|
|
|
|
2013-12-13 21:34:27 +01:00
|
|
|
type qualifierVariableType int
|
|
|
|
|
2013-10-26 18:56:58 +02:00
|
|
|
const (
|
2013-12-13 21:34:27 +01:00
|
|
|
qualifierVariableTypeAttribute qualifierVariableType = iota
|
2013-10-26 18:56:58 +02:00
|
|
|
qualifierVariableTypeUniform
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2014-12-06 07:47:48 +01:00
|
|
|
shaderLocationCache = map[qualifierVariableType]map[string]gl.AttribLocation{
|
|
|
|
qualifierVariableTypeAttribute: map[string]gl.AttribLocation{},
|
|
|
|
qualifierVariableTypeUniform: map[string]gl.AttribLocation{},
|
2013-10-26 18:56:58 +02:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2014-12-06 07:47:48 +01:00
|
|
|
func getLocation(program gl.Program, name string, qvType qualifierVariableType) gl.AttribLocation {
|
2013-12-13 21:34:27 +01:00
|
|
|
if location, ok := shaderLocationCache[qvType][name]; ok {
|
2013-10-26 18:56:58 +02:00
|
|
|
return location
|
|
|
|
}
|
|
|
|
|
2014-12-06 07:47:48 +01:00
|
|
|
location := gl.AttribLocation(-1)
|
2013-12-13 21:34:27 +01:00
|
|
|
switch qvType {
|
2013-10-26 18:56:58 +02:00
|
|
|
case qualifierVariableTypeAttribute:
|
2014-12-06 07:47:48 +01:00
|
|
|
location = program.GetAttribLocation(name)
|
2013-10-26 18:56:58 +02:00
|
|
|
case qualifierVariableTypeUniform:
|
2014-12-06 07:47:48 +01:00
|
|
|
location = gl.AttribLocation(program.GetUniformLocation(name))
|
2013-10-26 18:56:58 +02:00
|
|
|
default:
|
|
|
|
panic("no reach")
|
|
|
|
}
|
2014-12-06 07:47:48 +01:00
|
|
|
if location == -1 {
|
|
|
|
panic("GetAttribLocation failed")
|
2013-10-26 18:56:58 +02:00
|
|
|
}
|
2013-12-13 21:34:27 +01:00
|
|
|
shaderLocationCache[qvType][name] = location
|
2013-10-26 18:56:58 +02:00
|
|
|
|
|
|
|
return location
|
|
|
|
}
|
|
|
|
|
2014-12-06 07:47:48 +01:00
|
|
|
func getAttributeLocation(program gl.Program, name string) gl.AttribLocation {
|
2013-10-26 18:56:58 +02:00
|
|
|
return getLocation(program, name, qualifierVariableTypeAttribute)
|
|
|
|
}
|
|
|
|
|
2014-12-06 07:47:48 +01:00
|
|
|
func getUniformLocation(program gl.Program, name string) gl.UniformLocation {
|
|
|
|
return gl.UniformLocation(getLocation(program, name, qualifierVariableTypeUniform))
|
2013-10-26 18:56:58 +02:00
|
|
|
}
|
|
|
|
|
2014-12-06 07:47:48 +01:00
|
|
|
func use(projectionMatrix [16]float32, geometryMatrix matrix.Geometry, colorMatrix matrix.Color) gl.Program {
|
2014-05-11 12:44:36 +02:00
|
|
|
programId := programColorMatrix
|
2013-12-12 16:31:00 +01:00
|
|
|
program := programs[programId]
|
2014-05-11 12:44:36 +02:00
|
|
|
// TODO: Check the performance.
|
2014-12-06 07:47:48 +01:00
|
|
|
program.native.Use()
|
2013-10-27 11:54:28 +01:00
|
|
|
|
2014-12-06 07:47:48 +01:00
|
|
|
getUniformLocation(program.native, "projection_matrix").UniformMatrix4fv(false, projectionMatrix)
|
2013-10-26 18:56:58 +02:00
|
|
|
|
|
|
|
a := float32(geometryMatrix.Elements[0][0])
|
|
|
|
b := float32(geometryMatrix.Elements[0][1])
|
|
|
|
c := float32(geometryMatrix.Elements[1][0])
|
|
|
|
d := float32(geometryMatrix.Elements[1][1])
|
|
|
|
tx := float32(geometryMatrix.Elements[0][2])
|
|
|
|
ty := float32(geometryMatrix.Elements[1][2])
|
|
|
|
glModelviewMatrix := [...]float32{
|
|
|
|
a, c, 0, 0,
|
|
|
|
b, d, 0, 0,
|
|
|
|
0, 0, 1, 0,
|
|
|
|
tx, ty, 0, 1,
|
|
|
|
}
|
2014-12-06 07:47:48 +01:00
|
|
|
getUniformLocation(program.native, "modelview_matrix").UniformMatrix4fv(false, glModelviewMatrix)
|
2013-10-26 18:56:58 +02:00
|
|
|
|
2014-12-06 07:47:48 +01:00
|
|
|
getUniformLocation(program.native, "texture").Uniform1i(0)
|
2013-10-26 18:56:58 +02:00
|
|
|
|
|
|
|
e := [4][5]float32{}
|
|
|
|
for i := 0; i < 4; i++ {
|
|
|
|
for j := 0; j < 5; j++ {
|
|
|
|
e[i][j] = float32(colorMatrix.Elements[i][j])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
glColorMatrix := [...]float32{
|
|
|
|
e[0][0], e[1][0], e[2][0], e[3][0],
|
|
|
|
e[0][1], e[1][1], e[2][1], e[3][1],
|
|
|
|
e[0][2], e[1][2], e[2][2], e[3][2],
|
|
|
|
e[0][3], e[1][3], e[2][3], e[3][3],
|
|
|
|
}
|
2014-12-06 07:47:48 +01:00
|
|
|
getUniformLocation(program.native, "color_matrix").UniformMatrix4fv(false, glColorMatrix)
|
2013-10-26 18:56:58 +02:00
|
|
|
glColorMatrixTranslation := [...]float32{
|
|
|
|
e[0][4], e[1][4], e[2][4], e[3][4],
|
|
|
|
}
|
2014-12-06 07:47:48 +01:00
|
|
|
getUniformLocation(program.native, "color_matrix_translation").Uniform4fv(1, glColorMatrixTranslation[:])
|
2013-10-26 18:56:58 +02:00
|
|
|
|
2013-12-12 16:31:00 +01:00
|
|
|
return program.native
|
2013-10-26 18:56:58 +02:00
|
|
|
}
|