Shaders e programabilidade
Fragment shaders: programando o comportamento por pixel em GLSL — gradientes, ruído procedural, ondas animadas e os fundamentos que tornam jogos modernos visualmente ricos.
Uma função que roda por pixel
Um fragment shader é uma função que roda uma vez por pixel — em paralelo, para todos os pixels da tela ao mesmo tempo. Ela recebe a posição do pixel e uniformes (constantes como o tempo, resolução, texturas) e retorna uma cor RGBA.
Antes dos shaders programáveis (pré-2001), a GPU tinha um pipeline fixo: você podia escolher entre iluminação Phong ou Gouraud, mas nada mais. Com shaders, o comportamento por pixel é completamente programável em GLSL (OpenGL), HLSL (DirectX) ou WGSL (WebGPU). Isso permite reflexos físicos, subsurface scattering, pele realista, água — qualquer efeito visual imaginável.
Simulador de pixel shaders
Cada shader roda em cada pixel do canvas em paralelo. Ajuste os uniforms com os sliders e veja o resultado em tempo real.
Usa as coordenadas UV (0..1) diretamente como cor. Clássico para debugar UVs.
Fragment shader GLSL completo
// Fragment shader GLSL completo // Roda uma vez por pixel, em paralelo precision mediump float; // Uniforms: constantes passadas pela CPU para todos os pixels uniform float uTime; // tempo em segundos uniform vec2 uResolution; // tamanho da tela em pixels uniform sampler2D uTexture; // textura // Varyings: interpolados pelo rasterizador (por pixel) varying vec2 vUV; // coordenadas de textura 0..1 varying vec3 vNormal; // normal da superfície void main() { // Gradiente animado com seno vec2 uv = vUV; float wave = sin(uv.x * 10.0 + uTime) * 0.5 + 0.5; // Amostra textura e mistura com cor de onda vec4 texColor = texture2D(uTexture, uv); vec4 waveColor = vec4(0.36, 0.62, 1.0, 1.0); vec4 finalColor = mix(texColor, waveColor, wave * 0.3); // Iluminação Phong simples vec3 lightDir = normalize(vec3(1, 1, 2)); float diff = max(dot(vNormal, lightDir), 0.0); finalColor.rgb *= (0.3 + diff * 0.7); // ambient + diffuse gl_FragColor = finalColor; }
Ruído procedural e FBM
// Ruído procedural — base de texturas de nuvem, terreno, fogo // Hash pseudo-aleatório (determinístico) float hash(vec2 p) { p = fract(p * vec2(234.34, 435.345)); p += dot(p, p + 34.23); return fract(p.x * p.y); } // Value noise: interpola valores de hash numa grade float noise(vec2 p) { vec2 i = floor(p); vec2 f = fract(p); vec2 u = f * f * (3.0 - 2.0 * f); // smoothstep return mix(mix(hash(i + vec2(0,0)), hash(i + vec2(1,0)), u.x), mix(hash(i + vec2(0,1)), hash(i + vec2(1,1)), u.x), u.y); } // FBM: fractal Brownian Motion — soma oitavas de ruído float fbm(vec2 p) { float v = 0.0, a = 0.5; for (int i = 0; i < 5; i++) { v += a * noise(p); p *= 2.0; a *= 0.5; // dobra frequência, metade amplitude } return v; }
length(p) - r.
Combinando SDFs com operações de união/interseção/subtração, você renderiza geometria complexa
sem nenhuma malha 3D — tudo pelo cálculo matemático em cada pixel.
Seu primeiro shader
Mini projeto: escreva um fragment shader WebGL que cria um gradiente circular animado — a cor muda com sin(length(uv - vec2(0.5)) * 10.0 - uTime). Ajuste frequência e velocidade com uniforms.
Projeto principal: implemente um shader de "água" no shadertoy.com: combine duas camadas de ondas senoidais com frequências e direções diferentes, use fbm() para distorção, e adicione reflexo do céu (gradiente de azul claro a branco na vertical).
Desafio extra: implemente ray marching de uma esfera usando SDF: o fragment shader "caminha" ao longo de um raio da câmera, consultando sdf_sphere(p, center, radius) a cada passo. Quando a distância for menor que 0.001, você atingiu a superfície. Calcule a normal por gradiente numérico e aplique iluminação Phong.
Teste sua intuição
Onde você encontra isso
Água e oceanos em jogos
Far Cry, Assassin's Creed e God of War renderizam água com shaders de ondas (somas de senóides com direções e frequências variadas), reflexo da câmera (screen-space reflections), espuma procedural (fbm) e refração do fundo. Tudo calculado por pixel no fragment shader.
Shadertoy e arte generativa
shadertoy.com é uma comunidade onde artistas criam visuais impressionantes só em fragment shaders — planetas, galáxias, nuvens volumétricas — sem nenhum dado 3D. A técnica de ray marching permite renderizar objetos via funções SDF sem triângulos.
Pós-processamento
Após renderizar a cena, jogos aplicam uma passagem de pós-processamento: bloom (brilho em áreas claras), depth of field (desfoque de profundidade), SSAO (oclusão ambiente), motion blur, tonemapping HDR → LDR. Tudo são fragment shaders que lêem o framebuffer como textura.