Configuração Inicial
Antes de começar o trabalho foi preciso instalar o OpenGL/Glut onde foi instalado o FreeGlut e FreeGlut-Dev em ambiente Linux.
Rasterização de Ponto
Para desenhar um pixel foi utilizado um ponteiro FBptr onde o mesmo aponta para o inicio da memória de vídeo, onde especificamente trata-se do pixel(0,0).
Todo pixel da tela é formado por quatro componentes (R,G,B,A), as quais em conjunto, ocupam um espaço em memória de 4 bytes, sendo 1 byte para cada componente. Podemos acessar qualquer pixel da tela.
Foi feito uma estrutura para organizar e armazenar os valores do pixel.
Em seguida temos a função PutPixel, onde recebe como parâmetros as coordenadas do pixel e a cor ao qual será exibido na tela.
Para testar a função foram feitas modificações na função MyGlDraw, como mostrado no trecho de código abaixo:
Após compilar o código e executá-lo, temos o seguinte resultado:
Rasterização de Retas
Para determinada tarefa utilizou-se a função DrawLine onde a mesma é responsável pela rasterização da reta. Ela receberá como parâmetros dois pontos e suas respectivas cores. A reta formada por esses dois pontos, partindo do ponto inicial com coordenadas (x0, y0) até chegar ao ponto final com coordenadas (x1, y1) . O algoritmo utilizado como base para a execução desta função será o algoritmo de Bresenham.
Algoritmo de Brasenham
O algoritmo de Bresenham é um algoritmo utilizado para criar retas, ele utiliza uma variável de decisão normalmente chamada “d”. A cada novo ponto desenhado numa determinada posição (x,y), o valor de d é recalculado para determinar onde será desenhado o próximo ponto. Se o novo valor for positivo, o próximo ponto será desenhado no pixel que se encontra nas coordenadas (x+1, y+1), caso contrário, o próximo ponto será desenhado nas coordenada (x+1, y).
void DrawLine(ponto p_inicial, ponto p_final, color cor){
int slope;
int dx, dy, incremento_E, incremento_NE, d, x, y;
//inverte a linha x1 > x2
if (p_inicial.x > p_final.x){
DrawLine(p_final, p_inicial, cor);
return;
}//if
dx = p_final.x - p_inicial.x;
dy = p_final.y - p_inicial.y;
if (dy < 0){ //Incremento decrescente
slope = -1;
dy = -dy;
}
else{//Incremento Crescente
slope = 1;
}
// Constante de Bresenham
incremento_E = 2 * dy;
incremento_NE = 2 * dy - 2 * dx;
d = 2 * dy - dx;
x = p_inicial.x;/**inicia x com o valor de p_inicial**/
y = p_inicial.y;
PutPixel(p_inicial.x, p_inicial.y, cor);
while(x != p_final.x){
if (d <= 0){
d += incremento_E;
x++;/**Adicionado incremento de x**/
}
else{
d += incremento_NE;
x++;/**Adicionado incremento de x**/
y += slope;
}
PutPixel(x, y, cor);
}
}//fim da DrawLine
Para testar este algoritmo, a modificação na função MyGlDraw é mostrada no trecho de código a seguir e posteriormente o resultado obtido:
Interpolação Linear e Rasterização para todos os quadrantes.
O caso mais simples de resolver é quando x0 > x1. Sempre que este
caso ocorrer basta inverter os pontos inicial e final da reta, o
resultado será a mesma reta, só que agora com x0 < x1. Com isso é
garantido que x0 < x1 sempre irá ocorrer.
Para o caso de y0 > y1, um dos problemas é que dy terá sinal
negativo, a solução será inverter o sinal de dy para que ele volte a ser
positivo. O outro problema é que y agora deverá ser decrementado e não
somente incrementado, como o algoritmo faz. A solução
será criar uma variável que permita que as coordenadas y sejam
incrementadas ou decrementadas dependendo da situação.
Para o caso de dx < dy, o algoritmo é praticamente o mesmo, basta
apenas trocar todos valores de dx por dy e vice-versa, levando em
consideração que agora y também irá variar quando d<=0, e não x.
Feitas essas modificações e implementado a
interpolação linear, o código final da função DrawLine é mostrado
abaixo:
void DrawLine(ponto p_inicial, ponto p_final, color color0, color color1){
color cor;
int slope = 1; // Diz se o incremento de y é crescente ou decrescente
int dx, dy, incremento_E, incremento_NE, d, x, y;
int i = 0;
// Onde inverte a linha x1 > x2
if (p_inicial.x > p_final.x){
DrawLine(p_final, p_inicial, color0, color1);
return;
}//if
dx = p_final.x - p_inicial.x;
dy = p_final.y - p_inicial.y;
if(p_inicial.y > p_final.y){
dy = -dy;
slope = -1;
}else{
slope = 1;
}
/*if (dy < 0){ //Incremento decrescente
slope = -1;
dy = -dy;
}
else{//Incremento Crescente
slope = 1;
}*/
PutPixel(p_inicial.x, p_inicial.y, color0);
/*// Constante de Bresenham
incremento_E = 2 * dy;
incremento_NE = 2 * dy - 2 * dx;
d = 2 * dy - dx;
*/
x = p_inicial.x;
y = p_inicial.y;
//PutPixel(p_inicial.x, p_inicial.y, color);/**Antes não tinha essa linha**/
if(dx >= dy){
// Constante de Bresenham
incremento_E = 2 * dy;
incremento_NE = 2 * dy - 2 * dx;
d = 2 * dy - dx;
while(x != p_final.x){
if (d <= 0){
d += incremento_E;
x++;/**Adicionado incremento de x**/
}
else{
d += incremento_NE;
x++;/**Adicionado incremento de x**/
y += slope;
}
/* Interpolação Linear de cores*/
i++;
int R = color0.R - ((i)/(float)dx) * (color0.R - color1.R);
int G = color0.G - ((i)/(float)dx) * (color0.G - color1.G);
int B = color0.B - ((i)/(float)dx) * (color0.B - color1.B);
int A = color0.A - ((i)/(float)dx) * (color0.A - color1.A);
cor.R = R;
cor.G = G;
cor.B = B;
cor.A = A;
PutPixel(x, y, cor);
}//while
}else{
int d = 2 * dx - dy;
int incremento_E = 2 * dx;
int incremento_NE = 2 * dx - 2 * dy;
while (y != p_final.y){//Enquanto y for diferente de y1
if (d <= 0) {//se d <= 0
d += incremento_E;//d será somado ao valor de incr_e
y+=slope;
} else {//Senão,
d += incremento_NE;//d será somado ao valor de incr_ne
x++;
y+=slope;
}
/* Interpolação Linear de cores*/
i++;
int R = color0.R - ((i)/(float)dx) * (color0.R - color1.R);
int G = color0.G - ((i)/(float)dx) * (color0.G - color1.G);
int B = color0.B - ((i)/(float)dx) * (color0.B - color1.B);
int A = color0.A - ((i)/(float)dx) * (color0.A - color1.A);
cor.R = R;
cor.G = G;
cor.B = B;
cor.A = A;
PutPixel(x, y, cor);
}
}
}//fim da DrawLine
color cor;
int slope = 1; // Diz se o incremento de y é crescente ou decrescente
int dx, dy, incremento_E, incremento_NE, d, x, y;
int i = 0;
// Onde inverte a linha x1 > x2
if (p_inicial.x > p_final.x){
DrawLine(p_final, p_inicial, color0, color1);
return;
}//if
dx = p_final.x - p_inicial.x;
dy = p_final.y - p_inicial.y;
if(p_inicial.y > p_final.y){
dy = -dy;
slope = -1;
}else{
slope = 1;
}
/*if (dy < 0){ //Incremento decrescente
slope = -1;
dy = -dy;
}
else{//Incremento Crescente
slope = 1;
}*/
PutPixel(p_inicial.x, p_inicial.y, color0);
/*// Constante de Bresenham
incremento_E = 2 * dy;
incremento_NE = 2 * dy - 2 * dx;
d = 2 * dy - dx;
*/
x = p_inicial.x;
y = p_inicial.y;
//PutPixel(p_inicial.x, p_inicial.y, color);/**Antes não tinha essa linha**/
if(dx >= dy){
// Constante de Bresenham
incremento_E = 2 * dy;
incremento_NE = 2 * dy - 2 * dx;
d = 2 * dy - dx;
while(x != p_final.x){
if (d <= 0){
d += incremento_E;
x++;/**Adicionado incremento de x**/
}
else{
d += incremento_NE;
x++;/**Adicionado incremento de x**/
y += slope;
}
/* Interpolação Linear de cores*/
i++;
int R = color0.R - ((i)/(float)dx) * (color0.R - color1.R);
int G = color0.G - ((i)/(float)dx) * (color0.G - color1.G);
int B = color0.B - ((i)/(float)dx) * (color0.B - color1.B);
int A = color0.A - ((i)/(float)dx) * (color0.A - color1.A);
cor.R = R;
cor.G = G;
cor.B = B;
cor.A = A;
PutPixel(x, y, cor);
}//while
}else{
int d = 2 * dx - dy;
int incremento_E = 2 * dx;
int incremento_NE = 2 * dx - 2 * dy;
while (y != p_final.y){//Enquanto y for diferente de y1
if (d <= 0) {//se d <= 0
d += incremento_E;//d será somado ao valor de incr_e
y+=slope;
} else {//Senão,
d += incremento_NE;//d será somado ao valor de incr_ne
x++;
y+=slope;
}
/* Interpolação Linear de cores*/
i++;
int R = color0.R - ((i)/(float)dx) * (color0.R - color1.R);
int G = color0.G - ((i)/(float)dx) * (color0.G - color1.G);
int B = color0.B - ((i)/(float)dx) * (color0.B - color1.B);
int A = color0.A - ((i)/(float)dx) * (color0.A - color1.A);
cor.R = R;
cor.G = G;
cor.B = B;
cor.A = A;
PutPixel(x, y, cor);
}
}
}//fim da DrawLine
Ao compilar e executar temos o seguinte resultado:
Rasterização de Triângulos
Feito todos os processos anteriores, rasterizar triângulo passa a ser o mais fácil, onde é só chamar a função DrawLine 3 vezes. Para isso, foi criado a função DrawTriangle, onde ela recebe como parâmetros os 3 pontos do triângulo e suas cores, onde a partir daí será feito as retas que formaram o triângulo.
Por fim, temos o seguinte resultado:
Referências
RASTERIZAÇÃO. In: WIKIPÉDIA, a enciclopédia livre. Flórida: Wikimedia Foundation, 2015. Disponível em: http://pt.wikipedia.org/w/index.php?title=Rasteriza%C3%A7%C3%A3o&oldid=35151352. Acesso em: 01 maio 2015.
ALGORITMO DE BRESENHAM. In: WIKIPÉDIA, a enciclopédia livre. Flórida: Wikimedia Foundation, 2015. Disponível em: http://pt.wikipedia.org/w/index.php?title=Algoritmo_de_Bresenham&oldid=34646662. Acesso em: 02 maio 2015.
LUCIANA MONTERA. INTERPOLAÇÃO LINEAR. Disponível em: http://www.facom.ufms.br/~montera/Interpolacao_alunos.pdf. Acesso em: 02 maio 2015.
0 comentários:
Postar um comentário