Efficient Parallelization Techniques for GPU Ray Tracing

I
n
t
r
o
d
u
c
t
i
o
n
 
t
o
 
R
e
a
l
-
t
i
m
e
 
R
a
y
 
T
r
a
c
i
n
g
 
P
a
r
t
 
2
G
o
i
n
g
 
f
a
s
t
:
 
P
a
r
a
l
l
e
l
i
z
i
n
g
Y
o
u
r
 
R
a
y
 
T
r
a
c
e
r
C
h
r
i
s
 
W
y
m
a
n
P
r
i
n
c
i
p
a
l
 
R
e
s
e
a
r
c
h
 
S
c
i
e
n
t
i
s
t
N
V
I
D
I
A
1
S
O
M
E
 
P
R
E
L
I
M
I
N
A
R
I
E
S
Ideas needed before GPU ray tracing
Y
O
U
 
J
U
S
T
 
G
O
T
 
T
H
E
 
B
A
S
I
C
S
 
3
Y
O
U
 
J
U
S
T
 
G
O
T
 
T
H
E
 
B
A
S
I
C
S
B
u
t
 
a
d
d
i
t
i
o
n
a
l
 
f
e
a
t
u
r
e
s
 
e
x
p
e
c
t
e
d
 
f
o
r
 
G
P
U
 
r
e
n
d
e
r
i
n
g
4
Y
O
U
 
J
U
S
T
 
G
O
T
 
T
H
E
 
B
A
S
I
C
S
B
u
t
 
a
d
d
i
t
i
o
n
a
l
 
f
e
a
t
u
r
e
s
 
e
x
p
e
c
t
e
d
 
f
o
r
 
G
P
U
 
r
e
n
d
e
r
i
n
g
Typically, increased complexity; not just a few primitives
5
Y
O
U
 
J
U
S
T
 
G
O
T
 
T
H
E
 
B
A
S
I
C
S
B
u
t
 
a
d
d
i
t
i
o
n
a
l
 
f
e
a
t
u
r
e
s
 
e
x
p
e
c
t
e
d
 
f
o
r
 
G
P
U
 
r
e
n
d
e
r
i
n
g
Typically, increased complexity; not just a few primitives
Render triangle meshes
Just collections of triangles approximating 3D shapes
Easy enough; intersect each triangle in turn
6
Y
O
U
 
J
U
S
T
 
G
O
T
 
T
H
E
 
B
A
S
I
C
S
B
u
t
 
a
d
d
i
t
i
o
n
a
l
 
f
e
a
t
u
r
e
s
 
e
x
p
e
c
t
e
d
 
f
o
r
 
G
P
U
 
r
e
n
d
e
r
i
n
g
Typically, increased complexity; not just a few primitives
Render triangle meshes
Just collections of triangles approximating 3D shapes
Easy enough; intersect each triangle in turn
Mesh files usually contain material information
Often small-scale detail stored in textures
7
H
O
W
 
T
O
 
H
A
N
D
L
E
 
M
A
T
E
R
I
A
L
S
 
A
N
D
 
T
E
X
T
U
R
E
S
?
 
8
H
O
W
 
T
O
 
H
A
N
D
L
E
 
M
A
T
E
R
I
A
L
S
 
A
N
D
 
T
E
X
T
U
R
E
S
?
Ray-primitive intersection
Not just binary:  Did we hit?  Yes / No
A
l
s
o
 
n
e
e
d
 
t
o
 
s
t
o
r
e
 
a
t
t
r
i
b
u
t
e
s
 
a
t
 
t
h
e
 
h
i
t
 
p
o
i
n
t
,
 
e
.
g
.
:
Positions
Normal
Color
9
H
O
W
 
T
O
 
H
A
N
D
L
E
 
M
A
T
E
R
I
A
L
S
 
A
N
D
 
T
E
X
T
U
R
E
S
?
Ray-primitive intersection
Not just binary:  Did we hit?  Yes / No
A
l
s
o
 
n
e
e
d
 
t
o
 
s
t
o
r
e
 
a
t
t
r
i
b
u
t
e
s
 
a
t
 
t
h
e
 
h
i
t
 
p
o
i
n
t
,
 
e
.
g
.
:
Positions
Normal
Color
Texture coordinates
Material parameters
Et cetera
10
10
H
O
W
 
T
O
 
H
A
N
D
L
E
 
M
A
T
E
R
I
A
L
S
 
A
N
D
 
T
E
X
T
U
R
E
S
?
Ray-primitive intersection
Not just binary:  Did we hit?  Yes / No
A
l
s
o
 
n
e
e
d
 
t
o
 
s
t
o
r
e
 
a
t
t
r
i
b
u
t
e
s
 
a
t
 
t
h
e
 
h
i
t
 
p
o
i
n
t
,
 
e
.
g
.
:
Positions
Normal
Color
Texture coordinates
Material parameters
Et cetera
11
11
O
u
r
 
t
e
x
t
u
r
e
:
H
O
W
 
T
O
 
H
A
N
D
L
E
 
M
A
T
E
R
I
A
L
S
 
A
N
D
 
T
E
X
T
U
R
E
S
?
Ray-primitive intersection
Not just binary:  Did we hit?  Yes / No
A
l
s
o
 
n
e
e
d
 
t
o
 
s
t
o
r
e
 
a
t
t
r
i
b
u
t
e
s
 
a
t
 
t
h
e
 
h
i
t
 
p
o
i
n
t
,
 
e
.
g
.
:
Positions
Normal
Color
Texture coordinates
Material parameters
Et cetera
12
12
(0,0)
(1,0)
(0,1)
Triangle vertices have:
      texture coordinates
H
O
W
 
T
O
 
H
A
N
D
L
E
 
M
A
T
E
R
I
A
L
S
 
A
N
D
 
T
E
X
T
U
R
E
S
?
Ray-primitive intersection
Not just binary:  Did we hit?  Yes / No
A
l
s
o
 
n
e
e
d
 
t
o
 
s
t
o
r
e
 
a
t
t
r
i
b
u
t
e
s
 
a
t
 
t
h
e
 
h
i
t
 
p
o
i
n
t
,
 
e
.
g
.
:
Positions
Normal
Color
Texture coordinates
Material parameters
Et cetera
13
13
(0,0)
(1,0)
(0,1)
Triangle vertices have:
      texture coordinates
Coordinate here:
    Interpolates coordinates at vertices
H
O
W
 
T
O
 
H
A
N
D
L
E
 
M
A
T
E
R
I
A
L
S
 
A
N
D
 
T
E
X
T
U
R
E
S
?
Ray-primitive intersection
Not just binary:  Did we hit?  Yes / No
A
l
s
o
 
n
e
e
d
 
t
o
 
s
t
o
r
e
 
a
t
t
r
i
b
u
t
e
s
 
a
t
 
t
h
e
 
h
i
t
 
p
o
i
n
t
,
 
e
.
g
.
:
Positions
Normal
Color
Texture coordinates
Material parameters
Et cetera
14
14
(0,0)
(1,0)
(0,1)
Triangle vertices have:
      texture coordinates
Coordinate here:
    Interpolates coordinates at vertices
Same interpolation as position, 
    normal, color, etc.
Use coord to index in the image array
H
O
W
 
T
O
 
H
A
N
D
L
E
 
M
A
T
E
R
I
A
L
S
 
A
N
D
 
T
E
X
T
U
R
E
S
?
Ray-primitive intersection
Not just binary:  Did we hit?  Yes / No
A
l
s
o
 
n
e
e
d
 
t
o
 
s
t
o
r
e
 
a
t
t
r
i
b
u
t
e
s
 
a
t
 
t
h
e
 
h
i
t
 
p
o
i
n
t
,
 
e
.
g
.
:
Positions
Normal
Color
Texture coordinates
Material parameters
Et cetera
All attribute interpolation work the same way
15
15
B
A
S
I
C
S
 
O
F
 
O
P
T
I
M
I
Z
A
T
I
O
N
Before jumping to GPU, take some baby steps
B
E
F
O
R
E
 
D
I
V
I
N
G
 
I
N
T
O
 
P
A
R
A
L
L
E
L
I
Z
A
T
I
O
N
Need to talk about some performance basics
17
17
B
E
F
O
R
E
 
D
I
V
I
N
G
 
I
N
T
O
 
P
A
R
A
L
L
E
L
I
Z
A
T
I
O
N
Need to talk about some performance basics
Why is tracing rays slow at all?
18
18
B
E
F
O
R
E
 
D
I
V
I
N
G
 
I
N
T
O
 
P
A
R
A
L
L
E
L
I
Z
A
T
I
O
N
Need to talk about some performance basics
Why is tracing rays slow at all?
Consider basic ray tracing algorithm:
Take a ray through your scene
19
19
B
E
F
O
R
E
 
D
I
V
I
N
G
 
I
N
T
O
 
P
A
R
A
L
L
E
L
I
Z
A
T
I
O
N
Need to talk about some performance basics
Why is tracing rays slow at all?
Consider basic ray tracing algorithm:
Take a ray through your scene
Test triangle to find intersection
20
20
B
E
F
O
R
E
 
D
I
V
I
N
G
 
I
N
T
O
 
P
A
R
A
L
L
E
L
I
Z
A
T
I
O
N
Need to talk about some performance basics
Why is tracing rays slow at all?
Consider basic ray tracing algorithm:
Take a ray through your scene
Test triangle to find intersection
Repeat
21
21
B
E
F
O
R
E
 
D
I
V
I
N
G
 
I
N
T
O
 
P
A
R
A
L
L
E
L
I
Z
A
T
I
O
N
Need to talk about some performance basics
Why is tracing rays slow at all?
Consider basic ray tracing algorithm:
Take a ray through your scene
Test triangle to find intersection
Repeat
22
22
B
E
F
O
R
E
 
D
I
V
I
N
G
 
I
N
T
O
 
P
A
R
A
L
L
E
L
I
Z
A
T
I
O
N
Need to talk about some performance basics
Why is tracing rays slow at all?
Consider basic ray tracing algorithm:
Take a ray through your scene
Test triangle to find intersection
Repeat
23
23
B
E
F
O
R
E
 
D
I
V
I
N
G
 
I
N
T
O
 
P
A
R
A
L
L
E
L
I
Z
A
T
I
O
N
Need to talk about some performance basics
Why is tracing rays slow at all?
Consider basic ray tracing algorithm:
Take a ray through your scene
Test triangle to find intersection
Repeat
24
24
B
E
F
O
R
E
 
D
I
V
I
N
G
 
I
N
T
O
 
P
A
R
A
L
L
E
L
I
Z
A
T
I
O
N
Need to talk about some performance basics
Why is tracing rays slow at all?
Consider basic ray tracing algorithm:
Take a ray through your scene
Test triangle to find intersection
Repeat
How do you know when you’re done?
25
25
B
E
F
O
R
E
 
D
I
V
I
N
G
 
I
N
T
O
 
P
A
R
A
L
L
E
L
I
Z
A
T
I
O
N
Need to talk about some performance basics
Why is tracing rays slow at all?
Consider basic ray tracing algorithm:
Take a ray through your scene
Test triangle to find intersection
Repeat
How do you know when you’re done?
When you’ve tested every triangle?
26
26
B
E
F
O
R
E
 
D
I
V
I
N
G
 
I
N
T
O
 
P
A
R
A
L
L
E
L
I
Z
A
T
I
O
N
Need to talk about some performance basics
Why is tracing rays slow at all?
Consider basic ray tracing algorithm:
Take a ray through your scene
Test triangle to find intersection
Repeat
How do you know when you’re done?
When you’ve tested every triangle?
Very expensive…
Every ray could test, 1 million (or more) triangles
27
27
W
H
A
T
S
 
O
U
R
 
C
O
M
P
U
T
A
T
I
O
N
 
B
U
D
G
E
T
?
28
28
 
W
H
A
T
S
 
O
U
R
 
C
O
M
P
U
T
A
T
I
O
N
 
B
U
D
G
E
T
?
Let’s be easy on ourselves:
Target just 1920 x 1080 at 60 fps
29
29
W
H
A
T
S
 
O
U
R
 
C
O
M
P
U
T
A
T
I
O
N
 
B
U
D
G
E
T
?
Let’s be easy on ourselves:
Target just 1920 x 1080 at 60 fps
We need 125 million pixels per second!
30
30
W
H
A
T
S
 
O
U
R
 
C
O
M
P
U
T
A
T
I
O
N
 
B
U
D
G
E
T
?
Let’s be easy on ourselves:
Target just 1920 x 1080 at 60 fps
We need 125 million pixels per second!
With a ~10 TFLOP state-of-the-art GPU
If tracing one ray per pixel…
About 80,000 flops per ray
31
31
W
H
A
T
S
 
O
U
R
 
C
O
M
P
U
T
A
T
I
O
N
 
B
U
D
G
E
T
?
Let’s be easy on ourselves:
Target just 1920 x 1080 at 60 fps
We need 125 million pixels per second!
With a ~10 TFLOP state-of-the-art GPU
If tracing one ray per pixel…
About 80,000 flops per ray
An optimized triangle intersection:  ~10 flops
C
a
n
 
a
f
f
o
r
d
 
a
t
 
m
o
s
t
 
8
,
0
0
0
 
i
n
t
e
r
s
e
c
t
i
o
n
s
 
p
e
r
 
r
a
y
32
32
W
H
A
T
S
 
O
U
R
 
C
O
M
P
U
T
A
T
I
O
N
 
B
U
D
G
E
T
?
Let’s be easy on ourselves:
Target just 1920 x 1080 at 60 fps
We need 125 million pixels per second!
With a ~10 TFLOP state-of-the-art GPU
If tracing one ray per pixel…
About 80,000 flops per ray
An optimized triangle intersection:  ~10 flops
C
a
n
 
a
f
f
o
r
d
 
a
t
 
m
o
s
t
 
8
,
0
0
0
 
i
n
t
e
r
s
e
c
t
i
o
n
s
 
p
e
r
 
r
a
y
C
o
n
c
l
u
s
i
o
n
:
 
 
D
o
n
t
 
t
e
s
t
 
e
v
e
r
y
 
t
r
i
a
n
g
l
e
!
33
33
K
E
Y
 
P
R
I
N
C
I
P
A
L
 
T
O
 
O
P
T
I
M
I
Z
A
T
I
O
N
:
M
a
k
e
 
t
h
e
 
c
o
m
m
o
n
 
c
a
s
e
 
f
a
s
t
34
34
K
E
Y
 
P
R
I
N
C
I
P
A
L
 
T
O
 
O
P
T
I
M
I
Z
A
T
I
O
N
:
M
a
k
e
 
t
h
e
 
c
o
m
m
o
n
 
c
a
s
e
 
f
a
s
t
Common case in ray tracing?
Ray does not intersect a triangle
35
35
K
E
Y
 
P
R
I
N
C
I
P
A
L
 
T
O
 
O
P
T
I
M
I
Z
A
T
I
O
N
:
M
a
k
e
 
t
h
e
 
c
o
m
m
o
n
 
c
a
s
e
 
f
a
s
t
Common case in ray tracing?
Ray does not intersect a triangle
For any mesh, ray typically misses mesh
36
36
K
E
Y
 
P
R
I
N
C
I
P
A
L
 
T
O
 
O
P
T
I
M
I
Z
A
T
I
O
N
:
M
a
k
e
 
t
h
e
 
c
o
m
m
o
n
 
c
a
s
e
 
f
a
s
t
Common case in ray tracing?
Ray does not intersect a triangle
For any mesh, ray typically misses mesh
Perhaps:
First intersect a mesh bounding box
37
37
K
E
Y
 
P
R
I
N
C
I
P
A
L
 
T
O
 
O
P
T
I
M
I
Z
A
T
I
O
N
:
M
a
k
e
 
