diff --git a/main.go b/main.go index 1db7270..87dba0b 100755 --- a/main.go +++ b/main.go @@ -39,7 +39,7 @@ func main() { defer sdl.GLDeleteContext(glCtx) initOpenGL() - shaders.LoadShaders() + loadShaders() //Game loop for isRunning { @@ -67,11 +67,34 @@ func initOpenGL() { sdl.GLSetAttribute(sdl.GL_BLUE_SIZE, 8) sdl.GLSetAttribute(sdl.GL_DOUBLEBUFFER, 1) + gl.ClearColor(0, 0, 0, 1) sdl.GLSetAttribute(sdl.GL_CONTEXT_PROFILE_MASK, sdl.GL_CONTEXT_PROFILE_COMPATIBILITY) // sdl.GLSetAttribute(sdl.GL_CONTEXT_PROFILE_MASK, sdl.GL_CONTEXT_PROFILE_CORE) } +func loadShaders() { + + simpleShader, err := shaders.NewShaderProgram() + if err != nil { + logging.ErrLog.Fatalln("Failed to create new shader program. Err: ", err) + } + + vertShader, err := shaders.LoadAndCompilerShader("./res/shaders/simple.vert.glsl", shaders.VertexShaderType) + if err != nil { + logging.ErrLog.Fatalln("Failed to create new shader. Err: ", err) + } + + fragShader, err := shaders.LoadAndCompilerShader("./res/shaders/simple.frag.glsl", shaders.FragmentShaderType) + if err != nil { + logging.ErrLog.Fatalln("Failed to create new shader. Err: ", err) + } + + simpleShader.AttachShader(vertShader) + simpleShader.AttachShader(fragShader) + simpleShader.Link() +} + func handleInputs() { input.EventLoopStart() @@ -95,4 +118,20 @@ func runGameLogic() { } func draw() { + + gl.Clear(gl.COLOR_BUFFER_BIT) + + gl.Begin(gl.TRIANGLES) + + gl.Vertex3f(-0.5, 0.5, 0) + gl.Vertex3f(0.5, 0.5, 0) + gl.Vertex3f(-0.5, -0.5, 0) + + gl.Vertex3f(0.5, 0.5, 0) + gl.Vertex3f(0.5, -0.5, 0) + gl.Vertex3f(-0.5, -0.5, 0) + + gl.End() + + window.GLSwap() } diff --git a/res/shaders/simple.frag.glsl b/res/shaders/simple.frag.glsl index dd78aac..32fb60e 100755 --- a/res/shaders/simple.frag.glsl +++ b/res/shaders/simple.frag.glsl @@ -5,4 +5,4 @@ out vec4 FragColor; void main() { FragColor = vec4(1, 0, 0, 1.0); -} \ No newline at end of file +} diff --git a/shaders/shader_types.go b/shaders/shader_types.go new file mode 100755 index 0000000..f462404 --- /dev/null +++ b/shaders/shader_types.go @@ -0,0 +1,10 @@ +package shaders + +import "github.com/go-gl/gl/v4.6-compatibility/gl" + +type ShaderType int + +const ( + VertexShaderType ShaderType = gl.VERTEX_SHADER + FragmentShaderType ShaderType = gl.FRAGMENT_SHADER +) diff --git a/shaders/shaders.go b/shaders/shaders.go index 925e7f7..aa8a92e 100755 --- a/shaders/shaders.go +++ b/shaders/shaders.go @@ -1,6 +1,7 @@ package shaders import ( + "errors" "os" "strings" @@ -8,58 +9,94 @@ import ( "github.com/go-gl/gl/v4.6-compatibility/gl" ) +type Shader struct { + ID uint32 + ShaderType ShaderType +} + +func (s Shader) Delete() { + gl.DeleteShader(s.ID) +} + type ShaderProgram struct { ID uint32 VertShaderID uint32 FragShaderID uint32 } -func LoadShaders() { +func (sp *ShaderProgram) AttachShader(shader Shader) { - vertShaderText, err := os.ReadFile("./res/shaders/simple.vert.glsl") - if err != nil { - logging.ErrLog.Fatalln("Failed to read vertex shader. Err: ", err) + gl.AttachShader(sp.ID, shader.ID) + switch shader.ShaderType { + case VertexShaderType: + sp.VertShaderID = shader.ID + case FragmentShaderType: + sp.FragShaderID = shader.ID + default: + logging.ErrLog.Println("Unknown shader type ", shader.ShaderType, " for ID ", shader.ID) } - - fragShaderText, err := os.ReadFile("./res/shaders/simple.frag.glsl") - if err != nil { - logging.ErrLog.Fatalln("Failed to read fragment shader. Err: ", err) - } - - shader := &ShaderProgram{} - shader.ID = gl.CreateProgram() - if shader.ID == 0 { - logging.ErrLog.Fatalln("Failed to create shader program") - } - - shader.VertShaderID = gl.CreateShader(gl.VERTEX_SHADER) - shader.FragShaderID = gl.CreateShader(gl.FRAGMENT_SHADER) - - vertexCStr, vertFree := gl.Strs(string(vertShaderText) + "\x00") - defer vertFree() - gl.ShaderSource(shader.VertShaderID, 1, vertexCStr, nil) - - fragCStr, fragFree := gl.Strs(string(fragShaderText) + "\x00") - defer fragFree() - gl.ShaderSource(shader.FragShaderID, 1, fragCStr, nil) - - gl.CompileShader(shader.VertShaderID) - getShaderCompileErrors(shader.VertShaderID) - - gl.CompileShader(shader.FragShaderID) - getShaderCompileErrors(shader.FragShaderID) - - gl.AttachShader(shader.ID, shader.VertShaderID) - gl.AttachShader(shader.ID, shader.FragShaderID) - gl.LinkProgram(shader.ID) } -func getShaderCompileErrors(shaderID uint32) { +func (sp *ShaderProgram) Link() { + + gl.LinkProgram(sp.ID) + + if sp.VertShaderID != 0 { + gl.DeleteShader(sp.VertShaderID) + } + if sp.FragShaderID != 0 { + gl.DeleteShader(sp.FragShaderID) + } +} + +func (sp *ShaderProgram) Delete() { + gl.DeleteProgram(sp.ID) +} + +func NewShaderProgram() (ShaderProgram, error) { + + id := gl.CreateProgram() + if id == 0 { + return ShaderProgram{}, errors.New("failed to create shader program") + } + + return ShaderProgram{ID: id}, nil +} + +func LoadAndCompilerShader(shaderPath string, shaderType ShaderType) (Shader, error) { + + shaderSource, err := os.ReadFile(shaderPath) + if err != nil { + logging.ErrLog.Println("Failed to read shader. Err: ", err) + return Shader{}, err + } + + shaderID := gl.CreateShader(uint32(shaderType)) + if shaderID == 0 { + logging.ErrLog.Println("Failed to create shader.") + return Shader{}, errors.New("failed to create shader") + } + + //Load shader source and compile + shaderCStr, shaderFree := gl.Strs(string(shaderSource) + "\x00") + defer shaderFree() + gl.ShaderSource(shaderID, 1, shaderCStr, nil) + + gl.CompileShader(shaderID) + if err := getShaderCompileErrors(shaderID); err != nil { + gl.DeleteShader(shaderID) + return Shader{}, err + } + + return Shader{ID: shaderID, ShaderType: shaderType}, nil +} + +func getShaderCompileErrors(shaderID uint32) error { var compiledSuccessfully int32 gl.GetShaderiv(shaderID, gl.COMPILE_STATUS, &compiledSuccessfully) if compiledSuccessfully == gl.TRUE { - return + return nil } var logLength int32 @@ -69,5 +106,6 @@ func getShaderCompileErrors(shaderID uint32) { gl.GetShaderInfoLog(shaderID, logLength, nil, log) errMsg := gl.GoStr(log) - println("Compilation of shader with id ", shaderID, " failed. Err: ", errMsg) + logging.ErrLog.Println("Compilation of shader with id ", shaderID, " failed. Err: ", errMsg) + return errors.New(errMsg) }