diff --git a/example/main.go b/example/main.go index 332a992ed..2d1e7c40d 100644 --- a/example/main.go +++ b/example/main.go @@ -41,7 +41,7 @@ func main() { textureCreated := textureFactory.TextureCreated() renderTargetCreated := textureFactory.RenderTargetCreated() - + for tag, path := range TexturePaths { tag := tag path := path diff --git a/graphics/graphics.go b/graphics/graphics.go index b7471a7ed..264695288 100644 --- a/graphics/graphics.go +++ b/graphics/graphics.go @@ -20,7 +20,7 @@ type TexturePart struct { type Line struct { X1, Y1 int X2, Y2 int - Color color.Color + Color color.Color } type TextureId int diff --git a/graphics/opengl/shader/program.go b/graphics/opengl/shader/program.go index 3dcae1134..c7a81533f 100644 --- a/graphics/opengl/shader/program.go +++ b/graphics/opengl/shader/program.go @@ -10,49 +10,59 @@ 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() + } + }() + + for _, program := range programs { + program.create() } - colorMatrixShader.id = C.glCreateShader(C.GL_FRAGMENT_SHADER) - if colorMatrixShader.id == 0 { - panic("creating shader failed") - } - - 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 } diff --git a/graphics/opengl/shader/shader.go b/graphics/opengl/shader/shader.go index 585c7f137..f51cd4d90 100644 --- a/graphics/opengl/shader/shader.go +++ b/graphics/opengl/shader/shader.go @@ -6,92 +6,113 @@ package shader // #include import "C" import ( + "fmt" "unsafe" ) type shader struct { - id C.GLuint - name string - source 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) } diff --git a/ui/cocoa/window_events.go b/ui/cocoa/window_events.go index fbab520b0..d2f81a446 100644 --- a/ui/cocoa/window_events.go +++ b/ui/cocoa/window_events.go @@ -7,7 +7,7 @@ import ( type windowEvents struct { screenSizeUpdated chan ui.ScreenSizeUpdatedEvent // initialized lazily inputStateUpdated chan ui.InputStateUpdatedEvent // initialized lazily - windowClosed chan ui.WindowClosedEvent // initialized lazily + windowClosed chan ui.WindowClosedEvent // initialized lazily } func (w *windowEvents) ScreenSizeUpdated() <-chan ui.ScreenSizeUpdatedEvent { @@ -60,4 +60,3 @@ func (w *windowEvents) notifyWindowClosed(e ui.WindowClosedEvent) { w.windowClosed <- e }() } -