Example #1
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())
	}
}
Example #2
0
func runClient(c *cli.Context) error {
	scene, image := getArguments(c)
	workerAdresses := c.StringSlice("worker")

	if len(workerAdresses) == 0 {
		showError(c, "can't render on zero workers :(")
	}
	synchronous := c.Bool("synchronous")

	quiet := c.GlobalBool("quiet")

	if !quiet {
		fmt.Printf(
			"will render %s to %s of size %dx%d on those workers: %s, synchronous %v\n",
			scene, image,
			c.Int("width"), c.Int("height"),
			strings.Join(workerAdresses, ", "),
			synchronous,
		)
	}

	width, height := c.Int("width"), c.Int("height")
	totalSamples := c.Int("total-samples")
	sampleCounter := rpc.NewSampleCounter(totalSamples)
	renderedImages := make(chan *hdrimage.Image, len(workerAdresses))
	workers := make([]*rpc.RemoteRaytracerCaller, len(workerAdresses))
	finishWorker := &sync.WaitGroup{}
	data, err := ioutil.ReadFile(scene)

	var bar *progress.ProgressBar
	if !quiet {
		bar = progress.StartProgressBar(totalSamples, "rendering samples ")
	}

	if err != nil {
		return fmt.Errorf("Error when loading scene: %s", err)
	}
	for i := range workerAdresses {
		workers[i] = rpc.NewRemoteRaytracerCaller(workerAdresses[i], 10*time.Minute)
		finishWorker.Add(1)

		requests, err := workers[i].MaxRequestsAtOnce()
		if err != nil || requests < 1 {
			return fmt.Errorf("Can't get worker's allowed requests: %s", err)
		}

		samples, err := workers[i].MaxSamplesAtOnce()
		if err != nil || samples < 1 {
			return fmt.Errorf("Can't get worker's allowed samples: %s", err)
		}

		settings := &rpc.SampleSettings{
			Width:         width,
			Height:        height,
			SamplesAtOnce: samples,
		}

		err = workers[i].LoadScene(data)
		if err != nil {
			return fmt.Errorf("Can't load scene: %s", err)
		}

		go func(i int) {
			finishRender := &sync.WaitGroup{}
			finishRender.Add(requests)
			for request := 0; request < requests; request++ {
				go func() {
					RenderLoop(sampleCounter, workers[i], renderedImages, settings, synchronous, bar)
					finishRender.Done()
				}()
			}
			finishRender.Wait()
			if !synchronous {
				if !quiet {
					bar.Prefix(fmt.Sprintf("Getting image from %s", workerAdresses[i]))
				}
				image, err := workers[i].GetImage()
				if err == nil {
					if image.Width != 0 {
						renderedImages <- image
					}
				} else {
					fmt.Printf("Smelly image x_x %s\n", err)
				}
			}
			finishWorker.Done()
		}(i)
	}

	go func() {
		finishWorker.Wait()
		close(renderedImages)
		if !quiet {
			bar.Done()
		}
	}()

	averageImage := JoinSamples(renderedImages, width, height)
	return savePng(averageImage, image)
}