Optical Interfaces

Every Surface must have an OpticalInterface associated with it to defined the behavior of any ray when it intersects that surface.


Any subclass of OpticalInterface must implement the following:

processintersection(opticalinterface::OpticalInterface{T}, point::SVector{N,T}, normal::SVector{N,T}, incidentray::OpticalRay{T,N}, temperature::T, pressure::T, ::Bool, firstray::Bool = false) -> Tuple{SVector{N,T}, T, T}

See documentation for processintersection for details.

These methods are also commonly implemented, but not essential:

insidematerialid(i::OpticalInterface{T}) -> OpticSim.GlassCat.AbstractGlass
outsidematerialid(i::OpticalInterface{T}) -> OpticSim.GlassCat.AbstractGlass
reflectance(i::OpticalInterface{T}) -> T
transmission(i::OpticalInterface{T}) -> T
NullInterface{T} <: OpticalInterface{T}

Interface which will be ignored totally by any rays, used only in construction of CSG objects.

NullInterface(T = Float64)
FresnelInterface{T} <: OpticalInterface{T}

Interface between two materials with behavior defined according to the Fresnel equations, with a specified reflectance and transmission. Assumes unpolarized light.

FresnelInterface{T}(insidematerial, outsidematerial; reflectance = 0, transmission = 1, interfacemode = ReflectOrTransmit)

The interfacemode can be used to trace rays deterministically. Valid values are defined in the InterfaceMode enum. Reflect means that all values are reflected, Transmit means that all values are transmitted. ReflectOrTransmit will randomly reflect and transmit rays with the distribution given by the reflection and transmission arguments. This is also the default. In all cases the power recorded with the ray is correctly updated. This can be used to fake sequential raytracing. For example a beamsplitter surface may be set to either Reflect or Transmit to switch between the two outgoing ray paths.

ParaxialInterface{T} <: OpticalInterface{T}

Interface describing an idealized planar lens, i.e. one that is thin and with no aberrations.

In general this interface should not be constructed directly, the ParaxialLensEllipse and ParaxialLensRect functions should be used to create a ParaxialLens object directly.

ParaxialInterface(focallength::T, centroid::SVector{3,T}, outsidematerial::Y)
ThinGratingInterface{T} <: OpticalInterface{T}

Interface representing an idealized thin grating. period is in microns, vector should lie in the plane of the surface. Transmission and reflectance can be specified for an arbitrary number of orders up to 10, selected using the maxorder and minorder parameters. If nothing then reflectance is assumed to be 0 and transmission is assumed to be 1.

ThinGratingInterface(vector, period, insidematerial, outsidematerial; maxorder = 1, minorder = -1, reflectance = nothing, transmission = nothing)
HologramInterface{T} <: OpticalInterface{T}

Interface representing a thick hologram (though geometrically thin). The efficiency, η, is calculated using Kogelnik's coupled wave theory so is only valid for the first order. If the zero order is included then it has efficiency 1 - η. Also assumes that the HOE was recorded under similar conditions to the playback conditions, thickness is in microns.

BeatState arguments can be one of ConvergingBeam, DivergingBeam and CollimatedBeam. In the first two cases signalpointordir and referencepointordir are 3D point in global coordinate space. For CollimatedBeam they are normalized direction vectors.

For reference, see:

  • Coupled Wave Theory for Thick Hologram Gratings - H Kogelnik, 1995
  • Sequential and non-sequential simulation of volume holographic gratings - M Kick et al, 2018
HologramInterface(signalpointordir::SVector{3,T}, signalbeamstate::BeamState, referencepointordir::SVector{3,T}, referencebeamstate::BeamState, recordingλ::T, thickness::T, beforematerial, substratematerial, aftermaterial, signalrecordingmaterial, referencerecordingmaterial, RImodulation::T, include0order  = false)
MultiHologramInterface{T} <: OpticalInterface{T}

Interface to represent multiple overlapped HologramInterfaces on a single surface. Each ray randomly selects an interface to use.


The critical behavior of each interface is defined in the processintersection function:

processintersection(opticalinterface::OpticalInterface{T}, point::SVector{N,T}, normal::SVector{N,T}, incidentray::OpticalRay{T,N}, temperature::T, pressure::T, ::Bool, firstray::Bool = false) -> Tuple{SVector{N,T}, T, T}

Processes an intersection of an OpticalRay with an OpticalInterface, distinct behaviors must be implemented for each subclass of OpticalInterface.

point is the 3D intersection point in global space, normal is the surface normal at the intersection point.

If test is true then the behavior of the ray should be deterministic. firstray indicates that this ray is the first segment of the trace and therefore the origin is not offset.

The values returned are the normalized direction of the ray after the intersection, the instantaneous power of the ray after the intersection and the optical path length of the ray up to the intersection.

nothing is returned if the ray should stop here, in order to obtain the correct intensity on the detector through monte carlo integration nothing should be returned proportionally to create the correct power distribution. i.e. If the interface should modulate power to 76% then 24% of calls to this function should return nothing.