tracer

package
v0.0.0-...-405cb25 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 8, 2020 License: GPL-3.0 Imports: 11 Imported by: 0

Documentation

Index

Examples

Constants

View Source
const Tiny = (1. / (1204 * 1024))

Variables

This section is empty.

Functions

func CheckHit

func CheckHit(o Object, r *Ray, h *HitRecord)

func CheckRay

func CheckRay(r *Ray)

func FrontT

func FrontT(t1, t2 float64) float64

func IndexToCam

func IndexToCam(w, h int, ix, iy float64) (u, v float64)

IndexToCam maps a pixel index {ix, iy} inside an image with given width and height onto a u,v coordinate strictly inside the interval [0,1]. If the image's aspect ratio width:height is not square, then either u or v will not span the entire [0,1] interval.

Half-pixel offsets are applied so that the borders in u,v correspond exactly to pixel borders (not centers). This transformation is sketched below:

	             +----------------+ (u,v=1,1)
	             |                |
 (x,y=-.5,-.5)+----------------+
	             |                |
	             |                |
	             +----------------+ (x,y=w-.5,h-.5)
	             |                |
	    (u,v=0,0)+----------------+

Note that the v axis points up, while the y axis points down.

Example
for _, arg := range []struct {
	w, h   int
	ix, iy float64
}{
	{1, 1, -.5, -.5},
	{1, 1, 0, 0},
	{1, 1, 0.5, 0.5},

	{4, 2, -.5, -.5},
	{4, 2, 1.5, 0.5},
	{4, 2, 3.5, 1.5},
} {
	x, y := tracer.IndexToCam(arg.w, arg.h, arg.ix, arg.iy)
	fmt.Printf("[w: %2d, h: %2d]: (% 3.3f, % 3.3f)->(% 3.3f, % 3.3f)\n",
		arg.w, arg.h, arg.ix, arg.iy, x, y)
}
Output:

[w:  1, h:  1]: (-0.500, -0.500)->( 0.000,  1.000)
[w:  1, h:  1]: ( 0.000,  0.000)->( 0.500,  0.500)
[w:  1, h:  1]: ( 0.500,  0.500)->( 1.000,  0.000)
[w:  4, h:  2]: (-0.500, -0.500)->( 0.000,  0.750)
[w:  4, h:  2]: ( 1.500,  0.500)->( 0.500,  0.500)
[w:  4, h:  2]: ( 3.500,  1.500)->( 1.000,  0.250)

func PixelSize

func PixelSize(w, h int) float64

??

func Uniform

func Uniform(f ImageFunc, numPass, w, h int, antiAlias bool) Image

Types

type Camera

type Camera interface {
	// RayFrom constructs a ray starting from position u,v on the image sensor.
	// u, v are both in the interval [0,1].
	//
	// In case a non-square image is desired, u or v can simply be varied
	// over a rectangle inside the unit square.
	//
	// Ctx should be used to allocate the Ray,
	// and to generate random lens samples if needed.
	RayFrom(ctx *Ctx, u, v float64) *Ray
}

A Camera maps pixel positions to Rays. Various implementations are in package cameras.

type Ctx

type Ctx struct {
	CurrentRecursionDepth int // counts recursion depth from 1.

	AA sequence.Sequence

	Stats Stats
	// contains filtered or unexported fields
}

Ctx is a "execution context", scoped to the pixel currently being shaded. A Ctx lives though a single pixel shading process, similar to how Go's "context.Context" lives through a single RPC request.

A Ctx carries:

  • quasi-random sequences approprately seeded for the pixel
  • a storage pool for obtaining and recycling Rays (without allocation)
  • statistics about the compute resources used
  • the current recursion depth, for aborting recursion

The reason for this is twofold. (1) The random generator, storage pool and statistics are not thread-safe, so each goroutine needs its own instance. This avoids locking, and significantly speeds up execution. (2) Quasi Monte Carlo requires quasi-random numbers that depend on the pixel and recursion depth. Therefore, the context needs access to the recursion depth, and we might as well make the context responsible for limiting recursion depth.