t
h
e
 
c
o
m
m
o
n
 
c
a
s
e
 
f
a
s
t
Common case in ray tracing?
Ray does not intersect a triangle
For any mesh, ray typically misses mesh
Perhaps:
First intersect a mesh bounding box
Most rays avoid testing thousands of triangles
But, extra box test when hit bunny
38
38
K
E
Y
 
P
R
I
N
C
I
P
A
L
 
T
O
 
O
P
T
I
M
I
Z
A
T
I
O
N
:
39
39
What if you have thousands of bunnies?
K
E
Y
 
P
R
I
N
C
I
P
A
L
 
T
O
 
O
P
T
I
M
I
Z
A
T
I
O
N
:
40
40
What if you have thousands of bunnies?
K
E
Y
 
P
R
I
N
C
I
P
A
L
 
T
O
 
O
P
T
I
M
I
Z
A
T
I
O
N
:
41
41
What if you have thousands of bunnies?
Common case:  Ray misses most bunnies
K
E
Y
 
P
R
I
N
C
I
P
A
L
 
T
O
 
O
P
T
I
M
I
Z
A
T
I
O
N
:
42
42
What if you have thousands of bunnies?
Common case:  Ray misses most bunnies
Can skip testing this half…
K
E
Y
 
P
R
I
N
C
I
P
A
L
 
T
O
 
O
P
T
I
M
I
Z
A
T
I
O
N
:
43
43
What if you have thousands of bunnies?
Common case:  Ray misses most bunnies
Can skip testing this half… and this quarter… with a few more boxes
K
E
Y
 
P
R
I
N
C
I
P
A
L
 
T
O
 
O
P
T
I
M
I
Z
A
T
I
O
N
:
44
44
Build a tree of bounding boxes
Known as a “bounding volume hierarchy” or BVH
K
E
Y
 
P
R
I
N
C
I
P
A
L
 
T
O
 
O
P
T
I
M
I
Z
A
T
I
O
N
:
45
45
Build a tree of bounding boxes
Known as a “bounding volume hierarchy” or BVH
When using a principled tree build
Reduces number of required intersections
From O(N) to O(log N)
K
E
Y
 
P
R
I
N
C
I
P
A
L
 
T
O
 
O
P
T
I
M
I
Z
A
T
I
O
N
:
46
46
Build a tree of bounding boxes
Known as a “bounding volume hierarchy” or BVH
When using a principled tree build
Reduces number of required intersections
From O(N) to O(log N)
With a binary tree, 1 million ray-triangle tests becomes:
Around 20 ray-box tests
A few ray-triangle tests in leaf nodes
K
E
Y
 
P
R
I
N
C
I
P
A
L
 
T
O
 
O
P
T
I
M
I
Z
A
T
I
O
N
:
47
47
P
r
o
d
u
c
t
i
o
n
 
r
a
y
 
t
r
a
c
e
r
s
 
a
l
w
a
y
s
 
u
s
e
 
s
o
m
e
 
a
c
c
e
l
e
r
a
t
i
o
n
 
s
t
r
u
c
t
u
r
e
K
E
Y
 
P
R
I
N
C
I
P
A
L
 
T
O
 
O
P
T
I
M
I
Z
A
T
I
O
N
:
48
48
P
r
o
d
u
c
t
i
o
n
 
r
a
y
 
t
r
a
c
e
r
s
 
a
l
w
a
y
s
 
u
s
e
 
s
o
m
e
 
a
c
c
e
l
e
r
a
t
i
o
n
 
s
t
r
u
c
t
u
r
e
B
u
t
,
 
w
h
i
c
h
 
s
t
r
u
c
t
u
r
e
?
 
 
H
o
w
 
d
o
 
y
o
u
 
b
e
s
t
 
b
u
i
l
d
 
i
t
?
Literally decades of research
K
E
Y
 
P
R
I
N
C
I
P
A
L
 
T
O
 
O
P
T
I
M
I
Z
A
T
I
O
N
:
49
49
P
r
o
d
u
c
t
i
o
n
 
r
a
y
 
t
r
a
c
e
r
s
 
a
l
w
a
y
s
 
u
s
e
 
s
o
m
e
 
a
c
c
e
l
e
r
a
t
i
o
n
 
s
t
r
u
c
t
u
r
e
B
u
t
,
 
w
h
i
c
h
 
s
t
r
u
c
t
u
r
e
?
 
 
H
o
w
 
d
o
 
y
o
u
 
b
e
s
t
 
b
u
i
l
d
 
i
t
?
Literally decades of research
Continuing to today  
(e.g., “Wide BVH Traversal with a Short Stack,” Vaidyanathan et al. 2019)
K
E
Y
 
P
R
I
N
C
I
P
A
L
 
T
O
 
O
P
T
I
M
I
Z
A
T
I
O
N
:
50
50
P
r
o
d
u
c
t
i
o
n
 
r
a
y
 
t
r
a
c
e
r
s
 
a
l
w
a
y
s
 
u
s
e
 
s
o
m
e
 
a
c
c
e
l
e
r
a
t
i
o
n
 
s
t
r
u
c
t
u
r
e
B
u
t
,
 
w
h
i
c
h
 
s
t
r
u
c
t
u
r
e
?
 
 
H
o
w
 
d
o
 
y
o
u
 
b
e
s
t
 
b
u
i
l
d
 
i
t
?
Literally decades of research
Continuing to today  
(e.g., “Wide BVH Traversal with a Short Stack,” Vaidyanathan et al. 2019)
When starting real-time ray tracing, best bet:
Use someone else’s code
Quality of your BVH easily affects performance by 2x, 3x, or >10x
Varies per scene!
Luckily most APIs will build structure
G
O
I
N
G
 
P
A
R
A
L
L
E
L
Coding for massively parallel GPUs
R
A
Y
 
T
R
A
C
I
N
G
:
 
 
E
M
B
A
R
R
A
S
S
I
N
G
L
Y
 
P
A
R
A
L
L
E
L
Defined:  Little to no effort needed to separate into parallel tasks
52
52
R
A
Y
 
T
R
A
C
I
N
G
:
 
 
E
M
B
A
R
R
A
S
S
I
N
G
L
Y
 
P
A
R
A
L
L
E
L
Defined:  Little to no effort needed to separate into parallel tasks
Rendering often a prototypical example of 
embarrassingly parallel
One obvious way: assign one CPU or GPU core per pixel
53
53
R
A
Y
 
T
R
A
C
I
N
G
:
 
 
E
M
B
A
R
R
A
S
S
I
N
G
L
Y
 
P
A
R
A
L
L
E
L
On CPU, call fork() or spawn() to create multiple threads
Each thread works on separate pixels
Wait for all threads to complete
Some threads take longer 
 may need load balancing
54
54
R
A
Y
 
T
R
A
C
I
N
G
:
 
 
E
M
B
A
R
R
A
S
S
I
N
G
L
Y
 
P
A
R
A
L
L
E
L
GPU programming model hides thread spawning and load-balancing
Code 
appears
 serial, but you have access to current pixel index
55
55
R
A
Y
 
T
R
A
C
I
N
G
:
 
 
E
M
B
A
R
R
A
S
S
I
N
G
L
Y
 
P
A
R
A
L
L
E
L
GPU programming model hides thread spawning and load-balancing
Code 
appears
 serial, but you have access to current pixel index
56
56
// Simple DirectX-like ray tracing shader
RWTexture<float4> 
rayColors;
[shader(
“raygeneration”
)]
void
 SimpleRayTracer() {
   
uint2
       curPixel = 
DispatchRaysIndex
().xy;
   
RayDesc     ray      
= { 
GetRayOrigin
(curPixel), 
0.0f, 
GetRayDir
(curPixel)
, 1e+38f };
   RayPayload  payload  = { float3(0, 0, 0) };
   
TraceRay
( 
..., 
ray, payload );
   rayColors[
curPixel
]  = float4( payload.rayColor, 1.0f );
}
R
A
Y
 
T
R
A
C
I
N
G
:
 
 
E
M
B
A
R
R
A
S
S
I
N
G
L
Y
 
P
A
R
A
L
L
E
L
GPU programming model hides thread spawning and load-balancing
Code 
appears
 serial, but you have access to current pixel index
57
57
// Simple DirectX-like ray tracing shader
RWTexture<float4> 
rayColors;
[shader(
“raygeneration”
)]
void
 SimpleRayTracer() {
   
uint2
       curPixel = 
DispatchRaysIndex
().xy;
   
RayDesc     ray      
= { 
GetRayOrigin
(curPixel), 
0.0f, 
GetRayDir
(curPixel)
, 1e+38f };
   RayPayload  payload  = { float3(0, 0, 0) };
   
TraceRay
( 
..., 
ray, payload );
   rayColors[
curPixel
]  = float4( payload.rayColor, 1.0f );
}
Identify the current pixel
R
A
Y
 
T
R
A
C
I
N
G
:
 
 
E
M
B
A
R
R
A
S
S
I
N
G
L
Y
 
P
A
R
A
L
L
E
L
GPU programming model hides thread spawning and load-balancing
Code 
appears
 serial, but you have access to current pixel index
58
58
// Simple DirectX-like ray tracing shader
RWTexture<float4> 
rayColors;
[shader(
“raygeneration”
)]
void
 SimpleRayTracer() {
   
uint2
       curPixel = 
DispatchRaysIndex
().xy;
   
RayDesc     ray      
= { 
GetRayOrigin
(curPixel), 
0.0f, 
GetRayDir
(curPixel)
, 1e+38f };
   RayPayload  payload  = { float3(0, 0, 0) };
   
TraceRay
( 
..., 
ray, payload );
   rayColors[
curPixel
]  = float4( payload.rayColor, 1.0f );
}
Setup the ray
R
A
Y
 
T
R
A
C
I
N
G
:
 
 
E
M
B
A
R
R
A
S
S
I
N
G
L
Y
 
P
A
R
A
L
L
E
L
GPU programming model hides thread spawning and load-balancing
Code 
appears
 serial, but you have access to current pixel index
59
59
// Simple DirectX-like ray tracing shader
RWTexture<float4> 
rayColors;
[shader(
“raygeneration”
)]
void
 SimpleRayTracer() {
   
uint2
       curPixel = 
DispatchRaysIndex
().xy;
   
RayDesc     ray      
= { 
GetRayOrigin
(curPixel), 
0.0f, 
GetRayDir
(curPixel)
, 1e+38f };
   RayPayload  payload  = { float3(0, 0, 0) };
   
TraceRay
( 
..., 
ray, payload );
   rayColors[
curPixel
]  = float4( payload.rayColor, 1.0f );
}
Initialize ray return values
R
A
Y
 
T
R
A
C
I
N
G
:
 
 
E
M
B
A
R
R
A
S
S
I
N
G
L
Y
 
P
A
R
A
L
L
E
L
GPU programming model hides thread spawning and load-balancing
Code 
appears
 serial, but you have access to current pixel index
60
60
// Simple DirectX-like ray tracing shader
RWTexture<float4> 
rayColors;
[shader(
“raygeneration”
)]
void
 SimpleRayTracer() {
   
uint2
       curPixel = 
DispatchRaysIndex
().xy;
   
RayDesc     ray      
= { 
GetRayOrigin
(curPixel), 
0.0f, 
GetRayDir
(curPixel)
, 1e+38f };
   RayPayload  payload  = { float3(0, 0, 0) };
   
TraceRay
( 
..., 
ray, payload );
   rayColors[
curPixel
]  = float4( payload.rayColor, 1.0f );
}
Trace your ray 
R
A
Y
 
T
R
A
C
I
N
G
:
 
 
E
M
B
A
R
R
A
S
S
I
N
G
L
Y
 
P
A
R
A
L
L
E
L
GPU programming model hides thread spawning and load-balancing
Code 
appears
 serial, but you have access to current pixel index
61
61
// Simple DirectX-like ray tracing shader
RWTexture<float4> 
rayColors;
[shader(
“raygeneration”
)]
void
 SimpleRayTracer() {
   
uint2
       curPixel = 
DispatchRaysIndex
().xy;
   
RayDesc     ray      
= { 
GetRayOrigin
(curPixel), 
0.0f, 
GetRayDir
(curPixel)
, 1e+38f };
   RayPayload  payload  = { float3(0, 0, 0) };
   
TraceRay
( 
..., 
ray, payload );
   rayColors[
curPixel
]  = float4( payload.rayColor, 1.0f );
}
Output your results
D
O
I
N
G
 
I
T
 
Y
O
U
R
S
E
L
F
 
V
.
S
.
 
E
X
I
S
T
I
N
G
 
A
P
I
S
Embarrassingly parallel ≠ easy to parallelize
62
62
D
O
I
N
G
 
I
T
 
Y
O
U
R
S
E
L
F
 
V
.
S
.
 
E
X
I
S
T
I
N
G
 
A
P
I
S
Embarrassingly parallel ≠ easy to parallelize
N
o
t
 
t
h
e
 
s
a
m
e
 
a
s
 
g
e
t
t
i
n
g
 
b
e
s
t
 
p
e
r
f
o
r
m
a
n
c
e
63
63
D
O
I
N
G
 
I
T
 
Y
O
U
R
S
E
L
F
 
V
.
S
.
 
E
X
I
S
T
I
N
G
 
A
P
I
S
Embarrassingly parallel ≠ easy to parallelize
N
o
t
 
t
h
e
 
s
a
m
e
 
a
s
 
g
e
t
t
i
n
g
 
b
e
s
t
 
p
e
r
f
o
r
m
a
n
c
e
Many performance considerations:
# intersections, data structures, coherence, caching, load-balancing, SIMD
64
64
D
O
I
N
G
 
I
T
 
Y
O
U
R
S
E
L
F
 
V
.
S
.
 
E
X
I
S
T
I
N
G
 
A
P
I
S
Embarrassingly parallel ≠ easy to parallelize
N
o
t
 
t
h
e
 
s
a
m
e
 
a
s
 
g
e
t
t
i
n
g
 
b
e
s
t
 
p
e
r
f
o
r
m
a
n
c
e
Many performance considerations:
# intersections, data structures, coherence, caching, load-balancing, SIMD
APIs can leverage best-known methods behind your back
65
65
D
O
I
N
G
 
I
T
 
Y
O
U
R
S
E
L
F
 
V
.
S
.
 
E
X
I
S
T
I
N
G
 
A
P
I
S
Embarrassingly parallel ≠ easy to parallelize
N
o
t
 
t
h
e
 
s
a
m
e
 
a
s
 
g
e
t
t
i
n
g
 
b
e
s
t
 
p
e
r
f
o
r
m
a
n
c
e
Many performance considerations:
# intersections, data structures, coherence, caching, load-balancing, SIMD
APIs can leverage best-known methods behind your back
APIs allow you to shoot yourself in the foot without knowing it
66
66
D
O
I
N
G
 
I
T
 
Y
O
U
R
S
E
L
F
 
V
.
S
.
 
E
X
I
S
T
I
N
G
 
A
P
I
S
Embarrassingly parallel ≠ easy to parallelize
N
o
t
 
t
h
e
 
s
a
m
e
 
a
s
 
g
e
t
t
i
n
g
 
b
e
s
t
 
p
e
r
f
o
r
m
a
n
c
e
Many performance considerations:
# intersections, data structures, coherence, caching, load-balancing, SIMD
APIs can leverage best-known methods behind your back
APIs allow you to shoot yourself in the foot without knowing it
APIs come at many levels (e.g., use of CUDA without ray tracing API)
67
67
S
O
M
E
 
R
A
Y
 
T
R
A
C
I
N
G
 
