// NewConcurrentRaytracer creates a concurrent raytracer with parallelSamples // allowed number of parallel operations func NewConcurrentRaytracer( parallelSamples int, scene *scene.Scene, seed int64, ) *ConcurrentRaytracer { if parallelSamples < 1 { panic("must have at least one rendering unit") } cr := &ConcurrentRaytracer{ parallelSamples: parallelSamples, units: make(chan *renderUnit, parallelSamples), } randomGen := random.New(seed) for i := 0; i < parallelSamples; i++ { cr.units <- &renderUnit{ raytracer: raytracer.Raytracer{ Scene: scene, Random: random.New(randomGen.NewSeed()), }, image: nil, } } return cr }
func renderer( width, height int, renderedImages chan *hdrimage.Image, scene *scene.Scene, seed int64, totalSamples int, threads int, quiet bool, ) { randomGen := random.New(seed) sampleCounter := rpc.NewSampleCounter(totalSamples) var bar *progress.ProgressBar if !quiet { bar = progress.StartProgressBar(totalSamples, "rendering samples") } wg := sync.WaitGroup{} wg.Add(threads) defer func() { wg.Wait() if !quiet { bar.Done() } }() for i := 0; i < threads; i++ { go func(seed int64) { defer wg.Done() raytracer := raytracer.Raytracer{ Scene: scene, Random: random.New(seed), } image := hdrimage.New(width, height) image.Divisor = 0 for { if sampleCounter.Dec(1) == 0 { renderedImages <- image return } raytracer.Sample(image) if !quiet { bar.Add(1) } } }(randomGen.NewSeed()) } }