tofu

Making something with OpenGL in Go
Log | Files | Refs

commit b2d0180669048d007691ba434db948042d6adbc7
parent e928a2c0591c263868bec114b939b1f6c684200d
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Wed, 27 Nov 2024 08:53:22 +0900

muptiple lights

Diffstat:
Mcmd/sample/fragment.glsl | 40+++++++++++++++++++++++++++++++++++++++-
Mcmd/sample/main.go | 87+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
Mcmd/sample/teapot.glsl | 36+++++++++++++++++++++++++++++++++++-
Mshader.go | 16+++++++++++++---
Mtofu.go | 2+-
5 files changed, 147 insertions(+), 34 deletions(-)

diff --git a/cmd/sample/fragment.glsl b/cmd/sample/fragment.glsl @@ -13,6 +13,15 @@ struct DirLight { vec3 Specular; }; +struct PointLight { + vec3 Pos; + vec3 Ambient; + vec3 Diffuse; + vec3 Specular; + + float Kc, Kl, Kq; +}; + struct SpotLight { vec3 Pos; vec3 Dir; @@ -23,6 +32,7 @@ struct SpotLight { float Kc, Kl, Kq; float CutOff, OuterCutOff; }; + in vec3 fnormal; in vec3 fpos; in vec2 texPos; @@ -32,18 +42,46 @@ uniform vec3 objCol; uniform Material Cube; uniform DirLight Sun; uniform SpotLight Light; +uniform PointLight PointLights[10]; out vec4 fcol; +vec3 calcPointLight(PointLight, Material, vec3); vec3 calcSpotLight(SpotLight, Material, vec3); vec3 calcDirLight(DirLight, Material, vec3); void main() { fcol = vec4(0, 0, 0, 1); fcol += vec4(calcSpotLight(Light, Cube, CamPos), 0); - fcol += vec4(calcDirLight(Sun, Cube, CamPos), 0); +// fcol += vec4(calcDirLight(Sun, Cube, CamPos), 0); + for (int i = 0; i < PointLights.length(); i++) { + fcol += vec4(calcPointLight(PointLights[i], Cube, CamPos), 0); + } } +vec3 calcPointLight(PointLight l, Material m, vec3 camPos) { + vec3 ambient, diffuse, specular; + vec3 lightDir, viewDir, reflectDir; + float diff, spec, dist, attenuation; + + dist = length(l.Pos - fpos); + attenuation = 1 / (l.Kc + l.Kl * dist + l.Kq * dist * dist); + + ambient = vec3(texture(m.Diffuse, texPos)) * l.Ambient; + + lightDir = normalize(l.Pos - fpos); + diff = max(dot(fnormal, lightDir), 0.0); + diffuse = diff * vec3(texture(m.Diffuse, texPos)) * l.Diffuse; + + viewDir = normalize(camPos - fpos); + reflectDir = reflect(-lightDir, normalize(fnormal)); + spec = pow(max(dot(viewDir, reflectDir), 0.0), m.Shiness); + specular = vec3(texture(m.Specular, texPos)) * spec * l.Specular; + + return (ambient + diffuse + specular) * attenuation; +} + + vec3 calcSpotLight(SpotLight l, Material m, vec3 camPos) { vec3 ambient, diffuse, specular; vec3 lightDir, viewDir, reflectDir; diff --git a/cmd/sample/main.go b/cmd/sample/main.go @@ -83,6 +83,14 @@ type SpotLight struct { OuterCutOff float32 } +type PointLight struct { + Pos tofu.Vec3 + Ambient tofu.Vec3 + Diffuse tofu.Vec3 + Specular tofu.Vec3 + Kc, Kl, Kq float32 +} + var ( sunCol = tofu.Vec3{1, 1, 1} sun = &DirLight{ @@ -102,6 +110,8 @@ var ( Kl: 0.0009, Kq: 0.00032, } + pointLights = make([]PointLight, 10) + pointLightDiv float32 = 10.0 ) var teapot *tofu.Object @@ -164,25 +174,19 @@ var light = &tofu.Object{ {0.0, 1.0, 0.0}, {0.0, 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}, - }, Faces: []tofu.Face{ - {{0, 0, 0}, {1, 0, 1}, {2, 0, 2}}, - {{0, 0, 0}, {2, 0, 2}, {3, 0, 3}}, - {{0, 1, 0}, {1, 1, 1}, {5, 1, 2}}, - {{0, 1, 0}, {5, 1, 2}, {4, 1, 3}}, - {{1, 2, 0}, {2, 2, 1}, {6, 2, 2}}, - {{1, 2, 0}, {6, 2, 2}, {5, 2, 3}}, - {{2, 3, 0}, {3, 3, 1}, {7, 3, 2}}, - {{2, 3, 0}, {7, 3, 2}, {6, 3, 3}}, - {{3, 4, 0}, {0, 4, 1}, {4, 4, 2}}, - {{3, 4, 0}, {4, 4, 2}, {7, 4, 3}}, - {{4, 5, 0}, {5, 5, 1}, {6, 5, 2}}, - {{4, 5, 0}, {6, 5, 2}, {7, 5, 3}}, + {{0, 0, tofu.NoIndex}, {1, 0, tofu.NoIndex}, {2, 0, tofu.NoIndex}}, + {{0, 0, tofu.NoIndex}, {2, 0, tofu.NoIndex}, {3, 0, tofu.NoIndex}}, + {{0, 1, tofu.NoIndex}, {1, 1, tofu.NoIndex}, {5, 1, tofu.NoIndex}}, + {{0, 1, tofu.NoIndex}, {5, 1, tofu.NoIndex}, {4, 1, tofu.NoIndex}}, + {{1, 2, tofu.NoIndex}, {2, 2, tofu.NoIndex}, {6, 2, tofu.NoIndex}}, + {{1, 2, tofu.NoIndex}, {6, 2, tofu.NoIndex}, {5, 2, tofu.NoIndex}}, + {{2, 3, tofu.NoIndex}, {3, 3, tofu.NoIndex}, {7, 3, tofu.NoIndex}}, + {{2, 3, tofu.NoIndex}, {7, 3, tofu.NoIndex}, {6, 3, tofu.NoIndex}}, + {{3, 4, tofu.NoIndex}, {0, 4, tofu.NoIndex}, {4, 4, tofu.NoIndex}}, + {{3, 4, tofu.NoIndex}, {4, 4, tofu.NoIndex}, {7, 4, tofu.NoIndex}}, + {{4, 5, tofu.NoIndex}, {5, 5, tofu.NoIndex}, {6, 5, tofu.NoIndex}}, + {{4, 5, tofu.NoIndex}, {6, 5, tofu.NoIndex}, {7, 5, tofu.NoIndex}}, }, } @@ -221,11 +225,12 @@ var cubeUniforms = struct { CamPos tofu.Vec3 Trans Trans Cube MaterialTexture - Sun *DirLight - Light *SpotLight + // Sun *DirLight + Light *SpotLight + PointLights []PointLight }{ - Cube: MaterialTexture{Shiness: 32}, - Sun: sun, + Cube: MaterialTexture{Shiness: 32}, + // Sun: sun, Light: spotLight, } @@ -233,15 +238,16 @@ var teapotUniforms = struct { CamPos tofu.Vec3 Trans Trans Teapot Material - Sun *DirLight - Light *SpotLight + //Sun *DirLight + Light *SpotLight + PointLights []PointLight }{ Teapot: Material{ Diffuse: tofu.Vec3{0.3, 0.4, 0.4}, Specular: tofu.Vec3{0.3, 0.4, 0.4}, Shiness: 32, }, - Sun: sun, + //Sun: sun, Light: spotLight, } @@ -294,7 +300,7 @@ func (app *App) Update() error { Mul(tofu.Rotate(now*app.cubeRotate[i].vel, app.cubeRotate[i].axis)) cubeUniforms.Trans.Model = model if err := app.program.SetUniforms(); err != nil { - log.Println("setuniforms:", err) + log.Println("program.setuniforms:", err) } cube.Draw(app.program) } @@ -313,11 +319,20 @@ func (app *App) Update() error { lightUniforms.Trans.View = view lightUniforms.Trans.Projection = projection lightUniforms.Trans.Model = lightModel + lightUniforms.LightCol = spotLightCol if err := app.lightProgram.SetUniforms(); err != nil { log.Printf("lightprogram.setuniforms(): %v", err) } - light.Draw(app.lightProgram) + for _, pl := range pointLights { + lightUniforms.Trans.Model = tofu.Translate(pl.Pos). + Mul(tofu.Scale(0.3)) + lightUniforms.LightCol = pl.Specular + if err := app.lightProgram.SetUniforms(); err != nil { + log.Printf("lightprogram.setuniforms(): %v", err) + } + light.Draw(app.lightProgram) + } return nil } @@ -396,7 +411,23 @@ func main() { if err != nil { log.Fatalf("NewTesture: %v", err) } - + for i, _ := range pointLights { + col := tofu.Vec3{rand.Float32(), rand.Float32(), rand.Float32()} + pointLights[i] = PointLight{ + Pos: tofu.Vec3{ + (rand.Float32() - 0.5) * pointLightDiv, + (rand.Float32() - 0.5) * pointLightDiv, + (rand.Float32() - 0.5) * pointLightDiv}, + Ambient: col.MulF(0.3), + Diffuse: col.MulF(0.6), + Specular: col, + Kc: 1.0, + Kl: 0.009, + Kq: 0.0032, + } + } + cubeUniforms.PointLights = pointLights + teapotUniforms.PointLights = pointLights camera = tofu.NewCamera() camera.MoveTo(tofu.Vec3{0, 0, 3}) camera.LookAt(tofu.Vec3{0, 0, 0}) diff --git a/cmd/sample/teapot.glsl b/cmd/sample/teapot.glsl @@ -12,7 +12,14 @@ struct DirLight { vec3 Diffuse; vec3 Specular; }; +struct PointLight { + vec3 Pos; + vec3 Ambient; + vec3 Diffuse; + vec3 Specular; + float Kc, Kl, Kq; +}; struct SpotLight { vec3 Pos; vec3 Dir; @@ -32,16 +39,43 @@ uniform vec3 objCol; uniform Material Teapot; uniform DirLight Sun; uniform SpotLight Light; +uniform PointLight PointLights[10]; out vec4 fcol; +vec3 calcPointLight(PointLight, Material, vec3); vec3 calcSpotLight(SpotLight, Material, vec3); vec3 calcDirLight(DirLight, Material, vec3); void main() { fcol = vec4(0, 0, 0, 1); fcol += vec4(calcSpotLight(Light, Teapot, CamPos), 0); - fcol += vec4(calcDirLight(Sun, Teapot, CamPos), 0); +// fcol += vec4(calcDirLight(Sun, Teapot, CamPos), 0); + for (int i = 0; i < PointLights.length(); i++) { + fcol += vec4(calcPointLight(PointLights[i], Teapot, CamPos), 0); + } +} + +vec3 calcPointLight(PointLight l, Material m, vec3 camPos) { + vec3 ambient, diffuse, specular; + vec3 lightDir, viewDir, reflectDir; + float diff, spec, dist, attenuation; + + dist = length(l.Pos - fpos); + attenuation = 1 / (l.Kc + l.Kl * dist + l.Kq * dist * dist); + + ambient = m.Diffuse * l.Ambient; + + lightDir = normalize(l.Pos - fpos); + diff = max(dot(fnormal, lightDir), 0.0); + diffuse = diff * m.Diffuse * l.Diffuse; + + viewDir = normalize(camPos - fpos); + reflectDir = reflect(-lightDir, fnormal); + spec = pow(max(dot(viewDir, reflectDir), 0.0), m.Shiness); + specular = m.Specular * spec * l.Specular; + + return (ambient + diffuse + specular) * attenuation; } vec3 calcSpotLight(SpotLight l, Material m, vec3 camPos) { diff --git a/shader.go b/shader.go @@ -33,7 +33,11 @@ func compileShader(path string, xtype uint32) (shaderID uint32, err error) { 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)[2:]) + errmsg := gl.GoStr(l) + if strings.HasPrefix(errmsg, "0:") { + errmsg = errmsg[2:] + } + return 0, fmt.Errorf("%v", errmsg) } return shaderID, nil } @@ -135,12 +139,18 @@ func (p *Program) setUniforms(uniforms any, prefix string) error { if err := p.setUniforms(fv.Interface(), tag); err != nil { return err } - continue case reflect.Pointer: if err := p.setUniforms(fv.Elem().Interface(), tag); err != nil { return err } - continue + case reflect.Slice: + for i := 0; i < fv.Len(); i++ { + item := fv.Index(i).Interface() + tagi := fmt.Sprintf("%s[%d]", tag, i) + if err := p.setUniforms(item, tagi); err != nil { + return err + } + } default: return fmt.Errorf("unknown uniform type: %s", ft.Type) } diff --git a/tofu.go b/tofu.go @@ -94,7 +94,7 @@ func Run(app App) error { } for !window.ShouldClose() { - gl.ClearColor(1.0, 1.0, 0.918, 1.0) + gl.ClearColor(0.3, 0.3, 0, 1.0) gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) err := app.Update() if err == Termination {