A
P
I
S
Hardware vendor specific:
OptiX, Embree, FireRays
Cross-vendor APIs:
DirectX Raytracing, Vulkan RT
Game engine APIs:
Unity, Unreal
Different:
Audiences, learning curves, flexibility, performance, built-in optimizations
68
68
T
O
D
A
Y
:
 
 
U
S
I
N
G
 
D
I
R
E
C
T
X
 
F
O
R
 
S
A
M
P
L
E
 
C
O
D
E
Why?
DirectX widely used API for interactive graphics
Similar to Vulkan model
Abstracts some bits tricky for novices’ ray tracers
Tutorial frameworks for easy experimentation
69
69
D
I
R
E
C
T
X
 
R
A
Y
 
T
R
A
C
I
N
G
 
R
E
S
O
U
R
C
E
S
Some DirectX Ray Tracing tutorials:
Tutorial framework
 that hides the C++ API  ( 
http://intro-to-dxr.cwyman.org 
)
Easy to get started, not targeted at optimal performance
Used for my sample code today
Builds on 
Falcor
 for abstraction
Lower-level tutorial
 covering DirectX API
From the “
Introduction to DirectX Ray Tracing
Ray Tracing Gems 
article
A simple 
getting started blog
 post
Microsoft’s 
DXR samples
A DirectX Raytracing 
functional specification
70
70
W
E
L
L
 
F
O
C
U
S
 
O
N
 
G
P
U
 
S
H
A
D
E
R
 
C
O
D
E
Why?
Focus on tracing rays, identifying where to trace rays
Where interesting rendering algorithms mostly live
71
71
W
E
L
L
 
F
O
C
U
S
 
O
N
 
G
P
U
 
S
H
A
D
E
R
 
C
O
D
E
Why?
Focus on tracing rays, identifying where to trace rays
Where interesting rendering algorithms mostly live
The CPU has vital infrastructure…
But it’s largely reusable stuff like asset loaders
Not interesting (to me) to re-write
72
72
W
E
L
L
 
F
O
C
U
S
 
O
N
 
G
P
U
 
S
H
A
D
E
R
 
C
O
D
E
Why?
Focus on tracing rays, identifying where to trace rays
Where interesting rendering algorithms mostly live
The CPU has vital infrastructure…
But it’s largely reusable stuff like asset loaders
Not interesting (to me) to re-write
For parallel GPU ray tracer, CPU code is mostly glue:
Pass configuration and data to GPU
Launch GPU processes
73
73
S
T
R
U
C
T
U
R
E
 
O
F
 
G
P
U
 
S
H
A
D
E
R
S
Specifically DirectX HLSL, but many similarities elsewhere
F
I
V
E
 
T
Y
P
E
S
 
O
F
 
R
A
Y
 
T
R
A
C
I
N
G
 
S
H
A
D
E
R
S
75
75
R
a
y
 
t
r
a
c
i
n
g
 
p
i
p
e
l
i
n
e
 
s
p
l
i
t
 
i
n
t
o
 
f
i
v
e
 
s
h
a
d
e
r
s
:
A
 
r
a
y
 
g
e
n
e
r
a
t
i
o
n
 
s
h
a
d
e
r
 
d
e
f
i
n
e
 
h
o
w
 
t
o
 
s
t
a
r
t
 
t
r
a
c
i
n
g
 
r
a
y
s
F
I
V
E
 
T
Y
P
E
S
 
O
F
 
R
A
Y
 
T
R
A
C
I
N
G
 
S
H
A
D
E
R
S
76
76
R
a
y
 
t
r
a
c
i
n
g
 
p
i
p
e
l
i
n
e
 
s
p
l
i
t
 
i
n
t
o
 
f
i
v
e
 
s
h
a
d
e
r
s
:
A
 
r
a
y
 
g
e
n
e
r
a
t
i
o
n
 
s
h
a
d
e
r
 
d
e
f
i
n
e
 
h
o
w
 
t
o
 
s
t
a
r
t
 
t
r
a
c
i
n
g
 
r
a
y
s
I
n
t
e
r
s
e
c
t
i
o
n
 
s
h
a
d
e
r
(
s
)
 
d
e
f
i
n
e
 
h
o
w
 
r
a
y
s
 
i
n
t
e
r
s
e
c
t
 
g
e
o
m
e
t
r
y
F
I
V
E
 
T
Y
P
E
S
 
O
F
 
R
A
Y
 
T
R
A
C
I
N
G
 
S
H
A
D
E
R
S
77
77
R
a
y
 
t
r
a
c
i
n
g
 
p
i
p
e
l
i
n
e
 
s
p
l
i
t
 
i
n
t
o
 
f
i
v
e
 
s
h
a
d
e
r
s
:
A
 
r
a
y
 
g
e
n
e
r
a
t
i
o
n
 
s
h
a
d
e
r
 
d
e
f
i
n
e
 
h
o
w
 
t
o
 
s
t
a
r
t
 
t
r
a
c
i
n
g
 
r
a
y
s
I
n
t
e
r
s
e
c
t
i
o
n
 
s
h
a
d
e
r
(
s
)
 
d
e
f
i
n
e
 
h
o
w
 
r
a
y
s
 
i
n
t
e
r
s
e
c
t
 
g
e
o
m
e
t
r
y
M
i
s
s
 
s
h
a
d
e
r
(
s
)
 
s
h
a
d
i
n
g
 
f
o
r
 
w
h
e
n
 
r
a
y
s
 
m
i
s
s
 
g
e
o
m
e
t
r
y
F
I
V
E
 
T
Y
P
E
S
 
O
F
 
R
A
Y
 
T
R
A
C
I
N
G
 
S
H
A
D
E
R
S
78
78
R
a
y
 
t
r
a
c
i
n
g
 
p
i
p
e
l
i
n
e
 
s
p
l
i
t
 
i
n
t
o
 
f
i
v
e
 
s
h
a
d
e
r
s
:
A
 
r
a
y
 
g
e
n
e
r
a
t
i
o
n
 
s
h
a
d
e
r
 
d
e
f
i
n
e
 
h
o
w
 
t
o
 
s
t
a
r
t
 
t
r
a
c
i
n
g
 
r
a
y
s
I
n
t
e
r
s
e
c
t
i
o
n
 
s
h
a
d
e
r
(
s
)
 
d
e
f
i
n
e
 
h
o
w
 
r
a
y
s
 
i
n
t
e
r
s
e
c
t
 
g
e
o
m
e
t
r
y
M
i
s
s
 
s
h
a
d
e
r
(
s
)
 
s
h
a
d
i
n
g
 
f
o
r
 
w
h
e
n
 
r
a
y
s
 
m
i
s
s
 
g
e
o
m
e
t
r
y
C
l
o
s
e
s
t
-
h
i
t
 
s
h
a
d
e
r
(
s
)
 
s
h
a
d
i
n
g
 
a
t
 
t
h
e
 
i
n
t
e
r
s
e
c
t
i
o
n
 
p
o
i
n
t
F
I
V
E
 
T
Y
P
E
S
 
O
F
 
R
A
Y
 
T
R
A
C
I
N
G
 
S
H
A
D
E
R
S
79
79
R
a
y
 
t
r
a
c
i
n
g
 
p
i
p
e
l
i
n
e
 
s
p
l
i
t
 
i
n
t
o
 
f
i
v
e
 
s
h
a
d
e
r
s
:
A
 
r
a
y
 
g
e
n
e
r
a
t
i
o
n
 
s
h
a
d
e
r
 
d
e
f
i
n
e
 
h
o
w
 
t
o
 
s
t
a
r
t
 
t
r
a
c
i
n
g
 
r
a
y
s
I
n
t
e
r
s
e
c
t
i
o
n
 
s
h
a
d
e
r
(
s
)
 
d
e
f
i
n
e
 
h
o
w
 
r
a
y
s
 
i
n
t
e
r
s
e
c
t
 
g
e
o
m
e
t
r
y
M
i
s
s
 
s
h
a
d
e
r
(
s
)
 
s
h
a
d
i
n
g
 
f
o
r
 
w
h
e
n
 
r
a
y
s
 
m
i
s
s
 
g
e
o
m
e
t
r
y
C
l
o
s
e
s
t
-
h
i
t
 
s
h
a
d
e
r
(
s
)
 
s
h
a
d
i
n
g
 
a
t
 
t
h
e
 
i
n
t
e
r
s
e
c
t
i
o
n
 
p
o
i
n
t
A
n
y
-
h
i
t
 
s
h
a
d
e
r
(
s
)
 
r
u
n
 
o
n
c
e
 
p
e
r
 
h
i
t
*
*
 
(
e
.
g
.
,
 
f
o
r
 
t
r
a
n
s
p
a
r
e
n
c
y
)
F
I
V
E
 
T
Y
P
E
S
 
O
F
 
R
A
Y
 
T
R
A
C
I
N
G
 
S
H
A
D
E
R
S
80
80
R
a
y
 
t
r
a
c
i
n
g
 
p
i
p
e
l
i
n
e
 
s
p
l
i
t
 
i
n
t
o
 
f
i
v
e
 
s
h
a
d
e
r
s
:
A
 
r
a
y
 
g
e
n
e
r
a
t
i
o
n
 
s
h
a
d
e
r
 
d
e
f
i
n
e
 
h
o
w
 
t
o
 
s
t
a
r
t
 
t
r
a
c
i
n
g
 
r
a
y
s
I
n
t
e
r
s
e
c
t
i
o
n
 
s
h
a
d
e
r
(
s
)
 
d
e
f
i
n
e
 
h
o
w
 
r
a
y
s
 
i
n
t
e
r
s
e
c
t
 
g
e
o
m
e
t
r
y
M
i
s
s
 
s
h
a
d
e
r
(
s
)
 
s
h
a
d
i
n
g
 
f
o
r
 
w
h
e
n
 
r
a
y
s
 
m
i
s
s
 
g
e
o
m
e
t
r
y
C
l
o
s
e
s
t
-
h
i
t
 
s
h
a
d
e
r
(
s
)
 
s
h
a
d
i
n
g
 
a
t
 
t
h
e
 
i
n
t
e
r
s
e
c
t
i
o
n
 
p
o
i
n
t
A
n
y
-
h
i
t
 
s
h
a
d
e
r
(
s
)
 
r
u
n
 
o
n
c
e
 
p
e
r
 
h
i
t
*
*
 
(
e
.
g
.
,
 
f
o
r
 
t
r
a
n
s
p
a
r
e
n
c
y
)
← Controls other shaders
← Defines object shapes (one shader per type)
← Controls per-ray behavior (often many types)
H
O
W
 
D
O
 
T
H
E
S
E
 
F
I
T
 
T
O
G
E
T
H
E
R
?
 
 
 
 
 
 
[
E
Y
E
 
C
H
A
R
T
 
V
E
R
S
I
O
N
]
81
81
Traversal Loop
Ray Shading
Closest-Hit
Shader
TraceRay()
Called
Return From
TraceRay()
Miss
Shader
Acceleration
Traversal
No (additional) potential hits
Intersection
Shader
No intersection
Not closest
Any-Hit
Shader
This is closest hit
Ignore hit
(transparent)
Accept hit
Yes
Update
Closest
Hit Data
Yes
No
No
H
O
W
 
D
O
 
T
H
E
S
E
 
F
I
T
 
T
O
G
E
T
H
E
R
?
 
 
 
 
 
 
[
L
O
G
I
C
A
L
 
V
E
R
S
I
O
N
]
82
82
Traversal Loop
Ray Shading
Closest-Hit
Shader
TraceRay()
Called
Return From
TraceRay()
Miss
Shader
Acceleration
Traversal
Intersection
Shader
Any-Hit
Shader
Loop during ray tracing, testing hits until there’s no more; then shade
H
O
W
 
D
O
 
T
H
E
S
E
 
F
I
T
 
T
O
G
E
T
H
E
R
?
 
 
 
 
 
 
[
L
O
G
I
C
A
L
 
V
E
R
S
I
O
N
]
83
83
Traversal Loop
Ray Shading
Closest-Hit
Shader
TraceRay()
Called
Return From
TraceRay()
Miss
Shader
Acceleration
Traversal
Intersection
Shader
Any-Hit
Shader
Loop during ray tracing, testing hits until there’s no more; then shade
S
o
m
e
 
i
m
p
o
r
t
a
n
t
 
d
e
t
a
i
l
s
 
h
e
r
e
;
 
l
e
a
r
n
 
l
a
t
e
r
 
f
o
r
 
a
d
v
a
n
c
e
d
 
f
u
n
c
t
i
o
n
a
l
i
t
y
R
E
A
L
L
Y
 
S
I
M
P
L
E
 
G
P
U
 
R
A
Y
 
T
R
A
C
E
R
84
84
RWTexture
<
float4
> gOutTex;
struct
 RayPayload { 
float3
 color; };
[shader(
“miss”
)]
void
 MyMiss(
inout
 RayPayload payload)  {
     payload.color = float3( 0, 0, 1 );
}
[shader(
“closesthit”
)]
void
 MyClosestHit(
inout
 RayPayload data,
                  BuiltinTriangleIntersectAttribs attribs)  {
     data.color = float3( 1, 0, 0 );
}
[shader(
“raygeneration”
)]
void
 MyRayGen()  {
     
uint2
  curPixel    = DispatchRaysIndex().xy;
     
float3
 pixelRayDir = normalize( getRayDirFromPixelID( curPixel ) );
     
     RayDesc ray        = { gCamera.posW, 0.0f, pixelRayDir, 1e+38f };
     RayPayload payload = { 
float3
(0, 0, 0) };
     TraceRay( gRtScene, RAY_FLAG_NONE, 0xFF, 0, 1, 0, ray, payload );
     outTex[curPixel]   = 
float4
( payload.color, 1.0f );
}
Remember:
Ray generation shader starts work
R
E
A
L
L
Y
 
S
I
M
P
L
E
 
G
P
U
 
R
A
Y
 
T
R
A
C
E
R
85
85
RWTexture
<
float4
> gOutTex;
struct
 RayPayload { 
float3
 color; };
[shader(
“miss”
)]
void
 MyMiss(
inout
 RayPayload payload)  {
     payload.color = float3( 0, 0, 1 );
}
[shader(
“closesthit”
)]
void
 MyClosestHit(
inout
 RayPayload data,
                  BuiltinTriangleIntersectAttribs attribs)  {
     data.color = float3( 1, 0, 0 );
}
[shader(
“raygeneration”
)]
void
 MyRayGen()  {
     
uint2
  curPixel    = DispatchRaysIndex().xy;
     
float3
 pixelRayDir = normalize( getRayDirFromPixelID( curPixel ) );
     
     RayDesc ray        = { gCamera.posW, 0.0f, pixelRayDir, 1e+38f };
     RayPayload payload = { 
float3
(0, 0, 0) };
     TraceRay( gRtScene, RAY_FLAG_NONE, 0xFF, 0, 1, 0, ray, payload );
     outTex[curPixel]   = 
float4
( payload.color, 1.0f );
}
Remember:
Ray generation shader starts work
Output image buffer
Communicates results with CPU
R
E
A
L
L
Y
 
S
I
M
P
L
E
 
G
P
U
 
R
A
Y
 
T
R
A
C
E
R
86
86
RWTexture
<
float4
> gOutTex;
struct
 RayPayload { 
float3
 color; };
