LOG 03 · TÉCNICA

Renderização Híbrida CSS3D + WebGL

Conteúdo DOM real e acessível colocado dentro de uma cena WebGL 3D genuína usando o CSS3DRenderer do Three.js — o texto continua selecionável e rastreável mesmo enquanto orbita no espaço 3D.

Porquê não renderizar o texto diretamente em WebGL?

Cozer a interface num canvas WebGL (como textura, ou através de uma biblioteca de malhas de texto) permite colocá-la rapidamente no espaço 3D, mas deixa de ser conteúdo real — sem seleção de texto, sem pesquisa na página, nada que um leitor de ecrã ou um rastreador de pesquisa consiga ler. O CSS3DRenderer do Three.js resolve isto ao contrário: elementos DOM reais são posicionados e rodados em verdadeiro 3D, transformados através de CSS matrix3d, enquanto um segundo renderizador WebGL comum desenha a cena por trás deles — ambos guiados pela mesma câmara, para que a perspetiva corresponda exatamente entre as duas camadas.

Neste site, cada secção da página inicial é um componente React real, montado via portal num div que o CSS3DRenderer coloca num percurso helicoidal à volta do globo. O scroll ou o swipe conduzem um tween do GSAP da câmara partilhada; o CSS3DRenderer e o renderizador WebGL redesenham a partir do mesmo estado de câmara em cada frame, para que o conteúdo DOM e o globo 3D se mantenham em perfeita sincronia como se ocupassem uma única cena.

A armadilha do contexto de empilhamento

O ponto sensível desta técnica: `perspective`, `transform` e `filter` em qualquer elemento antepassado criam um novo contexto de empilhamento CSS — e tornam-se o bloco contentor para os descendentes com `position:fixed`. Um canvas WebGL de posição fixa que deveria estar por trás de tudo pode ficar silenciosamente preso dentro do contexto de empilhamento errado no momento em que um antepassado adquire uma dessas propriedades, quebrando a ordem das camadas de uma forma fácil de confundir com um bug de z-index quando na verdade é um bug de bloco contentor.

A solução é arquitetónica, não um remendo de z-index: manter o canvas WebGL e o contentor CSS3D como verdadeiros irmãos na raiz do documento, cada um com o seu próprio z-index explícito, em vez de aninhar qualquer um deles dentro de um elemento que um dia possa adquirir um `transform` ou `filter` por uma razão não relacionada.