tofu

Making something with OpenGL in Go
Log | Files | Refs

commit 235a82b16717a311840e0086b9e16b22f9756269
parent bdcf1967a838b2f2c0b5fc73c9a0c206c4e83195
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Sat, 19 Oct 2024 14:05:55 +0900

make Shader struct

Diffstat:
Acmd/sample/fragment.glsl | 8++++++++
Mcmd/sample/main.go | 90+++++++++++++++++--------------------------------------------------------------
Acmd/sample/vertex.glsl | 9+++++++++
Ashader.go | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dtest.png | 0
5 files changed, 116 insertions(+), 71 deletions(-)

diff --git a/cmd/sample/fragment.glsl b/cmd/sample/fragment.glsl @@ -0,0 +1,8 @@ + +#version 330 core +in vec3 vcol; +out vec4 fcol; +void main() { + fcol = vec4(vcol, 1); +} + diff --git a/cmd/sample/main.go b/cmd/sample/main.go @@ -1,14 +1,15 @@ package main import ( - "fmt" "log" "math" + "path/filepath" "runtime" - "strings" "github.com/go-gl/gl/v3.3-core/gl" "github.com/go-gl/glfw/v3.3/glfw" + + "git.mtkn.jp/draw" ) const ( @@ -32,69 +33,17 @@ func processInput(w *glfw.Window) { } } -func newShader(src string, xtype uint32) (shader uint32, err error) { - shader = gl.CreateShader(xtype) - cstrs, free := gl.Strs(src + "\x00") - defer free() - gl.ShaderSource(shader, 1, cstrs, nil) - gl.CompileShader(shader) - - var success int32 - gl.GetShaderiv(shader, gl.COMPILE_STATUS, &success) - if success == gl.FALSE { - var logLength int32 - gl.GetShaderiv(shader, gl.INFO_LOG_LENGTH, &logLength) - l := gl.Str(strings.Repeat("\x00", int(logLength))) - gl.GetShaderInfoLog(shader, logLength, nil, l) - gl.DeleteShader(shader) - return 0, fmt.Errorf("%v", gl.GoStr(l)) - } - return shader, nil -} - -func linkShaders(vertexShader, fragmentShader uint32) (shader uint32, err error) { - shader = gl.CreateProgram() - gl.AttachShader(shader, vertexShader) - gl.AttachShader(shader, fragmentShader) - gl.LinkProgram(shader) - - var success int32 - gl.GetProgramiv(shader, gl.LINK_STATUS, &success) - if success == gl.FALSE { - var logLength int32 - gl.GetProgramiv(shader, gl.INFO_LOG_LENGTH, &logLength) - l := gl.Str(strings.Repeat("\x00", int(logLength))) - gl.GetProgramInfoLog(shader, logLength, nil, l) - return 0, fmt.Errorf("%v", gl.GoStr(l)) - } - return shader, nil -} - var vertices = []float32{ - -0.5, -0.5, 0.0, - 0.5, -0.5, 0.0, - 0.0, 0.5, 0.0, + // positions, colors + -0.5, -0.5, 0.0, 1, 0, 0, + 0.5, -0.5, 0.0, 0, 1, 0, + 0.0, 0.5, 0.0, 0, 0, 1, } var indices = []uint32{ 0, 1, 2, } -const vertexShaderSource = `#version 330 core -layout (location = 0) in vec3 aPos; -void main() { - gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0); -} -` - -const fragmentShaderSource = `#version 330 core -out vec4 FragColor; - -void main() { - FragColor = vec4(1.0, 0.5, 0.2, 1.0); -} -` - func main() { err := glfw.Init() if err != nil { @@ -115,20 +64,17 @@ func main() { } gl.Viewport(0, 0, winW, winH) - vertexShader, err := newShader(vertexShaderSource, gl.VERTEX_SHADER) - if err != nil { - log.Fatalf("crete vertex shader: %v", err) - } - fragmentShader, err := newShader(fragmentShaderSource, gl.FRAGMENT_SHADER) - if err != nil { - log.Fatalf("crete fragment shader: %v", err) + _, f, _, ok := runtime.Caller(0) + if !ok { + log.Fatalf("unable to get source file information") } - shaderProgram, err := linkShaders(vertexShader, fragmentShader) + vpath := filepath.Join(filepath.Dir(f), "vertex.glsl") + fpath := filepath.Join(filepath.Dir(f), "fragment.glsl") + + shader, err := draw.NewShader(vpath, fpath) if err != nil { - log.Fatalf("link shaders: %v", err) + log.Fatalf("create shader: %v", err) } - gl.DeleteShader(vertexShader) - gl.DeleteShader(fragmentShader) var VBO, VAO, EBO uint32 gl.GenVertexArrays(1, &VAO) @@ -141,18 +87,20 @@ func main() { gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, EBO) gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, len(indices) * 4, gl.Ptr(indices), gl.STATIC_DRAW) - gl.VertexAttribPointer(0, 3, gl.FLOAT, false, 3*4, nil) + gl.VertexAttribPointerWithOffset(0, 3, gl.FLOAT, false, 6*4, 0) gl.EnableVertexAttribArray(0) + gl.VertexAttribPointerWithOffset(1, 3, gl.FLOAT, false, 6*4, 3*4) + gl.EnableVertexAttribArray(1) gl.BindBuffer(gl.ARRAY_BUFFER, 0); gl.BindVertexArray(0) window.SetFramebufferSizeCallback(framebufferSizeCallback) + shader.Use() for !window.ShouldClose() { processInput(window) gl.ClearColor(0.2, 0.3, 0.3, 1.0) gl.Clear(gl.COLOR_BUFFER_BIT) - gl.UseProgram(shaderProgram) gl.BindVertexArray(VAO) gl.DrawElements(gl.TRIANGLES, 3, gl.UNSIGNED_INT, nil) window.SwapBuffers() diff --git a/cmd/sample/vertex.glsl b/cmd/sample/vertex.glsl @@ -0,0 +1,9 @@ +#version 330 core +layout (location = 0) in vec3 pos; +layout (location = 1) in vec3 col; +out vec3 vcol; +void main() { + gl_Position = vec4(pos.x, -pos.y, pos.z, 1.0); + vcol = col; +} + diff --git a/shader.go b/shader.go @@ -0,0 +1,80 @@ +package draw + +import ( + "fmt" + "os" + "strings" + + "github.com/go-gl/gl/v3.3-core/gl" +) + +func compileShader(path string, xtype uint32) (shaderID uint32, err error) { + src, err := os.ReadFile(path) + if err != nil { + return 0, fmt.Errorf("readfile %s: %v", path, err) + } + shaderID = gl.CreateShader(xtype) + if shaderID == 0 { + return 0, fmt.Errorf("can't create shader") + } + cstrs, free := gl.Strs(string(src) + "\x00") + defer free() + gl.ShaderSource(shaderID, 1, cstrs, nil) + gl.CompileShader(shaderID) + + var success int32 + gl.GetShaderiv(shaderID, gl.COMPILE_STATUS, &success) + if success == gl.FALSE { + var logLength int32 + gl.GetShaderiv(shaderID, gl.INFO_LOG_LENGTH, &logLength) + l := gl.Str(strings.Repeat("\x00", int(logLength))) + gl.GetShaderInfoLog(shaderID, logLength, nil, l) + gl.DeleteShader(shaderID) + return 0, fmt.Errorf("%v", gl.GoStr(l)) + } + return shaderID, nil +} + +func linkShaders(vsID, fsID uint32) (shaderID uint32, err error) { + shaderID = gl.CreateProgram() + gl.AttachShader(shaderID, vsID) + gl.AttachShader(shaderID, fsID) + gl.LinkProgram(shaderID) + + var success int32 + gl.GetProgramiv(shaderID, gl.LINK_STATUS, &success) + if success == gl.FALSE { + var logLength int32 + gl.GetProgramiv(shaderID, gl.INFO_LOG_LENGTH, &logLength) + l := gl.Str(strings.Repeat("\x00", int(logLength))) + gl.GetProgramInfoLog(shaderID, logLength, nil, l) + return 0, fmt.Errorf("%v", gl.GoStr(l)) + } + return shaderID, nil +} + +type Shader struct { + id uint32 +} + +func NewShader(vpath, fpath string) (*Shader, error) { + vid, err := compileShader(vpath, gl.VERTEX_SHADER) + if err != nil { + return nil, fmt.Errorf("compile vertex shader: %v", err) + } + fid, err := compileShader(fpath, gl.FRAGMENT_SHADER) + if err != nil { + return nil, fmt.Errorf("compile fragment shader: %v", err) + } + sid, err := linkShaders(vid, fid) + if err != nil { + return nil, fmt.Errorf("link shaders: %v", err) + } + gl.DeleteShader(vid) + gl.DeleteShader(fid) + return &Shader{id: sid}, nil +} + +func (s *Shader) Use() { + gl.UseProgram(s.id) +} diff --git a/test.png b/test.png Binary files differ.