[shader(
“miss”
)]
void
 MyMiss(
inout
 RayPayload payload)  {
     payload.color = float3( 0, 0, 1 );
}
[shader(
“closesthit”
)]
void
 MyClosestHit(
inout
 RayPayload data,
                  BuiltinTriangleIntersectAttribs attribs)  {
     data.color = float3( 1, 0, 0 );
}
[shader(
“raygeneration”
)]
void
 MyRayGen()  {
     
uint2
  curPixel    = DispatchRaysIndex().xy;
     
float3
 pixelRayDir = normalize( getRayDirFromPixelID( curPixel ) );
     
     RayDesc ray        = { gCamera.posW, 0.0f, pixelRayDir, 1e+38f };
     RayPayload payload = { 
float3
(0, 0, 0) };
     TraceRay( gRtScene, RAY_FLAG_NONE, 0xFF, 0, 1, 0, ray, payload );
     outTex[curPixel]   = 
float4
( payload.color, 1.0f );
}
Remember:
Ray generation shader starts work
Information about scene
Passed as input from the CPU
R
E
A
L
L
Y
 
S
I
M
P
L
E
 
G
P
U
 
R
A
Y
 
T
R
A
C
E
R
87
87
RWTexture
<
float4
> gOutTex;
struct
 RayPayload { 
float3
 color; };
[shader(
“miss”
)]
void
 MyMiss(
inout
 RayPayload payload)  {
     payload.color = float3( 0, 0, 1 );
}
[shader(
“closesthit”
)]
void
 MyClosestHit(
inout
 RayPayload data,
                  BuiltinTriangleIntersectAttribs attribs)  {
     data.color = float3( 1, 0, 0 );
}
[shader(
“raygeneration”
)]
void
 MyRayGen()  {
     
uint2
  curPixel    = DispatchRaysIndex().xy;
     
float3
 pixelRayDir = normalize( getRayDirFromPixelID( curPixel ) );
     
     RayDesc ray        = { gCamera.posW, 0.0f, pixelRayDir, 1e+38f };
     RayPayload payload = { 
float3
(0, 0, 0) };
     TraceRay( gRtScene, RAY_FLAG_NONE, 0xFF, 0, 1, 0, ray, payload );
     outTex[curPixel]   = 
float4
( payload.color, 1.0f );
}
Remember:
Ray generation shader starts work
Each ray returns some value
Return payload is user-defined
Often, like this one, just a color
Before tracing, initialize payload
R
E
A
L
L
Y
 
S
I
M
P
L
E
 
G
P
U
 
R
A
Y
 
T
R
A
C
E
R
88
88
RWTexture
<
float4
> gOutTex;
struct
 RayPayload { 
float3
 color; };
[shader(
“miss”
)]
void
 MyMiss(
inout
 RayPayload payload)  {
     payload.color = float3( 0, 0, 1 );
}
[shader(
“closesthit”
)]
void
 MyClosestHit(
inout
 RayPayload data,
                  BuiltinTriangleIntersectAttribs attribs)  {
     data.color = float3( 1, 0, 0 );
}
[shader(
“raygeneration”
)]
void
 MyRayGen()  {
     
uint2
  curPixel    = DispatchRaysIndex().xy;
     
float3
 pixelRayDir = normalize( getRayDirFromPixelID( curPixel ) );
     
     RayDesc ray        = { gCamera.posW, 0.0f, pixelRayDir, 1e+38f };
     RayPayload payload = { 
float3
(0, 0, 0) };
     TraceRay( gRtScene, RAY_FLAG_NONE, 0xFF, 0, 1, 0, ray, payload );
     outTex[curPixel]   = 
float4
( payload.color, 1.0f );
}
Remember:
Ray generation shader starts work
You write a function here
Computes per-pixel ray direction
Based on location on screen
R
E
A
L
L
Y
 
S
I
M
P
L
E
 
G
P
U
 
R
A
Y
 
T
R
A
C
E
R
89
89
RWTexture
<
float4
> gOutTex;
struct
 RayPayload { 
float3
 color; };
[shader(
“miss”
)]
void
 MyMiss(
inout
 RayPayload payload)  {
     payload.color = float3( 0, 0, 1 );
}
[shader(
“closesthit”
)]
void
 MyClosestHit(
inout
 RayPayload data,
                  BuiltinTriangleIntersectAttribs attribs)  {
     data.color = float3( 1, 0, 0 );
}
[shader(
“raygeneration”
)]
void
 MyRayGen()  {
     
uint2
  curPixel    = DispatchRaysIndex().xy;
     
float3
 pixelRayDir = normalize( getRayDirFromPixelID( curPixel ) );
     
     RayDesc ray        = { gCamera.posW, 0.0f, pixelRayDir, 1e+38f };
     RayPayload payload = { 
float3
(0, 0, 0) };
     TraceRay( gRtScene, RAY_FLAG_NONE, 0xFF, 0, 1, 0, ray, payload );
     outTex[curPixel]   = 
float4
( payload.color, 1.0f );
}
Remember:
Ray generation shader starts work
You write a function here
Computes per-pixel ray direction
Based on location on screen
Setup the ray to trace
R
E
A
L
L
Y
 
S
I
M
P
L
E
 
G
P
U
 
R
A
Y
 
T
R
A
C
E
R
90
90
RWTexture
<
float4
> gOutTex;
struct
 RayPayload { 
float3
 color; };
[shader(
“miss”
)]
void
 MyMiss(
inout
 RayPayload payload)  {
     payload.color = float3( 0, 0, 1 );
}
[shader(
“closesthit”
)]
void
 MyClosestHit(
inout
 RayPayload data,
                  BuiltinTriangleIntersectAttribs attribs)  {
     data.color = float3( 1, 0, 0 );
}
[shader(
“raygeneration”
)]
void
 MyRayGen()  {
     
uint2
  curPixel    = DispatchRaysIndex().xy;
     
float3
 pixelRayDir = normalize( getRayDirFromPixelID( curPixel ) );
     
     RayDesc ray        = { gCamera.posW, 0.0f, pixelRayDir, 1e+38f };
     RayPayload payload = { 
float3
(0, 0, 0) };
     TraceRay( gRtScene, RAY_FLAG_NONE, 0xFF, 0, 1, 0, ray, payload );
     outTex[curPixel]   = 
float4
( payload.color, 1.0f );
}
Remember:
Ray generation shader starts work
You write a function here
Computes per-pixel ray direction
Based on location on screen
Setup the ray to trace
Min and max distances to search
R
E
A
L
L
Y
 
S
I
M
P
L
E
 
G
P
U
 
R
A
Y
 
T
R
A
C
E
R
91
91
RWTexture
<
float4
> gOutTex;
struct
 RayPayload { 
float3
 color; };
[shader(
“miss”
)]
void
 MyMiss(
inout
 RayPayload payload)  {
     payload.color = float3( 0, 0, 1 );
}
[shader(
“closesthit”
)]
void
 MyClosestHit(
inout
 RayPayload data,
                  BuiltinTriangleIntersectAttribs attribs)  {
     data.color = float3( 1, 0, 0 );
}
[shader(
“raygeneration”
)]
void
 MyRayGen()  {
     
uint2
  curPixel    = DispatchRaysIndex().xy;
     
float3
 pixelRayDir = normalize( getRayDirFromPixelID( curPixel ) );
     
     RayDesc ray        = { gCamera.posW, 0.0f, pixelRayDir, 1e+38f };
     RayPayload payload = { 
float3
(0, 0, 0) };
     TraceRay( gRtScene, RAY_FLAG_NONE, 0xFF, 0, 1, 0, ray, payload );
     outTex[curPixel]   = 
float4
( payload.color, 1.0f );
}
Remember:
Ray generation shader starts work
Trace your ray here
R
E
A
L
L
Y
 
S
I
M
P
L
E
 
G
P
U
 
R
A
Y
 
T
R
A
C
E
R
92
92
RWTexture
<
float4
> gOutTex;
struct
 RayPayload { 
float3
 color; };
[shader(
“miss”
)]
void
 MyMiss(
inout
 RayPayload payload)  {
     payload.color = float3( 0, 0, 1 );
}
[shader(
“closesthit”
)]
void
 MyClosestHit(
inout
 RayPayload data,
                  BuiltinTriangleIntersectAttribs attribs)  {
     data.color = float3( 1, 0, 0 );
}
[shader(
“raygeneration”
)]
void
 MyRayGen()  {
     
uint2
  curPixel    = DispatchRaysIndex().xy;
     
float3
 pixelRayDir = normalize( getRayDirFromPixelID( curPixel ) );
     
     RayDesc ray        = { gCamera.posW, 0.0f, pixelRayDir, 1e+38f };
     RayPayload payload = { 
float3
(0, 0, 0) };
     TraceRay( gRtScene, RAY_FLAG_NONE, 0xFF, 0, 1, 0, ray, payload );
     outTex[curPixel]   = 
float4
( payload.color, 1.0f );
}
Remember:
Ray generation shader starts work
Trace your ray here
Scene BVH
R
E
A
L
L
Y
 
S
I
M
P
L
E
 
G
P
U
 
R
A
Y
 
T
R
A
C
E
R
93
93
RWTexture
<
float4
> gOutTex;
struct
 RayPayload { 
float3
 color; };
[shader(
“miss”
)]
void
 MyMiss(
inout
 RayPayload payload)  {
     payload.color = float3( 0, 0, 1 );
}
[shader(
“closesthit”
)]
void
 MyClosestHit(
inout
 RayPayload data,
                  BuiltinTriangleIntersectAttribs attribs)  {
     data.color = float3( 1, 0, 0 );
}
[shader(
“raygeneration”
)]
void
 MyRayGen()  {
     
uint2
  curPixel    = DispatchRaysIndex().xy;
     
float3
 pixelRayDir = normalize( getRayDirFromPixelID( curPixel ) );
     
     RayDesc ray        = { gCamera.posW, 0.0f, pixelRayDir, 1e+38f };
     RayPayload payload = { 
float3
(0, 0, 0) };
     TraceRay( gRtScene, RAY_FLAG_NONE, 0xFF, 0, 1, 0, ray, payload );
     outTex[curPixel]   = 
float4
( payload.color, 1.0f );
}
Remember:
Ray generation shader starts work
Trace your ray here
Scene BVH
No special ray behaviors
R
E
A
L
L
Y
 
S
I
M
P
L
E
 
G
P
U
 
R
A
Y
 
T
R
A
C
E
R
94
94
RWTexture
<
float4
> gOutTex;
struct
 RayPayload { 
float3
 color; };
[shader(
“miss”
)]
void
 MyMiss(
inout
 RayPayload payload)  {
     payload.color = float3( 0, 0, 1 );
}
[shader(
“closesthit”
)]
void
 MyClosestHit(
inout
 RayPayload data,
                  BuiltinTriangleIntersectAttribs attribs)  {
     data.color = float3( 1, 0, 0 );
}
[shader(
“raygeneration”
)]
void
 MyRayGen()  {
     
uint2
  curPixel    = DispatchRaysIndex().xy;
     
float3
 pixelRayDir = normalize( getRayDirFromPixelID( curPixel ) );
     
     RayDesc ray        = { gCamera.posW, 0.0f, pixelRayDir, 1e+38f };
     RayPayload payload = { 
float3
(0, 0, 0) };
     TraceRay( gRtScene, RAY_FLAG_NONE, 0xFF, 0, 1, 0, ray, payload );
     outTex[curPixel]   = 
float4
( payload.color, 1.0f );
}
Remember:
Ray generation shader starts work
Trace your ray here
Scene BVH
No special ray behaviors
What geometry should we test?
Bitmask; 0xFF 
→ test all geometry
R
E
A
L
L
Y
 
S
I
M
P
L
E
 
G
P
U
 
R
A
Y
 
T
R
A
C
E
R
95
95
RWTexture
<
float4
> gOutTex;
struct
 RayPayload { 
float3
 color; };
[shader(
“miss”
)]
void
 MyMiss(
inout
 RayPayload payload)  {
     payload.color = float3( 0, 0, 1 );
}
[shader(
“closesthit”
)]
void
 MyClosestHit(
inout
 RayPayload data,
                  BuiltinTriangleIntersectAttribs attribs)  {
     data.color = float3( 1, 0, 0 );
}
[shader(
“raygeneration”
)]
void
 MyRayGen()  {
     
uint2
  curPixel    = DispatchRaysIndex().xy;
     
float3
 pixelRayDir = normalize( getRayDirFromPixelID( curPixel ) );
     
     RayDesc ray        = { gCamera.posW, 0.0f, pixelRayDir, 1e+38f };
     RayPayload payload = { 
float3
(0, 0, 0) };
     TraceRay( gRtScene, RAY_FLAG_NONE, 0xFF, 0, 1, 0, ray, payload );
     outTex[curPixel]   = 
float4
( payload.color, 1.0f );
}
Remember:
Ray generation shader starts work
Trace your ray here
Scene BVH
No special ray behaviors
What geometry should we test?
Bitmask; 0xFF 
→ test all geometry
Ray and payload from earlier
R
E
A
L
L
Y
 
S
I
M
P
L
E
 
G
P
U
 
R
A
Y
 
T
R
A
C
E
R
96
96
RWTexture
<
float4
> gOutTex;
struct
 RayPayload { 
float3
 color; };
[shader(
“miss”
)]
void
 MyMiss(
inout
 RayPayload payload)  {
     payload.color = float3( 0, 0, 1 );
}
[shader(
“closesthit”
)]
void
 MyClosestHit(
inout
 RayPayload data,
                  BuiltinTriangleIntersectAttribs attribs)  {
     data.color = float3( 1, 0, 0 );
}
[shader(
“raygeneration”
)]
void
 MyRayGen()  {
     
uint2
  curPixel    = DispatchRaysIndex().xy;
     
float3
 pixelRayDir = normalize( getRayDirFromPixelID( curPixel ) );
     
     RayDesc ray        = { gCamera.posW, 0.0f, pixelRayDir, 1e+38f };
     RayPayload payload = { 
float3
(0, 0, 0) };
     TraceRay( gRtScene, RAY_FLAG_NONE, 0xFF, 0, 1, 0, ray, payload );
     outTex[curPixel]   = 
float4
( payload.color, 1.0f );
}
Remember:
Ray generation shader starts work
Which miss shader to use?
There’s a list of miss shaders
Specify index of the one to use
R
E
A
L
L
Y
 
S
I
M
P
L
E
 
G
P
U
 
R
A
Y
 
T
R
A
C
E
R
97
97
RWTexture
<
float4
> gOutTex;
struct
 RayPayload { 
float3
 color; };
[shader(
“miss”
)]
void
 MyMiss(
inout
 RayPayload payload)  {
     payload.color = float3( 0, 0, 1 );
}
[shader(
“closesthit”
)]
void
 MyClosestHit(
inout
 RayPayload data,
                  BuiltinTriangleIntersectAttribs attribs)  {
     data.color = float3( 1, 0, 0 );
}
[shader(
“raygeneration”
)]
void
 MyRayGen()  {
     
uint2
  curPixel    = DispatchRaysIndex().xy;
     
float3
 pixelRayDir = normalize( getRayDirFromPixelID( curPixel ) );
     
     RayDesc ray        = { gCamera.posW, 0.0f, pixelRayDir, 1e+38f };
     RayPayload payload = { 
float3
(0, 0, 0) };
     TraceRay( gRtScene, RAY_FLAG_NONE, 0xFF, 0, 1, 0, ray, payload );
     outTex[curPixel]   = 
float4
( payload.color, 1.0f );
}
Remember:
Ray generation shader starts work
Which miss shader to use?
There’s a list of miss shaders
Specify index of the one to use
In my tutorials, 
MyMiss
 is index 0
Why? First miss shader I loaded
R
E
A
L
L
Y
 
S
I
M
P
L
E
 
G
P
U
 
R
A
Y
 
T
R
A
C
E
R
98
98
RWTexture
<
float4
> gOutTex;
struct
 RayPayload { 
float3
 color; };
