Git Product home page Git Product logo

pt's Introduction

pt: a golang path tracer

Build Status GoDoc

This is a CPU-only, unidirectional path tracing engine written in Go. It has lots of features and a simple API.

Examples


Features

  • Supports OBJ and STL
  • Supports textures, bump maps and normal maps
  • Supports raymarching of signed distance fields
  • Supports volume rendering from image slices
  • Supports various material properties
  • Supports configurable depth of field
  • Supports iterative rendering
  • Supports adaptive sampling and firefly reduction
  • Uses k-d trees to accelerate ray intersection tests
  • Uses all CPU cores in parallel
  • 100% pure Go with no dependencies besides the standard library

Installation

go get -u github.com/fogleman/pt/pt

Examples

The are lots of examples to learn from! To try them, just run, e.g.

cd go/src/github.com/fogleman/pt
go run examples/gopher.go

Optional Embree Acceleration

You can optionally utilize Intel's Embree ray tracing kernels to accelerate triangle mesh intersections. First, install embree on your system: http://embree.github.io/ Then get the go-embree wrapper and checkout the embree branch of pt.

git checkout embree
go get -u github.com/fogleman/go-embree

Hello World

The following code demonstrates the basics of the API.

package main

import . "github.com/fogleman/pt/pt"

func main() {
	// create a scene
	scene := Scene{}

	// create a material
	material := DiffuseMaterial(White)

	// add the floor (a plane)
	plane := NewPlane(V(0, 0, 0), V(0, 0, 1), material)
	scene.Add(plane)

	// add the ball (a sphere)
	sphere := NewSphere(V(0, 0, 1), 1, material)
	scene.Add(sphere)

	// add a spherical light source
	light := NewSphere(V(0, 0, 5), 1, LightMaterial(White, 8))
	scene.Add(light)

	// position the camera
	camera := LookAt(V(3, 3, 3), V(0, 0, 0.5), V(0, 0, 1), 50)

	// render the scene with progressive refinement
	sampler := NewSampler(4, 4)
	renderer := NewRenderer(&scene, &camera, sampler, 960, 540)
	renderer.AdaptiveSamples = 128
	renderer.IterativeRender("out%03d.png", 1000)
}

Hello World

Adaptive Sampling

There are several sampling options that can reduce the amount of time needed to converge to an acceptable noise level. Both images below were rendered in 60 seconds. On the left, no advanced features were enabled. On the right, the features listed below were used.

Gopher

Here are some of the options that are utilized to achieve this improvement:

  • stratified sampling - on first intersection, spawn NxN rays in a stratified pattern to ensure well-distributed coverage
  • sample all lights - at each intersection, sample all lights for direct lighting instead of one random light
  • forced specular reflections - at each intersection, force both a diffuse and specular bounce and weigh them appropriately
  • adaptive sampling - spend more time sampling pixels with high variance
  • firefly reduction - very heavily sample pixels with very high variance

Combining these features results in cleaner, faster renders. The specific parameters that should be used depend greatly on the scene being rendered.

Links

Here are some resources that I have found useful.

Samples

Go

Dragon

Cornell

Lucy

SDF

Spheres

Suzanne

Molecule

pt's People

Contributors

fogleman avatar gmlewis avatar xyproto avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pt's Issues

SDFShape support for ClearMaterial

I tried to add a SphereSDF to the materials example, on the far right, using the same ClearMaterial as the regular Sphere next to it, but the result looks metallic.

Curious to know:

  • Is transparency expected to work with SDF shapes?
  • If so, any pointers on how I can go about fixing this? My first guess is something to do with Hitinfo at https://github.com/fogleman/pt/blob/master/pt/hit.go#L37, but it seems best to ask for ideas before going down the rabbit hole :-)

out100

package main

import . "github.com/fogleman/pt/pt"

