Projeção 3D
Como objetos tridimensionais viram imagens 2D — o pipeline MVP, a diferença entre perspectiva e ortografia, e como a profundidade cria ilusão de distância.
O problema da dimensão perdida
Uma tela é plana — só tem X e Y. Mas o mundo 3D tem X, Y e Z. Para renderizar geometria 3D, precisamos de uma função que projete pontos (x,y,z) em pontos (x',y') da tela. Existem dois tipos fundamentais:
Projeção perspectiva: objetos mais distantes aparecem menores — exatamente
como nos nossos olhos. Linhas paralelas convergem para um ponto de fuga. Usada em jogos e cinema.
A fórmula é simples: x' = f·x / (z + d).
Projeção ortográfica: sem distorção de perspectiva. Objetos têm o mesmo tamanho independente da distância. Usada em CAD, plantas baixas e jogos isométricos.
Cubo 3D interativo
Rotacione o cubo com os sliders, alterne entre perspectiva e ortográfica. Observe como as arestas paralelas convergem (perspectiva) ou permanecem paralelas (ortográfica).
Pipeline MVP e projeção
// O pipeline de transformação 3D: MVP // 1. Model matrix — posição/rotação do objeto no mundo const M = translate(x, y, z) * rotate(rx, ry, rz) * scale(sx, sy, sz); // 2. View matrix — câmera: inverte posição/rotação do mundo const V = lookAt(cameraPos, target, up); // 3. Projection matrix — 3D → 2D (perspectiva ou ortográfica) const P_persp = perspective(fov, aspectRatio, near, far); const P_ortho = orthographic(left, right, top, bottom, near, far); // Vértice final (NDC = Normalized Device Coordinates −1..1) const clipPos = P * V * M * vec4(vertexPos, 1.0); // No vertex shader GLSL: void main() { gl_Position = uProjection * uView * uModel * vec4(aPos, 1.0); }
Projeção perspectiva e painter's algorithm
// Projeção perspectiva manual (sem matriz) function project(x, y, z, fov, d) { // Distância focal: quanto maior, menos distorção const f = fov / (z + d); // d = distância câmera-tela return { x: centerX + x * f, y: centerY - y * f, // Y invertido: +Y é para cima }; } // Projeção ortográfica (sem perspectiva) function projectOrtho(x, y, scale) { return { x: centerX + x * scale, y: centerY - y * scale, // Z completamente ignorado }; } // Painter's algorithm: draw back faces first faces.sort((a, b) => avgZ(b) - avgZ(a)); // back-to-front faces.forEach(face => drawFace(face));
near (plano de corte próximo) para aumentar a precisão do Z-buffer nas distâncias relevantes.
O Z-buffer usa representação de ponto flutuante não-linear — mais precisão perto, menos longe.
Renderizador 3D no Canvas 2D
Mini projeto: renderize um cubo wireframe (só arestas) no Canvas 2D usando projeção perspectiva manual (f/(z+d)). Adicione rotação controlada pelo mouse (drag).
Projeto principal: renderize um cubo com faces sólidas usando painter's algorithm: sort por Z médio, preencha polígonos com ctx.fill(). Adicione iluminação flat shading — calcule a normal de cada face e multiplique a cor pelo dot product com a direção da luz.
Desafio extra: carregue um arquivo OBJ simples (formato texto com vértices "v" e faces "f"), renderize com faces sólidas. Implemente backface culling: descarte faces cuja normal aponta para longe da câmera (dot product com view direction > 0).
Teste sua intuição
Onde você encontra isso
Engines 3D (Unity, Unreal)
A câmera é uma matriz de View + Projection armazenada como UBO (Uniform Buffer Object) na GPU. Cada frame, a CPU atualiza a matriz e todos os shaders lêem o mesmo buffer. FOV ajustável e near/far planes são parâmetros da matriz Projection.
CAD e engenharia
AutoCAD, SolidWorks e Blender usam projeção ortográfica para vistas técnicas (frontal, lateral, planta) porque dimensões devem ser preservadas sem distorção. A perspectiva só aparece na "viewport 3D" de visualização geral.
Google Maps 3D / AR
Mapas com modo 3D usam projeção perspectiva com FOV estreito para minimizar distorção em vistas de cima. AR (realidade aumentada) usa a matriz de câmera do sensor do celular como View matrix — alinhando objetos virtuais ao mundo físico.