Skip to content

Commit 033dae5

Browse files
committed
implement optional time, frame, dump period limits
also verbose timing for loading phases.
1 parent 68e04d9 commit 033dae5

File tree

7 files changed

+81
-13
lines changed

7 files changed

+81
-13
lines changed

cmd/pbr/main.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"os"
66
"strings"
77
"runtime/pprof"
8+
"time"
89

910
"github.com/hunterloftis/pbr/pkg/camera"
1011
"github.com/hunterloftis/pbr/pkg/env"
@@ -45,6 +46,20 @@ func stopProfile(f *os.File) {
4546
f.Close()
4647
}
4748

49+
func startTimer(o *Options, s string) time.Time {
50+
if o.Verbose {
51+
fmt.Print(s)
52+
}
53+
return time.Now()
54+
}
55+
56+
func stopTimer(o *Options, start time.Time) {
57+
if o.Verbose {
58+
elapsed := time.Since(start)
59+
fmt.Printf("done: %s\n", elapsed.Round(time.Millisecond))
60+
}
61+
}
62+
4863
func run(o *Options) error {
4964
if o.Profile {
5065
f, err := createProfile()
@@ -54,10 +69,12 @@ func run(o *Options) error {
5469
defer stopProfile(f)
5570
}
5671

72+
start := startTimer(o, "Loading object file... ")
5773
mesh, err := obj.ReadFile(o.Scene, true)
5874
if err != nil {
5975
return err
6076
}
77+
stopTimer(o, start)
6178

6279
if o.Scale != nil {
6380
mesh.Scale(*o.Scale)
@@ -69,7 +86,9 @@ func run(o *Options) error {
6986
m := materials[strings.ToLower(o.Material)]
7087
mesh.SetMaterial(m)
7188
}
89+
start = startTimer(o, "Calculating mesh bounds... ")
7290
bounds, surfaces := mesh.Bounds()
91+
stopTimer(o, start)
7392
camera := camera.NewSLR()
7493
environment := render.Environment(env.NewGradient(rgb.Black, *o.Ambient, 3))
7594

@@ -107,9 +126,12 @@ func run(o *Options) error {
107126
surfaces = append(surfaces, sun)
108127
}
109128

129+
start = startTimer(o, "Creating surface tree... ")
110130
tree := surface.NewTree(surfaces...)
131+
stopTimer(o, start)
111132
scene := render.NewScene(camera, tree, environment)
112133

113134
fmt.Println("Surfaces:", len(surfaces))
114-
return render.Iterative(scene, o.Out, o.Width, o.Height, o.Bounce, !o.Indirect)
135+
limits := render.NewLimits(o.DumpPeriod, o.Time, o.Frames)
136+
return render.Iterative(scene, limits, o.Out, o.Width, o.Height, o.Bounce, !o.Indirect)
115137
}

cmd/pbr/options.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package main
22

33
import (
4-
"math"
54
"path/filepath"
65

76
arg "github.com/alexflint/go-arg"
@@ -15,8 +14,9 @@ type Options struct {
1514
Scene string `arg:"positional,required" help:"input scene .obj"`
1615
Verbose bool `arg:"-v" help:"verbose output with scene information"`
1716
Info bool `help:"output scene information and exit"`
18-
Frames float64 `arg:"-f" help:"number of frames at which to exit"`
19-
Time float64 `arg:"-t" help:"time to run before exiting (seconds)"`
17+
DumpPeriod int `help:"how frequently to output progress frames"`
18+
Frames int `arg:"-f" help:"number of frames at which to exit"`
19+
Time int `arg:"-t" help:"time to run before exiting (seconds)"`
2020
Material string `help:"override material (glass, gold, mirror, plastic)"`
2121

2222
Width int `arg:"-w" help:"rendering width in pixels"`
@@ -57,8 +57,9 @@ func options() *Options {
5757
Rad: 100,
5858
Bounce: 6,
5959
Indirect: false,
60-
Frames: math.Inf(1),
61-
Time: math.Inf(1),
60+
DumpPeriod: 6,
61+
Frames: 0,
62+
Time: 0,
6263
Lens: 50,
6364
FStop: 4,
6465
Focus: 1,

examples/hello/hello.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func main() {
2424
e := env.NewGradient(rgb.Black, rgb.Energy{750, 750, 750}, 7)
2525

2626
scene := render.NewScene(c, s, e)
27-
err := render.Iterative(scene, "hello.png", 898, 450, 8, true)
27+
err := render.Iterative(scene, nil, "hello.png", 898, 450, 8, true)
2828
if err != nil {
2929
fmt.Fprintf(os.Stderr, "\nError: %v\n", err)
3030
}

examples/redblue/redblue.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,5 @@ func run() error {
4444
tree := surface.NewTree(surfaces...)
4545
scene := render.NewScene(camera, tree, environment)
4646

47-
return render.Iterative(scene, "redblue.png", 1280, 720, 6, true)
47+
return render.Iterative(scene, nil, "redblue.png", 1280, 720, 6, true)
4848
}

examples/shapes/shapes.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,5 @@ func run() error {
4848
)
4949
scene := render.NewScene(cam, surf, sky)
5050

51-
return render.Iterative(scene, "shapes.png", 800, 450, 6, true)
51+
return render.Iterative(scene, nil, "shapes.png", 800, 450, 6, true)
5252
}

examples/sponza/sponza.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,5 @@ func run() error {
4444
tree := surface.NewTree(surfaces...)
4545
scene := render.NewScene(camera, tree, environment)
4646

47-
return render.Iterative(scene, "sponza.png", 1280, 720, 8, true)
47+
return render.Iterative(scene, nil, "sponza.png", 1280, 720, 8, true)
4848
}

pkg/render/iterative.go

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,47 @@ import (
1414
"golang.org/x/text/message"
1515
)
1616

17-
func Iterative(scene *Scene, file string, width, height, depth int, direct bool) error {
17+
type Limits struct {
18+
DumpPeriod time.Duration
19+
Time time.Duration
20+
Frames int
21+
}
22+
23+
func NewLimits(d int, t int, f int) *Limits {
24+
if d == 0 {
25+
d = math.MaxInt32
26+
}
27+
if t == 0 {
28+
t = math.MaxInt32
29+
}
30+
return &Limits{
31+
DumpPeriod: time.Duration(d) * time.Second,
32+
Time: time.Duration(t) * time.Second,
33+
Frames: f,
34+
}
35+
}
36+
37+
func Iterative(scene *Scene, limits *Limits, file string, width, height, depth int, direct bool) error {
1838
kill := make(chan os.Signal, 2)
1939
signal.Notify(kill, os.Interrupt, syscall.SIGTERM)
2040

41+
if limits == nil {
42+
limits = NewLimits(6, 0, 0)
43+
fmt.Print("derp\n")
44+
}
45+
2146
frame := scene.Render(width, height, depth, direct)
2247
defer frame.Stop()
23-
ticker := time.NewTicker(6 * time.Second) // 10 .s = 1 minute, 100 .s = 1 hr
48+
ticker := time.NewTicker(limits.DumpPeriod)
2449
defer ticker.Stop()
50+
limiter := time.NewTicker(limits.Time)
51+
defer limiter.Stop()
52+
framelim := time.NewTicker(1 * time.Second)
53+
if limits.Frames == 0 {
54+
framelim.Stop()
55+
} else {
56+
defer framelim.Stop()
57+
}
2558

2659
start := time.Now().UnixNano()
2760
max := 0
@@ -31,6 +64,14 @@ func Iterative(scene *Scene, file string, width, height, depth int, direct bool)
3164
select {
3265
case <-kill:
3366
frame.Stop()
67+
case <-limiter.C:
68+
frame.Stop()
69+
fmt.Printf("\nTime limit reached.\n")
70+
case <-framelim.C:
71+
if _, n := frame.Sample(); n > limits.Frames {
72+
frame.Stop()
73+
fmt.Print("\nFrame limit reached.\n")
74+
}
3475
case <-ticker.C:
3576
if sample, n := frame.Sample(); n > max {
3677
max = n
@@ -43,12 +84,16 @@ func Iterative(scene *Scene, file string, width, height, depth int, direct bool)
4384
}
4485

4586
stop := time.Now().UnixNano()
46-
sample, _ := frame.Sample()
87+
sample, frames := frame.Sample()
4788
total := sample.Total()
4889
p := message.NewPrinter(language.English)
4990
secs := float64(stop-start) / 1e9
5091
sps := math.Round(float64(total) / secs) // TODO: rename to pixels/sec for clarity
5192
p.Printf("\n%v samples in %.1f seconds (%.0f samples/sec)\n", total, secs, sps)
93+
p.Printf("\n%v frames (%.1f frames/sec)\n", frames, float64(frames)/secs)
94+
if err := writePng(file, sample.Image()); err != nil {
95+
return err
96+
}
5297

5398
return nil
5499
}

0 commit comments

Comments
 (0)