Shader: o que é, tipos de shaders e como funcionam

Autor: IT Sectr Publicado: 2026-06-11 Tempo de leitura: 8 min

Shader (shader) é um programa executado na GPU para processar dados gráficos: vértices, fragmentos ou tarefas computacionais. Ao contrário do código comum na CPU, o shader funciona em paralelo em centenas de núcleos, processando cada elemento independentemente. Segundo a Khronos Group (2025), shaders são usados em 100% dos aplicativos 3D modernos — desde jogos mobile até efeitos de UI em aplicativos do sistema. Desenvolvedores escrevem shaders em linguagens especializadas: GLSL, HLSL, Metal Shading Language ou SPIR-V.

Principais pontos

  • Shader é um programa para GPU executado em paralelo em centenas de núcleos para cada elemento da cena.
  • Tipos de shaders: vertex, fragment, compute, geometry, tessellation e mesh shaders.
  • Linguagens: GLSL (OpenGL), HLSL (DirectX), MSL (Metal), SPIR-V (Vulkan) — todas compiladas para código de máquina da GPU.
  • Shaders no desenvolvimento mobile são usados para efeitos, pós-processamento, iluminação e computação.
  • Otimização de shaders: precisão mediump, minimização de ramificações e ATF (Adaptive Texture Fetch) para GPUs mobile.

O que é Shader?

Shader é um pequeno programa escrito em uma linguagem especializada e executado na GPU. Cada shader processa um elemento de dados — vértice, fragmento (pixel) ou elemento de trabalho — independentemente dos outros. O paralelismo da GPU permite executar milhares de instâncias de shader simultaneamente.

O termo foi introduzido pela Pixar nos anos 1980 para descrever programas que controlam a aparência de superfícies no RenderMan. Em tempo real, shaders surgiram com a NVIDIA GeForce 3 (2001) — a primeira placa de vídeo com pipeline programável. Antes dos shaders, os gráficos eram configurados por parâmetros fixos: cor, textura, modo de mesclagem.

Segundo a Unity Technologies (2025), um jogo mobile médio usa 50–200 shaders. Cada shader possui variantes (variants) para diferentes plataformas, níveis de qualidade e configurações de iluminação. O número de variantes pode chegar a 10.000 por projeto.

A arquitetura de um shader divide-se em dados de entrada (atributos, variáveis uniform, texturas), código do programa e dados de saída (cor, posição). Variáveis uniform são definidas pela CPU antes da execução do shader e permanecem inalteradas para todos os elementos do quadro. Atributos são dados por elemento (coordenadas do vértice, normal, coordenadas UV).

Modelo de execução SIMT

SIMT (Single Instruction, Multiple Threads) é o modelo de execução de shaders na GPU. Uma instrução é carregada uma vez e executada por centenas de threads sobre dados diferentes. Por exemplo, um Fragment Shader para 1000 pixels executa 1000 threads com o mesmo código, mas cada thread recebe suas próprias coordenadas UV e atributos interpolados.

Uma consequência importante do SIMT: ramificações em shaders são custosas. Se dentro de um bloco if metade dos threads segue um caminho e a outra metade outro, a GPU executa ambos os caminhos sequencialmente para todos os threads. O desempenho cai para 50%. Evite ramificações dinâmicas em shaders ou minimize-as por meio de cálculos prévios na CPU.

Tipos de shaders

GPUs modernas suportam vários tipos de shaders, cada um para seu estágio do pipeline gráfico ou computacional. Vamos considerar os principais tipos: vertex, fragment, compute e os modernos mesh shaders.

Tipo de shaderEstágio do pipelineProcessaLinguagem
Vertex ShaderVertexCada vérticeGLSL, HLSL
Fragment ShaderFragmentoCada pixelGLSL, HLSL
Compute ShaderComputaçãoDados arbitráriosGLSL, HLSL
Geometry ShaderGeometriaPrimitivasGLSL, HLSL
Tessellation ShaderTesselaçãoPatchesGLSL, HLSL
Mesh ShaderPipeline meshTask + MeshHLSL, MSL

Vertex Shader

Vertex Shader processa cada vértice da geometria: transforma coordenadas, calcula iluminação, passa dados para o fragment shader. É um estágio obrigatório do pipeline gráfico — sem ele, os vértices não chegam à tela. O Vertex Shader é chamado para cada vértice de cada quadro.

