domingo, 7 de agosto de 2016

Cores + PutPixel

Para colocarmos um pixel de determinada cor na tela precisamos implementar uma função que receba a posição do pixel em coordenadas x,y e sua cor em RGBA. Vamos falar um pouco sobre esse sistema de cores.

O sistema RGBA contém quatro canais: R(red), G(green), B(blue), A(alpha), que são valores numéricos que, para o projeto, variam de 0 a 255. Cada um dos três primeiros canais define a intensidade luminosa das três cores primárias que temos em um pixel na tela do computador. Por exemplo, se tivermos o canal R com um valor de 255 e os outros dois canais de cores primárias com 0, o pixel ficará vermelho. Se todas os três canais receberem 255, teremos o branco, e se todos receberem 0, teremos o preto. Assim, a mistura de diferentes intensidades de cada cor primária gera as diferentes cores que podemos enxergar! O último canal, Alpha, determina a "transparência" da cor do pixel, mas não vamos utilizar ele neste projeto.

Então, precisamos de quatro variáveis para representar a cor de um pixel. Vamos definir um novo tipo de variável para facilitar testes no futuro, o tipo cor:

struct cor{
    float r;
    float g;
    float b;

    float a = 255;    
};

Definimos as cores como float pois vamos modificá-las quando estivermos fazendo a interpolação linear. Como não vamos utilizar o canal Alpha, podemos definir ele como sendo sempre 255, ou seja, a cor do pixel é completamente opaca.

Agora, por conveniência, vamos inicializar algumas variáveis do tipo cor para fazermos testes no futuro:

cor white = (white = cor(), white.r = 255, white.g = 255, white.b = 255, white);
cor red = (red = cor(), red.r = 255, red.g = 0, red.b = 0, red);
cor green = (green = cor(), green.r = 0, green.g = 255, green.b = 0, green);
cor blue = (blue = cor(), blue.r = 0, blue.g = 0, blue.b = 255, blue);

Um dos problemas que eu encontrei foi como definir e inicializar variáveis desse struct, já que o código é em C++. Assim é feio, mas funciona.

Pronto, temos cores, agora vamos ver como escrever esses valores na "memória de vídeo" fake do framework. Sabendo que cada canal pode varias entre 0 e 255, temos 256 estados possíveis para cada canal, ou seja, podemos utilizar 1 byte para cada um dos quatro canais de cor, totalizando 4 bytes por pixel.

Para calcular em que posição de memória devemos escrever os valores de cada, utilizamos a equação

4*(Posição x do pixel) + 4*(Posição y do pixel)*(Largura da tela) + 0, 1, 2 ou 3, dependendo de qual canal queremos escrever na memória.

Assim, podemos finalmente implementar a função PutPixel em toda sua glória:


void PutPixel(int x, int y,  cor color){

    FBptr[4*x + 4*y*IMAGE_WIDTH + 0] = color.r;   // componente R
    FBptr[4*x + 4*y*IMAGE_WIDTH + 1] = color.g;   // componente G
    FBptr[4*x + 4*y*IMAGE_WIDTH + 2] = color.b;   // componente B
    FBptr[4*x + 4*y*IMAGE_WIDTH + 3] = color.a;   // componente A
}

A função recebe a coordenada x,y do pixel e uma variável tipo cor, escrevendo na memórias os valores de cada canal de color. O comando FBptr faz parte da framework do professor. IMAGE_WIDTH é definido em definitions.h como o número de colunas na tela, ou largura da tela, com valor 512.

Referências: Material do professor Christian.

Álbum da vez:

Nenhum comentário:

Postar um comentário