tofu

Making something with OpenGL in Go
Log | Files | Refs

commit 9cb807c52a03be40dd03fc91695b1efd4684638b
parent a3c25be3ed443829edb81e32c125b8ce4403cfea
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Wed, 20 Nov 2024 16:58:21 +0900

use reflect to upload uniforms

Diffstat:
Mcmd/sample/main.go | 46+++++++++++++++++++++++++++++-----------------
Mobject.go | 35++++++++++++++++++++++++++++++++++-
2 files changed, 63 insertions(+), 18 deletions(-)

diff --git a/cmd/sample/main.go b/cmd/sample/main.go @@ -75,8 +75,29 @@ func watchCursor(app *App) { } } -var teapot *tofu.Object +type Uniform struct { + Sun +} +type Sun struct { + Dir tofu.Vec3 `tofu:"sun.dir"` + Ambient tofu.Vec3 `tofu:"sun.ambient"` + Diffuse tofu.Vec3 `tofu:"sun.diffuse"` + Specular tofu.Vec3 `tofu:"sun.specular"` +} + +var ( + sunCol = tofu.Vec3{1, 1, 1} + sunDir = tofu.Vec3{-0.2, -1.0, -0.3} + sun = Sun{ + Dir: sunDir, + Ambient: sunCol.MulF(0.5), + Diffuse: sunCol.MulF(0.3), + Specular: sunCol, + } +) + +var teapot *tofu.Object var object = &tofu.Object{ Vertices: []tofu.Vec3{ tofu.Vec3{0.5, 0.5, -0.5}, @@ -116,6 +137,7 @@ var object = &tofu.Object{ {{4, 5, 0}, {5, 5, 1}, {6, 5, 2}}, {{4, 5, 0}, {6, 5, 2}, {7, 5, 3}}, }, + Uniforms: Uniform{Sun: sun}, } var cubePositions = []tofu.Vec3{ @@ -157,9 +179,6 @@ func (app *App) Update() error { view := camera.View() projection := tofu.Perspective(80*math.Pi/180, 800/600, 0.1, 100) - sunCol := tofu.Vec3{1, 1, 1} - sunDir := tofu.Vec3{-0.2, -1.0, -0.3} - lightCol := tofu.Vec3{1, 1, 1} lightModel := tofu.Rotate(now, tofu.Vec3{0, 1, 0}). Mul(tofu.Translate(tofu.Vec3{5, 4.5, 0})). @@ -174,10 +193,6 @@ func (app *App) Update() error { app.program.SetTexture("material.diffuse", app.texture) app.program.SetTexture("material.specular", app.specularMap) app.program.SetFloat32("material.shiness", 32) - app.program.SetVec3("sun.dir", sunDir) - app.program.SetVec3("sun.ambient", sunCol.MulF(0.5)) - app.program.SetVec3("sun.diffuse", sunCol.MulF(0.3)) - app.program.SetVec3("sun.specular", sunCol) app.program.SetVec3("light.pos", lightPos) app.program.SetVec3("light.dir", tofu.Vec3{0, 0, 0}.Sub(lightPos)) app.program.SetFloat32("light.cutOff", float32(math.Cos(25*math.Pi/180))) @@ -192,7 +207,7 @@ func (app *App) Update() error { model := tofu.Translate(p.Inverse()) // Mul(tofu.Rotate(20*float32(i)+now, tofu.Vec3{math.Sqrt2 / 2, -math.Sqrt2 / 2, 0})) app.program.SetMat4("model", model) - object.Draw() + object.Draw(app.program) } app.teapotProgram.Use() app.teapotProgram.SetMat4("view", view) @@ -202,28 +217,24 @@ func (app *App) Update() error { app.teapotProgram.SetVec3("material.diffuse", tofu.Vec3{0.3, 0.4, 0.4}) app.teapotProgram.SetVec3("material.specular", tofu.Vec3{0.3, 0.4, 0.4}) app.teapotProgram.SetFloat32("material.shiness", 32) - app.teapotProgram.SetVec3("sun.dir", sunDir) - app.teapotProgram.SetVec3("sun.ambient", sunCol.MulF(0.5)) - app.teapotProgram.SetVec3("sun.diffuse", sunCol.MulF(0.3)) - app.teapotProgram.SetVec3("sun.specular", sunCol) app.teapotProgram.SetVec3("light.pos", lightPos) app.teapotProgram.SetVec3("light.dir", tofu.Vec3{0, 0, 0}.Sub(lightPos)) app.teapotProgram.SetFloat32("light.outerCutOff", float32(math.Cos(35*math.Pi/180))) app.teapotProgram.SetFloat32("light.cutOff", float32(math.Cos(25*math.Pi/180))) - app.teapotProgram.SetVec3("light.ambient", lightCol.MulF(0.4)) - app.teapotProgram.SetVec3("light.diffuse", lightCol.MulF(0.9)) + app.teapotProgram.SetVec3("light.ambient", lightCol.MulF(0.9)) + app.teapotProgram.SetVec3("light.diffuse", lightCol.MulF(0.1)) app.teapotProgram.SetVec3("light.specular", lightCol) app.teapotProgram.SetFloat32("light.Kc", 1.0) app.teapotProgram.SetFloat32("light.Kl", 0.0009) app.teapotProgram.SetFloat32("light.Kq", 0.00032) - teapot.Draw() + teapot.Draw(app.teapotProgram) app.lightProgram.Use() app.program.SetMat4("view", view) app.program.SetMat4("projection", projection) app.program.SetMat4("model", lightModel) app.lightProgram.SetVec3("lightCol", lightCol) - object.Draw() + object.Draw(app.lightProgram) return nil } @@ -261,6 +272,7 @@ func main() { log.Fatal(err) } // teapot.SetNormals() + teapot.Uniforms = sun teapot.Load() app.program, err = tofu.NewProgram(vpath, fpath) diff --git a/object.go b/object.go @@ -6,6 +6,7 @@ import ( "log" "math" "os" + "reflect" "strconv" "strings" @@ -17,6 +18,7 @@ type Object struct { TexCoords []Vec2 Normals []Vec3 Faces []Face + Uniforms interface{} vao *VAO } @@ -237,9 +239,40 @@ func (obj *Object) Load() { obj.vao = newVAO(obj) } -func (obj *Object) Draw() { +func (obj *Object) setUniforms(prog *Program) { + if obj.Uniforms == nil { + return + } + setUniforms(obj.Uniforms, prog) +} + +func setUniforms(uniforms interface{}, prog *Program) { + s := reflect.ValueOf(uniforms) + fields := reflect.VisibleFields(s.Type()) + for i := 0; i < s.NumField(); i++ { + fv := s.Field(i) + ft := fields[i] + if fv.Kind() == reflect.Struct { + setUniforms(fv.Interface(), prog) + continue + } + tag, ok := ft.Tag.Lookup("tofu") + if !ok { + continue + } + switch ft.Type.String() { + case "tofu.Vec3": + log.Println(prog.SetVec3(tag, fv.Interface().(Vec3))) + default: + log.Printf("unknown uniform type: %s", ft.Type) + } + } +} + +func (obj *Object) Draw(prog *Program) { // TODO: performance? obj.vao.bind() + obj.setUniforms(prog) gl.DrawElements(gl.TRIANGLES, int32(obj.stride()*3*len(obj.Faces)), gl.UNSIGNED_INT, nil)