func NewCtx

func NewCtx(numPix int) *Ctx

func (*Ctx) Generate2

func (c *Ctx) Generate2() (u, v float64)

func (*Ctx) GenerateLens

func (c *Ctx) GenerateLens() (u, v float64)

func (*Ctx) Init

func (c *Ctx) Init(pixel, pass int)

func (*Ctx) IsInitial

func (c *Ctx) IsInitial() bool

IsInitial returns whether this is the context of the initial ray cast by the camera. I.e., returns true when we are at the root of recursion. At the root of recursion, we may apply some expensive Media like fog, or chose to use Quasi Monte Carlo rather than the regular method.

func (*Ctx) PutRay

func (c *Ctx) PutRay(r *Ray)

Put recycles Rays returned by GetRay.

func (*Ctx) Ray

func (c *Ctx) Ray() *Ray

Ray returns a new Ray, allocated from a pool. PutRay should be called to recycle the Ray. TODO: rename NewRay

type HitCoords

type HitCoords struct {
	T      float64 // Position along the ray
	Normal Vec     // Normal vector at intersection (needs not have unit length)
	Local  Vec     // Local coordinates at intersection, chosen by the Object. E.g. U,V coordinates for objects where this makes sense
}

HitCoords record where a Ray intersected an Object.

type HitRecord

type HitRecord struct {
	T        float64 // Position along the ray
	Normal   Vec     // Normal vector at intersection (needs not have unit length)
	Local    Vec     // Local coordinates at intersection, chosen by the Object. E.g. U,V coordinates for objects where this makes sense
	Material Material
}

A HitRecord records the position and material where a Ray intersected an Object. This allows for lazy evaluation of the Color seen by the Ray, after it has been established that the color is actually going to be used (i.e., the hit point is not occluded by another Object). Without this lazy evaluation, the complexity of recursive ray tracing would become exponential in the recursion depth.

The structure is designed to avoid allocations: It is passed by value, and the Material is only allocated once at initialization time.

func Frontmost

func Frontmost(a, b *HitRecord) HitRecord

type ImageFunc

type ImageFunc func(c *Ctx, u, v float64) Color

type Light

type Light interface {
	// Object is rendered when a viewing ray sees the light directly.
	// E.g. for a spherical yellow light source, this object is a
	// bright yellow sphere.
	//
	// Care must be taken that the properties of this object
	// (size, surface brightness) exactly match the light intensity
	// obtained by calling Sample(). I.e. The amount of light
	// that a scene receives from this object via unidirectional path
	// tracing must be exactly equal to the amout of light
	// received from Sample() using bidirectional path tracing.
	Object() Object

	// Sample returns a position on the light's surface
	// (used to determine shadows for extended sources),
	// and the intensity at given target position.
	Sample(ctx *Ctx, target Vec) (pos Vec, intens Color)
}

type Material

type Material interface {

	// Shade returns the brightness seen by Ray r which intersects
	// the scene at the given hit coordinates.
	//
	// Implementations may call s.LightField recursively,
	// recursion depth is limited automatically through the context ctx.
	Shade(ctx *Ctx, s *Scene, r *Ray, h HitCoords) Color
}

A Material determines the color of a surface fragment.

type Medium

type Medium interface {
	Filter(ctx *Ctx, s *Scene, r *Ray, tMax float64, original Color) Color
}

type Object

type Object interface {
	Intersect(r *Ray) HitRecord
}

An Object is any thing that can be rendered. E.g., a glass sphere, a white rectangle, ...

type Ray

type Ray struct {
	Start Vec
	Dir   Vec
}

A Ray is a half-line, starting at the Start point (exclusive) and extending in direction Dir.

func (*Ray) At

func (r *Ray) At(t float64) Vec

Returns point Start + t*Dir. t must be > 0 for the point to lie on the Ray.