[shader(
“miss”
)]
void
 MyMiss(
inout
 RayPayload payload)  {
     payload.color = float3( 0, 0, 1 );
}
[shader(
“closesthit”
)]
void
 MyClosestHit(
inout
 RayPayload data,
                  BuiltinTriangleIntersectAttribs attribs)  {
     data.color = float3( 1, 0, 0 );
}
[shader(
“raygeneration”
)]
void
 MyRayGen()  {
     
uint2
  curPixel    = DispatchRaysIndex().xy;
     
float3
 pixelRayDir = normalize( getRayDirFromPixelID( curPixel ) );
     
     RayDesc ray        = { gCamera.posW, 0.0f, pixelRayDir, 1e+38f };
     RayPayload payload = { 
float3
(0, 0, 0) };
     TraceRay( gRtScene, RAY_FLAG_NONE, 0xFF, 0, 1, 0, ray, payload );
     outTex[curPixel]   = 
float4
( payload.color, 1.0f );
}
Remember:
Ray generation shader starts work
W
h
i
c
h
 
h
i
t
 
g
r
o
u
p
 
t
o
 
u
s
e
?
May have 1 
any-hit shader
May have 1 
closest-hit shader
May have 1 
intersection shader
R
E
A
L
L
Y
 
S
I
M
P
L
E
 
G
P
U
 
R
A
Y
 
T
R
A
C
E
R
99
99
RWTexture
<
float4
> gOutTex;
struct
 RayPayload { 
float3
 color; };
[shader(
“miss”
)]
void
 MyMiss(
inout
 RayPayload payload)  {
     payload.color = float3( 0, 0, 1 );
}
[shader(
“closesthit”
)]
void
 MyClosestHit(
inout
 RayPayload data,
                  BuiltinTriangleIntersectAttribs attribs)  {
     data.color = float3( 1, 0, 0 );
}
[shader(
“raygeneration”
)]
void
 MyRayGen()  {
     
uint2
  curPixel    = DispatchRaysIndex().xy;
     
float3
 pixelRayDir = normalize( getRayDirFromPixelID( curPixel ) );
     
     RayDesc ray        = { gCamera.posW, 0.0f, pixelRayDir, 1e+38f };
     RayPayload payload = { 
float3
(0, 0, 0) };
     TraceRay( gRtScene, RAY_FLAG_NONE, 0xFF, 0, 1, 0, ray, payload );
     outTex[curPixel]   = 
float4
( payload.color, 1.0f );
}
Remember:
Ray generation shader starts work
W
h
i
c
h
 
h
i
t
 
g
r
o
u
p
 
t
o
 
u
s
e
?
May have 1 
any-hit shader
May have 1 
closest-hit shader
May have 1 
intersection shader
Here, has just one shader
It’s index 0 
→ specified first on load
R
E
A
L
L
Y
 
S
I
M
P
L
E
 
G
P
U
 
R
A
Y
 
T
R
A
C
E
R
100
100
100
RWTexture
<
float4
> gOutTex;
struct
 RayPayload { 
float3
 color; };
[shader(
“miss”
)]
void
 MyMiss(
inout
 RayPayload payload)  {
     payload.color = float3( 0, 0, 1 );
}
[shader(
“closesthit”
)]
void
 MyClosestHit(
inout
 RayPayload data,
                  BuiltinTriangleIntersectAttribs attribs)  {
     data.color = float3( 1, 0, 0 );
}
[shader(
“raygeneration”
)]
void
 MyRayGen()  {
     
uint2
  curPixel    = DispatchRaysIndex().xy;
     
float3
 pixelRayDir = normalize( getRayDirFromPixelID( curPixel ) );
     
     RayDesc ray        = { gCamera.posW, 0.0f, pixelRayDir, 1e+38f };
     RayPayload payload = { 
float3
(0, 0, 0) };
     TraceRay( gRtScene, RAY_FLAG_NONE, 0xFF, 0, 1, 0, ray, payload );
     outTex[curPixel]   = 
float4
( payload.color, 1.0f );
}
How to read at high level:
For each pixel determine ray
R
E
A
L
L
Y
 
S
I
M
P
L
E
 
G
P
U
 
R
A
Y
 
T
R
A
C
E
R
101
101
101
RWTexture
<
float4
> gOutTex;
struct
 RayPayload { 
float3
 color; };
[shader(
“miss”
)]
void
 MyMiss(
inout
 RayPayload payload)  {
     payload.color = float3( 0, 0, 1 );
}
[shader(
“closesthit”
)]
void
 MyClosestHit(
inout
 RayPayload data,
                  BuiltinTriangleIntersectAttribs attribs)  {
     data.color = float3( 1, 0, 0 );
}
[shader(
“raygeneration”
)]
void
 MyRayGen()  {
     
uint2
  curPixel    = DispatchRaysIndex().xy;
     
float3
 pixelRayDir = normalize( getRayDirFromPixelID( curPixel ) );
     
     RayDesc ray        = { gCamera.posW, 0.0f, pixelRayDir, 1e+38f };
     RayPayload payload = { 
float3
(0, 0, 0) };
     TraceRay( gRtScene, RAY_FLAG_NONE, 0xFF, 0, 1, 0, ray, payload );
     outTex[curPixel]   = 
float4
( payload.color, 1.0f );
}
How to read at high level:
For each pixel determine ray
Shoot the ray
R
E
A
L
L
Y
 
S
I
M
P
L
E
 
G
P
U
 
R
A
Y
 
T
R
A
C
E
R
102
102
102
RWTexture
<
float4
> gOutTex;
struct
 RayPayload { 
float3
 color; };
[shader(
“miss”
)]
void
 MyMiss(
inout
 RayPayload payload)  {
     payload.color = float3( 0, 0, 1 );
}
[shader(
“closesthit”
)]
void
 MyClosestHit(
inout
 RayPayload data,
                  BuiltinTriangleIntersectAttribs attribs)  {
     data.color = float3( 1, 0, 0 );
}
[shader(
“raygeneration”
)]
void
 MyRayGen()  {
     
uint2
  curPixel    = DispatchRaysIndex().xy;
     
float3
 pixelRayDir = normalize( getRayDirFromPixelID( curPixel ) );
     
     RayDesc ray        = { gCamera.posW, 0.0f, pixelRayDir, 1e+38f };
     RayPayload payload = { 
float3
(0, 0, 0) };
     TraceRay( gRtScene, RAY_FLAG_NONE, 0xFF, 0, 1, 0, ray, payload );
     outTex[curPixel]   = 
float4
( payload.color, 1.0f );
}
How to read at high level:
For each pixel determine ray
Shoot the ray
If it misses?  Return blue
R
E
A
L
L
Y
 
S
I
M
P
L
E
 
G
P
U
 
R
A
Y
 
T
R
A
C
E
R
103
103
103
RWTexture
<
float4
> gOutTex;
struct
 RayPayload { 
float3
 color; };
[shader(
“miss”
)]
void
 MyMiss(
inout
 RayPayload payload)  {
     payload.color = float3( 0, 0, 1 );
}
[shader(
“closesthit”
)]
void
 MyClosestHit(
inout
 RayPayload data,
                  BuiltinTriangleIntersectAttribs attribs)  {
     data.color = float3( 1, 0, 0 );
}
[shader(
“raygeneration”
)]
void
 MyRayGen()  {
     
uint2
  curPixel    = DispatchRaysIndex().xy;
     
float3
 pixelRayDir = normalize( getRayDirFromPixelID( curPixel ) );
     
     RayDesc ray        = { gCamera.posW, 0.0f, pixelRayDir, 1e+38f };
     RayPayload payload = { 
float3
(0, 0, 0) };
     TraceRay( gRtScene, RAY_FLAG_NONE, 0xFF, 0, 1, 0, ray, payload );
     outTex[curPixel]   = 
float4
( payload.color, 1.0f );
}
How to read at high level:
For each pixel determine ray
Shoot the ray
If it misses?  Return blue
If it hits?  Return red
R
E
A
L
L
Y
 
S
I
M
P
L
E
 
G
P
U
 
R
A
Y
 
T
R
A
C
E
R
104
104
104
RWTexture
<
float4
> gOutTex;
struct
 RayPayload { 
float3
 color; };
[shader(
“miss”
)]
void
 MyMiss(
inout
 RayPayload payload)  {
     payload.color = float3( 0, 0, 1 );
}
[shader(
“closesthit”
)]
void
 MyClosestHit(
inout
 RayPayload data,
                  BuiltinTriangleIntersectAttribs attribs)  {
     data.color = float3( 1, 0, 0 );
}
[shader(
“raygeneration”
)]
void
 MyRayGen()  {
     
uint2
  curPixel    = DispatchRaysIndex().xy;
     
float3
 pixelRayDir = normalize( getRayDirFromPixelID( curPixel ) );
     
     RayDesc ray        = { gCamera.posW, 0.0f, pixelRayDir, 1e+38f };
     RayPayload payload = { 
float3
(0, 0, 0) };
     TraceRay( gRtScene, RAY_FLAG_NONE, 0xFF, 0, 1, 0, ray, payload );
     outTex[curPixel]   = 
float4
( payload.color, 1.0f );
}
How to read at high level:
For each pixel determine ray
Shoot the ray
If it misses?  Return blue
If it hits?  Return red
Output our result
R
E
A
L
L
Y
 
S
I
M
P
L
E
 
G
P
U
 
R
A
Y
 
T
R
A
C
E
R
105
105
105
RWTexture
<
float4
> gOutTex;
struct
 RayPayload { 
float3
 color; };
[shader(
“miss”
)]
void
 MyMiss(
inout
 RayPayload payload)  {
     payload.color = float3( 0, 0, 1 );
}
[shader(
“closesthit”
)]
void
 MyClosestHit(
inout
 RayPayload data,
                  BuiltinTriangleIntersectAttribs attribs)  {
     data.color = float3( 1, 0, 0 );
}
[shader(
“raygeneration”
)]
void
 MyRayGen()  {
     
uint2
  curPixel    = DispatchRaysIndex().xy;
     
float3
 pixelRayDir = normalize( getRayDirFromPixelID( curPixel ) );
     
     RayDesc ray        = { gCamera.posW, 0.0f, pixelRayDir, 1e+38f };
     RayPayload payload = { 
float3
(0, 0, 0) };
     TraceRay( gRtScene, RAY_FLAG_NONE, 0xFF, 0, 1, 0, ray, payload );
     outTex[curPixel]   = 
float4
( payload.color, 1.0f );
}
F
o
r
 
t
h
i
s
 
s
c
e
n
e
T
h
i
s
 
c
o
d
e
 
r
e
n
d
e
r
s
 
t
h
i
s
W
H
A
T
 
A
B
O
U
T
 
A
 
R
E
A
L
 
E
X
A
M
P
L
E
?
106
106
106
W
H
A
T
 
A
B
O
U
T
 
A
 
R
E
A
L
 
E
X
A
M
P
L
E
?
107
107
107
Examples from my DXR tutors:   
http://intro-to-dxr.cwyman.org
Click on “code walkthrough”
Not quite equivalent to any of those, but close
W
H
A
T
 
A
B
O
U
T
 
A
 
R
E
A
L
 
E
X
A
M
P
L
E
?
108
108
108
How about adding shadows?
W
H
A
T
 
A
B
O
U
T
 
A
 
R
E
A
L
 
E
X
A
M
P
L
E
?
109
109
109
How about adding shadows?
For each pixel, determine if light visible
Shoot a ray towards light
H
O
W
 
D
O
E
S
 
T
H
I
S
 
W
O
R
K
?
110
110
110
Trace a ray from the camera
H
O
W
 
D
O
E
S
 
T
H
I
S
 
W
O
R
K
?
111
111
111
Trace a ray from the camera
At the shading point (i.e., the closest hit)
Trace another ray towards the light
?
H
O
W
 
D
O
E
S
 
T
H
I
S
 
W
O
R
K
?
112
112
112
Trace a ray from the camera
At the shading point (i.e., the closest hit)
Trace another ray towards the light
If it hits, shade the pixel as in shadow
If it misses, illuminate the pixel by the light
?
A
 
R
E
U
S
A
B
L
E
 
S
H
A
D
O
W
 
R
A
Y
113
113
113
Encapsulate a shadow ray
Create  
shootShadowRay()
Can call while shading
...
struct
 ShadowPayload {
     
float
 visibility;  
// 0.0 means ‘shadowed’, 1.0 means ‘lit’
};
[shader(
“miss”
)]
void
 ShadowMiss(
inout
 ShadowPayload pay) {
     pay.visibility = 1.0f;
}
[shader(
“anyhit”
)]
void
 ShadowAnyHit(
inout
 ShadowPayload pay, BuiltinIntersectAttribs attribs) {
     
if
 (alphaTestFails(attribs))
          IgnoreHit();
}
float
 shootShadowRay(
float3
 orig, 
float3
 dir, 
float
 minT, 
float
 maxT)  {
     RayDesc       ray = { orig, minT, dir, maxT };
     ShadowPayload pay = { 0.0f };
     
uint
 flags = RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH |
                  RAY_FLAG_SKIP_CLOSEST_HIT_SHADER;
     TraceRay( gRtScene, flags, 0xFF, 0, 1, 0, ray, pay );
    
     
return
 
pay.visibility;
}
...
A
 
R
E
U
S
A
B
L
E
 
S
H
A
D
O
W
 
R
A
Y
114
114
114
Encapsulate a shadow ray
Create a ray
From some origin
In some direction
Check occlusions in [t
min
…t
max
]
...
struct
 ShadowPayload {
     
float
 visibility;  
// 0.0 means ‘shadowed’, 1.0 means ‘lit’
};
[shader(
“miss”
)]
void
 ShadowMiss(
inout
 ShadowPayload pay) {
     pay.visibility = 1.0f;
}
[shader(
“anyhit”
)]
void
 ShadowAnyHit(
inout
 ShadowPayload pay, BuiltinIntersectAttribs attribs) {
     
if
 (alphaTestFails(attribs))
          IgnoreHit();
}
float
 shootShadowRay(
float3
 orig, 
float3
 dir, 
float
 minT, 
float
 maxT)  {
     RayDesc       ray = { orig, minT, dir, maxT };
     ShadowPayload pay = { 0.0f };
     
uint
 flags = RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH |
                  RAY_FLAG_SKIP_CLOSEST_HIT_SHADER;
     TraceRay( gRtScene, flags, 0xFF, 0, 1, 0, ray, pay );
    
     
return
 
pay.visibility;
}
...
A
 
R
E
U
S
A
B
L
E
 
S
H
A
D
O
W
 
R
A
Y
115
115
115
Encapsulate a shadow ray
Create a ray
From some origin
In some direction
Check occlusions in [t
min
…t
max
]
A
s
s
u
m
e
 
s
h
a
d
o
w
s
 
a
r
e
 
o
c
c
l
u
d
e
d
...
struct
 ShadowPayload {
     
float
 visibility;  
// 0.0 means ‘shadowed’, 1.0 means ‘lit’
};
[shader(
“miss”
)]
void
 ShadowMiss(
inout
 ShadowPayload pay) {
     pay.visibility = 1.0f;
}
[shader(
“anyhit”
)]
void
 ShadowAnyHit(
inout
 ShadowPayload pay, BuiltinIntersectAttribs attribs) {
     
if
 (alphaTestFails(attribs))
          IgnoreHit();
}
float
 shootShadowRay(
float3
 orig, 
float3
 dir, 
float
 minT, 
float
 maxT)  {
     RayDesc       ray = { orig, minT, dir, maxT };
     ShadowPayload pay = { 0.0f };
     
uint
 flags = RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH |
                  RAY_FLAG_SKIP_CLOSEST_HIT_SHADER;
     TraceRay( gRtScene, flags, 0xFF, 0, 1, 0, ray, pay );
    
     
return
 
pay.visibility;
}
...
A
 
R
E
U
S
A
B
L
E
 
S
H
A
D
O
W
 