func main() {
	scene := Scene{}
	r := 0.4
	var material Material

	material = DiffuseMaterial(HexColor(0x334D5C))
	scene.Add(NewSphere(V(-2, r, 0), r, material))

	material = SpecularMaterial(HexColor(0x334D5C), 2)
	scene.Add(NewSphere(V(-1, r, 0), r, material))

	material = GlossyMaterial(HexColor(0x334D5C), 2, Radians(50))
	scene.Add(NewSphere(V(0, r, 0), r, material))

	material = TransparentMaterial(HexColor(0x334D5C), 2, Radians(20), 1)
	scene.Add(NewSphere(V(1, r, 0), r, material))

	material = ClearMaterial(2, 0)
	scene.Add(NewSphere(V(2, r, 0), r, material))
	// Added SphereSDF
	scene.Add(NewSDFShape(NewTransformSDF(NewSphereSDF(r), Translate(V(3, r, 0))), material))

	material = MetallicMaterial(HexColor(0xFFFFFF), 0, 1)
	scene.Add(NewSphere(V(0, 1.5, -4), 1.5, material))

	scene.Add(NewCube(V(-1000, -1, -1000), V(1000, 0, 1000), GlossyMaterial(HexColor(0xFFFFFF), 1.4, Radians(20))))
	scene.Add(NewSphere(V(0, 5, 0), 1, LightMaterial(White, 25)))
	camera := LookAt(V(0, 3, 7), V(0, 1, 0), V(0, 1, 0), 30)
	sampler := NewSampler(16, 16)
	renderer := NewRenderer(&scene, &camera, sampler, 960, 540)
	renderer.IterativeRender("out%03d.png", 100)
}

Any pointers for docs?

This seems like a very cool project, thanks. As someone incredibly new to the domain, I was trying to play with the examples but it is very exhausting to play around without any documentation or comments in the code. I checked the source code as well, but couldn't see any comments around the variables and functions. Is there any documentation that I might have missed regarding how to use this project?

I can play around with all the variables and probably figure out how most of them work, but I was hoping to use this to inspire my brother with ray tracing, and I am afraid this might demotivate it, so if someone can point me to a simple documentation that'd be awesome.

Cheers!

Efficiency of Marching Cubes.

For each cube you do an evaluation on the 8 vertices of the cube.
Cubes are adjacent so many vertices will get evaluated up to 8 times - to produce the same result each time.
I borrowed your code for my project and improved it by evaluating and caching 2D layers.
It's a nice speed up if you care about STL generation (which I do).
https://github.com/deadsy/sdfx/blob/master/sdf/marching.go
Thanks for the code!

Intel Embree support

Hello. Will support for Intel Embree? As I know they support AVX2/SSE4.
I try write binding for Embree if need.

freestyle

Please look at freestyle in blender.
Is possible create this same but in go?
export for svg and [arrays of points]

Will OpenGL version of this PT?

Hello. Will you development OpenGL (or Vulkan) version of this good PT?
I tried to build octree with hardware rasterization (and atomics), and acheive not so bad speed (interactive) with 20k polygons. Even If rebuild octree. Tested only for Nvidia, but now I have option for non-conservative (and slower) method of voxelization.
https://github.com/acterhd/ogl-reflections

cornell works, but...

Hi,

When trying the examples, the cornell box works fine:

...t/pt/examples% ./cornell 
Building k-d tree (8 shapes)... OK

[Iteration 1 of 10]
512 x 512 pixels, 1 x 16 = 16 samples, 4 bounces, 2 cores
  44 / 512 (  8%) [===                               ] 0:00:02 1.0M ^C%                                                                                                                                                                        

However, the cube fails:

...t/pt/examples% ./cube 
Loading STL (Binary): examples/cube.stl
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x44183c]

goroutine 1 [running]:
github.com/fogleman/pt/pt.(*Mesh).FitInside(0x0, 0x0, 0x0, 0x0, 0x3ff0000000000000, 0x3ff0000000000000, 0x3ff0000000000000, 0x3fe0000000000000, 0x3fe0000000000000, 0x3fe0000000000000)
    /home/alexander/go/src/github.com/fogleman/pt/pt/mesh.go:105 +0x82c
main.createMesh(0x3fa473f4a209de04, 0x3fb943b1fbe850e5, 0x3fc28e725522c76e, 0x0, 0x0, 0x0, 0x3ff0000000000000, 0x0, 0x0, 0x3ff8000000000000, ...)
    /home/alexander/checkout/pt/examples/cube.go:11 +0x16c
main.main()
    /home/alexander/checkout/pt/examples/cube.go:18 +0x18e

goroutine 2 [runnable]:
runtime.forcegchelper()
    /usr/lib/go/src/runtime/proc.go:90
