-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmaterial_test.go
More file actions
96 lines (85 loc) · 2.93 KB
/
Copy pathmaterial_test.go
File metadata and controls
96 lines (85 loc) · 2.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package pix
import (
"testing"
"github.com/bluescreen10/pix/cameras"
"github.com/bluescreen10/pix/colors"
"github.com/bluescreen10/pix/glm"
"github.com/bluescreen10/pix/materials"
)
// TestMaterialClasses renders the same geometry with three different material
// classes side by side and checks each pipeline produces distinct shading: the
// unlit surface is uniformly bright (ignores lights), while the lit ones darken on
// faces angled away from the light. Exercises per-batch pipeline selection.
func TestMaterialClasses(t *testing.T) {
const size = 240
r, err := NewOffscreenRenderer(size, size)
if err != nil {
t.Fatal(err)
}
defer r.Destroy()
scene := r.NewScene()
defer scene.Destroy()
cube := r.GeometryStore.Create(normalCube())
basic := r.NewBasicMaterial()
basic.SetColor(colors.RGBA32F{0.8, 0.8, 0.8, 1})
phong := r.NewBlinnPhongMaterial()
phong.SetColor(colors.RGBA32F{0.8, 0.8, 0.8, 1})
pbr := r.NewPBRMaterial()
pbr.SetColor(colors.RGBA32F{0.8, 0.8, 0.8, 1})
place := func(mat materials.Material, x float32) {
m := scene.NewMesh(cube, mat)
m.SetPosition(glm.Vec3f{x, 0, 0})
m.SetRotationQuat(glm.NewQuat(float32(0.6), glm.Vec3f{0, 1, 0}))
scene.Add(m)
}
place(basic, -1.4)
place(phong, 0)
place(pbr, 1.4)
scene.SetAmbient(colors.RGB32F{0.15, 0.15, 0.15})
scene.AddDirectionalLight(glm.Vec3f{-1, -0.3, -0.6}, colors.RGB32F{1, 1, 1}, 1.0)
cam := cameras.NewPerspectiveCamera(45, 1, 0.1, 1000)
cam.SetPosition(glm.Vec3f{0, 0.5, 5})
r.Render(scene, cam)
// Split the frame into thirds (basic | phong | pbr) and measure, for each, the
// spread between the brightest and darkest lit pixel. Unlit is flat (small
// spread); the lit materials shade across faces (larger spread).
px := r.Pixels()
third := size / 3
spread := func(x0, x1 int) (float64, int) {
lo, hi := 1.0, 0.0
lit := 0
for y := 0; y < size; y++ {
for x := x0; x < x1; x++ {
i := (y*size + x) * 4
rr, gg, bb := px[i], px[i+1], px[i+2]
if rr == 0 && gg == 0 && bb == 0 {
continue
}
lit++
l := (0.299*float64(rr) + 0.587*float64(gg) + 0.114*float64(bb)) / 255
if l < lo {
lo = l
}
if l > hi {
hi = l
}
}
}
return hi - lo, lit
}
basicSpread, basicLit := spread(0, third)
phongSpread, phongLit := spread(third, 2*third)
pbrSpread, pbrLit := spread(2*third, size)
t.Logf("basic: spread=%.3f lit=%d | phong: spread=%.3f lit=%d | pbr: spread=%.3f lit=%d",
basicSpread, basicLit, phongSpread, phongLit, pbrSpread, pbrLit)
for name, lit := range map[string]int{"basic": basicLit, "phong": phongLit, "pbr": pbrLit} {
if lit < 300 {
t.Fatalf("%s cube barely rendered (%d px) — pipeline/material wrong", name, lit)
}
}
// The unlit cube should be markedly flatter than the lit ones.
if basicSpread > phongSpread || basicSpread > pbrSpread {
t.Fatalf("unlit spread %.3f not smaller than lit (phong %.3f, pbr %.3f) — classes not distinct",
basicSpread, phongSpread, pbrSpread)
}
}