Pular para o conteúdo
Fundamento · Funções de formaIniciante

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

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 UV, para caberem várias células na tela:

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