Shaders que reagem ao áudio: crie um visualizador de música em GLSL no navegador
Um fragment shader é um pequeno programa que roda para cada pixel da tela, a cada quadro. Dê a ele alguns números que descrevem a música naquele instante, como o volume dos graves ou se um bumbo acabou de bater, e ele vira um shader que reage ao áudio: um visualizador escrito por você, em algumas dezenas de linhas de GLSL.
A parte difícil normalmente não é o shader, e sim tudo em volta dele: capturar o áudio, rodar uma FFT, suavizar os valores, detectar batidas, mandar tudo para o WebGL. O Deus Studio faz essa parte por você, então você abre um editor no Chrome e já começa pelos visuais.
O que é o Deus Studio
O Deus Studio é um editor de GLSL dentro da extensão Deus, ligado ao motor real do Deus. Você escreve um fragment shader e vê na hora ele reagir à aba que o Deus está ouvindo, ou a um arquivo de áudio do seu computador. A prévia usa os mesmos uniforms, a mesma análise de som e o mesmo renderizador WebGL 1 do visualizador, então o que você vê na prévia é o que toca no Deus. O Studio está incluído no plano grátis.
Para abrir, inicie o visualizador em uma aba (veja o guia do visualizador para qualquer aba) e escolha Criar › GLSL no menu. Você pode começar pelo Modelo inicial, pelo Tour pelas entradas de áudio, que desenha cada entrada de áudio como um medidor, ou por uma cópia editável de qualquer um dos 70 presets WebGL embutidos. O preset original fica intacto.
As entradas que o seu shader recebe
O Studio usa GLSL ES 1.00 e mainImage no estilo do Shadertoy. O Deus entrega a todo shader um conjunto de uniforms, ao vivo, e você usa os nomes direto, sem declarar. Alguns dos mais úteis:
u_resolution: tamanho da renderização em pixels.u_time: segundos desde que o preset começou.u_bass,u_mid,u_treble,u_level: as três faixas e o volume geral, normalizados de 0 a 1.u_kick,u_snare,u_hihat: detectores de bateria, de 0 a 1.u_attackdá um pico a cada som novo;u_bass_pulseé um pulso que decai nas batidas de grave.u_level_integral: um relógio que anda mais rápido quando a música está mais alta. Use no lugar deu_timepara um movimento que acompanha a faixa.u_frequency[32]eu_waveform[32]: o espectro dos graves aos agudos e a forma de onda, 32 valores cada.u_note_color,u_note_intensity[12]e as outras entradasu_note_*: análise de notas para as 12 classes de altura, de Dó a Si.
O iTime, o iResolution e o iFrame do Shadertoy também funcionam, então trechos de lá entram com menos ajustes. Passe o mouse sobre qualquer nome u_ no editor para ver o que ele significa e o valor atual; a aba Entradas lista todos com valores ao vivo.
Um primeiro shader que reage ao áudio
Aqui está um preset completo: um anel que respira com os graves, pula a cada bumbo e gira mais rápido quando a faixa fica mais alta.
// Um anel que respira com os graves e pula nos bumbos.
uniform vec3 u_tint; // @color #ff2bd6 label="Tint"
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
// Coordenadas centralizadas: y de -1 a 1.
vec2 p = (fragCoord * 2.0 - u_resolution) / u_resolution.y;
float r = length(p);
float a = atan(p.y, p.x);
float radius = 0.35 + u_bass * 0.35 + u_kick * 0.15;
float ring = 1.0 - smoothstep(0.0, 0.04, abs(r - radius));
// Listras que giram mais rápido quando a música está mais alta.
float stripes = 0.6 + 0.4 * sin(a * 8.0 + u_level_integral * 2.0);
vec3 color = u_tint * ring * stripes;
color += u_tint * u_hihat * 0.25 * (1.0 - smoothstep(0.0, 0.6, r));
fragColor = vec4(color, 1.0);
}
Alguns detalhes que vale saber. Literais float precisam de ponto decimal (1.0, não 1). O comentário // @color transforma u_tint em um seletor de cor, tanto no Studio quanto no painel Ajustar do visualizador. Sliders funcionam do mesmo jeito: uniform float u_speed; // @param 0 3 1 cria um slider de 0 a 3 com padrão 1, e // @toggle 1 cria uma chave. Como cada controle é uma linha no código, ele viaja junto com o shader.
Controles sem digitar
Você não precisa escrever esses comentários à mão. Selecione um número no código, ou uma cor vec3, e clique em Criar slider: ele vira um controle no Studio e no painel Ajustar. Literais de cor ganham uma amostra clicável, e os erros de compilação aparecem marcados nas linhas que os causaram.
Veja o que o shader está ouvindo
A aba Áudio mostra o espectro bruto e o normalizado e os últimos 12 segundos de nível, graves, médios, agudos, ataques e batidas de bateria detectadas, cada um com o nome do uniform que o lê. Isso facilita muito o ajuste: se o anel quase não se mexe, você vê se u_bass realmente chega a 1.0 nessa faixa e ajusta a fórmula. A fonte de áudio pode ser a aba que o Deus está capturando ou uma faixa que você escolhe no computador.
Passes de renderização, feedback e outros nomes
Os comentários também configuram a renderização: // @pass buffA scale=0.5 adiciona um passe de renderização que você lê de volta como uniform sampler2D buffA;, // @feedback 0.09 esmaece o último quadro em vez de apagá-lo, o que cria rastros, e // @fps 30 limita a taxa de quadros. Se você está portando um shader no estilo Synesthesia, nomes como syn_BassLevel, syn_Hits ou TIME também são preenchidos pelo motor; declare-os no código para usá-los.
Salve no Deus
Clique em Salvar (⌘S) e o preset aparece em Presets › Personalizados com uma miniatura da prévia, ou em Salvar e tocar no Deus para o visualizador passar a tocá-lo na hora. Edições não salvas sobrevivem a um recarregamento como rascunho, e os seus presets ficam guardados localmente no navegador.
A partir daí, o seu shader toca no visualizador ao lado dos presets embutidos, então você também pode colocá-lo em tela cheia em uma TV ou segundo monitor. Se quiser entender a análise por trás dos uniforms, leia como funciona um visualizador de música.