Rasterização de pontos e linhas


Nesse post será abordado uma forma de implementação dos algoritmos de rasterização de pontos e linhas escritos na linguagem de programação C/C++, com o suporte das bibliotecas da GLUT (The OpenGL Utility Toolkit) e do framework disponibilizado pelo professor, que simula o acesso à memória de vídeo.

Rasterização de pontos

A rasterização dos pontos será feita através da função PutPixel que rasteriza um ponto na memória de vídeo, recebendo como parâmetros as coordenadas (x,y) do pixel na tela e uma cor em RGBA.

A implementação da função PutPixel é bem simples, primeiro é necessário identificar a posição do pixel na memória de vídeo uma vez que as coordenadas recebidas estão em um plano bidimensional, e a memória é linear. Para isso, foi apresentado em sala de aula uma expressão que calcula a posição de um pixel na memória, considerando a largura (em pixels) da janela.




Abaixo segue um exemplo da implementação da função PutPixel.

Função PutPixel

Resultado da função:

Teste da função PutPixel

Rasterização de Linhas

A rasterização de linhas consiste em, dado dois pontos extremos de um seguimento de reta, determinar que pixeis localizados entre eles devem ser plotados para compor o seguimento.

A função DrawLine rasteriza uma linha na tela, recebendo como parâmetros os pontos extremos, ou seja, o ponto inicial (x0,y0) e o ponto final (x1,y1), além da cor (RGBA) da linha.

O algoritmo

O algoritmo utilizado para rasterização, nesse caso, é o algoritmo de Bresenham que realiza a rasterização de linhas empregando apenas operações com números inteiros, permitindo assim, um melhor desempenho. Ele é baseado no critério do ponto médio.


Algoritmo de Bresenham


O problema desse algoritmo é que ele funciona apenas para retas no primeiro octante, ou seja, retas entre 0º e 45º.

Abaixo temos dois printscreens que demonstram a limitação do algoritmo.

Desenho no primeiro octante
Desenho no quinto octante

Para que possamos representar as retas nos demais octantes, precisamos generalizar o algoritmo.


Generalização do algoritmo de Bresenham


Como a tela não possui coordenadas negativas e precisamos representar as retas dos demais octantes, modificaremos o algoritmo de tal forma que, todas as retas consigam ser representadas no primeiro quadrante, mantendo seu sentido e inclinação.

A primeira modificação a ser feita, e a mais fácil, é considerar apenas os valores absolutos das variações dx e dy.

A segunda modificação é expandir o algoritmo para ar suporte à simetria das retas com o seguinte algoritmo:

Passo 1: Verificar se os valores das coordenadas (xf, yf) do ponto final são menores que as coordenadas (xi,yi) do ponto inicial.

Passo 2: Se xf < xi então o valor de x será decrementado, ou seja, o próximo pixel estará à esquerda do pixel anterior, caso contrário, x será incrementado e o próximo pixel estará à direita.

Passo 3: Se yf < yi então o valor de x será decrementado, ou seja, o próximo pixel estará abaixo do pixel anterior, caso contrário, x será incrementado e o próximo pixel acima.

Código:

A terceira modificação adiciona ao algoritmo uma rotina que desenha retas com ângulo de 90º.

Passo 1: Verificar se há variação da reta no eixo x do plano.

Passo 2: Se a reta for invariante no eixo x, ou seja, dx = 0. plota-se os pontos com o valor constante de x e incrementa o valor de y até que yi = yf.

Código:


Para a quarta e ultima modificação, verificamos se o valor da variação da reta no eixo y é maior que a variação da reta no eixo x.

Passo 1: Verificar se dy > dx.

Passo 2: Se dy > dx então troque o valor de dx com o valor de dy e faça a iteração em relação ao eixo y.

Código:

Resultado após as modificações feitas no algoritmo:

Resultado da generalização do algoritmo de Bresenham

Interpolação de cores

A interpolação de cores em aplicada a uma reta nada mais é que a mudança gradativa das cores ao longo dessa reta, partindo da cor do ponto inicial até chegar na cor do ponto final.

Tendo isso em mente, foi desenvolvida a função ColorIncrement que calcula o valor de incremento da cada componente RGBA baseado na variação de cada um.

Para obter a variação é preciso calcular a diferença entre os valores da cor inicial e os valores da cor final, e depois dividir os resultados pela distância entre os pontos, uma vez que queremos que a cor mude gradativamente.

Obs.: Neste trabalho não é utilizado o valor do Alfa (A).

Código:
Cálculo do valor de incremento
Resultado da aplicação da interpolação de cores:

Resultado da interpolação de cores

Rasterização de triângulos

Após ter implementado e modificado o algoritmo de rasterização de Brasenham, é possível plotar triângulos a partir da rasterização de suas arestas na tela. A função DrawTriangle será implementada com esse propósito, rasterizar arestas, recebendo como parâmetros as posições dos três vértices vem como as cores (RGBA) de cada vértice.

Código:


Resultado da rasterização de triângulos:

Resultado da função DrawTriangle

Dificuldades

Na generalização do algoritmo de Brasenham esteve a maior dificuldade encontrada neste trabalho, levando em conta a análise do algoritmo e o tempo para desenvolver uma solução do problema, incluindo tentativas e erros.

Melhorias

Melhorias podem ser feitas no desempenho do algoritmo generalizado, implementar um algoritmo para o preenchimento dos triângulos e desenvolver funções que permitam alterar a inclinação das retas em tempo de execução.

Repositório

O algoritmo implementado neste trabalho pode ser encontrado no seguinte repositório:

Referências:

Comentários