Saltar al contenido

Tabla de equivalencias con GLSL

La traducción completa de tipos, operadores, funciones integradas, constantes y accesores, para convertir cualquier GLSL que ya conozcas.

Tipos y construcción

GLSL TSL Nota
float x = 1.0; float( 1 ) también const x = float( 1 ).toVar()
int, uint, bool int(), uint(), bool()
vec2, vec3, vec4 vec2(), vec3(), vec4()
ivec3, uvec3, bvec3 ivec3(), uvec3(), bvec3() y sus versiones de 2 y 4
mat2, mat3, mat4 mat2(), mat3(), mat4()
sin equivalente color( 0xff8800 ) atajo para colores, admite hexadecimal
float y = x; (conversión) x.toFloat() también toVec3(), toMat4(), toInt()…

El swizzling funciona como propiedades del nodo y admite las tres nomenclaturas de GLSL:

JS
p.x        p.xy      p.xyz     p.wzyxc.r        c.rgb     c.bgrt.s        t.stp

Y hay dos familias de métodos que GLSL no tiene:

JS
p.setX( 1 );        // devuelve un nodo con la componente sustituidap.setXY( vec2() );  // idem para varias componentesp.flipY();          // invierte el signo de una componente

Para acceder a elementos de un array hay índice directo, de 0 a 31, y el método general:

JS
const a = miArray[ 3 ];const b = miArray.element( indiceNodo );   // el indice puede ser un nodo

Operadores

GLSL TSL funcional TSL encadenado
a + b add( a, b ) a.add( b )
a - b sub( a, b ) a.sub( b )
a * b mul( a, b ) a.mul( b )
a / b div( a, b ) a.div( b )
a % b mod( a, b ) a.mod( b )
-a negate( a ) a.negate()
a += b — a.addAssign( b )
a *= b — a.mulAssign( b )
a == b equal( a, b ) a.equal( b )
a != b notEqual( a, b ) a.notEqual( b )
a < b lessThan( a, b ) a.lessThan( b )
a > b greaterThan( a, b ) a.greaterThan( b )
a <= b lessThanEqual( a, b ) a.lessThanEqual( b )
a >= b greaterThanEqual( a, b ) a.greaterThanEqual( b )
a && b and( a, b ) a.and( b )
a || b or( a, b ) a.or( b )
!a not( a ) a.not()
a & b bitAnd( a, b ) a.bitAnd( b )
a | b bitOr( a, b ) a.bitOr( b )
a ^ b bitXor( a, b ) a.bitXor( b )
~a bitNot( a ) a.bitNot()
a << b shiftLeft( a, b ) a.shiftLeft( b )
a >> b shiftRight( a, b ) a.shiftRight( b )
a ? b : c — a.mix( b, c )

add, sub, mul, div, and y or aceptan más de dos argumentos.

Funciones integradas

Casi todas conservan el nombre exacto de GLSL. Estas son las que no:

GLSL TSL
inversesqrt inverseSqrt
faceforward faceForward
dFdx, dFdy dFdx, dFdy (igual, pero solo en fragmento)

Los alias en minúscula inversesqrt y faceforward existen como función, pero no están registrados como métodos encadenados.

Y estas existen en TSL sin equivalente directo en GLSL:

TSL Equivale a
oneMinus( x ) 1.0 - x
reciprocal( x ) 1.0 / x
saturate( x ) clamp( x, 0.0, 1.0 )
lengthSq( v ) dot( v, v )
pow2, pow3, pow4 x*x, x*x*x, x*x*x*x
cbrt( x ) raíz cúbica con signo
difference( a, b ) abs( a - b )
rand( uv ) ruido pseudoaleatorio determinista
mixElement, smoothstepElement, stepElement las versiones con el orden invertido que usan los métodos

El resto se llaman igual: abs, sign, floor, ceil, round, trunc, fract, mod, min, max, clamp, mix, step, smoothstep, length, distance, dot, cross, normalize, reflect, refract, pow, exp, exp2, log, log2, sqrt, sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh, radians, degrees, all, any, fwidth, transpose, determinant, inverse.

atan acepta uno o dos argumentos; con dos hace de atan2, y el generador emite el nombre correcto según el backend.

Constantes

GLSL de Three.js TSL
PI PI
PI2 TWO_PI
PI_HALF HALF_PI
EPSILON EPSILON
sin equivalente INFINITY

PI2 sigue exportándose en TSL pero está marcada como obsoleta desde r181 en favor de TWO_PI.

El entorno del shader

Variables integradas y accesores

Aquí es donde la traducción deja de ser mecánica, porque los nombres cambian y hay más opciones.

GLSL en un shader de Three.js TSL
position positionGeometry o positionLocal
normal normalGeometry o normalLocal
uv uv()
uv1, uv2 uv( 1 ), uv( 2 )
modelMatrix modelWorldMatrix
modelViewMatrix modelViewMatrix
normalMatrix modelNormalMatrix
projectionMatrix cameraProjectionMatrix
viewMatrix cameraViewMatrix
cameraPosition cameraPosition
gl_FragCoord.xy screenCoordinate
gl_VertexID vertexIndex
gl_InstanceID instanceIndex
gl_FrontFacing frontFacing
resolución del viewport screenSize
tiempo (uniforme propio) time

Y hay accesores de posición y normal en varios espacios que en GLSL habría que calcular a mano:

TSL Qué es
positionLocal posición en espacio de objeto, modificable
positionWorld posición en espacio de mundo
positionView posición en espacio de vista
positionViewDirection dirección desde el fragmento a la cámara
normalLocal normal en espacio de objeto
normalView normal en espacio de vista
normalWorld normal en espacio de mundo
normalFlat normal reconstruida por derivadas

positionLocal está definido como positionGeometry convertido en varying, y es el que hay que modificar cuando quieres desplazar vértices. Y normalWorld está definido como normalView.transformDirection( cameraViewMatrix ), que es exactamente el cálculo que harías a mano.

Estructura del shader

GLSL TSL
uniform float x; const x = uniform( 0 )
attribute vec3 a; const a = attribute( 'a', 'vec3' )
varying float v; const v = expr.toVarying( 'v' )
float f( vec3 p ) { ... } const f = Fn( ( [ p ] ) => { ... } )
if / else if / else If( c, fn ).ElseIf( c, fn ).Else( fn )
switch / case / default Switch( v ).Case( n, fn ).Default( fn )
for ( int i = 0; i < n; i++ ) Loop( n, ( { i } ) => { ... } )
break; / continue; Break(); / Continue();
float t = expr; (temporal) const t = expr.toVar()
const float k = 2.0; const k = float( 2 ).toConst()
gl_Position = ... material.positionNode = ...
gl_FragColor = ... material.colorNode = ... u outputNode
discard; .discard() sobre una condición
#define, #ifdef un if normal de JavaScript al construir el grafo

Esa última fila merece una nota: no hay preprocesador y no hace falta. Una variante que en GLSL se resolvería con un #ifdef en TSL se resuelve eligiendo qué nodos montar, con JavaScript corriente, y el shader generado no contiene ninguna rama.

JS
let c = materialColor;if ( config.tinte ) c = mix( c, color( config.tinte ), 0.3 );if ( config.franjas ) c = c.mul( uv().y.mul( 80 ).sin().mul( 0.1 ).add( 0.9 ) );material.colorNode = c;