Fract, floor e mod
Separe uma coordenada em número da célula e posição dentro da célula, para repetir o espaço.
Como funciona
Todo número se divide numa parte inteira e numa parte fracionária: 3.75 é 3 mais 0.75. Num shader, essa divisão é o jeito de ladrilhar o espaço. A parte inteira diz em qual célula o pixel está, e a fracionária diz onde ele está dentro dela.
floor e fract
Coordenadas UV Uma posição 2D numa superfície ou na tela, em geral de 0 a 1 nos dois eixos. Shaders desenham formas e padrões como funções dela.floor(x) arredonda para baixo até um número inteiro, e fract(x) é o que sobra, x - floor(x), sempre maior ou
igual a 0 e menor que 1. As duas funcionam componente a componente em vetores. Primeiro amplie a
UVUma posição 2D numa superfície ou na tela, em geral de 0 a 1 nos dois eixos. Shaders desenham formas e padrões como funções dela.uv = gl_FragCoord.xy / resolution
vec2 grid = uv * 8.0; // 0..8 de um lado a outro da tela
vec2 cell = floor(grid); // qual célula: de (0, 0) a (7, 7)
vec2 local = fract(grid); // onde dentro da célula: 0..1 de novo
Tudo o que você desenhar com local se repete em todas as células, porque cada célula agora vê o próprio intervalo de
0 a 1, uma pequena UV só dela. cell muda de célula para célula, então serve para diferenciar as cópias. Um tabuleiro
de xadrez alterna conforme a soma das coordenadas da célula:
float checker = mod(cell.x + cell.y, 2.0); // 0 ou 1, alternando
floor arredonda em direção ao menos infinito, não em direção ao zero: floor(-0.25) é -1.0, e fract(-0.25) é
0.75. Isso mantém todas as células do mesmo tamanho dos dois lados do zero. Truncar em direção ao zero deixaria a
célula em volta do zero com o dobro da largura das outras.
mod
mod(x, y) repete com qualquer período. Ele devolve x - y * floor(x / y), que para um y positivo fica entre 0 e
y; fract(x) é mod(x, 1.0). Use quando o período não for 1:
float stripes = step(0.1, mod(uv.x, 0.2)); // cinco listras, metade acesa e metade apagada
Como o mod do GLSL é construído sobre o floor, ele continua positivo para x negativo: mod(-0.25, 1.0) é 0.75. O
fmod do HLSL e o fmod do C truncam e devolvem -0.25, o que quebra o ladrilhamento à esquerda ou abaixo da origem
quando um shader é portado. No HLSL, escreva x - y * floor(x / y) onde o GLSL tinha mod.
Centralização e emendas
Para uma forma centralizada em cada célula, desloque a coordenada local: fract(grid) - 0.5 vai de -0.5 a 0.5 com o
centro da célula no zero, pronta para o length e as outras ferramentas das UVs centralizadas.
O fract salta de quase 1 de volta para 0 em toda borda de célula. A matemática calculada por pixel não se importa,
mas qualquer coisa que compare pixels vizinhos se importa: uma textura amostrada com local pode mostrar uma emenda de
um pixel nas bordas, porque a GPU escolhe o nível de mipmap pela rapidez com que a coordenada muda entre pixels, e o
salto parece uma mudança enorme. As derivadas de espaço de tela e a amostragem de texturas, mais adiante na ordem,
explicam o porquê e como evitar.
Leitura complementar
- fract (abre em uma nova aba)Referência
- mod (abre em uma nova aba)Referência
- Patterns (abre em uma nova aba)Livro