예제 #1
0
파일: render.go 프로젝트: DexterLB/traytor
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())
	}
}
예제 #2
0
파일: client.go 프로젝트: DexterLB/traytor
// RenderLoop renders samples of an image until the sample counter reaches
// 0, and then returns the combined result. If synchronous is set, images
// will be transferred from the worker after every sample. Otherwise,
// the image is transferred at the end.
func RenderLoop(
	sampleCounter *rpc.SampleCounter,
	client *rpc.RemoteRaytracerCaller,
	renderedImages chan<- *hdrimage.Image,
	globalSettings *rpc.SampleSettings,
	synchronous bool,
	bar *progress.ProgressBar,
) {
	settings := *globalSettings
	for {
		settings.SamplesAtOnce = sampleCounter.Dec(globalSettings.SamplesAtOnce)
		if settings.SamplesAtOnce == 0 {
			return
		}
		var err error
		var image *hdrimage.Image

		if synchronous {
			image, err = client.Sample(&settings)
		} else {
			err = client.StoreSample(&settings)
		}
		//both samples log the error, but only synchronous sample pushes
		//image into the channel
		if err == nil {
			if synchronous {
				renderedImages <- image
			}
			if bar != nil {
				bar.Add(1)
			}
		} else {
			log.Printf("No sample :( %s\n", err)
		}
	}
}
예제 #3
0
파일: client.go 프로젝트: DexterLB/traytor
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)
}