ProyectosExperimentos

Grid TSL

Un material de grilla procedural para suelos en Three.js con WebGPU y TSL: líneas principales, secundarias y cruces, filtradas para que no aparezcan moiré ni parpadeo, ni a lo lejos ni en ángulos rasantes.

Estado
Activo
Periodo
2025.09 — actualidad
Tipo
Librería / paquete
Rol
Proyecto individual, Shaders, Optimización de rendimiento
Tecnologías
  • Three.js
  • WebGPU
  • TSL
  • Vite
Log de desarrollo
1 entrada

Contexto y objetivo

Una grilla de suelo es de los primeros elementos de casi cualquier escena 3D, y también de los que peor se ven si no están bien filtrados: a lo lejos las líneas se vuelven más finas que un píxel, parpadean al mover la cámara y forman patrones de moiré.

La primera versión, de septiembre de 2025, era un material con dos capas de líneas y una de cruces, con presets fijos y una variante triplanar. La versión 2, de noviembre de 2026, es una reescritura desde cero: un único material para suelos, con todas las capas filtradas, todos los parámetros editables en vivo y empaquetado para usar en otros proyectos.

Demo interactiva

Arrastrá para girar la cámara y bajala hasta un ángulo rasante: a lo lejos la grilla se vuelve un tono parejo, sin moiré. Con #debug al final de la URL aparece el panel del material en el Inspector de three.js, que permite editar cada parámetro y copiar la configuración como JS o JSON. Necesita un navegador con WebGPU.

Cómo se filtra

  • Huella anisotrópica del píxel: las derivadas de la posición se calculan una sola vez y por eje. En ángulos rasantes, cada dirección se filtra según lo que de verdad cubre en pantalla.
  • Líneas: con la técnica pristine grid de Ben Golus, el ancho dibujado nunca baja de un píxel, pero su intensidad se reduce en la misma proporción, así las líneas finas no parpadean. Cuando una celda ocupa menos de unos dos píxeles, la capa converge a su cobertura media: a lo lejos se ve un tono parejo en lugar de moiré.
  • Cruces: cada brazo es una línea filtrada multiplicada por una banda con un filtro de caja analítico, que conserva la energía. El grosor y el largo de los brazos también convergen a su media.
  • Composición en espacio lineal según la cobertura de cada capa: fondo, líneas secundarias, cruces y líneas principales.

Como paquete

Se instala con npm y usa el three.js del proyecto que lo importa, sin otras dependencias:

import { GridMaterial } from 'grid-tsl'

const material = new GridMaterial({
  primaryColor: '#5c6370',
  secondarySpacing: 0.5,
  fadeRadius: 80,
})
material.crossSize = 0.3 // cualquier parámetro se cambia en vivo
  • grid-tsl: el material y sus valores por defecto.
  • grid-tsl/debug: un panel en el Inspector de three.js que edita el material y copia los parámetros como JS o JSON. Se importa de forma dinámica, así no entra en el bundle de producción.
  • grid-tsl/nodes: las funciones de TSL sueltas, para armar un material propio.

Para que el shader sea liviano, los valores derivados (inversas, proporciones respecto de la celda, radios del fundido) se calculan en la CPU al cambiar un parámetro, y el fundido circular solo se compila si está activado: apagado, el material es opaco y no tiene ese código ni blending.

Resultados y limitaciones

  • La grilla se proyecta sobre el plano XZ del mundo, así que solo sirve para superficies horizontales. La variante triplanar de la versión 1, para objetos sin UV, ya no existe.
  • La versión 2 cambió los nombres de los parámetros y eliminó los presets: un proyecto que usaba la versión 1 tiene que adaptarse. La 1 sigue disponible en el tag v1.0.0.
  • Necesita un navegador con WebGPU.

Créditos

LOG

Log de desarrollo

  1. Grid TSL v2: lo que saqué y lo que mejoró

    Una reescritura desde cero: menos variantes y presets, y una grilla que ya no hace moiré en ninguna de sus capas.