opengl-deferred/types/shader/shader.go

100 lines
2.2 KiB
Go
Raw Normal View History

2024-10-11 16:38:21 +00:00
package shader
import (
"errors"
"strings"
"github.com/go-gl/gl/v4.6-core/gl"
2024-10-11 23:02:12 +00:00
"github.com/go-gl/mathgl/mgl32"
2024-10-11 16:38:21 +00:00
)
type Shader struct {
program uint32
2024-10-11 23:02:12 +00:00
uniforms map[string]int32
2024-10-11 16:38:21 +00:00
}
func (s *Shader) Use() {
gl.UseProgram(s.program)
}
func (s *Shader) Delete() {
gl.DeleteProgram(s.program)
}
2024-10-11 23:02:12 +00:00
func (s *Shader) getUniformLocation(name string) int32 {
if val, ok := s.uniforms[name]; ok {
return val
}
uniform := gl.GetUniformLocation(s.program, gl.Str(name+"\x00"))
s.uniforms[name] = uniform
return uniform
}
func (s *Shader) Mat4(name string, mat mgl32.Mat4) {
gl.UniformMatrix4fv(s.getUniformLocation(name), 1, false, &mat[0])
}
func (s *Shader) Int(name string, val int32) {
gl.Uniform1i(s.getUniformLocation(name), val)
}
2024-10-11 16:38:21 +00:00
func compileShader(source string, shaderType uint32) (uint32, error) {
shader := gl.CreateShader(shaderType)
csource, free := gl.Strs(source)
gl.ShaderSource(shader, 1, csource, nil)
free()
gl.CompileShader(shader)
var status int32
gl.GetShaderiv(shader, gl.COMPILE_STATUS, &status)
if status == gl.FALSE {
var logLength int32
gl.GetShaderiv(shader, gl.INFO_LOG_LENGTH, &logLength)
log := strings.Repeat("\x00", int(logLength+1))
gl.GetShaderInfoLog(shader, logLength, nil, gl.Str(log))
return 0, errors.New(log)
}
return shader, nil
}
func New(vertexSource string, fragmantSource string) (shader Shader, _ error) {
2024-10-11 23:02:12 +00:00
shader.uniforms = make(map[string]int32)
2024-10-11 16:38:21 +00:00
vertexShader, err := compileShader(vertexSource, gl.VERTEX_SHADER)
if err != nil {
return shader, err
}
fragmantShader, err := compileShader(fragmantSource, gl.FRAGMENT_SHADER)
if err != nil {
return shader, err
}
shader.program = gl.CreateProgram()
gl.AttachShader(shader.program, vertexShader)
gl.AttachShader(shader.program, fragmantShader)
gl.LinkProgram(shader.program)
defer gl.DeleteShader(vertexShader)
defer gl.DeleteShader(fragmantShader)
var status int32
gl.GetProgramiv(shader.program, gl.LINK_STATUS, &status)
if status == gl.FALSE {
var logLength int32
gl.GetProgramiv(shader.program, gl.INFO_LOG_LENGTH, &logLength)
log := strings.Repeat("\x00", int(logLength+1))
gl.GetProgramInfoLog(shader.program, logLength, nil, gl.Str(log))
return shader, errors.New(log)
}
return shader, nil
}