示例#1
0
// 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
}
示例#2
0
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())
	}
}