type Sampler

type Sampler struct {
	Stats Stats
	// contains filtered or unexported fields
}

A Sampler renders a ray-traced image.

func NewSampler

func NewSampler(f ImageFunc, w, h int, antiAlias bool) *Sampler

func (*Sampler) Image

func (s *Sampler) Image() Image

Image returns the rendered image currently accumulated by the Sampler. Successive calls to Sample progressively improve this image's quality.

func (*Sampler) Sample

func (s *Sampler) Sample(nPass int)

func (*Sampler) SampleWithCancel

func (s *Sampler) SampleWithCancel(nPass int, _ chan struct{})

TODO: cancellation

func (*Sampler) StdDev

func (s *Sampler) StdDev() Image

StdDev returns an image whose pixel values are the standard deviation of all samples currently accumulated.

type Scene

type Scene struct {
	RecursionDepth int
	// contains filtered or unexported fields
}

Scene is the ray tracer's central data type. A Scene stores a collection of objects and lights, and provides methods to evaluate the brightness seen by an arbitrary ray (I.e. the light field).

func NewScene

func NewScene(recursionDepth int, lights []Light, objs ...Object) *Scene

NewScene constructs a scene from objects and light sources. At render time, recursion will be limited to recursionDepth at maximum.

func NewSceneWithMedia

func NewSceneWithMedia(recDepth int, media []Medium, lights []Light, objs ...Object) *Scene

TODO: unify

func (*Scene) ImageFunc

func (s *Scene) ImageFunc(c Camera) ImageFunc

ImageFunc returns an image function that can be sampled to obtain an image of the Scene seen through the given Camera.

The image function expects to be sampled at (u,v) coordinates in the interval [0..1].

Evaluating the image function returns potentially noisy sample, and typically many samples must be averaged to obtain a high-quality image.

The context (*Ctx) is used to generate random numbers deterministically.

TODO: when testing indirect lighting: ImageFunc for non-luminous, lights only

func (*Scene) LightField

func (s *Scene) LightField(ctx *Ctx, r *Ray) Color

LightField returns the light field of all objects in scene.

func (*Scene) LightFieldIndirect

func (s *Scene) LightFieldIndirect(ctx *Ctx, r *Ray) Color

LightFieldIndirect returns the light field the Scene's objects but replaces the light sources by black. This is used by Bi-directional path tracing which adds light sources separately.

func (*Scene) Lights

func (s *Scene) Lights() []Light

func (*Scene) ObjectsAndLights

func (s *Scene) ObjectsAndLights() []Object

func (*Scene) Occlude

func (s *Scene) Occlude(r *Ray, len float64, orig Color) Color

type Stats

type Stats struct {
	NumPixels int // number of pixels evaluated
	NumRays   int // number of rays evaluated
	NumNaN    int // number of NaN colors encountered
	WallTime  time.Duration
}

func (*Stats) Add

func (s *Stats) Add(b *Stats)

type TransparentMaterial

type TransparentMaterial interface {
	Filter(r *Ray, h HitRecord, background Color) Color
}

Directories

Path Synopsis
Package cameras provides various implementations of the camera interface tracer.Camera.
Package cameras provides various implementations of the camera interface tracer.Camera.
Package lights provides implementations of the tracer.Light interface.
Package lights provides implementations of the tracer.Light interface.
Package objects provides concrete implementations of the tracer.Object interface.
Package objects provides concrete implementations of the tracer.Object interface.
obj
ply
Package sequence implements a low-discrepancy sequence for Quasi Monte Carlo integration, and mappings from a uniform sequence to a disk or sphere.
Package sequence implements a low-discrepancy sequence for Quasi Monte Carlo integration, and mappings from a uniform sequence to a disk or sphere.
Package test provides test helpers for BruteRay.
Package test provides test helpers for BruteRay.
Package types provides constants and type aliases that are considered bruteray primitives.
Package types provides constants and type aliases that are considered bruteray primitives.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL