General Utilities
List of the General Functions and Types provided by the RayTracer. Most of the other functionalities are built upon these.
RayTracer.FixedParamsRayTracer.Vec3RayTracer.rgbRayTracer.bigmulRayTracer.camera2worldRayTracer.extractRayTracer.get_imageRayTracer.get_paramsRayTracer.placeRayTracer.place_idx!RayTracer.set_params!RayTracer.world2cameraRayTracer.zeroonenormRayTracer.@diffops
Documentation
RayTracer.Vec3 — Type.Vec3This is the central type for RayTracer. All of the other types are defined building upon this.
All the fields of the Vec3 instance contains Arrays. This ensures that we can collect the gradients w.r.t the fields using the Params API of Zygote.
Fields:
xyz
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.dotl2normcrossclampzerosimilaronemaximumminimumnormalizesizegetindex– 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.FixedParamsAny 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.0RayTracer.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 trues 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 thisVec3will be updatedb- The contents ofbare copied intoaidx- The indices ofawhich are updated. This is a BitArray with length ofidxbeing 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::DataTypeGenerates 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.5RayTracer.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)