R
A
Y
116
116
116
Encapsulate a shadow ray
Create a ray
From some origin
In some direction
Check occlusions in [t
min
…t
max
]
A
s
s
u
m
e
 
s
h
a
d
o
w
s
 
a
r
e
 
o
c
c
l
u
d
e
d
Trace the ray
Return 1 if lit, 0 otherwise
...
struct
 ShadowPayload {
     
float
 visibility;  
// 0.0 means ‘shadowed’, 1.0 means ‘lit’
};
[shader(
“miss”
)]
void
 ShadowMiss(
inout
 ShadowPayload pay) {
     pay.visibility = 1.0f;
}
[shader(
“anyhit”
)]
void
 ShadowAnyHit(
inout
 ShadowPayload pay, BuiltinIntersectAttribs attribs) {
     
if
 (alphaTestFails(attribs))
          IgnoreHit();
}
float
 shootShadowRay(
float3
 orig, 
float3
 dir, 
float
 minT, 
float
 maxT)  {
     RayDesc       ray = { orig, minT, dir, maxT };
     ShadowPayload pay = { 0.0f };
     
uint
 flags = RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH |
                  RAY_FLAG_SKIP_CLOSEST_HIT_SHADER;
     TraceRay( gRtScene, flags, 0xFF, 0, 1, 0, ray, pay );
    
     
return
 
pay.visibility;
}
...
A
 
R
E
U
S
A
B
L
E
 
S
H
A
D
O
W
 
R
A
Y
117
117
117
Encapsulate a shadow ray
Create a ray
From some origin
In some direction
Check occlusions in [t
min
…t
max
]
A
s
s
u
m
e
 
s
h
a
d
o
w
s
 
a
r
e
 
o
c
c
l
u
d
e
d
Trace the ray
Return 1 if lit, 0 otherwise
Some shadow ray optimizations
No shading; skip closest hit
End at any occlusion
N
e
e
d
 
i
f
 
n
o
t
 
w
h
e
r
e
...
struct
 ShadowPayload {
     
float
 visibility;  
// 0.0 means ‘shadowed’, 1.0 means ‘lit’
};
[shader(
“miss”
)]
void
 ShadowMiss(
inout
 ShadowPayload pay) {
     pay.visibility = 1.0f;
}
[shader(
“anyhit”
)]
void
 ShadowAnyHit(
inout
 ShadowPayload pay, BuiltinIntersectAttribs attribs) {
     
if
 (alphaTestFails(attribs))
          IgnoreHit();
}
float
 shootShadowRay(
float3
 orig, 
float3
 dir, 
float
 minT, 
float
 maxT)  {
     RayDesc       ray = { orig, minT, dir, maxT };
     ShadowPayload pay = { 0.0f };
     
uint
 flags = RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH |
                  RAY_FLAG_SKIP_CLOSEST_HIT_SHADER;
     TraceRay( gRtScene, flags, 0xFF, 0, 1, 0, ray, pay );
    
     
return
 
pay.visibility;
}
...
A
 
R
E
U
S
A
B
L
E
 
S
H
A
D
O
W
 
R
A
Y
118
118
118
Miss shader:
We missed…
Set visibility to 1.0
...
struct
 ShadowPayload {
     
float
 visibility;  
// 0.0 means ‘shadowed’, 1.0 means ‘lit’
};
[shader(
“miss”
)]
void
 ShadowMiss(
inout
 ShadowPayload pay) {
     pay.visibility = 1.0f;
}
[shader(
“anyhit”
)]
void
 ShadowAnyHit(
inout
 ShadowPayload pay, BuiltinIntersectAttribs attribs) {
     
if
 (alphaTestFails(attribs))
          IgnoreHit();
}
float
 shootShadowRay(
float3
 orig, 
float3
 dir, 
float
 minT, 
float
 maxT)  {
     RayDesc       ray = { orig, minT, dir, maxT };
     ShadowPayload pay = { 0.0f };
     
uint
 flags = RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH |
                  RAY_FLAG_SKIP_CLOSEST_HIT_SHADER;
     TraceRay( gRtScene, flags, 0xFF, 0, 1, 0, ray, pay );
    
     
return
 
pay.visibility;
}
...
A
 
R
E
U
S
A
B
L
E
 
S
H
A
D
O
W
 
R
A
Y
119
119
119
Miss shader:
We missed…
Set visibility to 1.0
Any hit shader:
Asks is occluder transparent?
If so, ignore this hit
...
struct
 ShadowPayload {
     
float
 visibility;  
// 0.0 means ‘shadowed’, 1.0 means ‘lit’
};
[shader(
“miss”
)]
void
 ShadowMiss(
inout
 ShadowPayload pay) {
     pay.visibility = 1.0f;
}
[shader(
“anyhit”
)]
void
 ShadowAnyHit(
inout
 ShadowPayload pay, BuiltinIntersectAttribs attribs) {
     
if
 (alphaTestFails(attribs))
          IgnoreHit();
}
float
 shootShadowRay(
float3
 orig, 
float3
 dir, 
float
 minT, 
float
 maxT)  {
     RayDesc       ray = { orig, minT, dir, maxT };
     ShadowPayload pay = { 0.0f };
     
uint
 flags = RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH |
                  RAY_FLAG_SKIP_CLOSEST_HIT_SHADER;
     TraceRay( gRtScene, flags, 0xFF, 0, 1, 0, ray, pay );
    
     
return
 
pay.visibility;
}
...
A
 
R
E
U
S
A
B
L
E
 
S
H
A
D
O
W
 
R
A
Y
120
120
120
Gives reusable shadow rays
Useful in many contexts
...
struct
 ShadowPayload {
     
float
 visibility;  
// 0.0 means ‘shadowed’, 1.0 means ‘lit’
};
[shader(
“miss”
)]
void
 ShadowMiss(
inout
 ShadowPayload pay) {
     pay.visibility = 1.0f;
}
[shader(
“anyhit”
)]
void
 ShadowAnyHit(
inout
 ShadowPayload pay, BuiltinIntersectAttribs attribs) {
     
if
 (alphaTestFails(attribs))
          IgnoreHit();
}
float
 shootShadowRay(
float3
 orig, 
float3
 dir, 
float
 minT, 
float
 maxT)  {
     RayDesc       ray = { orig, minT, dir, maxT };
     ShadowPayload pay = { 0.0f };
     
uint
 flags = RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH |
                  RAY_FLAG_SKIP_CLOSEST_HIT_SHADER;
     TraceRay( gRtScene, flags, 0xFF, 0, 1, 0, ray, pay );
    
     
return
 
pay.visibility;
}
...
A
 
R
E
U
S
A
B
L
E
 
S
H
A
D
O
W
 
R
A
Y
121
121
121
Gives reusable shadow rays
Useful in many contexts
Like where?
 
Maybe:  want to shade this point
?
float3
 DiffuseShade( 
float3
 hitPos, 
float3
 hitNorm, 
float3
 difColor ) {
     // Get information about the light; access your framework’s scene structs
     float
  distToLight    = length( gLight.position – hitPos );
     
float3
 dirToLight     = normalize( gLight.position – hitPos );
     // Shoot shadow ray with our encapsulated shadow tracing function
     
float
  isLit    = shootShadowRay(hitPos, dirToLight, 1.0e-4f, distToLight );
     // Compute our NdotL term; shoot our shadow ray in selected direction
     
float
  NdotL    = saturate( dot( hitNorm, dirToLight ) );  
// In range [0..1]
     
// Return shaded color
     
return
 isLit
            ? (NdotL * gLight.intensity * (difColor / M_PI) )
            : float3(0, 0, 0);
}
S
H
A
D
I
N
G
 
A
 
D
I
F
F
U
S
E
 
S
U
R
F
A
C
E
122
122
122
To shade, we need:
Position at hit point
Normal at hit point
Material at hit point
float3
 DiffuseShade( 
float3
 hitPos, 
float3
 hitNorm, 
float3
 difColor ) {
     // Get information about the light; access your framework’s scene structs
     float
  distToLight    = length( gLight.position – hitPos );
     
float3
 dirToLight     = normalize( gLight.position – hitPos );
     // Shoot shadow ray with our encapsulated shadow tracing function
     
float
  isLit    = shootShadowRay(hitPos, dirToLight, 1.0e-4f, distToLight );
     // Compute our NdotL term; shoot our shadow ray in selected direction
     
float
  NdotL    = saturate( dot( hitNorm, dirToLight ) );  
// In range [0..1]
     
// Return shaded color
     
return
 isLit
            ? (NdotL * gLight.intensity * (difColor / M_PI) )
            : float3(0, 0, 0);
}
S
H
A
D
I
N
G
 
A
 
D
I
F
F
U
S
E
 
S
U
R
F
A
C
E
123
123
123
To shade, we need:
Position at hit point
Normal at hit point
Material at hit point
Grab light information
Direction to light
How far away is it?
S
H
A
D
I
N
G
 
A
 
D
I
F
F
U
S
E
 
S
U
R
F
A
C
E
124
124
124
To shade, we need:
Position at hit point
Normal at hit point
Material at hit point
Grab light information
Direction to light
How far away is it?
Trace our shadow ray
float3
 DiffuseShade( 
float3
 hitPos, 
float3
 hitNorm, 
float3
 difColor ) {
     // Get information about the light; access your framework’s scene structs
     float
  distToLight    = length( gLight.position – hitPos );
     
float3
 dirToLight     = normalize( gLight.position – hitPos );
     // Shoot shadow ray with our encapsulated shadow tracing function
     
float
  isLit    = shootShadowRay(hitPos, dirToLight, 1.0e-4f, distToLight );
     // Compute our NdotL term; shoot our shadow ray in selected direction
     
float
  NdotL    = saturate( dot( hitNorm, dirToLight ) );  
// In range [0..1]
     
// Return shaded color
     
return
 isLit
            ? (NdotL * gLight.intensity * (difColor / M_PI) )
            : float3(0, 0, 0);
}
S
H
A
D
I
N
G
 
A
 
D
I
F
F
U
S
E
 
S
U
R
F
A
C
E
125
125
125
To shade, we need:
Position at hit point
Normal at hit point
Material at hit point
Grab light information
Direction to light
How far away is it?
Trace our shadow ray
Compute diffuse shading
float3
 DiffuseShade( 
float3
 hitPos, 
float3
 hitNorm, 
float3
 difColor ) {
     // Get information about the light; access your framework’s scene structs
     float
  distToLight    = length( gLight.position – hitPos );
     
float3
 dirToLight     = normalize( gLight.position – hitPos );
     // Shoot shadow ray with our encapsulated shadow tracing function
     
float
  isLit    = shootShadowRay(hitPos, dirToLight, 1.0e-4f, distToLight );
     // Compute our NdotL term; shoot our shadow ray in selected direction
     
float
  NdotL    = saturate( dot( hitNorm, dirToLight ) );  
// In range [0..1]
     
// Return shaded color
     
return
 isLit
            ? (NdotL * gLight.intensity * (difColor / M_PI) )
            : float3(0, 0, 0);
}
S
H
A
D
I
N
G
 
A
 
D
I
F
F
U
S
E
 
S
U
R
F
A
C
E
126
126
126
To shade, we need:
Position at hit point
Normal at hit point
Material at hit point
Grab light information
Direction to light
How far away is it?
Trace our shadow ray
Compute diffuse shading
Want more complex material?
Insert different code here
float3
 DiffuseShade( 
float3
 hitPos, 
float3
 hitNorm, 
float3
 difColor ) {
     // Get information about the light; access your framework’s scene structs
     float
  distToLight    = length( gLight.position – hitPos );
     
float3
 dirToLight     = normalize( gLight.position – hitPos );
     // Shoot shadow ray with our encapsulated shadow tracing function
     
float
  isLit    = shootShadowRay(hitPos, dirToLight, 1.0e-4f, distToLight );
     // Compute our NdotL term; shoot our shadow ray in selected direction
     
float
  NdotL    = saturate( dot( hitNorm, dirToLight ) );  
// In range [0..1]
     
// Return shaded color
     
return
 isLit
            ? (NdotL * gLight.intensity * (difColor / M_PI) )
            : float3(0, 0, 0);
}
U
S
E
 
A
 
S
H
A
D
E
 
F
U
N
C
T
I
O
N
127
127
127
Where to use 
DiffuseShade()
?
U
S
E
 
A
 
S
H
A
D
E
 
F
U
N
C
T
I
O
N
128
128
128
Where to use 
DiffuseShade()
?
Encapsulate tracing a color ray
struct
 IndirectPayload {
     
float3
 color;    
// will store ray color
};
[shader(
“miss”
)]
void
 IndirectMiss(
inout
 IndirectPayload pay) {
     pay.color = GetBackgroundColor( WorldRayDirection() );
}
[shader(
“anyhit”
)]
void
 IndirectAnyHit(
inout
 IndirectPayload pay, BuiltinIntersectAttribs attribs) {
     
if
 (alphaTestFails(attribs))
          IgnoreHit();
}
[shader(
“closesthit”
)]
void
 IndirectClosestHit(
inout
 IndirectPayload pay,
                        BuiltinTriangleIntersectAttribs attribs) {
     ShadingData hit = getHitShadingData( attribs );
     pay.color = DiffuseShade( hit.pos, hit.norm, hit.difColor );
}
float3
 shootColorRay(
float3
 orig, 
float3
 dir, 
float
 minT )  {
     RayDesc         ray = { orig, minT, dir, 1.0e+38 };
     IndirectPayload pay = { 
float3
( 0.0f ) };
     TraceRay( gRtScene, RAY_FLAG_NONE, 0xFF, 1, 2, 1, ray, pay );
    
     return 
pay.color;
}
U
S
E
 
A
 
S
H
A
D
E
 
F
U
N
C
T
I
O
N
129
129
129
Where to use 
DiffuseShade()
?
Encapsulate tracing a color ray
Setup a ray
Initialize return color to black
struct
 IndirectPayload {
     
float3
 color;    
// will store ray color
};
[shader(
“miss”
)]
void
 IndirectMiss(
inout
 IndirectPayload pay) {
     pay.color = GetBackgroundColor( WorldRayDirection() );
}
[shader(
“anyhit”
)]
void
 IndirectAnyHit(
inout
 IndirectPayload pay, BuiltinIntersectAttribs attribs) {
     
if
 (alphaTestFails(attribs))
          IgnoreHit();
}
[shader(
“closesthit”
)]
void
 IndirectClosestHit(
inout
 IndirectPayload pay,
                        BuiltinTriangleIntersectAttribs attribs) {
     ShadingData hit = getHitShadingData( attribs );
     pay.color = DiffuseShade( hit.pos, hit.norm, hit.difColor );
}
float3
 shootColorRay(
float3
 orig, 
float3
 dir, 
float
 minT )  {
     RayDesc         ray = { orig, minT, dir, 1.0e+38 };
     IndirectPayload pay = { 
float3
( 0.0f ) };
     TraceRay( gRtScene, RAY_FLAG_NONE, 0xFF, 1, 2, 1, ray, pay );
    
     return 
pay.color;
}
U
S
E
 
A
 
S
H
A
D
E
 