runtime.goexit()
    /usr/lib/go/src/runtime/asm_amd64.s:2232 +0x1

goroutine 3 [runnable]:
runtime.bgsweep()
    /usr/lib/go/src/runtime/mgc0.go:82
runtime.goexit()
    /usr/lib/go/src/runtime/asm_amd64.s:2232 +0x1

goroutine 4 [runnable]:
runtime.runfinq()
    /usr/lib/go/src/runtime/malloc.go:712
runtime.goexit()
    /usr/lib/go/src/runtime/asm_amd64.s:2232 +0x1

So does the gopher:

2...t/pt/examples% ./gopher
Loading OBJ: examples/gopher.obj
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x43fb9b]

goroutine 1 [running]:
github.com/fogleman/pt/pt.(*Mesh).SmoothNormals(0x0)
    /home/alexander/go/src/github.com/fogleman/pt/pt/mesh.go:84 +0x98b
main.main()
    /home/alexander/checkout/pt/examples/gopher.go:13 +0xa4e

goroutine 2 [runnable]:
runtime.forcegchelper()
    /usr/lib/go/src/runtime/proc.go:90
runtime.goexit()
    /usr/lib/go/src/runtime/asm_amd64.s:2232 +0x1

goroutine 3 [runnable]:
runtime.bgsweep()
    /usr/lib/go/src/runtime/mgc0.go:82
runtime.goexit()
    /usr/lib/go/src/runtime/asm_amd64.s:2232 +0x1

goroutine 4 [runnable]:
runtime.runfinq()
    /usr/lib/go/src/runtime/malloc.go:712
runtime.goexit()
    /usr/lib/go/src/runtime/asm_amd64.s:2232 +0x1

And the cylinder:

...t/pt/examples% ./cylinder 
Loading STL (Binary): examples/cylinder.stl
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x44018c]

goroutine 1 [running]:
github.com/fogleman/pt/pt.(*Mesh).FitInside(0x0, 0xbfb999999999999a, 0xbfb999999999999a, 0x0, 0x3ff199999999999a, 0x3ff199999999999a, 0x4059000000000000, 0x3fe0000000000000, 0x3fe0000000000000, 0x0)
    /home/alexander/go/src/github.com/fogleman/pt/pt/mesh.go:105 +0x82c
main.createMesh(0x3fc633401672b92a, 0x0, 0x3fadcab5b09790d5, 0x0, 0x0, 0x0, 0x3ff0000000000000, 0x0, 0x0, 0x3ff999999999999a, ...)
    /home/alexander/checkout/pt/examples/cylinder.go:7 +0x16c
main.main()
    /home/alexander/checkout/pt/examples/cylinder.go:15 +0x18e

goroutine 2 [runnable]:
runtime.forcegchelper()
    /usr/lib/go/src/runtime/proc.go:90
runtime.goexit()
    /usr/lib/go/src/runtime/asm_amd64.s:2232 +0x1

goroutine 3 [runnable]:
runtime.bgsweep()
    /usr/lib/go/src/runtime/mgc0.go:82
runtime.goexit()
    /usr/lib/go/src/runtime/asm_amd64.s:2232 +0x1

goroutine 4 [runnable]:
runtime.runfinq()
    /usr/lib/go/src/runtime/malloc.go:712
runtime.goexit()
    /usr/lib/go/src/runtime/asm_amd64.s:2232 +0x1

This is on 64-bit Arch Linux, kernel 3.18.6, go 1.4.1.

Wonderful project, btw!

Best regards,
Alexander F Rødseth

Scene.RayCount crashes on 32bit systems with cgo

Hey

First thank you for this lib and also for your other lib ln :)
I had great fun playing around with the examples and even build an example on top of your examples for my lib here: https://github.com/therecipe/qt/tree/master/internal/examples/widgets/renderer

But it seems like the examples crash if you compile them for windows/386 in combination with cgo.
I tracked the problem down and wrote some about it here: therecipe/qt#125

Basically to fix this you would just have to re-order this struct https://github.com/fogleman/pt/blob/master/pt/scene.go#L5-L13
and simply move rays to the top.

I hoped that you would fix this, so that I don't have to send a PR for such a small change.

Crytek sponza not working :'(

