ebiten/graphics/opengl/shader/shader.go

119 lines
2.4 KiB
Go
Raw Normal View History

2013-10-25 21:15:27 +02:00
package shader
2013-06-15 10:07:14 +02:00
// #cgo LDFLAGS: -framework OpenGL
//
// #include <OpenGL/gl.h>
// #include <stdlib.h>
import "C"
import (
2013-12-12 16:31:00 +01:00
"fmt"
2013-06-15 10:07:14 +02:00
"unsafe"
)
type shader struct {
2013-12-12 16:31:00 +01:00
native C.GLuint
shaderType C.GLenum
source string
2013-06-15 10:07:14 +02:00
}
2013-12-12 16:31:00 +01:00
type shaderId int
const (
shaderVertex shaderId = iota
shaderFragment
shaderColorMatrix
shaderSolidColor
)
var shaders = map[shaderId]*shader{
shaderVertex: &shader{
shaderType: C.GL_VERTEX_SHADER,
2013-06-15 10:07:14 +02:00
source: `
2013-12-12 16:31:00 +01:00
uniform mat4 projection_matrix;
uniform mat4 modelview_matrix;
2013-12-13 21:34:27 +01:00
attribute vec2 vertex;
attribute vec2 tex_coord;
varying vec2 vertex_out_tex_coord;
2013-06-15 10:07:14 +02:00
void main(void) {
2013-12-13 21:34:27 +01:00
vertex_out_tex_coord = tex_coord;
2013-06-15 10:07:14 +02:00
gl_Position = projection_matrix * modelview_matrix * vec4(vertex, 0, 1);
}
`,
2013-12-12 16:31:00 +01:00
},
shaderFragment: &shader{
shaderType: C.GL_FRAGMENT_SHADER,
2013-06-15 10:07:14 +02:00
source: `
2013-12-12 16:31:00 +01:00
uniform sampler2D texture;
2013-12-13 21:34:27 +01:00
varying vec2 vertex_out_tex_coord;
2013-06-15 10:07:14 +02:00
void main(void) {
2013-12-13 21:34:27 +01:00
gl_FragColor = texture2D(texture, vertex_out_tex_coord);
2013-06-15 10:07:14 +02:00
}
`,
2013-12-12 16:31:00 +01:00
},
shaderColorMatrix: &shader{
shaderType: C.GL_FRAGMENT_SHADER,
2013-06-15 10:07:14 +02:00
source: `
2013-12-12 16:31:00 +01:00
uniform sampler2D texture;
uniform mat4 color_matrix;
uniform vec4 color_matrix_translation;
2013-12-13 21:34:27 +01:00
varying vec2 vertex_out_tex_coord;
2013-06-15 10:07:14 +02:00
void main(void) {
2013-12-13 21:34:27 +01:00
vec4 color = texture2D(texture, vertex_out_tex_coord);
2013-06-15 10:07:14 +02:00
gl_FragColor = (color_matrix * color) + color_matrix_translation;
}
`,
2013-12-12 16:31:00 +01:00
},
shaderSolidColor: &shader{
shaderType: C.GL_FRAGMENT_SHADER,
source: `
uniform vec4 color;
2013-06-15 10:07:14 +02:00
2013-12-12 16:31:00 +01:00
void main(void) {
gl_FragColor = color;
}
`,
},
}
2013-06-15 10:07:14 +02:00
func (s *shader) compile() {
2013-12-12 16:31:00 +01:00
s.native = C.glCreateShader(s.shaderType)
if s.native == 0 {
panic("glCreateShader failed")
}
2013-06-15 10:07:14 +02:00
csource := (*C.GLchar)(C.CString(s.source))
// TODO: defer?
2013-10-26 19:25:41 +02:00
// defer C.free(unsafe.Pointer(csource))
2013-06-15 10:07:14 +02:00
2013-12-12 16:31:00 +01:00
C.glShaderSource(s.native, 1, &csource, nil)
C.glCompileShader(s.native)
2013-06-15 10:07:14 +02:00
compiled := C.GLint(C.GL_FALSE)
2013-12-12 16:31:00 +01:00
C.glGetShaderiv(s.native, C.GL_COMPILE_STATUS, &compiled)
2013-06-15 10:07:14 +02:00
if compiled == C.GL_FALSE {
s.showShaderLog()
2013-12-12 16:31:00 +01:00
panic("shader compile failed")
2013-06-15 10:07:14 +02:00
}
}
func (s *shader) showShaderLog() {
logSize := C.GLint(0)
2013-12-12 16:31:00 +01:00
C.glGetShaderiv(s.native, C.GL_INFO_LOG_LENGTH, &logSize)
2013-06-15 10:07:14 +02:00
if logSize == 0 {
return
}
length := C.GLsizei(0)
buffer := make([]C.GLchar, logSize)
2013-12-12 16:31:00 +01:00
C.glGetShaderInfoLog(s.native, C.GLsizei(logSize), &length, &buffer[0])
2013-06-15 10:07:14 +02:00
message := string(C.GoBytes(unsafe.Pointer(&buffer[0]), C.int(length)))
2013-12-12 16:31:00 +01:00
fmt.Printf("shader error: %s\n", message)
}
func (s *shader) delete() {
C.glDeleteShader(s.native)
2013-06-15 10:07:14 +02:00
}