F
U
N
C
T
I
O
N
130
130
130
Where to use 
DiffuseShade()
?
Encapsulate tracing a color ray
Setup a ray
Initialize return color to black
Trace ray, then return its color
struct
 IndirectPayload {
     
float3
 color;    
// will store ray color
};
[shader(
“miss”
)]
void
 IndirectMiss(
inout
 IndirectPayload pay) {
     pay.color = GetBackgroundColor( WorldRayDirection() );
}
[shader(
“anyhit”
)]
void
 IndirectAnyHit(
inout
 IndirectPayload pay, BuiltinIntersectAttribs attribs) {
     
if
 (alphaTestFails(attribs))
          IgnoreHit();
}
[shader(
“closesthit”
)]
void
 IndirectClosestHit(
inout
 IndirectPayload pay,
                        BuiltinTriangleIntersectAttribs attribs) {
     ShadingData hit = getHitShadingData( attribs );
     pay.color = DiffuseShade( hit.pos, hit.norm, hit.difColor );
}
float3
 shootColorRay(
float3
 orig, 
float3
 dir, 
float
 minT )  {
     RayDesc         ray = { orig, minT, dir, 1.0e+38 };
     IndirectPayload pay = { 
float3
( 0.0f ) };
     TraceRay( gRtScene, RAY_FLAG_NONE, 0xFF, 1, 2, 1, ray, pay );
    
     return 
pay.color;
}
U
S
E
 
A
 
S
H
A
D
E
 
F
U
N
C
T
I
O
N
131
131
131
Where to use 
DiffuseShade()
?
Encapsulate tracing a color ray
Setup a ray
Initialize return color to black
Trace ray, then return its color
For every hit, check transparency
struct
 IndirectPayload {
     
float3
 color;    
// will store ray color
};
[shader(
“miss”
)]
void
 IndirectMiss(
inout
 IndirectPayload pay) {
     pay.color = GetBackgroundColor( WorldRayDirection() );
}
[shader(
“anyhit”
)]
void
 IndirectAnyHit(
inout
 IndirectPayload pay, BuiltinIntersectAttribs attribs) {
     
if
 (alphaTestFails(attribs))
          IgnoreHit();
}
[shader(
“closesthit”
)]
void
 IndirectClosestHit(
inout
 IndirectPayload pay,
                        BuiltinTriangleIntersectAttribs attribs) {
     ShadingData hit = getHitShadingData( attribs );
     pay.color = DiffuseShade( hit.pos, hit.norm, hit.difColor );
}
float3
 shootColorRay(
float3
 orig, 
float3
 dir, 
float
 minT )  {
     RayDesc         ray = { orig, minT, dir, 1.0e+38 };
     IndirectPayload pay = { 
float3
( 0.0f ) };
     TraceRay( gRtScene, RAY_FLAG_NONE, 0xFF, 1, 2, 1, ray, pay );
    
     return 
pay.color;
}
U
S
E
 
A
 
S
H
A
D
E
 
F
U
N
C
T
I
O
N
132
132
132
Where to use 
DiffuseShade()
?
Encapsulate tracing a color ray
Setup a ray
Initialize return color to black
Trace ray, then return its color
For every hit, check transparency
On miss, return background
struct
 IndirectPayload {
     
float3
 color;    
// will store ray color
};
[shader(
“miss”
)]
void
 IndirectMiss(
inout
 IndirectPayload pay) {
     pay.color = GetBackgroundColor( WorldRayDirection() );
}
[shader(
“anyhit”
)]
void
 IndirectAnyHit(
inout
 IndirectPayload pay, BuiltinIntersectAttribs attribs) {
     
if
 (alphaTestFails(attribs))
          IgnoreHit();
}
[shader(
“closesthit”
)]
void
 IndirectClosestHit(
inout
 IndirectPayload pay,
                        BuiltinTriangleIntersectAttribs attribs) {
     ShadingData hit = getHitShadingData( attribs );
     pay.color = DiffuseShade( hit.pos, hit.norm, hit.difColor );
}
float3
 shootColorRay(
float3
 orig, 
float3
 dir, 
float
 minT )  {
     RayDesc         ray = { orig, minT, dir, 1.0e+38 };
     IndirectPayload pay = { 
float3
( 0.0f ) };
     TraceRay( gRtScene, RAY_FLAG_NONE, 0xFF, 1, 2, 1, ray, pay );
    
     return 
pay.color;
}
U
S
E
 
A
 
S
H
A
D
E
 
F
U
N
C
T
I
O
N
133
133
133
Where to use 
DiffuseShade()
?
Encapsulate tracing a color ray
Setup a ray
Initialize return color to black
Trace ray, then return its color
For every hit, check transparency
On miss, return background
On closest hit, shade
struct
 IndirectPayload {
     
float3
 color;    
// will store ray color
};
[shader(
“miss”
)]
void
 IndirectMiss(
inout
 IndirectPayload pay) {
     pay.color = GetBackgroundColor( WorldRayDirection() );
}
[shader(
“anyhit”
)]
void
 IndirectAnyHit(
inout
 IndirectPayload pay, BuiltinIntersectAttribs attribs) {
     
if
 (alphaTestFails(attribs))
          IgnoreHit();
}
[shader(
“closesthit”
)]
void
 IndirectClosestHit(
inout
 IndirectPayload pay,
                        BuiltinTriangleIntersectAttribs attribs) {
     ShadingData hit = getHitShadingData( attribs );
     pay.color = DiffuseShade( hit.pos, hit.norm, hit.difColor );
}
float3
 shootColorRay(
float3
 orig, 
float3
 dir, 
float
 minT )  {
     RayDesc         ray = { orig, minT, dir, 1.0e+38 };
     IndirectPayload pay = { 
float3
( 0.0f ) };
     TraceRay( gRtScene, RAY_FLAG_NONE, 0xFF, 1, 2, 1, ray, pay );
    
     return 
pay.color;
}
P
U
T
T
I
N
G
 
I
T
 
T
O
G
E
T
H
E
R
134
134
134
 
P
U
T
T
I
N
G
 
I
T
 
T
O
G
E
T
H
E
R
135
135
135
Go back to ray gen shader
Similar to simple one we started with
[shader(
“raygeneration”
)]
void
 BasicRayTracer()  {
     
uint2
  curPixel    = DispatchRaysIndex().xy;
     
float3
 pixelRayDir = normalize( getRayDirFromPixelID( curPixel ) );
     
float3
 pixelColor  = shootColorRay( gCamera.posW, pixelRayDir, 0.0f );
     outTex[curPixel]   = 
float4
( pixelColor, 1.0f );
}
P
U
T
T
I
N
G
 
I
T
 
T
O
G
E
T
H
E
R
136
136
136
Go back to ray gen shader
Similar to simple one we started with
Get current pixel, it’s ray direction
[shader(
“raygeneration”
)]
void
 BasicRayTracer()  {
     
uint2
  curPixel    = DispatchRaysIndex().xy;
     
float3
 pixelRayDir = normalize( getRayDirFromPixelID( curPixel ) );
     
float3
 pixelColor  = shootColorRay( gCamera.posW, pixelRayDir, 0.0f );
     outTex[curPixel]   = 
float4
( pixelColor, 1.0f );
}
P
U
T
T
I
N
G
 
I
T
 
T
O
G
E
T
H
E
R
137
137
137
Go back to ray gen shader
Similar to simple one we started with
Get current pixel, it’s ray direction
Shoot a color ray in that direction
[shader(
“raygeneration”
)]
void
 BasicRayTracer()  {
     
uint2
  curPixel    = DispatchRaysIndex().xy;
     
float3
 pixelRayDir = normalize( getRayDirFromPixelID( curPixel ) );
     
float3
 pixelColor  = shootColorRay( gCamera.posW, pixelRayDir, 0.0f );
     outTex[curPixel]   = 
float4
( pixelColor, 1.0f );
}
P
U
T
T
I
N
G
 
I
T
 
T
O
G
E
T
H
E
R
138
138
138
Go back to ray gen shader
Similar to simple one we started with
Get current pixel, it’s ray direction
Shoot a color ray in that direction
Output the final result
[shader(
“raygeneration”
)]
void
 BasicRayTracer()  {
     
uint2
  curPixel    = DispatchRaysIndex().xy;
     
float3
 pixelRayDir = normalize( getRayDirFromPixelID( curPixel ) );
     
float3
 pixelColor  = shootColorRay( gCamera.posW, pixelRayDir, 0.0f );
     outTex[curPixel]   = 
float4
( pixelColor, 1.0f );
}
D
E
M
O
?
139
139
139
Full code, binaries, and walk through:
http://intro-to-dxr.cwyman.org
G
O
I
N
G
 
F
U
R
T
H
E
R
More complex materials, multi-bounce lighting, etc.
G
O
I
N
G
 
F
U
R
T
H
E
R
141
141
141
Take code for color ray & tweak
struct
 IndirectPayload {
     
float3
 color;    
// will store ray color
};
[shader(
“miss”
)]
void
 IndirectMiss(
inout
 IndirectPayload pay) {
     pay.color = GetBackgroundColor( WorldRayDirection() );
}
[shader(
“anyhit”
)]
void
 IndirectAnyHit(
inout
 IndirectPayload pay, BuiltinIntersectAttribs attribs) {
     
if
 (alphaTestFails(attribs))
          IgnoreHit();
}
[shader(
“closesthit”
)]
void
 IndirectClosestHit(
inout
 IndirectPayload pay,
                        BuiltinTriangleIntersectAttribs attribs) {
     ShadingData hit = getHitShadingData( attribs );
     pay.color = DiffuseShade( hit.pos, hit.norm, hit.difColor );
}
float3
 shootColorRay(
float3
 orig, 
float3
 dir, 
float
 minT )  {
     RayDesc         ray = { orig, minT, dir, 1.0e+38 };
     IndirectPayload pay = { 
float3
( 0.0f ) };
     TraceRay( gRtScene, RAY_FLAG_NONE, 0xFF, 1, 2, 1, ray, pay );
    
     return 
pay.color;
}
G
O
I
N
G
 
F
U
R
T
H
E
R
142
142
142
Take code for color ray & tweak
Mostly here:
struct
 IndirectPayload {
     
float3
 color;    
// will store ray color
};
[shader(
“miss”
)]
void
 IndirectMiss(
inout
 IndirectPayload pay) {
     pay.color = GetBackgroundColor( WorldRayDirection() );
}
[shader(
“anyhit”
)]
void
 IndirectAnyHit(
inout
 IndirectPayload pay, BuiltinIntersectAttribs attribs) {
     
if
 (alphaTestFails(attribs))
          IgnoreHit();
}
[shader(
“closesthit”
)]
void
 IndirectClosestHit(
inout
 IndirectPayload pay,
                        BuiltinTriangleIntersectAttribs attribs) {
     ShadingData hit = getHitShadingData( attribs );
     pay.color = DiffuseShade( hit.pos, hit.norm, hit.difColor );
}
float3
 shootColorRay(
float3
 orig, 
float3
 dir, 
float
 minT )  {
     RayDesc         ray = { orig, minT, dir, 1.0e+38 };
     IndirectPayload pay = { 
float3
( 0.0f ) };
     TraceRay( gRtScene, RAY_FLAG_NONE, 0xFF, 1, 2, 1, ray, pay );
    
     return 
pay.color;
}
G
O
I
N
G
 
F
U
R
T
H
E
R
143
143
143
Want global illumination?
[shader(
“closesthit”
)]
void
 IndirectClosestHit(
inout
 IndirectPayload pay,
                        BuiltinTriangleIntersectAttribs attribs) {
     ShadingData hit = getHitShadingData( attribs );
     float3 directLight = DiffuseShade( hit.pos, hit.norm, hit.difColor );
     float3 bounceDir = selectRandomDirection();
     float3 indirectColor = shootColorRay( hit.pos, bouncDir );
     float3 indirectLight = DiffuseIndirect( bounceDir, indirectColor );
     pay.color = directLight + indirectLight;
}
G
O
I
N
G
 
F
U
R
T
H
E
R
144
144
144
Want global illumination?
Add a random outgoing ray
Recursive call: 
shootColorRay()
Account for BRDF
Add contributions together
A
 
b
a
s
i
c
 
p
a
t
h
 
t
r
a
c
e
r
[shader(
“closesthit”
)]
void
 IndirectClosestHit(
inout
 IndirectPayload pay,
                        BuiltinTriangleIntersectAttribs attribs) {
     ShadingData hit = getHitShadingData( attribs );
     float3 directLight = DiffuseShade( hit.pos, hit.norm, hit.difColor );
     float3 bounceDir = selectRandomDirection();
     float3 indirectColor = shootColorRay( hit.pos, bouncDir );
     float3 indirectLight = DiffuseIndirect( bounceDir, indirectColor );
     pay.color = directLight + indirectLight;
}
G
O
I
N
G
 
F
U
R
T
H
E
R
145
145
145
Want global illumination?
Add a random outgoing ray
Recursive call: 
shootColorRay()
Account for BRDF
Add contributions together
A
 
b
a
s
i
c
 
p
a
t
h
 
t
r
a
c
e
r
Usually encapsulate BRDF
Direct light done with BRDF::evaluate()
[shader(
“closesthit”
)]
void
 IndirectClosestHit(
inout
 IndirectPayload pay,
                        BuiltinTriangleIntersectAttribs attribs) {
     ShadingData hit = getHitShadingData( attribs );
     float3 directLight = DiffuseShade( hit.pos, hit.norm, hit.difColor );
     float3 bounceDir = selectRandomDirection();
     float3 indirectColor = shootColorRay( hit.pos, bouncDir );
     float3 indirectLight = DiffuseIndirect( bounceDir, indirectColor );
     pay.color = directLight + indirectLight;
}
G
O
I
N
G
 
F
U
R
T
H
E
R
146
146
146
Want global illumination?
Add a random outgoing ray
Recursive call: 
shootColorRay()
Account for BRDF
Add contributions together
A
 
b
a
s
i
c
 
p
a
t
h
 
t
r
a
c
e
r
Usually encapsulate BRDF
Direct light done with 
BRDF::evaluate()
Indirect done with 
BRDF::scatter()
Also sometimes called 
sample()
[shader(
“closesthit”
)]
void
 IndirectClosestHit(
inout
 IndirectPayload pay,
                        BuiltinTriangleIntersectAttribs attribs) {
     ShadingData hit = getHitShadingData( attribs );
     float3 directLight = DiffuseShade( hit.pos, hit.norm, hit.difColor );
     float3 bounceDir = selectRandomDirection();
     float3 indirectColor = shootColorRay( hit.pos, bouncDir );
     float3 indirectLight = DiffuseIndirect( bounceDir, indirectColor );
     pay.color = directLight + indirectLight;
}
G
O
I
N
G
 
F
U
R
T
H
E
R
147
147
147
Want global illumination?
Add a random outgoing ray
Recursive call: 
shootColorRay()
Account for BRDF
Add contributions together
A
 
b
a
s
i
c
 
p
a
t
h
 
t
r
a
c
e
r
Usually encapsulate BRDF
Direct light done with 
BRDF::evaluate()
Indirect done with 
BRDF::scatter()
Also sometimes called 
sample()
Makes it easy to plug in new materials
[shader(
“closesthit”
)]
void
 IndirectClosestHit(
inout
 IndirectPayload pay,
                        BuiltinTriangleIntersectAttribs attribs) {
     ShadingData hit = getHitShadingData( attribs );
     float3 directLight = DiffuseShade( hit.pos, hit.norm, hit.difColor );
     float3 bounceDir = selectRandomDirection();
     float3 indirectColor = shootColorRay( hit.pos, bouncDir );
     float3 indirectLight = DiffuseIndirect( bounceDir, indirectColor );
     pay.color = directLight + indirectLight;
}
M
A
N
Y
 
L
I
G
H
T
S
?
148
148
148
 
M
A
N
Y
 
L
I
G
H
T
S
?
149
149
149
Don’t just evaluate BRDF for one light
float3
 DiffuseShade( 
float3
 hitPos, 
float3
 hitNorm, 
float3
 difColor ) {
     // Get information about the light; access your framework’s scene structs
     float
  distToLight    = length( gLight.position – hitPos );
     
float3
 dirToLight     = normalize( gLight.position – hitPos );
     // Shoot shadow ray with our encapsulated shadow tracing function
     
float
  isLit    = shootShadowRay(hitPos, dirToLight, 1.0e-4f, distToLight );
     // Compute our NdotL term; shoot our shadow ray in selected direction
     
float
  NdotL    = saturate( dot( hitNorm, dirToLight ) );  
// In range [0..1]
     
// Return shaded color
     
return
 isLit
            ? (NdotL * gLight.intensity * (difColor / M_PI) )
            : float3(0, 0, 0);
}
M
A
N
Y
 
