tofu

Making something with OpenGL in Go
Log | Files | Refs

commit e189458839b984fd4ea4f16eadc8b1ef69aadcf3
parent 1ec5b8b3dd5c6bd525846632517b91f1b97d2c84
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Sat,  9 Nov 2024 08:45:19 +0900

lighting

Diffstat:
Acamera.go | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Mcmd/sample/fragment.glsl | 9+++------
Acmd/sample/light_fragment.glsl | 7+++++++
Mcmd/sample/main.go | 107+++++++++++++++++++++++++++++++++++++++----------------------------------------
Mcmd/sample/vertex.glsl | 4----
Aerror.go | 15+++++++++++++++
Mmath.go | 2+-
Mobject.go | 22+++++++---------------
Mshader.go | 9+++++++++
9 files changed, 146 insertions(+), 80 deletions(-)

diff --git a/camera.go b/camera.go @@ -0,0 +1,50 @@ +package tofu + +type Camera struct { + Pos, Front, Up, Right Vec3 +} + +func NewCamera() *Camera { + return &Camera{ + Pos: Vec3{0, 0, 0}, + Front: Vec3{0, 0, 1}, + Up: Vec3{0, 1, 0}, + Right: Vec3{1, 0, 0}, + } +} + +func (cam *Camera) MoveTo(target Vec3) { + cam.Pos = target +} + +func (cam *Camera) Move(right, up, back float32) { + cam.Pos = cam.Pos.Add(cam.Right.MulF(right)). + Add(cam.Up.MulF(up)). + Add(cam.Front.MulF(-back)) +} + +func (cam *Camera) Yaw(delta float32) { + rot := Rotate3(delta, cam.Up) + cam.Front = rot.MulV(cam.Front) + cam.Right = rot.MulV(cam.Right) +} + +func (cam *Camera) Pitch(delta float32) { + rot := Rotate3(-delta, cam.Right) + cam.Front = rot.MulV(cam.Front) + cam.Up = rot.MulV(cam.Up) +} + +func (cam *Camera) LookAt(target Vec3) { + cam.Front = target.Sub(cam.Pos).Normalize() + cam.Right = cam.Up.Cross(cam.Front.Inverse()).Normalize() +} + +func (cam *Camera) View() Mat4 { + return Mat4{ + cam.Right[0], cam.Up[0], -cam.Front[0], 0, + cam.Right[1], cam.Up[1], -cam.Front[1], 0, + cam.Right[2], cam.Up[2], -cam.Front[2], 0, + 0, 0, 0, 1, + }.Mul(Translate(cam.Pos.Inverse())) +} +\ No newline at end of file diff --git a/cmd/sample/fragment.glsl b/cmd/sample/fragment.glsl @@ -1,11 +1,8 @@ #version 330 core -in vec3 vcol; -in vec2 texCoord; -uniform sampler2D texture1; -uniform sampler2D texture2; -uniform float alpha; +uniform vec3 lightCol; +uniform vec3 objCol; out vec4 fcol; void main() { - fcol = mix(texture(texture1, texCoord), texture(texture2, texCoord), alpha); + fcol = vec4(objCol * lightCol, 1.0); } diff --git a/cmd/sample/light_fragment.glsl b/cmd/sample/light_fragment.glsl @@ -0,0 +1,7 @@ +#version 330 core +uniform vec3 lightCol; +out vec4 fcol; +void main() { + fcol = vec4(lightCol, 1.0); +} + diff --git a/cmd/sample/main.go b/cmd/sample/main.go @@ -6,6 +6,7 @@ import ( "math" "path/filepath" "runtime" + "unsafe" "github.com/go-gl/gl/v3.3-core/gl" "github.com/go-gl/glfw/v3.3/glfw" @@ -87,16 +88,20 @@ func mouseCallback(w *glfw.Window, x, y float64) { camera.Pitch(dy) } +func messageCallback(source, gltype, id, severity uint32, length int32, message string, userProgram unsafe.Pointer) { + log.Printf("debug: type = 0x%x, severity = 0x%x, message = %s", gltype, severity, message) +} + var object = tofu.Object{ - Vertices: []tofu.Point3D{ - tofu.Point3D{0.5, 0.5, -0.5}, - tofu.Point3D{0.5, -0.5, -0.5}, - tofu.Point3D{-0.5, -0.5, -0.5}, - tofu.Point3D{-0.5, 0.5, -0.5}, - tofu.Point3D{0.5, 0.5, 0.5}, - tofu.Point3D{0.5, -0.5, 0.5}, - tofu.Point3D{-0.5, -0.5, 0.5}, - tofu.Point3D{-0.5, 0.5, 0.5}, + Vertices: []tofu.Vec3{ + tofu.Vec3{0.5, 0.5, -0.5}, + tofu.Vec3{0.5, -0.5, -0.5}, + tofu.Vec3{-0.5, -0.5, -0.5}, + tofu.Vec3{-0.5, 0.5, -0.5}, + tofu.Vec3{0.5, 0.5, 0.5}, + tofu.Vec3{0.5, -0.5, 0.5}, + tofu.Vec3{-0.5, -0.5, 0.5}, + tofu.Vec3{-0.5, 0.5, 0.5}, }, Colors: []color.Color{ color.RGBA{255, 0, 0, 255}, @@ -108,15 +113,15 @@ var object = tofu.Object{ color.RGBA{0, 0, 255, 255}, color.RGBA{255, 255, 0, 255}, }, - TexCoords: []tofu.Point2D{ - tofu.Point2D{1.0, 1.0}, - tofu.Point2D{1.0, 0.0}, - tofu.Point2D{0.0, 0.0}, - tofu.Point2D{0.0, 1.0}, - tofu.Point2D{1.0, 1.0}, - tofu.Point2D{1.0, 0.0}, - tofu.Point2D{0.0, 0.0}, - tofu.Point2D{0.0, 1.0}, + TexCoords: []tofu.Vec2{ + tofu.Vec2{1.0, 1.0}, + tofu.Vec2{1.0, 0.0}, + tofu.Vec2{0.0, 0.0}, + tofu.Vec2{0.0, 1.0}, + tofu.Vec2{1.0, 1.0}, + tofu.Vec2{1.0, 0.0}, + tofu.Vec2{0.0, 0.0}, + tofu.Vec2{0.0, 1.0}, }, Faces: [][3]uint32{ {0, 1, 2}, @@ -134,19 +139,6 @@ var object = tofu.Object{ }, } -var cubePositions = []tofu.Vec3{ - {0, 0, 0}, - {2, 5, -15}, - {-1.5, -2.2, -2.5}, - {-3.8, -2, -12.3}, - {2.4, -0.4, -3.5}, - {-1.7, 3.0, -7.5}, - {1.3, -2.0, -2.5}, - {1.5, 2.0, -2.5}, - {1.5, 0.2, -1.5}, - {-1.3, 1.0, -1.5}, -} - var alpha float32 = 0.2 func main() { @@ -169,14 +161,16 @@ func main() { } gl.Viewport(0, 0, winW, winH) + gl.Enable(gl.DEBUG_OUTPUT) + gl.DebugMessageCallback(messageCallback, nil) + _, f, _, ok := runtime.Caller(0) if !ok { log.Fatalf("unable to get source file information") } vpath := filepath.Join(filepath.Dir(f), "vertex.glsl") fpath := filepath.Join(filepath.Dir(f), "fragment.glsl") - texpath1 := filepath.Join(filepath.Dir(f), "container.jpg") - texpath2 := filepath.Join(filepath.Dir(f), "awesomeface.png") + lightFpath := filepath.Join(filepath.Dir(f), "light_fragment.glsl") object.Load() @@ -184,20 +178,13 @@ func main() { if err != nil { log.Fatalf("create shader program: %v", err) } - texture1, err := tofu.NewTexture(texpath1) - if err != nil { - log.Fatalf("create texture: %v", err) - } - texture2, err := tofu.NewTextureFlip(texpath2, true, false) + lightProgram, err := tofu.NewProgram(vpath, lightFpath) if err != nil { - log.Fatalf("create texture: %v", err) - } - if err := program.SetTexture(texture1, "texture1"); err != nil { - log.Fatalf("set texture: %v", err) - } - if err := program.SetTexture(texture2, "texture2"); err != nil { - log.Fatalf("set texture: %v", err) + log.Fatalf("create light shader program: %v", err) } + objCol := tofu.Vec3{1.0, 0.5, 0.32} + lightCol := tofu.Vec3{1.0, 1.0, 1.0} + gl.Enable(gl.DEPTH_TEST) camera = tofu.NewCamera() @@ -210,20 +197,32 @@ func main() { for !window.ShouldClose() { keyboardCallback(window) - gl.ClearColor(0.2, 0.3, 0.3, 1.0) + gl.ClearColor(0.1, 0.2, 0.2, 1.0) gl.Clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT) - program.SetFloat32("alpha", alpha) view := camera.View() projection := tofu.Perspective(80*math.Pi/180, 800/600, 0.1, 100) + + program.Use() program.SetMat4("view", view) program.SetMat4("projection", projection) - for _, p := range cubePositions { - model := tofu.Translate(p). - Mul(tofu.Rotate(float32(glfw.GetTime()), tofu.Vec3{0, 0, 1})). - Mul(tofu.Rotate(float32(glfw.GetTime()), tofu.Vec3{0, 1, 0})) - program.SetMat4("model", model) - gl.DrawElements(gl.TRIANGLES, 36, gl.UNSIGNED_INT, nil) - } + model := tofu.Translate(tofu.Vec3{0, 0, 0}). + Mul(tofu.Rotate(float32(glfw.GetTime()), tofu.Vec3{0, 0, 1})). + Mul(tofu.Rotate(float32(glfw.GetTime()), tofu.Vec3{0, 1, 0})) + program.SetMat4("model", model) + program.SetVec3("lightCol", lightCol) + program.SetVec3("objCol", objCol) + + gl.DrawElements(gl.TRIANGLES, 36, gl.UNSIGNED_INT, nil) + lightProgram.Use() + lightProgram.SetMat4("view", view) + lightProgram.SetMat4("projection", projection) + model = tofu.Translate(tofu.Vec3{3, 3, 0}). + Mul(tofu.Rotate(float32(glfw.GetTime()), tofu.Vec3{0, 0, 1})). + Mul(tofu.Rotate(float32(glfw.GetTime()), tofu.Vec3{0, 1, 0})) + lightProgram.SetMat4("model", model) + lightProgram.SetVec3("lightCol", lightCol) + gl.DrawElements(gl.TRIANGLES, 36, gl.UNSIGNED_INT, nil) + window.SwapBuffers() glfw.PollEvents() } diff --git a/cmd/sample/vertex.glsl b/cmd/sample/vertex.glsl @@ -2,12 +2,8 @@ layout (location = 0) in vec3 pos; layout (location = 1) in vec3 col; layout (location = 2) in vec2 vtexCoord; -out vec3 vcol; -out vec2 texCoord; uniform mat4 projection, view, model; void main() { gl_Position = projection * view * model * vec4(pos, 1.0); - vcol = col; - texCoord = vtexCoord; } diff --git a/error.go b/error.go @@ -0,0 +1,14 @@ +package tofu + +import ( + "fmt" + "github.com/go-gl/gl/v3.3-core/gl" +) + +func Error() error { + errno := gl.GetError() + if errno == gl.NO_ERROR { + return nil + } + return fmt.Errorf("err: 0x%04X", errno) +} +\ No newline at end of file diff --git a/math.go b/math.go @@ -2,9 +2,9 @@ package tofu import "math" +type Vec2 [2]float32 type Vec3 [3]float32 - func (v Vec3) Normalize() Vec3 { r := float32(math.Sqrt(float64(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]))) return Vec3{v[0] / r, v[1] / r, v[2] / r} diff --git a/object.go b/object.go @@ -6,18 +6,10 @@ import ( "github.com/go-gl/gl/v3.3-core/gl" ) -type Point2D struct { - X, Y float32 -} - -type Point3D struct { - X, Y, Z float32 -} - type Object struct { - Vertices []Point3D + Vertices []Vec3 Colors []color.Color - TexCoords []Point2D + TexCoords []Vec2 Faces [][3]uint32 vao *VAO } @@ -25,15 +17,15 @@ type Object struct { func (obj Object) data() []float32 { data := make([]float32, 8 * len(obj.Vertices)) for i := 0; i < len(obj.Vertices); i++ { - data[8 * i] = obj.Vertices[i].X - data[8 * i + 1] = obj.Vertices[i].Y - data[8 * i + 2] = obj.Vertices[i].Z + data[8 * i] = obj.Vertices[i][0] + data[8 * i + 1] = obj.Vertices[i][1] + data[8 * i + 2] = obj.Vertices[i][2] r, g, b, _ := obj.Colors[i].RGBA() data[8 * i + 3] = float32(r)/0xffff data[8 * i + 4] = float32(g)/0xffff data[8 * i + 5] = float32(b)/0xffff - data[8 * i + 6] = obj.TexCoords[i].X - data[8 * i + 7] = obj.TexCoords[i].Y + data[8 * i + 6] = obj.TexCoords[i][0] + data[8 * i + 7] = obj.TexCoords[i][1] } return data } diff --git a/shader.go b/shader.go @@ -98,6 +98,15 @@ func (p *Program) SetFloat32(name string, val float32) error { return nil } +func (p *Program) SetVec3(name string, val Vec3) error { + l := gl.GetUniformLocation(p.id, gl.Str(name + "\x00")) + if l == -1 { + return fmt.Errorf("uniform %s not found", name) + } + gl.Uniform3fv(l, 1, &val[0]) + return nil +} + func (p *Program) SetMat4(name string, val Mat4) error { l := gl.GetUniformLocation(p.id, gl.Str(name + "\x00")) if l == -1 {