commit e189458839b984fd4ea4f16eadc8b1ef69aadcf3
parent 1ec5b8b3dd5c6bd525846632517b91f1b97d2c84
Author: Matsuda Kenji <info@mtkn.jp>
Date: Sat, 9 Nov 2024 08:45:19 +0900
lighting
Diffstat:
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 {