⌘ REFERENCIA · 202 elementos
Cheatsheet de Three.js y 3D
De la matriz al shader en un solo sitio: geometría, materiales, luz, assets, shaders, TSL y producción. Busca por API o por lo que quieres conseguir.
🧊 Escena, cámara y bucle 11
La raíz del árbol y el entorno globalTHREE.Scene
Cuatro números describen el volumen visiblePerspectiveCamera(fov, aspect, near, far)
Uno por aplicación: el contexto es un recurso escasoWebGLRenderer({ antialias })
Tamaño CSS y densidad son cosas distintassetSize() · setPixelRatio()
El bucle correcto; con null se parasetAnimationLoop(fn)
Sustituye a Clock, obsoleto desde r183THREE.Timer
Una vez por fotograma, antes de consultar nadatimer.update(t)
Consultas puras: mismo valor durante todo el framegetDelta() · getElapsed()
No contar el tiempo con la pestaña ocultatimer.connect(document)
Obligatorio si cuelgas algo de la cámarascene.add(camera)
Pintar todo en alambre y ver dónde fallascene.overrideMaterial
📐 Espacios y matrices 12
Donde vive el atributo position: reutilizableEspacio de modelo
El único compartido: física, distancias, audioEspacio de mundo
La cámara en el origen para simplificar la proyecciónEspacio de vista
Recortar antes de dividir por w, que puede ser ceroEspacio de recorte
Cubo unitario; la Z va de -1 a 1 en WebGL y de 0 a 1 en WebGPUNDC
La transformación acumulada desde la raízobject.matrixWorld
Modelo y vista ya combinadas, por objeto y por framemodelViewMatrix
Traspuesta de la inversa; lleva a espacio de vistanormalMatrix
Construirla desde cualquier Matrix4getNormalMatrix()
El único caso donde la normal mal transformada se veEscala no uniforme
Sin gimbal lock y con el camino más cortoQuaternion · slerp()
Forzarla antes de leer una posición globalupdateMatrixWorld()
🎥 Cámaras y frustum 12
Campo de visión vertical, en gradoscamera.fov
Ancho entre alto; si miente, la escena se estiracamera.aspect
Nada cambia hasta que la llamasupdateProjectionMatrix()
Fuera de ese rango no se dibuja nadanear y far
Casi siempre culpa de un near demasiado pequeñoz-fighting
Se guarda como el inverso de la distanciaLa profundidad no es lineal
Sin perspectiva: left, right, top, bottom y zoomOrthographicCamera
Los seis planos, para probar visibilidad a manoTHREE.Frustum
A false si deformas la geometría en el vertex shaderobject.frustumCulled
Varias vistas con viewport propio en una pasadaArrayCamera
Qué capas entran en esta vistacamera.layers
Con damping hay que llamar a update() cada frameOrbitControls + damping
🧱 BufferGeometry y atributos 12
Un array tipado y cuántos números por vérticeBufferAttribute(array, itemSize)
Los tres atributos que los materiales dan por hechosposition · normal · uv
El segundo juego de UV, el que piden aoMap y lightMapuv1
Reutilizar vértices: menos memoria y menos vertex shadersetIndex()
Sin esa bandera el cambio no sube a la GPUattribute.needsUpdate
Promedia por vértice: superficie suavecomputeVertexNormals()
Un cubo suave necesita 24 vértices, no 8Normales duras
El orden de los tres vértices decide qué cara es la de fueraWinding order
Dibujar solo un tramo sin tocar los bufferssetDrawRange()
Lo que consultan el culling y el raycastcomputeBoundingSphere()
Soldar duplicados; vive en BufferGeometryUtilsmergeVertices()
Lo único que borra el buffer del drivergeometry.dispose()
🧬 Instancing y lotes 10
Una geometría, miles de copias, un draw callInstancedMesh(geo, mat, count)
La transformación de cada instanciasetMatrixAt(i, matriz)
El paso que todo el mundo olvida la primera vezinstanceMatrix.needsUpdate
Crea instanceColor al vuelo; sin canal alfasetColorAt(i, color)
Tus propios datos por instanciaInstancedBufferAttribute
InstancedMesh se descarta entero o no se descartaEl culling que se pierde
Geometrías distintas, un material, un dibujo múltipleBatchedMesh
Dos identificadores distintos; confundirlos fallaaddGeometry() y addInstance()
Descarte por instancia, lo que InstancedMesh no daperObjectFrustumCulled
Ordena por profundidad: transparencias que sí mezclansortObjects
🎨 Materiales 13
Color plano: ignora la luz por completoMeshBasicMaterial
Pinta la normal; el mejor para descartar problemas de luzMeshNormalMaterial
Solo difuso y barato; el especular no existeMeshLambertMaterial
Especular empírico con shininess, sin base físicaMeshPhongMaterial
PBR metallic-roughness: el material por defectoMeshStandardMaterial
Standard más capas; cada una cuestaMeshPhysicalMaterial
Cuantiza la difusa con un gradientMapMeshToonMaterial
Profundidad: es lo que dibuja el mapa de sombrasMeshDepthMaterial
Qué caras se dibujan; el doble duplica el fragmentside · DoubleSide
Saca el objeto del bloque opaco y lo ordena apartetransparent · opacity
Recorte duro sin entrar en la cola de transparentesalphaTest
Normal por cara sin tocar la geometríaflatShading
Usar el atributo color de la geometríavertexColors
⚪ PBR y capas físicas 14
En la realidad es binario: 0 o 1, casi nunca en mediometalness
Cómo de disperso es el reflejo, no cómo de oscuroroughness
Lo que refleja el especular se lo quita al difusoConservación de energía
Reflectancia de frente; un 4 % en casi todos los dieléctricosF0
Índice de refracción: de ahí sale el F0ior
Sin entorno el término indirecto vale exactamente ceroenvMap · scene.environment
Una segunda capa especular encima: barnizclearcoat · clearcoatRoughness
Relieve del barniz independiente del de la baseclearcoatNormalMap
Vidrio de verdad; caro y dependiente del iortransmission · thickness
El color que gana la luz al atravesar el volumenattenuationColor · attenuationDistance
El brillo rasante de los tejidossheen · sheenColor · sheenRoughness
Película fina: pompa de jabón, aceite, escarabajoiridescence
Reflejo estirado: metal cepillado y peloanisotropy
Retocar el F0 de un dieléctricospecularIntensity · specularColor
🖼️ Texturas, color y compresión 15
Cargar y saber cuánto queda de verdadTextureLoader · LoadingManager
Color base y máscara de opacidadmap · alphaMap
Relieve falso en espacio tangentenormalMap · normalScale
Canales verde y azul del mapa ORMroughnessMap · metalnessMap
Exige un segundo juego de UV en uv1aoMap
Mueve vértices de verdad: sin subdivisión no hace nadadisplacementMap
Repetir necesita RepeatWrapping en los dos ejeswrapS · repeat · offset
Cómo se reduce y cómo se amplía la texturaminFilter · magFilter
Trilineal: el filtro por defecto y el correctoLinearMipmapLinearFilter
Sin mipmaps la textura lejana hierve al moversegenerateMipmaps
Lo que salva las superficies muy inclinadasanisotropy · getMaxAnisotropy()
Solo en texturas de color; nunca en datoscolorSpace = SRGBColorSpace
ACESFilmic, AgX o Neutral antes de salir a pantallaoutputColorSpace · toneMapping
Sin él transcodifica a RGBA y pierdes el ahorroKTX2Loader.detectSupport(renderer)
Barato para color, caro y fiel para normalesETC1S frente a UASTC
💡 Luces y sombras 14
Suma constante: aplana la escena por igualAmbientLight
Color de cielo arriba y rebote de suelo abajoHemisphereLight
Rayos paralelos: la posición solo marca la direcciónDirectionalLight
Atenuación física por cuadrado inversoPointLight · decay · distance
Cono con borde blando y objetivo propioSpotLight · angle · penumbra
Solo Standard y Physical, y no proyecta sombraRectAreaLight
Y castShadow y receiveShadow objeto a objetoshadowMap.enabled
Resolución del mapa: potencia de dos y memoria realshadow.mapSize
La sombra tiene su propio frustum; ajústalo o se cortashadow.camera
La superficie se sombrea a sí misma por falta de precisiónShadow acne
Bias de más: la sombra se despega del objetoPeter-panning
Desplaza por la normal; suele ser mejor que biasshadow.normalBias
Filtrados; solo VSM respeta radius y blurSamplesPCFSoftShadowMap · VSMShadowMap
Ver el frustum de sombra y dejar de adivinarCameraHelper(luz.shadow.camera)
🌅 Entornos e IBL 11
El nombre vigente desde r180; RGBELoader solo avisa y delegaHDRLoader
Half-float real, sin la descompresión RLE en el hilo principalEXRLoader
Pesa como un JPEG y lo decodifica el navegadorUltraHDRLoader
Prefiltra el entorno: un nivel de mip por rugosidadPMREMGenerator
Devuelve un render target: hay que coger .texturefromEquirectangular()
Un entorno de estudio sin descargar un bytefromScene(scene, sigma)
El estudio procedural de los ejemplos oficialesRoomEnvironment
Ilumina; scene.background solo se ve detrásscene.environment
Subir el indirecto sin tocar las lucesscene.environmentIntensity
Ya viene lineal: le destrozarías el contrasteNo marques un HDRI como sRGB
Los recursos son compartidos: uno por aplicaciónpmrem.dispose()
📦 glTF y pipeline de assets 11
JSON con ficheros aparte, o todo en un binarioglTF frente a GLB
Las tres capas que describen qué hay en cada byteaccessor · bufferView · buffer
Lo segundo impide abrir el fichero sin soportarloextensionsUsed / extensionsRequired
Devuelve scene, scenes, animations y camerasGLTFLoader
Hay que servir el decodificador WebAssembly aparteDRACOLoader.setDecoderPath()
Comprime muchísimo y cuesta descomprimirKHR_draco_mesh_compression
EXT_meshopt_compression: descomprime mucho más rápidoMeshoptDecoder
Menos bits por atributo y cero coste al cargarKHR_mesh_quantization
Lo único que baja la VRAM, no solo la descargaKHR_texture_basisu
dedup, prune, weld, palette y reordergltf-transform · gltfpack
Un PNG pequeño ocupa igual en GPU que uno enormePeso descargado no es memoria
🦴 Animación y skinning 13
Un mezclador por modelo animadoAnimationMixer(root)
Nada avanza si no le pasas el deltamixer.update(dt)
Devuelve la acción; hay que llamar a play()clipAction(clip)
Un clip son pistas, y cada pista un canalAnimationClip · KeyframeTrack
Cambiar de animación sin salto visiblecrossFadeTo(otra, dur)
Llevar el peso de 0 a 1 en un tiempo dadofadeIn() · fadeOut()
Mezclar varias acciones a la vezsetEffectiveWeight()
Que se quede en el último fotogramaLoopOnce + clampWhenFinished
La forma correcta de encadenar accionesEvento finished
Malla, jerarquía de huesos y la pose actualSkinnedMesh · Skeleton · Bone
Hasta cuatro huesos por vértice, con sus pesosskinIndex · skinWeight
El pellizco del linear blend skinning al torcerCandy wrapper
Soltar el modelo del mezclador al desmontarmixer.uncacheRoot()
🧪 Shaders GLSL 14
Te inyecta matrices y atributos ya declaradosShaderMaterial
No te inyecta nada: lo declaras todo túRawShaderMaterial
Un objeto de nombre a { value }: igual para toda la mallauniforms
Un dato por vértice, solo visible en el vertex shaderattribute
Sale del vértice y llega interpolada al fragmentovarying
Cambiarlas recompila; multiplican las permutacionesdefines
projectionMatrix por modelViewMatrix por la posicióngl_Position
La interpolación acorta las normales unitariasEl segundo normalize
Reordenar componentes sin coste: xy, rgb, xxxSwizzling
Con esas tres se construye casi cualquier patrónstep · smoothstep · mix
Un if no ahorra: el grupo ejecuta las dos ramasEjecución divergente
Inyectar en el shader de Three sin perder el PBRonBeforeCompile
Sin ella, tus variantes comparten programa compiladocustomProgramCacheKey
Cadena de passes con ping-pong de render targetsEffectComposer · RenderPass
🔗 TSL, nodos y WebGPU 16
De aquí salen los node materials, no del paquete threethree/webgpu
De aquí salen los nodos y las funciones del lenguajethree/tsl
El mismo árbol compila a GLSL y a WGSLUn grafo, dos backends
PBR completo con los slots de superficie abiertosMeshStandardNodeMaterial
Sustituir una entrada sin reescribir el materialcolorNode · roughnessNode · metalnessNode
El resto de slots, cada uno con su tiponormalNode · emissiveNode · opacityNode
Mover el vértice; el raycaster no se enterapositionNode
Sin layout hace inlining; con layout emite funciónFn(() => ...)
Se importa; ElseIf y Else son métodos encadenadosIf
Bucle dentro del grafo, no en JavaScriptLoop · Break
Cambiar su .value no recompila nadauniform(valor)
Hay que esperar a init() antes del primer renderWebGPURenderer
El fallback a WebGL existe y es automáticoforceWebGL
Aquí sí; render.calls cuenta otra cosainfo.render.drawCalls
Storage buffers y el índice dentro del computeinstancedArray · instanceIndex
Despachar el kernel escrito en TSLcomputeAsync()
🎯 Raycasting e interacción 9
Delega: cada objeto implementa su propio raycast()THREE.Raycaster
Un Vector2 de -1 a 1, con la Y invertidasetFromCamera(ndc, camera)
Mejor una lista corta que recorrer la escena enteraintersectObjects(lista, false)
Los umbrales de Points, Line y Line2raycaster.params
No se dibuja, pero sigue robando clicsvisible = false
Un AND de 32 bits: el filtro más barato que hayobject.layers
El rayo choca con la geometría sin deformarDeformar en el vertex shader
Un árbol en lugar de un bucle por triángulothree-mesh-bvh
Para picking es siempre la opción correctafirstHitOnly
🧹 Rendimiento y limpieza 15
Los draw calls del frame en WebGLRendererrenderer.info.render.calls
Enviados, no dibujados: no sabe nada de cullingrenderer.info.render.triangles
Si crece al arrancar, tienes compilación diferidarenderer.info.programs.length
A false para contar también sombras y post-procesorenderer.info.autoReset
Compilar antes de quitar la pantalla de cargacompileAsync(scene, camera)
Si solo sube durante la sesión, hay fugarenderer.info.memory
Menos triángulos cuanto más lejos estáTHREE.LOD · addLevel()
Clonar un material clona su programa y su cachéCompartir materiales
Quita de una lista; no libera un solo byte de VRAMscene.remove()
No libera sus texturas: hay que recorrerlas apartematerial.dispose()
Se comparten: libérala una sola vez y lleva registrotexture.dispose()
Post-proceso y PMREM no cuelgan de la escenarenderTarget.dispose()
Y quitar el canvas del DOM detrásrenderer.dispose()
Cierra los workers; si no, quedan hilos vivosDRACOLoader.dispose()
Parar el bucle es el primer paso de toda limpiezasetAnimationLoop(null)