Close

Write a GLSL POP

Overviewedit

This helps you write shaders for the GLSL POP, GLSL Advanced POP, GLSL Copy POP, and access POPs buffers in GLSL_TOP and GLSL_MAT

The official GLSL documentation can be found at this address. TouchDesigner's main supported version of GLSL is 4.60.

Reading and writing attributesedit

GLSL POPs can either create and write new attributes with the "Create Attributes" page of each POP, or select input attributes to be modified, with the "Output Attributes" parameters, that are then allocated for writing. Unmodified input attributes for the POP from the first input are passed to downstream POP with references and don't use extra memory. See Memory Reduction via References in POP#Some_POP_Features_and_Concepts.

Each attribute is a Shader Storage Buffer Object (SSBO).

Output attributes (including new attributes) are unitialized, and it is up to the shader code to write values, except if "Initialize Output Attributes" is On (default), in that case, for existing attributes, a copy from the input values is performed, and new attributes are filled with the default values from the "Create Attributes" page. This is an extra shader dispatch happening before the custom shader is run, and should be off for performance if the users know all the output values are written to. Reading from unitialized values in downstream POPs can cause unpredictable behavior and crashes.

The "Output Access" menu allows to set up the output attributes to be write-only (writeonly SSBO qualifier) or Read-Write. Read-Write is necessary to perform atomic operations. In that case the output values should be initialized first, either using the toggle parameter, or during the first pass in a multi-pass POP (GLSL POP only).

The input attributes from all inputs are automatically made available for reading.

Number of Threadsedit

See Compute_Shader and Compute Shader for an overview on how threads are arranged in number of dispatches and number of threads per workgroup. The GLSL POPs offer simplified modes as well as full control over the number of threads. In most case one will want one thread to read and write the value for one attribute element (one point, vertex or primitive), which is accomplished with different menu entries depending on the GLSL POP.

Uniformsedit

Uniforms declared with the parameter fields on their respective pages are declared automatically in the shader.

POPs overviewedit

GLSL POPedit

This is the simplest of the GLSL POPs. It allows the user to work on one class of attributes at a time: point, vertex, or primitive attributes.

The only feature present in the GLSL POP and not the GLSL Advanced POP is the ability to run the shader multiple times, with the "Passes" parameter.

All the input attributes are available for reading. For attributes from a different class than the selected class, the functions to access the attributes have a prefix with the attribute class, similarly to the GLSL Advanced POP. For example if working on point attributes, an attribute called "Attrib" can be accessed with TDIn_Attrib() if it's a point attribute, TDInVert_Attrib() if it's a vertex attribute, and TDInPrim_Attrib() if it's a primitive attribute. See below for details.

The index buffer for all inputs is also available for reading, see uint TDInputPointIndex(uint inputIndex, uint vertIndex) below.

  • The "Number of Threads" mode "Auto" creates one thread per element of the selected class, point, vertex, or primitive.
  • "Number of Elements in Other Input" is similar to "Auto" for other inputs.

