General Utilities
List of the General Functions and Types provided by the RayTracer. Most of the other functionalities are built upon these.
RayTracer.FixedParams
RayTracer.Vec3
RayTracer.rgb
RayTracer.bigmul
RayTracer.camera2world
RayTracer.extract
RayTracer.get_image
RayTracer.get_params
RayTracer.place
RayTracer.place_idx!
RayTracer.set_params!
RayTracer.world2camera
RayTracer.zeroonenorm
RayTracer.@diffops
Documentation
RayTracer.Vec3
— Type.Vec3
This is the central type for RayTracer. All of the other types are defined building upon this.
All the fields of the Vec3 instance contains Array
s. This ensures that we can collect the gradients w.r.t the fields using the Params
API of Zygote.
Fields:
x
y
z
The types of x
, y
, and z
must match. Also, if scalar input is given to the constructor it will be cnverted into a 1-element Vector.
Defined Operations for Vec3:
+
,-
,*
– These operations will be broadcasted even though there is no explicit mention of broadcasting.dot
l2norm
cross
clamp
zero
similar
one
maximum
minimum
normalize
size
getindex
– This returns a named tuple
RayTracer.rgb
— Type.rgb
is an alias for Vec3
. It makes more sense to use this while defining colors.
RayTracer.get_image
— Method.get_image(image, width, height)
Reshapes and normalizes a Vec3 color format to the RGB format of Images for easy loading, saving and visualization.
Arguments:
image
- The rendered image in flattened Vec3 format (i.e., the output of the raytrace, rasterize, etc.)width
- Width of the output imageheight
- Height of the output image
RayTracer.zeroonenorm
— Method.zeroonenorm(x::AbstractArray)
Normalizes the elements of the array to values between 0
and 1
.
This function exists because the version of Zygote we use returns incorrect gradient for 1/maximum(x)
function. This has been fixed on the latest release of Zygote.
RayTracer.FixedParams
— Type.FixedParams
Any subtype of FixedParams is not optimized using the update!
API. For example, we don't want the screen size to be altered while inverse rendering, this is ensured by wrapping those parameters in a subtype of FixedParams.
RayTracer.bigmul
— Method.bigmul(x)
Returns the output same as typemax
. However, in case gradients are computed, it will return the gradient to be 0
instead of nothing
as in case of typemax.
RayTracer.camera2world
— Method.camera2world(point::Vec3, cameratoworld::Matrix)
Converts a point
in 3D Camera Space to the 3D World Space. To obtain the camera_to_world
matrix use the get_transformation_matrix
function.
RayTracer.extract
— Method.extract(cond, x<:Number)
extract(cond, x<:AbstractArray)
extract(cond, x::Vec3)
Extracts the elements of x
(in case it is an array) for which the indices corresponding to the cond
are true
.
extract
has a performance penalty when used on GPUs.
Example:
julia> using RayTracer;
julia> a = [1.0, 2.0, 3.0, 4.0]
4-element Array{Float64,1}:
1.0
2.0
3.0
4.0
julia> cond = a .< 2.5
4-element BitArray{1}:
1
1
0
0
julia> RayTracer.extract(cond, a)
2-element Array{Float64,1}:
1.0
2.0
RayTracer.place
— Method.place(a::Vec3, cond)
place(a::Array, cond, val = 0)
Constructs a new Vec3
or Array
depending on the type of a
with array length equal to that of cond
filled with zeros (or val). Then it fills the positions corresponding to the true
values of cond
with the values in a
.
The length of each array in a
must be equal to the number of true
values in the cond
array.
Example:
julia> using RayTracer;
julia> a = Vec3(1, 2, 3)
x = 1, y = 2, z = 3
julia> cond = [1, 2, 3] .> 2
3-element BitArray{1}:
0
0
1
julia> RayTracer.place(a, cond)
Vec3 Object
Length = 3
x = [0, 0, 1]
y = [0, 0, 2]
z = [0, 0, 3]
RayTracer.place_idx!
— Method.place_idx!(a::Vec3, b::Vec3, idx)
Number of true
s in idx
must be equal to the number of elements in b
.
This function involves mutation of arrays. Since the version of Zygote we use does not support mutation we specify a custom adjoint for this function.
Arguments:
a
- The contents of thisVec3
will be updatedb
- The contents ofb
are copied intoa
idx
- The indices ofa
which are updated. This is a BitArray with length ofidx
being equal toa.x
RayTracer.world2camera
— Method.world2camera(point::Vec3, world_to_camera::Matrix)
Converts a point
in 3D World Space to the 3D Camera Space. To obtain the world_to_camera
matrix take the inv
of the output from the get_transformation_matrix
function.
RayTracer.@diffops
— Macro.@diffops MyType::DataType
Generates functions for performing gradient based optimizations on this custom type. 5 functions are generated.
x::MyType + y::MyType
– For Gradient Accumulationx::MyType - y::MyType
– For Gradient Based Updatesx::MyType * η<:Real
– For Multiplication of the Learning Rate with Gradientη<:Real * x::MyType
– For Multiplication of the Learning Rate with Gradientx::MyType * y::MyType
– Just for the sake of completeness.
Most of these functions do not make semantic sense. For example, adding 2 PointLight
instances do not make sense but in case both of them are gradients, it makes perfect sense to accumulate them in a third PointLight
instance.
RayTracer.get_params
— Function.get_params(x)
Get the parameters from a struct that can be tuned. The output is in the form of an array.
Example:
julia> using RayTracer;
julia> scene = Triangle(Vec3(-1.9f0, 1.6f0, 1.0f0), Vec3(1.0f0, 1.0f0, 0.0f0), Vec3(-0.5f0, -1.0f0, 0.0f0),
Material())
Triangle Object:
Vertex 1 - x = -1.9, y = 1.6, z = 1.0
Vertex 2 - x = 1.0, y = 1.0, z = 0.0
Vertex 3 - x = -0.5, y = -1.0, z = 0.0
Material{Array{Float32,1},Array{Float32,1},Nothing,Nothing,Nothing,Nothing}(x = 1.0, y = 1.0, z = 1.0, x = 1.0, y = 1.0, z = 1.0, x = 1.0, y = 1.0, z = 1.0, Float32[50.0], Float32[0.5], nothing, nothing, nothing, nothing)
julia> RayTracer.get_params(scene)
20-element Array{Float32,1}:
-1.9
1.6
1.0
1.0
1.0
0.0
-0.5
-1.0
0.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
50.0
0.5
RayTracer.set_params!
— Function.set_params!(x, y::AbstractArray)
Sets the tunable parameters of the struct x
. The index of the last element set into the struct is returned as output. This may be used to confirm that the size of the input array was as expected.
Example:
julia> using RayTracer;
julia> scene = Triangle(Vec3(-1.9f0, 1.6f0, 1.0f0), Vec3(1.0f0, 1.0f0, 0.0f0), Vec3(-0.5f0, -1.0f0, 0.0f0),
Material())
Triangle Object:
Vertex 1 - x = -1.9, y = 1.6, z = 1.0
Vertex 2 - x = 1.0, y = 1.0, z = 0.0
Vertex 3 - x = -0.5, y = -1.0, z = 0.0
Material{Array{Float32,1},Array{Float32,1},Nothing,Nothing,Nothing,Nothing}(x = 1.0, y = 1.0, z = 1.0, x = 1.0, y = 1.0, z = 1.0, x = 1.0, y = 1.0, z = 1.0, Float32[50.0], Float32[0.5], nothing, nothing, nothing, nothing)
julia> new_params = collect(1.0f0:20.0f0)
20-element Array{Float32,1}:
1.0
2.0
3.0
4.0
5.0
6.0
7.0
8.0
9.0
10.0
11.0
12.0
13.0
14.0
15.0
16.0
17.0
18.0
19.0
20.0
julia> RayTracer.set_params!(scene, new_params);
julia> scene
Triangle Object:
Vertex 1 - x = 1.0, y = 2.0, z = 3.0
Vertex 2 - x = 4.0, y = 5.0, z = 6.0
Vertex 3 - x = 7.0, y = 8.0, z = 9.0
Material{Array{Float32,1},Array{Float32,1},Nothing,Nothing,Nothing,Nothing}(x = 10.0, y = 11.0, z = 12.0, x = 13.0, y = 14.0, z = 15.0, x = 16.0, y = 17.0, z = 18.0, Float32[19.0], Float32[20.0], nothing, nothing, nothing, nothing)