mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-01-12 12:08:58 +01:00
Refactoring
This commit is contained in:
parent
63fc25d24c
commit
d087333e48
@ -10,50 +10,60 @@ import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func createProgram(shaders ...*shader) C.GLuint {
|
||||
program := C.glCreateProgram()
|
||||
for _, shader := range shaders {
|
||||
C.glAttachShader(program, shader.id)
|
||||
type program struct {
|
||||
native C.GLuint
|
||||
shaderIds []shaderId
|
||||
}
|
||||
|
||||
type programId int
|
||||
|
||||
const (
|
||||
programRegular programId = iota
|
||||
programColorMatrix
|
||||
)
|
||||
|
||||
var programs = map[programId]*program{
|
||||
programRegular: &program{
|
||||
shaderIds: []shaderId{shaderVertex, shaderFragment},
|
||||
},
|
||||
programColorMatrix: &program{
|
||||
shaderIds: []shaderId{shaderVertex, shaderColorMatrix},
|
||||
},
|
||||
}
|
||||
|
||||
func (p *program) create() {
|
||||
p.native = C.glCreateProgram()
|
||||
if p.native == 0 {
|
||||
panic("glCreateProgram failed")
|
||||
}
|
||||
C.glLinkProgram(program)
|
||||
|
||||
for _, shaderId := range p.shaderIds {
|
||||
C.glAttachShader(p.native, shaders[shaderId].native)
|
||||
}
|
||||
C.glLinkProgram(p.native)
|
||||
linked := C.GLint(C.GL_FALSE)
|
||||
C.glGetProgramiv(program, C.GL_LINK_STATUS, &linked)
|
||||
C.glGetProgramiv(p.native, C.GL_LINK_STATUS, &linked)
|
||||
if linked == C.GL_FALSE {
|
||||
panic("program error")
|
||||
}
|
||||
return program
|
||||
}
|
||||
|
||||
var (
|
||||
initialized = false
|
||||
)
|
||||
var initialized = false
|
||||
|
||||
func initialize() {
|
||||
// TODO: when should this function be called?
|
||||
vertexShader.id = C.glCreateShader(C.GL_VERTEX_SHADER)
|
||||
if vertexShader.id == 0 {
|
||||
panic("creating shader failed")
|
||||
for _, shader := range shaders {
|
||||
shader.compile()
|
||||
}
|
||||
fragmentShader.id = C.glCreateShader(C.GL_FRAGMENT_SHADER)
|
||||
if fragmentShader.id == 0 {
|
||||
panic("creating shader failed")
|
||||
defer func() {
|
||||
for _, shader := range shaders {
|
||||
shader.delete()
|
||||
}
|
||||
colorMatrixShader.id = C.glCreateShader(C.GL_FRAGMENT_SHADER)
|
||||
if colorMatrixShader.id == 0 {
|
||||
panic("creating shader failed")
|
||||
}()
|
||||
|
||||
for _, program := range programs {
|
||||
program.create()
|
||||
}
|
||||
|
||||
vertexShader.compile()
|
||||
fragmentShader.compile()
|
||||
colorMatrixShader.compile()
|
||||
|
||||
programRegular = createProgram(vertexShader, fragmentShader)
|
||||
programColorMatrix = createProgram(vertexShader, colorMatrixShader)
|
||||
|
||||
C.glDeleteShader(vertexShader.id)
|
||||
C.glDeleteShader(fragmentShader.id)
|
||||
C.glDeleteShader(colorMatrixShader.id)
|
||||
|
||||
initialized = true
|
||||
}
|
||||
|
||||
@ -105,13 +115,14 @@ func getUniformLocation(program C.GLuint, name string) C.GLint {
|
||||
|
||||
func use(projectionMatrix [16]float32,
|
||||
geometryMatrix matrix.Geometry, colorMatrix matrix.Color) C.GLuint {
|
||||
program := programRegular
|
||||
programId := programRegular
|
||||
if !colorMatrix.IsIdentity() {
|
||||
program = programColorMatrix
|
||||
programId = programColorMatrix
|
||||
}
|
||||
C.glUseProgram(program)
|
||||
program := programs[programId]
|
||||
C.glUseProgram(program.native)
|
||||
|
||||
C.glUniformMatrix4fv(C.GLint(getUniformLocation(program, "projection_matrix")),
|
||||
C.glUniformMatrix4fv(C.GLint(getUniformLocation(program.native, "projection_matrix")),
|
||||
1, C.GL_FALSE, (*C.GLfloat)(&projectionMatrix[0]))
|
||||
|
||||
a := float32(geometryMatrix.Elements[0][0])
|
||||
@ -126,14 +137,14 @@ func use(projectionMatrix [16]float32,
|
||||
0, 0, 1, 0,
|
||||
tx, ty, 0, 1,
|
||||
}
|
||||
C.glUniformMatrix4fv(getUniformLocation(program, "modelview_matrix"),
|
||||
C.glUniformMatrix4fv(getUniformLocation(program.native, "modelview_matrix"),
|
||||
1, C.GL_FALSE,
|
||||
(*C.GLfloat)(&glModelviewMatrix[0]))
|
||||
|
||||
C.glUniform1i(getUniformLocation(program, "texture"), 0)
|
||||
C.glUniform1i(getUniformLocation(program.native, "texture"), 0)
|
||||
|
||||
if program != programColorMatrix {
|
||||
return program
|
||||
if programId != programColorMatrix {
|
||||
return program.native
|
||||
}
|
||||
|
||||
e := [4][5]float32{}
|
||||
@ -149,14 +160,14 @@ func use(projectionMatrix [16]float32,
|
||||
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(getUniformLocation(program, "color_matrix"),
|
||||
C.glUniformMatrix4fv(getUniformLocation(program.native, "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(getUniformLocation(program, "color_matrix_translation"),
|
||||
C.glUniform4fv(getUniformLocation(program.native, "color_matrix_translation"),
|
||||
1, (*C.GLfloat)(&glColorMatrixTranslation[0]))
|
||||
|
||||
return program
|
||||
return program.native
|
||||
}
|
||||
|
@ -6,92 +6,113 @@ package shader
|
||||
// #include <stdlib.h>
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type shader struct {
|
||||
id C.GLuint
|
||||
name string
|
||||
native C.GLuint
|
||||
shaderType C.GLenum
|
||||
source string
|
||||
}
|
||||
|
||||
var (
|
||||
vertexShader = &shader{
|
||||
id: 0,
|
||||
name: "vertex_shader",
|
||||
type shaderId int
|
||||
|
||||
const (
|
||||
shaderVertex shaderId = iota
|
||||
shaderFragment
|
||||
shaderColorMatrix
|
||||
shaderSolidColor
|
||||
)
|
||||
|
||||
var shaders = map[shaderId]*shader{
|
||||
shaderVertex: &shader{
|
||||
shaderType: C.GL_VERTEX_SHADER,
|
||||
source: `
|
||||
attribute /*highp*/ vec2 vertex;
|
||||
attribute /*highp*/ vec2 texture;
|
||||
uniform /*highp*/ mat4 projection_matrix;
|
||||
uniform /*highp*/ mat4 modelview_matrix;
|
||||
varying /*highp*/ vec2 tex_coord;
|
||||
attribute vec2 vertex;
|
||||
attribute vec2 texture;
|
||||
uniform mat4 projection_matrix;
|
||||
uniform mat4 modelview_matrix;
|
||||
varying vec2 tex_coord;
|
||||
|
||||
void main(void) {
|
||||
tex_coord = texture;
|
||||
gl_Position = projection_matrix * modelview_matrix * vec4(vertex, 0, 1);
|
||||
}
|
||||
`,
|
||||
}
|
||||
fragmentShader = &shader{
|
||||
id: 0,
|
||||
name: "fragment_shader",
|
||||
},
|
||||
shaderFragment: &shader{
|
||||
shaderType: C.GL_FRAGMENT_SHADER,
|
||||
source: `
|
||||
uniform /*lowp*/ sampler2D texture;
|
||||
varying /*highp*/ vec2 tex_coord;
|
||||
uniform sampler2D texture;
|
||||
varying vec2 tex_coord;
|
||||
|
||||
void main(void) {
|
||||
gl_FragColor = texture2D(texture, tex_coord);
|
||||
}
|
||||
`,
|
||||
}
|
||||
colorMatrixShader = &shader{
|
||||
id: 0,
|
||||
name: "color_matrix_shader",
|
||||
},
|
||||
shaderColorMatrix: &shader{
|
||||
shaderType: C.GL_FRAGMENT_SHADER,
|
||||
source: `
|
||||
uniform /*highp*/ sampler2D texture;
|
||||
uniform /*lowp*/ mat4 color_matrix;
|
||||
uniform /*lowp*/ vec4 color_matrix_translation;
|
||||
varying /*highp*/ vec2 tex_coord;
|
||||
uniform sampler2D texture;
|
||||
uniform mat4 color_matrix;
|
||||
uniform vec4 color_matrix_translation;
|
||||
varying vec2 tex_coord;
|
||||
|
||||
void main(void) {
|
||||
/*lowp*/ vec4 color = texture2D(texture, tex_coord);
|
||||
vec4 color = texture2D(texture, tex_coord);
|
||||
gl_FragColor = (color_matrix * color) + color_matrix_translation;
|
||||
}
|
||||
`,
|
||||
}
|
||||
)
|
||||
},
|
||||
shaderSolidColor: &shader{
|
||||
shaderType: C.GL_FRAGMENT_SHADER,
|
||||
source: `
|
||||
uniform vec4 color;
|
||||
|
||||
var (
|
||||
programRegular = C.GLuint(0)
|
||||
programColorMatrix = C.GLuint(0)
|
||||
)
|
||||
void main(void) {
|
||||
gl_FragColor = color;
|
||||
}
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
func (s *shader) compile() {
|
||||
s.native = C.glCreateShader(s.shaderType)
|
||||
if s.native == 0 {
|
||||
panic("glCreateShader failed")
|
||||
}
|
||||
|
||||
csource := (*C.GLchar)(C.CString(s.source))
|
||||
// TODO: defer?
|
||||
// defer C.free(unsafe.Pointer(csource))
|
||||
|
||||
C.glShaderSource(s.id, 1, &csource, nil)
|
||||
C.glCompileShader(s.id)
|
||||
C.glShaderSource(s.native, 1, &csource, nil)
|
||||
C.glCompileShader(s.native)
|
||||
|
||||
compiled := C.GLint(C.GL_FALSE)
|
||||
C.glGetShaderiv(s.id, C.GL_COMPILE_STATUS, &compiled)
|
||||
C.glGetShaderiv(s.native, C.GL_COMPILE_STATUS, &compiled)
|
||||
if compiled == C.GL_FALSE {
|
||||
s.showShaderLog()
|
||||
panic("shader compile failed: " + s.name)
|
||||
panic("shader compile failed")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *shader) showShaderLog() {
|
||||
logSize := C.GLint(0)
|
||||
C.glGetShaderiv(s.id, C.GL_INFO_LOG_LENGTH, &logSize)
|
||||
C.glGetShaderiv(s.native, C.GL_INFO_LOG_LENGTH, &logSize)
|
||||
if logSize == 0 {
|
||||
return
|
||||
}
|
||||
length := C.GLsizei(0)
|
||||
buffer := make([]C.GLchar, logSize)
|
||||
C.glGetShaderInfoLog(s.id, C.GLsizei(logSize), &length, &buffer[0])
|
||||
C.glGetShaderInfoLog(s.native, C.GLsizei(logSize), &length, &buffer[0])
|
||||
|
||||
message := string(C.GoBytes(unsafe.Pointer(&buffer[0]), C.int(length)))
|
||||
print("shader error (", s.name, "):\n", message)
|
||||
fmt.Printf("shader error: %s\n", message)
|
||||
}
|
||||
|
||||
func (s *shader) delete() {
|
||||
C.glDeleteShader(s.native)
|
||||
}
|
||||
|
@ -60,4 +60,3 @@ func (w *windowEvents) notifyWindowClosed(e ui.WindowClosedEvent) {
|
||||
w.windowClosed <- e
|
||||
}()
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user