Fragment Shader

Fragment Shader (ou Pixel Shader) é o estágio que mais consome recursos. Ele calcula a cor final de cada fragmento usando texturas, iluminação e material. O Fragment Shader é executado para cada pixel coberto pela geometria, considerando todas as texturas e efeitos aplicados. A otimização deste shader proporciona o maior ganho de desempenho.

Compute Shader

Compute Shader é um shader universal para cálculos arbitrários na GPU. Ao contrário dos shaders gráficos, ele não está vinculado à geometria ou pixels. O Compute Shader trabalha com buffers de dados arbitrários por meio de grupos de trabalho. É usado para física, simulação de partículas, pós-efeitos e inferência de redes neurais.

Mesh Shader

Mesh Shader é o tipo mais recente de shader, surgido na NVIDIA Turing (2018) e Metal 3. O Mesh Shader substitui os shaders vertex, geometry e tessellation por um único pipeline mesh. Funciona em conjunto com o Task Shader: o Task Shader decide quais grupos mesh renderizar, e o Mesh Shader gera a geometria em tempo real.

Linguagens para escrever shaders

Shaders são escritos em linguagens especializadas que são compiladas para código de máquina da GPU. A escolha da linguagem depende da plataforma e da API. Vamos considerar as principais linguagens: GLSL, HLSL, Metal Shading Language e o formato intermediário SPIR-V.

GLSL (OpenGL Shading Language)

GLSL é a linguagem de shaders para OpenGL, OpenGL ES e WebGL. A sintaxe é baseada em C com adição de tipos vetoriais (vec2, vec4, mat4) e funções embutidas (texture, normalize, reflect). GLSL ES é a versão para dispositivos mobile com precisão limitada (lowp, mediump, highp). Segundo a Khronos (2025), GLSL continua sendo a linguagem de shaders mais difundida devido à sua natureza multiplataforma.

glsl
#version 300 es
precision mediump float;
in vec2 v_texCoord;
uniform sampler2D u_texture;
out vec4 fragColor;

void main() {
    fragColor = texture(u_texture, v_texCoord);
}

Um fragment shader simples lê a cor da textura pelas coordenadas UV. precision mediump instrui a GPU a usar meia precisão para float — acelera a execução em dispositivos mobile em 25–40%.

HLSL (High-Level Shader Language)

HLSL é a linguagem de shaders da Microsoft para DirectX. A sintaxe é mais próxima de C++ com suporte a classes, estruturas e templates. HLSL é usado em aplicativos Windows e, através do Shader Model 6.7+, suporta Ray Tracing, Mesh Shaders e Sampler Feedback. Para desenvolvimento mobile, HLSL não é usado diretamente, mas é compilado para SPIR-V para Vulkan.

Metal Shading Language

MSL (Metal Shading Language) é a linguagem de shaders da Apple, baseada em C++14. Ao contrário de GLSL e HLSL, o MSL é compilado junto com o aplicativo, eliminando a compilação JIT no dispositivo. MSL suporta ponteiros, templates e a biblioteca padrão C++. É usado em todos os dispositivos Apple: iPhone, iPad, Mac, Apple TV.

cpp
#include <metal_stdlib>
using namespace metal;
struct VertexOut {
    float4 position [[position]];
    float2 texCoord;
};

fragment float4
myFragment(VertexOut in [[stage_in]],
            texture2d<float> tex [[texture(0)]]) {
    constexpr sampler s = sampler(filter::linear);
    return tex.sample(s, in.texCoord);
}

MSL usa atributos [[position]], [[stage_in]] e [[texture(N)]] para vinculação de recursos. O compilador da Apple gera código otimizado para a GPU atual, considerando o número de registradores e cache.

SPIR-V

SPIR-V é um formato binário intermediário de shaders, padrão para Vulkan. Shaders são escritos em GLSL ou HLSL, compilados para SPIR-V e carregados no aplicativo Vulkan. SPIR-V não está vinculado a uma linguagem específica — existem compiladores de Rust, Python, OpenCL C para SPIR-V.

Shaders no desenvolvimento mobile