Hello. I trying crytek sponza (not dabrovic). And gets these errors.

Code

package main

// http://graphics.cs.williams.edu/data/meshes/dabrovic-sponza.zip

import . "../pt"

func main() {
	scene := Scene{}
	material := GlossyMaterial(HexColor(0xFCFAE1), 1.5, Radians(20))
	mesh, err := LoadOBJ("sponza.obj", material)
	if err != nil {
		panic(err)
	}
	mesh.MoveTo(Vector{}, Vector{0.5, 0, 0.5})
	scene.Add(mesh)
	scene.Add(NewSphere(Vector{0, 20, 0}, 3, LightMaterial(White, 100)))
	camera := LookAt(Vector{-10, 2, 0}, Vector{0, 4, 0}, Vector{0, 1, 0}, 45)
	sampler := NewSampler(4, 4)
	renderer := NewRenderer(&scene, &camera, sampler, 960, 540)
	renderer.IterativeRender("out%03d.png", 1000)
}

Error

C:\Users\acterhd\Downloads\pt-master\examples>go run sponza.go
Loading OBJ: sponza.obj
Loading MTL: sponza.mtl
Loading IMG: textures\sponza_thorn_diff.png
Loading IMG: textures\sponza_thorn_bump.png
Loading IMG: textures\vase_round.png
Loading IMG: textures\vase_round_bump.png
Loading IMG: textures\vase_plant.png
Loading IMG: textures\background.png
Loading IMG: textures\background_bump.png
Loading IMG: textures\gi_flag.png
Loading IMG: textures\spnza_bricks_a_diff.png
Loading IMG: textures\spnza_bricks_a_bump.png
Loading IMG: textures\sponza_arch_diff.png
Loading IMG: textures\sponza_ceiling_a_diff.png
Loading IMG: textures\sponza_column_a_diff.png
Loading IMG: textures\sponza_column_a_bump.png
Loading IMG: textures\sponza_floor_a_diff.png
Loading IMG: textures\sponza_column_c_diff.png
Loading IMG: textures\sponza_column_c_bump.png
Loading IMG: textures\sponza_details_diff.png
Loading IMG: textures\sponza_column_b_diff.png
Loading IMG: textures\sponza_column_b_bump.png
Loading IMG: textures\sponza_flagpole_diff.png
Loading IMG: textures\sponza_fabric_green_diff.png
Loading IMG: textures\sponza_fabric_blue_diff.png
Loading IMG: textures\sponza_fabric_diff.png
Loading IMG: textures\sponza_curtain_blue_diff.png
Loading IMG: textures\sponza_curtain_diff.png
Loading IMG: textures\sponza_curtain_green_diff.png
Loading IMG: textures\chain_texture.png
Loading IMG: textures\chain_texture_bump.png
Loading IMG: textures\vase_hanging.png
Loading IMG: textures\vase_dif.png
Loading IMG: textures\vase_bump.png
Loading IMG: textures\lion.png
Loading IMG: textures\lion_bump.png
Loading IMG: textures\sponza_roof_diff.png
Loading IMG: textures\sponza_roof_bump.png
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x38 pc=0x4596c6]

goroutine 1 [running]:
panic(0x505b60, 0xc04200c090)
        C:/Go/src/runtime/panic.go:500 +0x1af
_/C_/Users/acterhd/Downloads/pt-master/pt.LoadMTL(0xc04205c4a7, 0xa, 0x3fef2d779e37e205, 0x3feea2c5857ecb8e, 0x3fe84c2e92434b0b, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
        C:/Users/acterhd/Downloads/pt-master/pt/obj.go:137 +0x5c6
_/C_/Users/acterhd/Downloads/pt-master/pt.LoadOBJ(0x526f3e, 0xa, 0x3fef2d779e37e205, 0x3feea2c5857ecb8e, 0x3fe84c2e92434b0b, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
        C:/Users/acterhd/Downloads/pt-master/pt/obj.go:46 +0x1423
main.main()
        C:/Users/acterhd/Downloads/pt-master/examples/sponza.go:10 +0x1fd
exit status 2

There these models, with you can test
https://1drv.ms/f/s!AgEr-N6c2tdUhLMh11zNIP1besSUbQ

Light baking

Hi,

how hard would it be to add a feature for light/shadow baking?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.