ebiten/graphics/opengl/internal/shader/program.go

149 lines
3.7 KiB
Go
Raw Normal View History

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
}