diff --git a/pixelgl/shader.go b/pixelgl/shader.go new file mode 100644 index 0000000000000000000000000000000000000000..bcd0d941f67ac1edb4b1534a2d5dc1e083db02e0 --- /dev/null +++ b/pixelgl/shader.go @@ -0,0 +1,122 @@ +package pixelgl + +import ( + "fmt" + + "github.com/go-gl/gl/v3.3-core/gl" + "github.com/pkg/errors" +) + +// Shader is an OpenGL shader program. +type Shader struct { + parent BeginEnder + program uint32 +} + +// NewShader creates a new shader program from the specified vertex shader and fragment shader sources. +// +// Note that vertexShader and fragmentShader parameters must contain the source code, they're not filenames. +func NewShader(parent BeginEnder, vertexShader, fragmentShader string) (*Shader, error) { + shader := &Shader{ + parent: parent, + } + err, glerr := DoErrGLErr(func() error { + var vshader, fshader uint32 + + // vertex shader + { + vshader = gl.CreateShader(gl.VERTEX_SHADER) + src, free := gl.Strs(vertexShader) + defer free() + length := int32(len(vertexShader)) + gl.ShaderSource(vshader, 1, src, &length) + gl.CompileShader(vshader) + + var ( + success int32 + infoLog = make([]byte, 512) + ) + gl.GetShaderiv(vshader, gl.COMPILE_STATUS, &success) + if success == 0 { + gl.GetShaderInfoLog(vshader, int32(len(infoLog)), nil, &infoLog[0]) + return fmt.Errorf("error compiling vertex shader: %s", string(infoLog)) + } + } + + // fragment shader + { + fshader = gl.CreateShader(gl.FRAGMENT_SHADER) + src, free := gl.Strs(fragmentShader) + defer free() + length := int32(len(fragmentShader)) + gl.ShaderSource(fshader, 1, src, &length) + gl.CompileShader(fshader) + + var ( + success int32 + infoLog = make([]byte, 512) + ) + gl.GetShaderiv(fshader, gl.COMPILE_STATUS, &success) + if success == 0 { + gl.GetShaderInfoLog(fshader, int32(len(infoLog)), nil, &infoLog[0]) + return fmt.Errorf("error compiling fragment shader: %s", string(infoLog)) + } + } + + // shader program + { + shader.program = gl.CreateProgram() + gl.AttachShader(shader.program, vshader) + gl.AttachShader(shader.program, fshader) + gl.LinkProgram(shader.program) + + var ( + success int32 + infoLog = make([]byte, 512) + ) + gl.GetProgramiv(shader.program, gl.LINK_STATUS, &success) + if success == 0 { + gl.GetProgramInfoLog(shader.program, int32(len(infoLog)), nil, &infoLog[0]) + return fmt.Errorf("error linking shader program: %s", string(infoLog)) + } + } + + gl.DeleteShader(vshader) + gl.DeleteShader(fshader) + + return nil + }) + if err != nil { + if glerr != nil { + err = errors.Wrap(glerr, err.Error()) + } + return nil, err + } + if glerr != nil { + return nil, glerr + } + return shader, nil +} + +// Delete deletes a shader program. Don't use a shader after deletion. +func (s *Shader) Delete() { + Do(func() { + gl.DeleteProgram(s.program) + }) +} + +// Begin starts using a shader program. +func (s *Shader) Begin() { + s.parent.Begin() + Do(func() { + gl.UseProgram(s.program) + }) +} + +// End stops using a shader program. +func (s *Shader) End() { + Do(func() { + gl.UseProgram(0) + }) + s.parent.End() +} diff --git a/pixelgl/texture.go b/pixelgl/texture.go index d9cad7b036392654416edf4921ab4c06ba6a4ce1..021873051edf1f0f40872797f59272fcfb41ef4e 100644 --- a/pixelgl/texture.go +++ b/pixelgl/texture.go @@ -40,6 +40,13 @@ func NewTexture(parent BeginEnder, width, height int, pixels []uint8) (*Texture, return texture, nil } +// Delete deletes a texture. Don't use a texture after deletion. +func (t *Texture) Delete() { + Do(func() { + gl.DeleteTextures(1, &t.tex) + }) +} + // Begin binds a texture. func (t *Texture) Begin() { t.parent.Begin() diff --git a/pixelgl/vertex.go b/pixelgl/vertex.go index 63cc498ace23de8f0e7931cb97ae5f7e0a003e1c..2b172600a4887d10201c56735322bff2c4b5b1d4 100644 --- a/pixelgl/vertex.go +++ b/pixelgl/vertex.go @@ -139,6 +139,14 @@ func NewVertexArray(parent BeginEnder, format VertexFormat, mode VertexDrawMode, return va, nil } +// Delete deletes a vertex array and it's associated vertex buffer. Don't use a vertex array after deletion. +func (va *VertexArray) Delete() { + Do(func() { + gl.DeleteVertexArrays(1, &va.vao) + gl.DeleteBuffers(1, &va.vbo) + }) +} + // VertexFormat returns the format of the vertices inside a vertex array. // // Do not change this format!