L
I
G
H
T
S
?
150
150
150
Don’t just evaluate BRDF for one light
Loop per light
float3
 DiffuseShade( 
float3
 hitPos, 
float3
 hitNorm, 
float3
 difColor ) {
     // Get information about the light; access your framework’s scene structs
     float
  distToLight    = length( gLight.position – hitPos );
     
float3
 dirToLight     = normalize( gLight.position – hitPos );
     // Shoot shadow ray with our encapsulated shadow tracing function
     
float
  isLit    = shootShadowRay(hitPos, dirToLight, 1.0e-4f, distToLight );
     // Compute our NdotL term; shoot our shadow ray in selected direction
     
float
  NdotL    = saturate( dot( hitNorm, dirToLight ) );  
// In range [0..1]
     
// Return shaded color
     
return
 isLit
            ? (NdotL * gLight.intensity * (difColor / M_PI) )
            : float3(0, 0, 0);
}
M
A
N
Y
 
L
I
G
H
T
S
?
151
151
151
Don’t just evaluate BRDF for one light
Loop per light
Thousands of lights?  Becomes expensive
float3
 DiffuseShade( 
float3
 hitPos, 
float3
 hitNorm, 
float3
 difColor ) {
     // Get information about the light; access your framework’s scene structs
     float
  distToLight    = length( gLight.position – hitPos );
     
float3
 dirToLight     = normalize( gLight.position – hitPos );
     // Shoot shadow ray with our encapsulated shadow tracing function
     
float
  isLit    = shootShadowRay(hitPos, dirToLight, 1.0e-4f, distToLight );
     // Compute our NdotL term; shoot our shadow ray in selected direction
     
float
  NdotL    = saturate( dot( hitNorm, dirToLight ) );  
// In range [0..1]
     
// Return shaded color
     
return
 isLit
            ? (NdotL * gLight.intensity * (difColor / M_PI) )
            : float3(0, 0, 0);
}
M
A
N
Y
 
L
I
G
H
T
S
?
152
152
152
Don’t just evaluate BRDF for one light
Loop per light
Thousands of lights?  Becomes expensive
What if: emissive triangles, spheres, bunnies?
M
A
N
Y
 
L
I
G
H
T
S
?
153
153
153
Don’t just evaluate BRDF for one light
Loop per light
Thousands of lights?  Becomes expensive
What if: emissive triangles, spheres, bunnies?
N
e
e
d
 
t
o
 
s
a
m
p
l
e
 
y
o
u
r
 
l
i
g
h
t
s
Pick a random location on some light
Evaluate direct lighting from that point
N
A
Ï
V
E
 
L
I
G
H
T
 
S
A
M
P
L
I
N
G
:
154
154
154
Lots of point lights (e.g., N points):
Randomly pick number in [1…N], use that light for shading
N
A
Ï
V
E
 
L
I
G
H
T
 
S
A
M
P
L
I
N
G
:
155
155
155
Lots of point lights (e.g., N points):
Randomly pick number in [1…N], use that light for shading
One surface light:
Pick a point uniformly over the surface
E.g., on a quad, pick both (u, v) randomly in [0…1]
N
A
Ï
V
E
 
L
I
G
H
T
 
S
A
M
P
L
I
N
G
:
156
156
156
Lots of point lights (e.g., N points):
Randomly pick number in [1…N], use that light for shading
One surface light:
Pick a point uniformly over the surface
E.g., on a quad, pick both (u, v) randomly in [0…1]
For many emissive surfaces (e.g., N surfaces):
First pick number in [1…N], then pick random point on surface
N
A
Ï
V
E
 
L
I
G
H
T
 
S
A
M
P
L
I
N
G
:
157
157
157
Lots of point lights (e.g., N points):
Randomly pick number in [1…N], use that light for shading
One surface light:
Pick a point uniformly over the surface
E.g., on a quad, pick both (u, v) randomly in [0…1]
For many emissive surfaces (e.g., N surfaces):
First pick number in [1…N], then pick random point on surface
Alternatively weight choice of light based on area
U
P
 
N
E
X
T
M
o
r
g
a
n
 
M
c
G
u
i
r
e
With more on materials, sampling, and how to think about
GPU ray tracing performance
Q
U
E
S
T
I
O
N
S
?
E-mail: 
cwyman@nvidia.com
Twitter: @_cwyman_
Code: 
http://intro-to-dxr.cwyman.org
Slide Note
Embed
Share

Dive into the world of real-time ray tracing with part 2 of this series, focusing on parallelizing your ray tracer for optimal performance. Explore the essentials needed before GPU ray tracing, handle materials, textures, and mesh files efficiently, and understand the complexities of rendering triangle meshes with additional features expected in GPU rendering.

  • Ray Tracing
  • Parallelization
  • GPU
  • Materials
  • Textures

Uploaded on Oct 03, 2024 | 0 Views


Download Presentation

Please find below an Image/Link to download the presentation.

The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author. Download presentation by click this link. If you encounter any issues during the download, it is possible that the publisher has removed the file from their server.

E N D

Presentation Transcript


  1. Introduction to Real-time Ray Tracing Part 2 GOING FAST: PARALLELIZING YOUR RAY TRACER Chris Wyman Principal Research Scientist NVIDIA 1

  2. SOME PRELIMINARIES Ideas needed before GPU ray tracing

  3. YOU JUST GOT THE BASICS 3

  4. YOU JUST GOT THE BASICS But additional features expected for GPU rendering 4

  5. YOU JUST GOT THE BASICS But additional features expected for GPU rendering Typically, increased complexity; not just a few primitives 5

  6. YOU JUST GOT THE BASICS But additional features expected for GPU rendering Typically, increased complexity; not just a few primitives Render triangle meshes Just collections of triangles approximating 3D shapes Easy enough; intersect each triangle in turn 6

  7. YOU JUST GOT THE BASICS But additional features expected for GPU rendering Typically, increased complexity; not just a few primitives Render triangle meshes Just collections of triangles approximating 3D shapes Easy enough; intersect each triangle in turn Mesh files usually contain material information Often small-scale detail stored in textures 7

  8. HOW TO HANDLE MATERIALS AND TEXTURES? 8

  9. HOW TO HANDLE MATERIALS AND TEXTURES? Ray-primitive intersection Not just binary: Did we hit? Yes / No Also need to store attributes at the hit point, e.g.: Positions Normal Color 9

  10. HOW TO HANDLE MATERIALS AND TEXTURES? Ray-primitive intersection Not just binary: Did we hit? Yes / No Also need to store attributes at the hit point, e.g.: Positions Normal Color Texture coordinates Material parameters Et cetera 10

  11. HOW TO HANDLE MATERIALS AND TEXTURES? Ray-primitive intersection Not just binary: Did we hit? Yes / No Also need to store attributes at the hit point, e.g.: Positions Normal Color Texture coordinates Material parameters Et cetera Our texture: 11

  12. HOW TO HANDLE MATERIALS AND TEXTURES? Ray-primitive intersection Not just binary: Did we hit? Yes / No Also need to store attributes at the hit point, e.g.: Positions Normal Color Texture coordinates Material parameters Et cetera Triangle vertices have: texture coordinates (0,0) (1,0) (0,1) 12

  13. HOW TO HANDLE MATERIALS AND TEXTURES? Ray-primitive intersection Not just binary: Did we hit? Yes / No Also need to store attributes at the hit point, e.g.: Positions Normal Color Texture coordinates Material parameters Et cetera Triangle vertices have: texture coordinates (0,0) (1,0) Coordinate here: Interpolates coordinates at vertices (0,1) 13

  14. HOW TO HANDLE MATERIALS AND TEXTURES? Ray-primitive intersection Not just binary: Did we hit? Yes / No Also need to store attributes at the hit point, e.g.: Positions Normal Color Texture coordinates Material parameters Et cetera Triangle vertices have: texture coordinates (0,0) (1,0) Coordinate here: Interpolates coordinates at vertices Same interpolation as position, normal, color, etc. (0,1) Use coord to index in the image array 14

  15. HOW TO HANDLE MATERIALS AND TEXTURES? Ray-primitive intersection Not just binary: Did we hit? Yes / No Also need to store attributes at the hit point, e.g.: Positions Normal Color Texture coordinates Material parameters Et cetera All attribute interpolation work the same way 15

  16. BASICS OF OPTIMIZATION Before jumping to GPU, take some baby steps

  17. BEFORE DIVING INTO PARALLELIZATION Need to talk about some performance basics 17

  18. BEFORE DIVING INTO PARALLELIZATION Need to talk about some performance basics Why is tracing rays slow at all? 18

  19. BEFORE DIVING INTO PARALLELIZATION Need to talk about some performance basics Why is tracing rays slow at all? Consider basic ray tracing algorithm: Take a ray through your scene 19

  20. BEFORE DIVING INTO PARALLELIZATION Need to talk about some performance basics Why is tracing rays slow at all? Consider basic ray tracing algorithm: Take a ray through your scene Test triangle to find intersection 20

  21. BEFORE DIVING INTO PARALLELIZATION Need to talk about some performance basics Why is tracing rays slow at all? Consider basic ray tracing algorithm: Take a ray through your scene Test triangle to find intersection Repeat 21

  22. BEFORE DIVING INTO PARALLELIZATION Need to talk about some performance basics Why is tracing rays slow at all? Consider basic ray tracing algorithm: Take a ray through your scene Test triangle to find intersection Repeat 22

  23. BEFORE DIVING INTO PARALLELIZATION Need to talk about some performance basics Why is tracing rays slow at all? Consider basic ray tracing algorithm: Take a ray through your scene Test triangle to find intersection Repeat 23

  24. BEFORE DIVING INTO PARALLELIZATION Need to talk about some performance basics Why is tracing rays slow at all? Consider basic ray tracing algorithm: Take a ray through your scene Test triangle to find intersection Repeat 24

  25. BEFORE DIVING INTO PARALLELIZATION Need to talk about some performance basics Why is tracing rays slow at all? Consider basic ray tracing algorithm: Take a ray through your scene Test triangle to find intersection Repeat How do you know when you re done? 25

  26. BEFORE DIVING INTO PARALLELIZATION Need to talk about some performance basics Why is tracing rays slow at all? Consider basic ray tracing algorithm: Take a ray through your scene Test triangle to find intersection Repeat How do you know when you re done? When you ve tested every triangle? 26

  27. BEFORE DIVING INTO PARALLELIZATION Need to talk about some performance basics Why is tracing rays slow at all? Consider basic ray tracing algorithm: Take a ray through your scene Test triangle to find intersection Repeat How do you know when you re done? When you ve tested every triangle? Very expensive Every ray could test, 1 million (or more) triangles 27

  28. WHATS OUR COMPUTATION BUDGET? 28

  29. WHATS OUR COMPUTATION BUDGET? Let s be easy on ourselves: Target just 1920 x 1080 at 60 fps 29

  30. WHATS OUR COMPUTATION BUDGET? Let s be easy on ourselves: Target just 1920 x 1080 at 60 fps We need 125 million pixels per second! 30

  31. WHATS OUR COMPUTATION BUDGET? Let s be easy on ourselves: Target just 1920 x 1080 at 60 fps We need 125 million pixels per second! With a ~10 TFLOP state-of-the-art GPU If tracing one ray per pixel About 80,000 flops per ray 31

  32. WHATS OUR COMPUTATION BUDGET? Let s be easy on ourselves: Target just 1920 x 1080 at 60 fps We need 125 million pixels per second! With a ~10 TFLOP state-of-the-art GPU If tracing one ray per pixel About 80,000 flops per ray An optimized triangle intersection: ~10 flops Can afford at most 8,000 intersections per ray 32

  33. WHATS OUR COMPUTATION BUDGET? Let s be easy on ourselves: Target just 1920 x 1080 at 60 fps We need 125 million pixels per second! With a ~10 TFLOP state-of-the-art GPU If tracing one ray per pixel About 80,000 flops per ray An optimized triangle intersection: ~10 flops Can afford at most 8,000 intersections per ray Conclusion: Don t test every triangle! 33

  34. KEY PRINCIPAL TO OPTIMIZATION: Make the common case fast 34

  35. KEY PRINCIPAL TO OPTIMIZATION: Make the common case fast Common case in ray tracing? Ray does not intersect a triangle 35

  36. KEY PRINCIPAL TO OPTIMIZATION: Make the common case fast Common case in ray tracing? Ray does not intersect a triangle For any mesh, ray typically misses mesh 36

  37. KEY PRINCIPAL TO OPTIMIZATION: Make the common case fast Common case in ray tracing? Ray does not intersect a triangle For any mesh, ray typically misses mesh Perhaps: First intersect a mesh bounding box 37

  38. KEY PRINCIPAL TO OPTIMIZATION: Make the common case fast Common case in ray tracing? Ray does not intersect a triangle For any mesh, ray typically misses mesh Perhaps: First intersect a mesh bounding box Most rays avoid testing thousands of triangles But, extra box test when hit bunny 38

  39. KEY PRINCIPAL TO OPTIMIZATION: What if you have thousands of bunnies? 39

  40. KEY PRINCIPAL TO OPTIMIZATION: What if you have thousands of bunnies? 40

  41. KEY PRINCIPAL TO OPTIMIZATION: What if you have thousands of bunnies? Common case: Ray misses most bunnies 41

  42. KEY PRINCIPAL TO OPTIMIZATION: What if you have thousands of bunnies? Common case: Ray misses most bunnies Can skip testing this half 42

  43. KEY PRINCIPAL TO OPTIMIZATION: What if you have thousands of bunnies? Common case: Ray misses most bunnies Can skip testing this half and this quarter with a few more boxes 43

  44. KEY PRINCIPAL TO OPTIMIZATION: Build a tree of bounding boxes Known as a bounding volume hierarchy or BVH 44

  45. KEY PRINCIPAL TO OPTIMIZATION: Build a tree of bounding boxes Known as a bounding volume hierarchy or BVH When using a principled tree build Reduces number of required intersections From O(N) to O(log N) 45

  46. KEY PRINCIPAL TO OPTIMIZATION: Build a tree of bounding boxes Known as a bounding volume hierarchy or BVH When using a principled tree build Reduces number of required intersections From O(N) to O(log N) With a binary tree, 1 million ray-triangle tests becomes: Around 20 ray-box tests A few ray-triangle tests in leaf nodes 46

  47. KEY PRINCIPAL TO OPTIMIZATION: Production ray tracers always use some acceleration structure 47

  48. KEY PRINCIPAL TO OPTIMIZATION: Production ray tracers always use some acceleration structure But, which structure? How do you best build it? Literally decades of research 48

  49. KEY PRINCIPAL TO OPTIMIZATION: Production ray tracers always use some acceleration structure But, which structure? How do you best build it? Literally decades of research Continuing to today (e.g., Wide BVH Traversal with a Short Stack, Vaidyanathan et al. 2019) 49

  50. KEY PRINCIPAL TO OPTIMIZATION: Production ray tracers always use some acceleration structure But, which structure? How do you best build it? Literally decades of research Continuing to today (e.g., Wide BVH Traversal with a Short Stack, Vaidyanathan et al. 2019) When starting real-time ray tracing, best bet: Use someone else s code Quality of your BVH easily affects performance by 2x, 3x, or >10x Varies per scene! Luckily most APIs will build structure 50

More Related Content

giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#