Rasterização
Neste primeiro trabalho, foi solicitada a criação de três funções de rasterização. Foram elas:
- PutPixel - Colocar um pixel na tela, dado a posição do pixel na tela bem como sua cor.
- DrawLine - Desenhar uma linha na tela(pelo algoritmo de Bresenham), utilizando a posição inicial e final da linha e também a sua cor RGBA.
- DrawTriangle - Desenhar um triangulo dado três pontos e sua cor RGBA.
Obs: Utilizou-se apenas a linguagem C/C++ para codificar as funções e o GLUT para rodar o framework.
A função putPixel é simples de ser implementada, sendo necessário apenas conhecer o offset que é o endereço do bloco de memória para determinada coordenada e saber utiliza-lo no ponteiro FBptr que apontava para o inicio da memória.
O cálculo do offset se dá por: 4*x + 4*y*IMAGE_WIDTH, onde (x,y) são as coordenadas. Incrementando obtemos a posição das outras componentes de cor.
Offset das componente:
R = 4*x + 4*y*IMAGE_WIDTH
G = 4*x + 4*y*IMAGE_WIDTH + 1
B = 4*x + 4*y*IMAGE_WIDTH + 2
A = 4*x + 4*y*IMAGE_WIDTH + 3
A figura abaixo mostra a execução da função PutPixel, colocando 4 pontos de cores diferentes em posições distintas na tela.
Figura 1. Exemplo da função putPixel. |
Parâmetros: (200, 100, 255, 255, 0, 255); - amarelo
(150, 110, 255, 0, 0, 255); - vermelho
(128, 256, 0, 0, 255, 255); - azul
(310, 335, 0, 255, 0, 255); - verde
Próxima etapa: Função drawLine.
Nesta função o algoritmo implementado foi o de Bresenham. Também conhecido como algoritmo do ponto médio, pois a partir do cálculo do mesmo, decide-se qual pixel deve ser ligado a fim de formar uma boa aproximação a uma linha reta entre dois pontos indicados.
Para as retas do 1º octante, dado um pixel sobre a reta, o próximo pixel é para direita (E) ou para Direita acima (NE). Tendo o pixel (xi,yi), o próximo pixel é NE em (xi+1, yi+1) ou E em (xi+1, yi).
Fazendo dy = y2 - y1, e dx = x2 - x1, a equação da reta em termos de sua inclinação pode
ser escrita como:
y = dy/dx*x + B
para:
d = 2 * dy - dx;
se d < 0
incrementamos para direita (E). Do contrário, incrementamos para direita acima (NE).
Exemplo da função drawLine com os seguintes parâmetros: (10, 255, 255, 0, 0, 255, 0, 255).
Figura 2. Exemplo da função drawLine. |
E por fim, a função drawTriangle. Esta função é simples de ser implementada, pois é só chamar a função drawLine três vezes. A única ponderação a ser feita é matemática, uma vez que os pontos precisam ser não colineares para que haja a formação do triângulo.
Figura 3. Exemplo da função drawTriangle. |
Parâmetros: (200, 150, 200, 350, 400, 350, 0, 0, 255, 255);
A nível de ilustração, abaixo temos a imagem da chamada de várias funções putPixel, bem como uma chamada da função drawLine e drawTriangle.
Figura 4. Exemplo de chamada das três funções: putPixel, drawLine e drawTriangle. |
O algoritmo de Bresenham, inicialmente causou dificuldade de entendimento na implementação. Portanto, devido ao maior grau de complexidade, a função drawLine foi a mais custosa.
As funções ficaram com muitos parâmetros, devido a especificar a cor, porém tudo está de fácil entendimento.
Referências
http://pt.wikipedia.org/wiki/Algoritmo_de_Bresenham
http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
http://marciobueno.com/arquivos/ensino/cg/CG_03_Primitivas_Graficas.pdf
Foley et al.; Computer Graphics - Principles and Practice with C; Addison-Wesley.
Slides das aulas.