Shaders em plataformas mobile têm limitações em comparação com desktop: menos registradores, precisão limitada e falta de suporte para algumas instruções. Vamos considerar as especificidades dos shaders no Android (Vulkan/OpenGL ES) e iOS (Metal).

Shaders no Android

Android usa GLSL ES para OpenGL e SPIR-V para Vulkan. OpenGL ES 3.2 suporta shaders com mediump por padrão. Vulkan requer compilação explícita de GLSL para SPIR-V via glslangValidator. No Android, shaders são carregados de recursos de string ou de arquivos SPIR-V compilados.

Qualcomm Adreno otimiza shaders no nível do driver. Recomendações: use mediump para cor e UV, highp apenas para posições; evite amostragens de textura em vertex shaders; agrupe cálculos em vetores (vec4 em vez de 4x float). Segundo a Qualcomm (2025), essas otimizações proporcionam ganho de 30–50%.

Shaders no iOS

iOS usa exclusivamente Metal Shading Language. Os shaders são compilados para código de máquina junto com o aplicativo via Xcode. Metal fornece Shader Debugger e GPU Capture para perfilamento de shaders. A GPU da Apple (TBDR) tem otimizações específicas: early fragment test, render targets sem memória e blending programável.

Segundo a Apple WWDC 2024, para shaders iOS é crítico usar half em vez de float, limitar a pressão de registradores (máx 64 registradores) e evitar amostragens de textura dependentes. Shaders iOS devem ser compactos — tamanho ideal de 50–100 instruções ALU.

Shaders no Unity e Unreal Engine

Os motores de jogo Unity e Unreal Engine fornecem editores visuais de shaders (Shader Graph, Material Editor) e linguagens abstratas (ShaderLab, USF). O desenvolvedor escreve o shader em uma linguagem de alto nível, e o motor compila para a plataforma alvo. Unity usa HLSL como linguagem intermediária, Unreal usa USF (Unreal Shader Format).

Otimização de shaders

Otimização de shaders é uma etapa fundamental no desenvolvimento de gráficos para dispositivos mobile. Um shader mal escrito pode reduzir o FPS de 60 para 20. Vamos considerar as principais regras e técnicas de otimização.

Precisão de cálculos

Use a precisão mínima suficiente: lowp para cor e UV, mediump para normais e iluminação, highp apenas para posições e matrizes. Segundo a ARM (2025), operações mediump são 2 vezes mais rápidas que highp em GPUs Mali. No GLSL ES, isso é definido por qualificadores de precisão.

Minimização de amostragens de textura

Amostragens de textura são a operação mais cara em um shader (10–30 ciclos contra 1–2 para uma instrução ALU). Reduza o número de amostragens: combine texturas em atlas, use armazenamento de dados em arrays uniform em vez de texturas, cacheie resultados de pixels vizinhos por meio de instruções de derivada.

Evite ramificações

Ramificações dinâmicas (if com variável uniform) reduzem o desempenho do pipeline SIMT. Substitua ramificações por funções matemáticas: mix(), step(), smoothstep() e clamp(). Essas funções são executadas em 1–2 instruções, enquanto uma ramificação pode custar 8–16 instruções devido à divergência de threads.

glsl
// Ruim: desvio dinâmico no shader
if (u_enableLight) {
    color *= computeLighting(normal);
}

// Bom: substituição matemática de desvio
color *= mix(1.0, computeLighting(normal),
              float(u_enableLight));

mix() realiza interpolação linear entre dois valores. Quando u_enableLight=0, retorna 1.0 — a cor não muda. Quando u_enableLight=1, retorna o resultado da iluminação. Sem ramificação — todos os threads executam o mesmo código.

Exemplos de shaders

Vamos considerar exemplos práticos de shaders para desenvolvimento mobile — desde sombreamento simples até geração procedural de texturas. Cada exemplo demonstra uma técnica específica.

Sombreamento Phong (vertex shader)

Modelo Phong é o modelo clássico de iluminação com componentes difusa e especular. O Vertex Shader calcula a iluminação para cada vértice, e o Fragment Shader apenas interpola o resultado (Gouraud shading). Adequado para dispositivos mobile devido ao baixo custo.

