mirror of
https://github.com/bloeys/nmage.git
synced 2025-12-29 05:18:21 +00:00
Shader handling
This commit is contained in:
32
main.go
32
main.go
@ -4,8 +4,9 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/bloeys/go-sdl-engine/input"
|
||||
"github.com/bloeys/go-sdl-engine/shaders"
|
||||
"github.com/bloeys/go-sdl-engine/timing"
|
||||
"github.com/go-gl/gl/v4.6-compatibility/gl"
|
||||
"github.com/go-gl/gl/v4.6-core/gl"
|
||||
"github.com/veandco/go-sdl2/sdl"
|
||||
)
|
||||
|
||||
@ -50,8 +51,7 @@ func main() {
|
||||
panicIfErr(err, "")
|
||||
|
||||
//Run in compatiability (old and modern opengl) or modern (core) opengl only
|
||||
// sdl.GLSetAttribute(sdl.GL_CONTEXT_PROFILE_MASK, sdl.GL_CONTEXT_PROFILE_CORE)
|
||||
err = sdl.GLSetAttribute(sdl.GL_CONTEXT_PROFILE_MASK, sdl.GL_CONTEXT_PROFILE_COMPATIBILITY)
|
||||
err = sdl.GLSetAttribute(sdl.GL_CONTEXT_PROFILE_MASK, sdl.GL_CONTEXT_PROFILE_CORE)
|
||||
panicIfErr(err, "")
|
||||
|
||||
//Set wanted opengl version
|
||||
@ -86,6 +86,7 @@ func main() {
|
||||
}
|
||||
|
||||
initGL()
|
||||
loadShaders()
|
||||
gameLoop()
|
||||
}
|
||||
|
||||
@ -99,6 +100,18 @@ func initGL() {
|
||||
gl.Viewport(0, 0, winWidth, winHeight)
|
||||
}
|
||||
|
||||
func loadShaders() {
|
||||
|
||||
simpleProg := shaders.NewProgram("simple")
|
||||
simpleVert, err := shaders.NewShaderFromFile("./res/shaders/simple.vert.glsl", shaders.Vertex)
|
||||
panicIfErr(err, "Parsing vert shader failed")
|
||||
simpleFrag, err := shaders.NewShaderFromFile("./res/shaders/simple.frag.glsl", shaders.Fragment)
|
||||
panicIfErr(err, "Parsing frag shader failed")
|
||||
|
||||
simpleProg.AttachShader(simpleVert)
|
||||
simpleProg.AttachShader(simpleFrag)
|
||||
}
|
||||
|
||||
func gameLoop() {
|
||||
|
||||
for isRunning {
|
||||
@ -138,24 +151,11 @@ func handleEvents() {
|
||||
}
|
||||
|
||||
func update() {
|
||||
println(input.AnyKeyDown(), ";", input.AnyMouseBtnDown())
|
||||
}
|
||||
|
||||
func draw() {
|
||||
//Clear screen and depth buffers
|
||||
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
|
||||
|
||||
gl.Begin(gl.TRIANGLES)
|
||||
|
||||
gl.Color3f(1, 0, 0)
|
||||
gl.Vertex3f(0, 0.5, 0)
|
||||
|
||||
gl.Color3f(1, 0, 0)
|
||||
gl.Vertex3f(0.5, 0, 0)
|
||||
|
||||
gl.Color3f(1, 0, 0)
|
||||
gl.Vertex3f(-0.5, 0, 0)
|
||||
gl.End()
|
||||
}
|
||||
|
||||
func panicIfErr(err error, msg string) {
|
||||
|
||||
5
res/shaders/simple.frag.glsl
Executable file
5
res/shaders/simple.frag.glsl
Executable file
@ -0,0 +1,5 @@
|
||||
#version 400
|
||||
|
||||
void main() {
|
||||
|
||||
}
|
||||
5
res/shaders/simple.vert.glsl
Executable file
5
res/shaders/simple.vert.glsl
Executable file
@ -0,0 +1,5 @@
|
||||
#version 400
|
||||
|
||||
void main() {
|
||||
|
||||
}
|
||||
89
shaders/program.go
Executable file
89
shaders/program.go
Executable file
@ -0,0 +1,89 @@
|
||||
package shaders
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/go-gl/gl/v4.6-core/gl"
|
||||
)
|
||||
|
||||
type Program struct {
|
||||
Name string
|
||||
ID uint32
|
||||
Shaders []Shader
|
||||
}
|
||||
|
||||
func NewProgram(name string) Program {
|
||||
|
||||
p := Program{Name: name}
|
||||
p.Shaders = make([]Shader, 0)
|
||||
|
||||
if p.ID = gl.CreateProgram(); p.ID == 0 {
|
||||
log.Fatalln("Creating OpenGL program failed")
|
||||
}
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
//AttachShader adds the shader to list of shaders and attaches it in opengl
|
||||
func (p *Program) AttachShader(s Shader) {
|
||||
|
||||
p.Shaders = append(p.Shaders, s)
|
||||
gl.AttachShader(p.ID, s.ID)
|
||||
}
|
||||
|
||||
//DetachShader removes the shader from the list of shaders and detaches it in opengl
|
||||
func (p *Program) DetachShader(s Shader) {
|
||||
|
||||
//To remove a shader we move the last shader to its place, then shrink the slice by one
|
||||
for i := 0; i < len(p.Shaders); i++ {
|
||||
|
||||
if p.Shaders[i].ID != s.ID {
|
||||
continue
|
||||
}
|
||||
|
||||
gl.DetachShader(p.ID, s.ID)
|
||||
|
||||
p.Shaders[i] = p.Shaders[len(p.Shaders)-1]
|
||||
p.Shaders = p.Shaders[:len(p.Shaders)-1]
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Program) Link() error {
|
||||
|
||||
gl.LinkProgram(p.ID)
|
||||
return getProgramLinkError(*p)
|
||||
}
|
||||
|
||||
func getProgramLinkError(p Program) error {
|
||||
|
||||
var linkSuccessful int32
|
||||
gl.GetProgramiv(p.ID, gl.LINK_STATUS, &linkSuccessful)
|
||||
if linkSuccessful == gl.TRUE {
|
||||
return nil
|
||||
}
|
||||
|
||||
//Get the log length and create a string big enough for it and fill it with NULL
|
||||
var logLength int32
|
||||
gl.GetProgramiv(p.ID, gl.INFO_LOG_LENGTH, &logLength)
|
||||
infoLog := gl.Str(strings.Repeat("\x00", int(logLength)))
|
||||
|
||||
//Read the error log and return a go error
|
||||
gl.GetProgramInfoLog(p.ID, logLength, nil, infoLog)
|
||||
return fmt.Errorf("Program linking failed. Linking log: %s", gl.GoStr(infoLog))
|
||||
}
|
||||
|
||||
func (p *Program) Use() {
|
||||
gl.UseProgram(p.ID)
|
||||
}
|
||||
|
||||
//Delete deletes all shaders and then deletes the program
|
||||
func (p *Program) Delete() {
|
||||
for _, v := range p.Shaders {
|
||||
v.Delete()
|
||||
}
|
||||
|
||||
gl.DeleteProgram(p.ID)
|
||||
}
|
||||
65
shaders/shader.go
Executable file
65
shaders/shader.go
Executable file
@ -0,0 +1,65 @@
|
||||
package shaders
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/go-gl/gl/v4.6-core/gl"
|
||||
)
|
||||
|
||||
type Shader struct {
|
||||
ID uint32
|
||||
Type ShaderType
|
||||
}
|
||||
|
||||
//NewShaderFromFile reads a shader from file, creates a new opengl shader and compiles it
|
||||
func NewShaderFromFile(shaderFilePath string, st ShaderType) (Shader, error) {
|
||||
|
||||
b, err := os.ReadFile(shaderFilePath)
|
||||
if err != nil {
|
||||
return Shader{}, err
|
||||
}
|
||||
|
||||
return NewShaderFromString(string(b), st)
|
||||
}
|
||||
|
||||
//NewShaderFromString creates a new opengl shader and compiles it
|
||||
func NewShaderFromString(sourceString string, st ShaderType) (Shader, error) {
|
||||
|
||||
glString, freeFunc := gl.Strs(sourceString + "\x00")
|
||||
defer freeFunc()
|
||||
|
||||
newShader := Shader{Type: st}
|
||||
if newShader.ID = gl.CreateShader(st.GLType()); newShader.ID == 0 {
|
||||
log.Fatalln("Creating shader failed. ShaderType:", st)
|
||||
}
|
||||
|
||||
gl.ShaderSource(newShader.ID, 1, glString, nil)
|
||||
gl.CompileShader(newShader.ID)
|
||||
|
||||
return newShader, getShaderCompileError(newShader)
|
||||
}
|
||||
|
||||
func getShaderCompileError(s Shader) error {
|
||||
|
||||
var compileSuccessful int32
|
||||
gl.GetShaderiv(s.ID, gl.COMPILE_STATUS, &compileSuccessful)
|
||||
if compileSuccessful == gl.TRUE {
|
||||
return nil
|
||||
}
|
||||
|
||||
//Get the log length and create a string big enough for it and fill it with NULL
|
||||
var logLength int32
|
||||
gl.GetShaderiv(s.ID, gl.INFO_LOG_LENGTH, &logLength)
|
||||
infoLog := gl.Str(strings.Repeat("\x00", int(logLength)))
|
||||
|
||||
//Read the error log and return a go error
|
||||
gl.GetShaderInfoLog(s.ID, logLength, nil, infoLog)
|
||||
return fmt.Errorf("Shader compilation failed. Compilation log: %s", gl.GoStr(infoLog))
|
||||
}
|
||||
|
||||
func (s *Shader) Delete() {
|
||||
gl.DeleteShader(s.ID)
|
||||
}
|
||||
45
shaders/shader_type.go
Executable file
45
shaders/shader_type.go
Executable file
@ -0,0 +1,45 @@
|
||||
package shaders
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/go-gl/gl/v4.6-core/gl"
|
||||
)
|
||||
|
||||
type ShaderType int
|
||||
|
||||
const (
|
||||
Unknown ShaderType = iota
|
||||
Vertex
|
||||
Fragment
|
||||
)
|
||||
|
||||
//GLType returns the GL shader type of this ShaderType
|
||||
//Panics if not known
|
||||
func (t ShaderType) GLType() uint32 {
|
||||
|
||||
switch t {
|
||||
case Vertex:
|
||||
return gl.VERTEX_SHADER
|
||||
case Fragment:
|
||||
return gl.FRAGMENT_SHADER
|
||||
}
|
||||
|
||||
log.Panicf("Converting ShaderType->GL Shader Type failed. Unknown ShaderType of value: %v\n", t)
|
||||
return 0
|
||||
}
|
||||
|
||||
//FromGLShaderType returns the ShaderType of the passed GL shader type.
|
||||
//Panics if not known
|
||||
func (t ShaderType) FromGLShaderType(glShaderType int) ShaderType {
|
||||
|
||||
switch glShaderType {
|
||||
case gl.VERTEX_SHADER:
|
||||
return Vertex
|
||||
case gl.FRAGMENT_SHADER:
|
||||
return Fragment
|
||||
default:
|
||||
log.Printf("Converting GL shader type->ShaderType failed. Unknown GL shader type of value: %v\n", glShaderType)
|
||||
return Unknown
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user