COLOR A
TEXTURA
FILTRO
EFECTO
ESCALA
COLOR B

Inconveniente al sentido común x Lucas Sosa

«Crear una escena de apariencia tridimensional y con interacciones mínimas, sin JavaScript, es lo menos conveniente al sentido común. Mi intuición me llevaría de inmediato a recurrir a Three.js o JavaScript vanilla para orquestar la escena y resolver los eventos básicos. Sin embargo, el desafío de esta pieza consistió en resolver cada capa de interacción, renderizado, y texturizado exclusivamente mediante estrategias nativas y declarativas de HTML y CSS.»

Co-creado junto a Gemini 3.7 Flash a lo largo de 2 días de trabajo continuo y más de 20 iteraciones técnicas y visuales. El proceso consistió en explorar y tensar los límites de los estándares web nativos, transformando al motor de renderizado del navegador en un entorno 3D reactivo y procedural sin depender de motores gráficos externos ni de una sola línea de script imperativo.


La Arquitectura sin JavaScript: ¿Cómo funciona?

El Motor de Estados Reactivo (:checked + <label>)

Al carecer de variables mutables de JavaScript o gestores de estado, el sistema utiliza el patrón CSS Checkbox/Radio Hack como memoria de la aplicación:

  1. Estado en el DOM: Se declaran <input type="radio"> e <input type="checkbox"> en la raíz del <body>.
  2. Ocultamiento nativo: Los inputs permanecen invisibles (opacity: 0; pointer-events: none; position: absolute;).
  3. Disparadores desacoplados: Los botones de la consola HUD y los hitboxes interactivos dentro del espacio 3D son etiquetas <label for="id-del-input">.
  4. Propagación en cascada: Mediante el selector de hermanos generales (~) y el pseudo-estado :checked, los cambios de estado viajan hacia las variables de diseño y los componentes 3D:
/* Inyección reactiva de parámetros globales al activar un control */
#c-h200:checked ~ .viewport { --color: #06b6d4; }
#s-scale-lg:checked ~ .viewport { --mult: 3; }
#paint-room:checked ~ .header-controls { opacity: 1; pointer-events: auto; }

Geometría 3D y Espacialidad en el DOM

El espacio no es un <canvas>, sino un conjunto de elementos HTML renderizados en el espacio tridimensional gracias a CSS 3D Transforms:

  • Cámara y Perspectiva: Regulada mediante perspective: 950px y perspective-origin: 50% 46%.
  • Preservación 3D: Cada contenedor jerárquico hereda transform-style: preserve-3d;.
  • Cubo Vóxel: Construido a partir de 6 caras (.f, .bk, .tp, .bt, .lt, .rt) orientadas con transformaciones euclidianas y sombreadas dinámicamente con color-mix():
.part .bk {
  transform: rotateY(180deg) translateZ(calc(var(--d) / 2));
  background-color: color-mix(in srgb, var(--c), black 25%);
}
  • La Habitación y la Ventana 3D: El entorno cuenta con paredes, piso y techo en perspectiva forzada, además de una ventana batiente interactiva cuyos postigos de madera giran sobre bisagras reales en el eje Y (rotateY(-140deg) / rotateY(140deg)) al alternar #window-toggle:checked. El paisaje exterior integra sol radiante, nubes con deriva continua (animation: drift-cloud) y cordilleras montañosas trazadas geométricamente con clip-path: polygon(...).

Texturas Procedurales sin Imágenes Rasterizadas

Ninguna de las texturas (cuadrícula, rayas, ajedrez, zigzag, fibra de carbono) es una imagen externa (.png o .jpg). Todas se sintetizan en tiempo real mediante funciones de degradado matemático de CSS:

  • linear-gradient(...) y repeating-linear-gradient(...) para tramas ortogonales y diagonales.
  • radial-gradient(...) en capas superpuestas para emular patrones de carbono.
  • Escalado dinámico en tiempo de ejecución combinando calc() con la variable --mult.

Distorsión Orgánica mediante Filtros SVG y GPU

Uno de los logros más singulares de la pieza es la generación de efectos fluidos, deformaciones holográficas (glitch) y derretimiento (warp) sin recurrir a shaders WebGL ni cálculos de CPU en JavaScript:

  1. Ruido Perlin nativo: Se genera con <feTurbulence> (modos fractalNoise y turbulence).
  2. Animación infinita SMIL: Se rota el mapa de color del ruido mediante <feColorMatrix> animado con <animate attributeName="values" ... repeatCount="indefinite"/>.
  3. Mapeo de desplazamiento: La etiqueta <feDisplacementMap> toma la imagen renderizada (SourceGraphic) y distorsiona sus píxeles en función de los canales de color del ruido animado:
<filter id="filter-liquid-high">
  <feTurbulence type="turbulence" baseFrequency="0.015 0.022" numOctaves="2" result="wNoise"/>
  <feColorMatrix in="wNoise" type="hueRotate" values="0" result="wRot">
    <animate attributeName="values" from="0" to="360" dur="3.5s" repeatCount="indefinite"/>
  </feColorMatrix>
  <feDisplacementMap in="SourceGraphic" in2="wRot" scale="38" xChannelSelector="R" yChannelSelector="G"/>
</filter>
  1. Matriz de intensidades en CSS: Mediante selectores combinados de radio buttons, CSS asigna el filtro correspondiente según el tipo y el multiplicador de efecto:
#f-glitch:checked ~ #s-int-chaos:checked ~ .viewport .scene {
  filter: url(#filter-glitch-chaos);
}

Iluminación y Comportamiento Atmosférico

La escena posee dos regímenes de iluminación interdependientes:

  • Ventana Cerrada (Penumbra): La habitación se oscurece y el cubo 3D se transforma en una fuente emisora de luz propia, desprendiendo un resplandor ambiental volumétrico (box-shadow: 0 0 35px var(--color)).
  • Ventana Abierta (Día): La luz solar exterior baña las paredes, proyecta sombras oblicuas sobre el piso (.floor-window-light) y neutraliza el resplandor artificial del cubo, devolviéndole su acabado físico mate.