commit b2d0180669048d007691ba434db948042d6adbc7
parent e928a2c0591c263868bec114b939b1f6c684200d
Author: Matsuda Kenji <info@mtkn.jp>
Date: Wed, 27 Nov 2024 08:53:22 +0900
muptiple lights
Diffstat:
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 {