If the number of elements for the selected class and input is known on the GPU and not on the CPU (see POP#Indirect_POPs_and_Memory_Management), an indirect command buffer is filled, and the compute shader is launched with an indirect dispatch.

  • "Manual Number of Elements" creates threads according to the "Number of Elements" parameter.
  • "Number of Elements" from Attribute create threads according the value of the first element of the POP and attribute specified. In that case the compute shader is launched with an indirect dispatch.

In all those cases, the actual number of threads is the requested number of threads rounded up to the nearest workgroup size, uint TDNumElements() contains the number of requested threads, and uint TDIndex() contains a 1d index.

With the "Manual" mode, the work group size and number of dispatches can be specified in 3 dimensions, in that case TDNumElements() and TDIndex() are undefined and will causes a compile error.

Example shader:

void main() {
	const uint id = TDIndex();
	if(id >= TDNumElements())
		return;
		
	P[id] = TDIn_P(); //same as TDIn_P(0, TDIndex());
}

For P[id] = TDIn_P(); to compile without error, P needs to be present in the input, and selected for writing in "Output Attributes".

TDIn_P() reads the P attribute in input 0 (first input), at element TDIndex(), it is a short hand for TDIn_P(0, id), since id is mapped to TDIndex().

This is written to element id in the output with P[id].

As described above, TDNumElements() is the number of requested threads (one per point in "Auto" mode and with Attribute Class "Point" selected). The actual number of threads is most likely higher, since it is rounded up to the work group size, which is set to 32 for NVIDIA hardware and 64 for AMD hardware. The if condition prevents the shader to write outside of the bounds of the allocated SSBO, which can lead to unpredictible results and crashes.

GLSL Advanced POPedit

The GLSL Advanced POP allows to do what the GLSL POP can with the following differences and additional features:

  • ability to read, write and create all classes of attributes (point, primitive, vertex) in the same shader
  • ability to write to attributes from multiple POPs ("Extra Outputs" page). The modified outputs can be selected with the GLSL Select POP.
  • ability to modify the number of points and primitives ("Output" page)
  • ability to write to index buffer
  • additional "Per Primitive Batch" Shader Dispatch Mode, which runs the shader once per primitive batch present in the first input.

All the primitives of the same type (Triangles, Quads, Line Strips, Lines, Point Primitives) are grouped together in the index buffer for processing and rendering efficiency. When working with multiple primitive types it can be advantageous to dispatch the shader once per primitive type, since in that case some variables are constants and the users knows all the primitives are the same type without extra if() conditions.

When working with primitives the GLSL Advanced POP allows to set the number of primitives from each type, using the parameters or attributes, but it can also be convenient to use a Topology POP to combine the result of multiple GLSL Advanced POPs (it is often advantageous to have one shader per attribute class) and set the topology info.

Example shader:

void main() {
	const uint id = TDIndex();
	if(id >= TDNumElements())
		return;
		
	oTDPoint_P[id] = TDInPoint_P(); //same as TDInPoint_P(0, TDIndex());
}

Basic shader reading the input P attribute and writing it unmodified to the output. Note the extra "Point" prefix to differentiate the class of the attribute, since there is attributes with the same name can exist in different attribute classes.

Here's a code snippet showing how to iterate on all the points of a primitive:

for (int i = 0; i < TDInputNumVertsPerPrim(); i++)
{
	uint vertId = TDInputPrimVertsStartIndex() + i;
	uint pointId = TDInputPointIndex(0, vertId);
}

When the number of output points is changed, references to unchanged input point attributes are not created anymore, since there would be a mismatch between the number of points in the existing attribute buffers and the new number of points. It is left to the user to manually update the attributes, for existing and new points. Similarly, when vertices or primitives numbers are changed, references to unchanged input vertices and primitives attributes are not created anymore.

GLSL Copy POPedit

The GLSL Copy POP allows to run custom GLSL code on each copy. All the copies are limited to have the same topology though, similar to the Copy POP. Also similar to the copy POP a template input is available. There are no other inputs so other POP attributes need to be accessed using the "POP Buffers" page and the TDBuffer() function, similar to GLSL TOP and MAT, see below.

Similar to how the Copy POP works internally, one compute shader is dispatched to update the points, one for the vertices, and one for the primitives.

By default, only the points run a custom shader, while vertices and primitives only copy input attributes to all copies.

However it is also possible to have a custom shader for the vertices and for the primitives.

Example Point shader:

void main() {
	const uint id = TDIndex();
	if(id >= TDNumPoints())
		return;
		
	//TDInputNumPoints(): number of points on input geo
	//TDInputPointIndex(), TDInputIndex(): point id matching current point id on input
	//TDCopyIndex(): copy number
	
	//TDTemplate_Attrib() functions to sample template input attributes

	//P[id] = TDIn_P() + TDTemplate_P();
	//same as P[id] = TDIn_P(TDInputPointIndex()) + TDTemplate_P(TDCopyIndex());

	P[id] =  TDIn_P() + TDCopyIndex() * vec3(0.5, 0, 0);
	
	//updates existing point groups if any
	TDUpdatePointGroups();
}

One thread is executed per output point, meaning TDIndex() is the output point index. The TDInputPointIndex() refers to the index of the input point matching the current output point. TDIn_P() with no attribute reads TDInputPointIndex() since we assume we want to read from the matching original point in the input. TDCopyIndex() is the current copy index. TDTemplate_P() reads P from the template input at the copy index location when no argument are provided. TDUpdatePointGroups() is a helper function to update any point group that was on the input: in each copy points that were part of a group in the input will be part of the same group.

Built-in functions and constantsedit

Number of Elements and Indexingedit

GLSL POP, and GLSL Advanced POP single dispatch mode and per batch mode

 uint TDNumElements();
 
 //number of requested threads based on dispatch mode and number of threads mode (so depending on mode sometimes = TDInputNumPoints() etc)
 //(actual number of threads is ceil of workgroup size 32 on nvidia)
 //undefined when number of threads is manual and user chooses workgroup size and number of workgroup dispatches
 uint TDIndex();
 
 //1d index for current thread
 //undefined when number of threads is manual
uint TDInputNumPoints(uint inputIndex); //number of points in inputIndex input
uint TDInputNumPrims(uint inputIndex); //number of prims in inputIndex input
uint TDInputNumVerts(uint inputIndex); //number of verts in inputIndex input

//returns 0 if input doesn't exist
TDInputNumPoints() = TDInputNumPoints(0);
TDInputNumPrims() = TDInputNumPrims(0);
TDInputNumVerts() = TDInputNumVerts(0);
//if no input index argument is specified it returns values for input 0

GLSL POP only:

uint TDInputNumElements(); //wrapper for TDInputNumPoints() or TDInputNumPrims() or TDInputNumVerts() depending on attribute class

Index Buffer Accessedit

Read Accessedit

uint TDInputPointIndex(uint inputIndex, uint vertIndex); //index buffer access with bounds checking
uint TDInputPointIndex(uint vertIndex) = TDInputPointIndex(0, uint vertIndex);

Write Accessedit

Only enabled in the GLSL Advanced POP when one of the Max Primitives parameter is set to custom.

uint I[]; //array variable

Attribute Access:edit

All the attributes from the inputs are bound and available for reading.

Attributes added to the “Output Attributes” param or attributes created in the POP are allocated and can be written to.

A reference to the input attributes from the first input is created for the other attributes, similar to unmodified attributes in the other POPs ((r) in info panel)

GLSL POP:edit

Input Attributesedit
attribType TDIn_AttribName(uint inputIndex, uint elementId, uint arrayIndex) //to access input inputIndex AttribName

TDIn_AttribName() = TDIn_AttribName(0, TDIndex(), 0); //if no argument is specified it returns the value at elementId for input 0, at arrayIndex 0 if attribute is an array attribute
TDIn_AttribName(uint inputIndex, uint elementId) = TDIn_AttribName(inputIndex, elementId, 0); arrayIndex is optional and defaults to 0

//this performs bounds checking, return last elements if outside of bounds, last arrayIndex if arrayIndex is out of bounds

attribType TDInCache_AttribName(uint inputIndex, uint cacheIndex, uint elemId, uint arrayIndex); //to access frames cached with cache POPs, arrayIndex is optional
Input Attributes From Non Selected Attribute Classedit
  • If the attribute class is Point, Vertex and Primitive attributes can be accessed with TDInVert_AttribName() and TDInPrim_AttribName().
  • If the attribute class is Vertex, Point and Primitive attributes can be accessed with TDInPoint_AttribName() and TDInPrim_AttribName().
  • If the attribute class is Primitive, Point and Vertex attributes can be accessed with TDInPoint_AttribName() and TDInVert_AttribName().
attribType TDInPoint_AttribName(uint inputIndex, uint pointId, uint arrayIndex);
attribType TDInPrim_AttribName(uint inputIndex, uint primId, uint arrayIndex);
attribType TDInVert_AttribName(uint inputIndex, uint vertId, uint arrayIndex);
attribType TDInCachePoint_AttribName(uint inputIndex, uint cacheIndex, uint elemId, uint arrayIndex);
attribType TDInCacheVert_AttribName(uint inputIndex, uint cacheIndex, uint elemId, uint arrayIndex);
attribType TDInCachePrim_AttribName(uint inputIndex, uint cacheIndex, uint elemId, uint arrayIndex);
Output Attributesedit
attribType AttribName[]; //output variable, no function to allow use in atomic functions (AtomicAdd, etc)
Attribute Array Sizeedit
const uint cTDArraySize_Attrib;

GLSL Advanced POP:edit

Similar to GLSL POP with extra attribute class prefix in function names.

Input Attributesedit
attribType TDInPoint_AttribName(uint inputIndex, uint pointId, uint arrayIndex);
attribType TDInPrim_AttribName(uint inputIndex, uint primId, uint arrayIndex);
attribType TDInVert_AttribName(uint inputIndex, uint vertId, uint arrayIndex);

//similar to GLSL POP function for point, prim, vert attribute
attribType TDInCachePoint_AttribName(uint inputIndex, uint cacheIndex, uint elemId, uint arrayIndex);
attribType TDInCacheVert_AttribName(uint inputIndex, uint cacheIndex, uint elemId, uint arrayIndex);
attribType TDInCachePrim_AttribName(uint inputIndex, uint cacheIndex, uint elemId, uint arrayIndex);
Output Attributesedit
attribType oTDPoint_AttribName[];
attribType oTDPrim_AttribName[];
attribType oTDVert_AttribName[];

//output variable for point, prim, vert attributes
Attribute Array Sizeedit
const uint cTDArraySizePoint_Attrib;
const uint cTDArraySizePrim_Attrib;
const uint cTDArraySizeVert_Attrib;

GLSL Advanced POP Extra outputs:edit

Similar to GLSL Advanced POP, except the extra output names are part of the functions, instead of them being access by an index.

Number of Elements in Inputedit

uint TDInputNumPoints_OutputName();
uint TDInputNumPrims_OutputName();
uint TDInputNumVerts_OutputName();

Input Attributesedit

attribType TDInPoint_OutputName_AttribName(uint pointId, uint arrayIndex);
attribType TDInPrim_OutputName_AttribName(uint primId, uint arrayIndex);
attribType TDInVert_OutputName_AttribName(uint vertId, uint arrayIndex);

Output Attributesedit

attribType oTDPoint_OutputName_AttribName[];
attribType oTDPrim_OutputName_AttribName[];
attribType oTDVert_OutputName_AttribName[];
Attribute Array Sizeedit
const uint cTDArraySizePoint_OutputName_Attrib;
const uint cTDArraySizePrim_OutputName_Attrib;
const uint cTDArraySizeVert_OutputName_Attrib;

Index Bufferedit

uint TDInputPointIndex_OuputName(uint vertIndex);

GLSL Copy POP:edit

Number of Elements and Indexingedit

Point shaderedit

One thread per output point

uint TDNumPoints(); //number of output points
uint TDInputNumPoints(); //number of input points
Vertex shaderedit

One thread per output vert in current primitive batch

uint TDNumVertsBatch(); //number of output verts in current primitive batch
uint TDInputNumVertsBatch(); //number of input verts in current primitive batch
uint TDInputNumVerts(); //total number of input verts
uint TDVertIndex(); //current global vert index
Primitive shaderedit

One thread per output prim in current primitive batch

uint TDNumPrimsBatch(); //number of output prims in current primitive batch
uint TDInputNumPrimsBatch(); //number of input prims in current primitive batch
uint TDInputNumPrims(); //total number of input prims
uint TDPrimIndex();  //current global prim index
All GLSL Copy POP shadersedit
TDInputIndex(); //index matching the input (source) point/prim/vert
TDCopyIndex(); //current copy index
TDTemplateNumPoints(); //number of poinst in template input

Attribute Access:edit

Source input:edit
attribType TDIn_AttribName(uint elementId, uint arrayIndex);
TDIn_AttribName(uint elementId) = TDIn_AttribName(elementId, 0); //arrayIndex is optional and defaults to 0
TDIn_AttribName() = TDIn_AttribName(TDInputIndex(), 0); //if no argument is specified it returns the value for element at TDInputIndex()

const uint cTDArraySize_Attrib; //constant with size of array for array attributes
Template input:edit
attribType TDTemplate_AttribName(uint elementId, uint arrayIndex);
TDTemplate_AttribName(uint elementId) = TDTemplate_AttribName(elementId, 0);
TDTemplate_AttribName() = TDTemplate_AttribName(TDCopyIndex(), 0); //if no argument is specified it returns the value for the point at TDCopyIndex()

const uint cTDTemplateArraySize_Attrib; //constant with size of array for array attributes
Other POP attribute access:edit

Since the GLSL Copy POP doesn't have other inputs, other POP attributes can be accessed with the TDBuffer() function and related constants, see Write_GLSL_POPs#GLSL_TOP_and_MAT:_POP_attribute_access

Output Attributesedit
attribType AttribName[]; //output variable, no function to allow use in atomic functions (AtomicAdd, etc)

Misc Functionsedit

  • Point Shader:
void TDUpdatePointGroups(); //updates existing point groups if any
  • Vertex Shader:
void TDUpdateTopology(); //updates topology (index buffer and line strip index buffer for line strips)
  • Primitive Shader
void TDUpdateLineStripsInfo(); //updates topology (line strips info buffer)

void TDUpdatePrimGroups(); //updates existing prim groups if any

Primitive restart index for line stripsedit

The maximum unsigned value, 0xFFFFFFFF in 32bits

const uint cTDPrimIndexRestart;

Dimension info and helper functionsedit

GLSL POP and GLSL Advanced POP only

const uint cTDDimSizeN; //constant that holds the number of dimensions for input N
uint[cTDDimSizeN] TDDimensionN(); //returns an array with the dimensions for input N
uint[cTDDimSizeN] TDDimCoordsN(uint pointIndex); //returns an array with the coordinates of pointIndex relative to dimensions for input N: matches _DimI[] built-in attribute
uint TDDimPointIndexN(uint[cTDDimSizeN] coords); //returns the point index at coordinates coords for input N

For convenience, if N is not included, the constant and functions refer to the first input

const uint cTDDimSize;
uint[cTDDimSize] TDDimension();
uint[cTDDimSize] TDDimCoords(uint pointIndex);
uint TDDimPointIndex(uint[cTDDimSize] coords);

The functions are also available for the inputs of the extra outputs in the GLSL Advanced POP:

const uint cTDDimSize_OutputName;
uint[cTDDimSize_OutputName] TDDimension_OutputName();
uint[cTDDimSize_OutputName] TDDimCoords_OutputName(uint pointIndex);
uint TDDimPointIndex_OutputName(uint[cTDDimSize_OutputName] coords);

Primitive Batches info and built-in attributes equivalentedit

GLSL POP, and GLSL Advanced POPedit

(for per primitive batch dispatch mode, only useful for secondary inputs)

uint TDInputPrimIndex(uint vertIndex);

//The index of the primitive vertIndex vertex is part of.
//This matches builtin attribute _PrimI run on vertices.
//This also matches Line Strip Index on Line Metrics for Line Strips
uint TDInputVertPrimIndex(uint vertIndex);

//the index of vertIndex vertex in the current primitive (goes from 0 to numVertsPerPrim - 1)
//this matches builtin attribute _VertPrimI run on vertices.
uint TDInputPrimType(uint primIndex); //primitive type for primIndex primitive
uint TDInputPrimType_Vert(uint vertIndex); //primitive type for the primitive vertIndex is part of

//Primitive types:

const uint cTDTrianglesType = 0;
const uint cTDQuadsType = 1;
const uint cTDLineStripsType = 2;
const uint cTDLinesType  = 3;
const uint cTDPointPrimsType  = 4;
uint TDInputNumVertsPerPrim(uint inputIndex, uint primIndex);

//the number of vertices in primIndex primitive in input inputIndex
//this matches builtin attribute _NumVertsPerPrim run on primitives
uint TDInputNumVertsPerPrimFromVert(uint inputIndex, uint vertIndex);

//the number of vertices of the primitive vertIndex vertex is part of in input inputIndex
//this matches builtin attribute _NumVertsPerPrim run on vertices
//this also matches Number of Verts in Line Metrics
	
For line strips this doesn't include the restart index at the end of the line strip
uint TDInputPrimVertsStartIndex(uint inputIndex, uint primIndex); //the index of the first vertex for primIndex primitive in input inputIndex
uint TDInputPrimsStartIndex(uint inputIndex, uint primType); //index of first input primitive in primType primitive batch
uint TDInputVertsStartIndex(uint inputIndex, uint primType); //index of first input vertex in primType primitive batch

For the above, if only one argument is specified, inputIndex = 0.

For GLSL POP, extra functions with no argument are wrapping some of the above as follow:

  • run on vertices:
TDInputPrimIndex() = TDInputPrimIndex(TDIndex());
TDInputPrimType() = TDInputPrimType_Vert(TDIndex());
TDInputNumVertsPerPrim() = TDInputNumVertsPerPrim_Vert(TDIndex());
TDInputVertPrimIndex() = TDInputVertPrimIndex(TDIndex());
  • run on primitives
TDInputPrimIndex() = TDIndex();
TDInputPrimType() = TDInputPrimType(TDIndex());
TDInputNumVertsPerPrim() = TDInputNumVertsPerPrim(TDIndex());
TDInputPrimVertsStartIndex() = TDInputPrimVertsStartIndex(TDIndex());

These have "Input" in their names because GLSL Advanced POP can have a different output, and to have the same functions for GLSL POP and GLSL Advanced POP. The functions for the output are currently not defined for GLSL Advanced POP single dispatch mode.

GLSL Advanced POP per primitive batch dispatch mode:edit

uint TDInputPrimIndex();

//for primitives : index of current input primitive (TDInputPrimsStartIndex() + TDIndex())
//for vertices : index of primitive the current vertex is part of
uint TDInputNumVertsPerPrim();

//for primitives : number of verts of current input primitive
//for vertices : number of verts of primtive the current vertex is part of
uint TDInputPrimType();

//for primitives : primitive type of current input primitive (constant over batch)
//for vertices : primitive type of primitive the current vertex is part of (constant over batch)
uint TDInputPrimVertsStartIndex(); //primitives only: the index of the first vertex for the current input primitive
uint TDInputVertPrimIndex(); //vertices only: the index of the current vertex in the input primitive (goes from 0 to numVertsPerPrim - 1)
	
uint TDInputPrimsStartIndex(); //index of first input primitive in current primitive batch
uint TDPrimsStartIndex(); //index of first output primitive in current primitive batch

uint TDInputVertsStartIndex(); //index of first input vertex in current primitive batch
uint TDVertsStartIndex(); //index of first output vertex in current primitive batch

uint TDInputNumPrimsBatch(); //number of input primitives in current primitives batch
uint TDNumPrimsBatch(); //number of output primitives in current primitives batch

uint TDInputNumVertsBatch(); //number of input verts in current primitives batch
uint TDNumVertsBatch(); //number of output verts in current primitives batch

GLSL POPs Helper functionsedit

Common Functions on the Write a GLSL material page Write_a_GLSL_Material#Common_Functions

Math Functionsedit

// TDMath

// Creates a rotation matrix that rotates starting from looking down +Z, to the 'forward' vector direction.
// The 'forward' and 'up' vectors passed to this function do not need to be normalized.
mat3 TDRotateToVector(vec3 forward, vec3 up);

// Creates a rotation matrix that rotates around the 'axis', the given number of 'radians'
// The 'axis' vector must already be normalized before being passed to this function.
mat3 TDRotateOnAxis(float radians, vec3 axis);

// Creates a rotation matrix that rotates around the +X, +Y and +Z axis repectively.
mat3 TDRotateX(float radians);
mat3 TDRotateY(float radians);
mat3 TDRotateZ(float radians);

// Creates a scale matrix for the given 3 scale values.
mat3 TDScale(float x, float y, float z);

// Creates a translation matrix for the given 3 translation values.
mat4 TDTranslate(float x, float y, float z);

// A function that gives a half-sine ramp from 0 to 1.
// Sampling it with a coordinate outside the (0, 1) range will return 0 for anything below 0 and 1 for anything above 1.
// It's possibly faster than using the GLSL sin() function, depending on the hardware.
float TDSineLookup(float v);

// Creates a rotation matrix to rotate from vector 'from' to vector 'to'. The solution isn't particularly stable, but useful in some cases.
// The 'from' and 'to' vectors must already be normalized before being passed to this function.
mat3 TDCreateRotMatrix(vec3 from, vec3 to);

// Takes a surface normal, the tangent to the surface, and a handedness value (either -1 or 1)
// Returns a matrix that will convert vectors from tangent space, to the space the normal and tangent are in
// Both the normal and the tangent must be normalized before this function is called.
// The w coordinate of the T attribute created by the [[Attribute Create SOP]] contains the handedness
// that should be passed in as-is.
mat3 TDCreateTBNMatrix(vec3 N, vec3 T, float handedness);

// Converts between RGB and HSV color space
vec3 TDRGBToHSV(vec3 c);
vec3 TDHSVToRGB(vec3 c);

// Converts a 0-1 equirectangular texture coordinate into cubemap coordinates.
// A 0 for the U coordinate corresponds to the middle of the +X face. So along the vec3(1, Y, 0) plane.
// As U rises, equirectangular coordinates rotate from +X, to +Z, then -X and -Z.vec3 TDEquirectangularToCubeMap(vec2 mapCoord);
vec3 TDEquirectangularToCubeMap(vec2 mapCoord);

// Converts from cubemap coordinates to equirectangular
// cubemapCoord MUST be normalized before calling this function.
vec2 TDCubeMapToEquirectangular(vec3 envMapCoord)

// Available in builds 2019.18140
// This version will also output a mipmap bias float. This float should be passed in the 'bias'
// parameter of texture(), to help select the mipmap level. This helps avoids seams at the edge
// of equirectangular map.
vec2 TDCubeMapToEquirectangular(vec3 envMapCoord, out float mipMapBias)

// Converts from RGB to monochrome using the standard weights of luminance (0.2126, 0.7152, 0.0722)
float TDLuminance(vec3 c);

// Returns a looping value between low and high
float TDLoop(float val, float low, float high);
// Returns a value that zigzags between low and high
float TDZigZag(float val, float low, float high);
// Returns the average between the two values.
float TDAverage(float valA, float valB);

// Like the remap feature in the Math CHOP, will remap 'value' frmo thew range [low1, high1] to the range [low2, high2].
float TDRemap(float value, float low1, float high1, float low2, float high2);
vec2 TDRemap(vec2 value, vec2 low1, vec2 high1, vec2 low2, vec2 high2);
vec3 TDRemap(vec3 value, vec3 low1, vec3 high1, vec3 low2, vec3 high2);
vec4 TDRemap(vec4 value, vec4 low1, vec4 high1, vec4 low2, vec4 high2);

// Triplanar blend function. Blends between the 3 orthogonal color values weighted by the normal vector. <code>blendPower</code> argument is the exponent taken by the weight function to control the falloff.
vec4 TDTriplanarBlend(vec3 normal, vec4 xcolor, vec4 ycolor, vec4 zcolor, int blendPower);

// Performs Tricubic and bicubic sampling/interlolation on the given sampler.
// texSize and invTexSize should be the resolution and 1.0 / resolution of the texture.
vec4 TDBicubicInterpolation(sampler2D tex, vec2 texCoord, vec2 texSize, vec2 invTexSize);
vec4 TDBicubicInterpolation(sampler2D tex, vec2 texCoord);
vec4 TDTricubicInterpolation(sampler3D tex, vec3 texCoord, vec3 texSize, vec3 invTexSize);
vec4 TDTricubicInterpolation(sampler3D tex, vec3 texCoord);

// Generate 2D coordinates to look up into a sphere-map from 3D environment coordinates.
vec2 TDTexGenSphere(vec3 envMapCoord);
// TDQuaternionMath
// Builds a quaternion representing a rotation around an axis, using an angle in radians.
vec4 TDAxisAngleToQuaternion(vec3 axis, float angle) ;
// Builds a 3×3 rotation matrix from a quaternion.
mat3 TDQuaternionToRotMatrix(vec4 q);
// Extracts a quaternion representing the rotation of a 3×3 matrix.
vec4 TDRotMatrixToQuaternion(mat3 rotMat);
// Rotates a vector or a point using a quaternion rotation.
vec3 TDRotateFromQuaternion(vec3 v, vec4 q);
// Combines two quaternions to apply their rotations sequentially.
vec4 TDQuaternionMultiply(vec4 Q1, vec4 Q2);
// Performs spherical linear interpolation between two quaternions.
vec4 TDSlerpQuaternions(vec4 q0, vec4 q1, float t);
// Extracts the pure rotation component from a 4×4 transform matrix.
mat3 TDExtractRotation(mat4 m);
// Interpolates smoothly between two rotation matrices via quaternion slerp.
mat3 TDSlerpRotationMatrices(mat3 m0, mat3 m1, float t);
// Interpolates translation, rotation, and scale between two transform matrices.
mat4 TDInterpolateTransformMatrices(mat4 m0, mat4 m1, float t);
// Computes the quaternion that rotates one vector direction into another.
vec4 TDQuaternionFromTo(vec3 from, vec3 to);

Noise Functionsedit

// Returns <code>t*t*t*(t*(t*6.0-15.0)+10.0);</code>.
float TDFade(float t);

// Perlin 2D,3D,4D noise functions
float TDPerlinNoise(vec2 P);
float TDPerlinNoise(vec3 P);
float TDPerlinNoise(vec4 P);

// Simplex 2D,3D,4D noise functions
float TDSimplexNoise(vec2 P);
float TDSimplexNoise(vec3 P);
float TDSimplexNoise(vec4 P);

// Derivative of the TDFade() function. Returns <code>30*t*t*(t*(t-2)+1)</code>
float TDFadeDeriv(float t);

// Gradients of the TDPerlinNoise() functions. The gradient is an analytical derivative, calculated in the noise space.
vec4 TDPerlinNoiseDeriv(vec2 P);
vec4 TDPerlinNoiseDeriv(vec3 P);
vec4 TDPerlinNoiseDeriv(vec4 P, out float outNoise);
vec4 TDPerlinNoiseDeriv(vec4 P);

// Gradients of the TDSimplexNoise() functions. The gradient is an analytical derivative, calculated in the noise space.
vec4 TDSimplexNoiseDeriv(vec2 P);
vec4 TDSimplexNoiseDeriv(vec3 P);
vec4 TDSimplexNoiseDeriv(vec4 P, out float outNoise);
vec4 TDSimplexNoiseDeriv(vec4 P);

Color Space Functionsedit

The TDTransfer* functions will convert between a linear and non-linear transfer for the color data. If a vec4 is provided then the RGB will be un-premultipled by Alpha before applying the operation, and then then mulitpled by alpha again at the end.

// TDBasicColorSpace
vec3 TDTransferLinearToSRGB(vec3 c);
vec4 TDTransferLinearToSRGB(vec4 c);

vec3 TDTransferSRGBToLinear(vec3 c);
vec4 TDTransferSRGBToLinear(vec4 c);

// TDColorSpace
vec3 TDTransferLinearToRec709(vec3 c);
vec3 TDTransferRec709ToLinear(vec3 c);

vec3 TDTransferLinearToGamma1_8(vec3 c);
vec3 TDTransferLinearToGamma2_2(vec3 c);
vec3 TDTransferLinearToGamma2_4(vec3 c);
vec3 TDTransferLinearToGamma2_6(vec3 c);
vec3 TDTransferLinearToGamma2_8(vec3 c);

vec3 TDTransferACESproxyToLinear(vec3 c);
vec3 TDTransferLinearToACESproxy(vec3 c);

vec3 TDTransferGamma1_8ToLinear(vec3 c);
vec3 TDTransferGamma2_2ToLinear(vec3 c);
vec3 TDTransferGamma2_4ToLinear(vec3 c);
vec3 TDTransferGamma2_6ToLinear(vec3 c);
vec3 TDTransferGamma2_8ToLinear(vec3 c);

// referenceWhiteNits denotes what brightness in nits a value of 1.0 will be for the linear data.
vec3 TDTransferLinearToST2084PQ(vec3 color, float referenceWhiteNits);
vec3 TDTransferST2084PQToLinear(vec3 color, float referenceWhiteNits);

vec3 TDTransferBT2100HLGToLinear(vec3 color, float peakNits, float referenceWhiteNits);
vec3 TDTransferLinearToBT2100HLG(vec3 color, float peakNits, float referenceWhiteNits);

vec3 TDGamutRec709ToRec2020(vec3 c);
vec3 TDGamutRec2020ToRec709(vec3 c);