glsl
#version 300 es
layout(location = 0) in vec4 a_position;
layout(location = 1) in vec3 a_normal;
uniform mat4 u_mvp;
uniform mat4 u_modelView;
out vec3 v_color;

void main() {
    vec3 normal = normalize(mat3(u_modelView) * a_normal);
    vec3 lightDir = normalize(vec3(0.0, 1.0, 1.0));
    float diff = max(dot(normal, lightDir), 0.0);
    v_color = vec3(0.8, 0.2, 0.2) * (0.3 + diff * 0.7);
    gl_Position = u_mvp * a_position;
}

O shader calcula a iluminação difusa: produto escalar da normal com a direção da luz. O resultado é misturado com as componentes ambiente (0.3) e difusa (0.7). Executa 10–15 instruções ALU por vértice — aceitável para 100.000 polígonos a 60 FPS em uma GPU mobile.

Textura procedural (fragment shader)

Texturas procedurais são geradas no Fragment Shader sem carregamento de arquivo. Economiza memória de vídeo e simplifica a animação. Exemplo — tabuleiro de xadrez com tamanho de célula ajustável. Apenas algumas instruções ALU — carga mínima na GPU.

glsl
#version 300 es
precision mediump float;
in vec2 v_uv;
uniform float u_cells;
out vec4 fragColor;

void main() {
    vec2 cell = floor(v_uv * u_cells);
    float isWhite = mod(cell.x + cell.y, 2.0);
    fragColor = mix(vec4(0.1, 0.1, 0.1, 1.0),
                     vec4(0.9, 0.9, 0.9, 1.0),
                     isWhite);
}

8 instruções ALU — shader ideal para dispositivos mobile. u_cells define o número de células por eixo. floor e mod são operações baratas, executadas em 1 ciclo em todas as GPUs mobile.

Perguntas frequentes

Qual a diferença entre um shader e um programa comum em C++?

Shader é executado na GPU em modo SIMT — uma instrução para centenas de threads. Um programa comum em C++ é executado na CPU em modo MIMD. O shader não tem acesso ao sistema de arquivos, E/S ou memória dinâmica. Ele recebe dados por meio de buffers e texturas e retorna uma posição ou cor.

Qual linguagem de shaders aprender para desenvolvimento mobile?

GLSL — para OpenGL ES e WebGL, multiplataforma. Metal Shading Language — para iOS. HLSL — base para Unity e Unreal Engine. Comece com GLSL — a compreensão dos fundamentos é transferível para qualquer linguagem de shaders.

Por que shaders são lentos em dispositivos mobile?

Principais causas: alta precisão (highp em vez de mediump), amostragens excessivas de textura, ramificações dinâmicas e excedência do limite de registradores. Use RenderDoc ou Xcode GPU Frame Debugger para análise de shaders.

O que é compute shader e para que serve?

Compute Shader é um shader para cálculos arbitrários na GPU: física de partículas, processamento de imagem, simulação de tecidos. Ao contrário do Fragment Shader, ele não está vinculado a pixels e pode escrever em buffers arbitrários.

É possível escrever shaders sem conhecimento de linguagens de programação?

Sim, por meio de editores visuais: Shader Graph no Unity, Material Editor no Unreal Engine ou Metal Shader Converter. Eles geram código de shader com base em um esquema de nós. Para otimização profunda, é necessário entender a linguagem de shaders.

Resumo

  • Shader é um programa paralelo para GPU que processa vértices, fragmentos ou dados arbitrários em massa.
  • Tipos de shaders: Vertex, Fragment, Compute, Geometry, Tessellation e Mesh — cada um responsável por seu estágio do pipeline.
  • Linguagens: GLSL (OpenGL), HLSL (DirectX), MSL (Metal), SPIR-V (Vulkan) — compiladas para código de máquina da GPU.
  • Especificidade mobile: precisão mediump, mínimo de amostragens de textura, ausência de ramificações dinâmicas.
  • Otimização: mix() em vez de if, precisão half, ATF, combinação de texturas em atlas e cálculos prévios na CPU.
  • Aplicações: iluminação Phong, texturas procedurais, pós-efeitos, física de partículas e efeitos de UI.
  • Ferramentas: RenderDoc, Xcode GPU Debugger, Qualcomm Adreno Profiler e Mali Offline Compiler para análise de shaders.

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também