{
Haha, essas duas lições foram traduzidas há muito tempo, mas ainda não foram postadas. Todo mundo está esperando há muito tempo (alguém está esperando mais?)
transparência simples
A grande maioria dos efeitos especiais no OpenGL está relacionada a algum tipo de mistura (de cores).
A mistura de cores é definida como a combinação da cor de um determinado pixel com a cor do pixel correspondente desenhado na tela.
A maneira como as duas cores são combinadas depende dos valores dos componentes do canal alfa da cor e/ou da função de mistura de cores usada.
Alpha é geralmente o quarto componente de cor no final do valor da cor.
Nas lições anteriores usamos GL_RGB para especificar os três componentes da cor.
O GL_RGBA correspondente pode especificar o valor do componente alfa.
Indo um passo adiante, podemos usar glColor4f() em vez de glColor3f().
A maioria das pessoas concorda que o componente Alpha representa a transparência de um material.
Isso significa que um valor alfa de 0,0 representa um material completamente transparente.
Um valor alfa de 1,0 representa um material completamente opaco.
fórmula de mistura de cores
Se você não está interessado em matemática e quer apenas ver como conseguir transparência, pule esta seção.
Se você deseja uma compreensão mais profunda de como funciona a mistura (de cores), esta seção deve ser para você.
『Adição de CKER: Na verdade não é difícil ^-^. A fórmula do artigo original é a seguinte, deixe o CKER falar sobre isso novamente.
Na verdade, o princípio básico da mistura é separar a cor de cada pixel e a cor de fundo da imagem a ser separada de acordo com as regras RGB.
De acordo com - componente de cor RGB da imagem * valor alfa + componente de cor RGB do fundo * (valor 1-alfa)
-Depois de misturar com uma fórmula tão simples, os componentes RGB obtidos pela mistura são finalmente mesclados novamente. 』
A fórmula é a seguinte:
(Rs Sr + Rd Dr, Gs Sg + Gd Dg, Bs Sb + Bd Db, As Sa + Ad Da)
OpenGL calcula o resultado da mistura de cores desses dois pixels de acordo com a fórmula acima.
Os s e r minúsculos representam pixels de origem e pixels de destino, respectivamente. Os S e D maiúsculos são os fatores de mistura de cores correspondentes.
Eles determinam como você mistura cores para esses pixels.
Na maioria dos casos, os valores de mistura alfa de cada canal de cor são os mesmos.
Desta forma, temos (As, As, As, As) para o pixel de origem,
Os pixels alvo são 1, 1, 1, 1) - (As, As, As, As).
A fórmula acima passa a ser a seguinte:
(Rs As + Rd (1 - As), Gs As + Gd (1 - As), Bs As + Bs (1 - As), As As + Ad (1 - As))
Esta fórmula produz um efeito transparente/translúcido.
Mistura de cores em OpenGL
As etapas para implementar a mistura de cores no OpenGL são semelhantes ao processo OpenGL mencionado anteriormente.
Em seguida, defina a fórmula e desative o cache de profundidade de gravação ao desenhar objetos transparentes.
Porque queremos desenhar o objeto atrás de uma forma semitransparente.
Esta não é a maneira correta de misturar cores, mas na maioria das vezes funciona bem em projetos simples.
Adição de Rui Martins: O processo correto de mistura de cores deve ser desenhar primeiro a cena inteira e depois desenhar os gráficos transparentes.
E eles são desenhados na ordem inversa do buffer de profundidade (os objetos mais distantes são desenhados primeiro).
Considere a combinação alfa de dois polígonos (1 e 2). Ordens de desenho diferentes darão resultados diferentes.
(Aqui assume-se que o polígono 1 está mais próximo do observador, então o processo correto deve desenhar primeiro o polígono 2 e depois desenhar o polígono 1.
Como você pode ver na realidade,
A luz que vem de trás desses dois polígonos <transparentes> sempre passa primeiro pelo polígono 2.
Depois passa pelo polígono 1 e finalmente chega aos olhos do observador. )
Quando o cache de profundidade está ativado, você deve classificar os gráficos transparentes por profundidade,
E desenhe esses objetos transparentes depois que todas as cenas forem desenhadas. Caso contrário, você obterá resultados incorretos.
Eu sei que é doloroso fazer isso algumas vezes, mas é o jeito certo de fazer.
Usaremos o código da Lição 7.
Comece adicionando duas novas variáveis no início do código. Reescrevi todo o código para maior clareza.
}
Var
h_RC: HGLRC; // Contexto de renderização (tabela de descrição de sombreamento).
h_DC: HDC; // Contexto do dispositivo (tabela de descrição do dispositivo)
h_Wnd: HWND; // identificador da janela
h_Instance: HINST; // Instância do programa (instância).
teclas: Array[0..255] Of Boolean; // Array para rotinas de teclado
light : Boolean; // fonte de luz ligada/desligada;
blend : Boolean; // Mesclagem DESLIGADA/LIGADA (novo)
lp : Boolean; // A tecla L está pressionada?
fp : Boolean; // A tecla F está pressionada?
bp : Boolean; // A tecla B está pressionada?
xrot: GLfloat; // rotação X
yrot : GLfloat; // rotação Y
xspeed : GLfloat; // Velocidade de rotação X
yspeed : GLfloat; // Velocidade de rotação Y
z : GLfloat = -5.0 f; // Distância profunda na tela
LightAmbient: Array[0..3] Of GLfloat = (0,5, 0,5, 0,5, 1,0); //Parâmetros de luz ambiente (novos);
LightDiffuse: Array[0..3] Of GLfloat = (1.0, 1.0, 1.0, 1.0) // Parâmetros de luz difusa (novos);
LightPosition: Array[0..3] Of GLfloat = (0.0, 0.0, 2.0, 1.0) // Posição da fonte de luz (nova));
filtro: GLuint; // Tipo de filtro
textura: Array[0..2] Of GLuint; // Espaço de armazenamento para 3 texturas
Procedimento glGenTextures(n: GLsizei; Var texturas: GLuint externo stdcall);
opengl32;
Procedimento glBindTexture(destino: GLenum; textura: GLuint externo);
opengl32;
Função gluBuild2DMipmaps(destino: GLenum; componentes, largura, altura: GLint;
formato, tipo: GLenum dados: Ponteiro): Inteiro stdcall;
'gluBuild2DMipmaps';
{
Em seguida, vá para LoadGLTextures().
Encontre se (TextureImage[0]=LoadBMP('Data/Crate.bmp'))
Esta linha. Agora estamos usando uma textura de vidro colorido no lugar da textura de caixa de madeira da lição anterior.
if (TextureImage[0]=LoadBMP("Data/glass.bmp")); // Carrega bitmap de vidro (modificado)
}
Function LoadTexture: boolean; //Carrega o bitmap e converte-o em uma textura
Var
Status: booleano; // Indicador de status
TextureImage: Array[0..1] Of PTAUX_RGBImageRec; // Cria espaço de armazenamento de textura
Começar
Estado := falso;
ZeroMemory(@TextureImage, sizeof(TextureImage)); // Define o ponteiro para NULL
TextureImage[0] := LoadBMP('Walls.bmp');
Se TextureImage[0] <> Nulo Então
Começar
Status := VERDADEIRO; // Define o status como VERDADEIRO;
glGenTextures(1, textura[0]); // Cria textura
// Cria o mapa de filtro mais próximo
glBindTexture(GL_TEXTURE_2D, textura[0]);
//Gera textura
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0].tamanhoX,
TexturaImagem[0].tamanhoY, 0, GL_RGB, GL_UNSIGNED_BYTE,
TexturaImage[0].data);
glBindTexture(GL_TEXTURE_2D, textura[1]); //Use uma textura típica gerada a partir de dados bitmap
//Gera textura
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0].tamanhoX,
TexturaImagem[0].tamanhoY, 0, GL_RGB, GL_UNSIGNED_BYTE,
TexturaImage[0].data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//Cria textura MipMapped
glBindTexture(GL_TEXTURE_2D, textura[2]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_NEAREST); // (novo)
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage[0].sizeX,
TextureImage[0].sizey, GL_RGB, GL_UNSIGNED_BYTE,
TexturaImage[0].data); //(novo) }
Fim;
Se atribuído(TextureImage[0]) Then // Se a textura existe
Se atribuído(TextureImage[0].data) Then // Se a imagem de textura existe
TextureImage[0].data := Nil; // Libera a memória ocupada pela imagem de textura
TextureImage[0] := Nil; // Libera a estrutura da imagem
resultado := Status; // Status de retorno
Fim;
{
Adicione as duas linhas a seguir à seção de código glInit().
A primeira linha desenha este objeto com brilho total e fornece 50% de mesclagem alfa (semitransparente).
Quando a opção de mesclagem estiver ativada, este objeto ficará 50% transparente.
A segunda linha define o tipo de mistura usada.
Adicionado por Rui Martins:
Um valor de canal alfa de 0,0 significa que o material do objeto é completamente transparente.
1,0 significa completamente opaco.
}
Procedimento glInit(); // Inicie todas as configurações do OpenGL aqui
Começar
If (Not LoadTexture) Then // Chama a sub-rotina de carregamento de textura
exit; // Se não conseguir carregar, saia
glEnable(GL_TEXTURE_2D); // Habilita mapeamento de textura
glShadeModel(GL_SMOOTH); // Habilita suavização de sombra
glClearColor(0.0, 0.0, 0.0, 0.0); // fundo preto
glClearDepth(1.0); //Definir o buffer de profundidade
glEnable(GL_DEPTH_TEST); // Habilita teste de profundidade
glDepthFunc(GL_LESS); // Tipo de teste de profundidade realizado
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); //Cálculo de projeção de perspectiva altamente otimizado
glLightfv(GL_LIGHT1, GL_AMBIENT, @LightAmbient[0]);
glLightfv(GL_LIGHT1, GL_DIFFUSE, @LightDiffuse[0]);
glLightfv(GL_LIGHT1, GL_POSITION, @LightPosition); // Posição da fonte de luz
glEnable(GL_LIGHT1); // Habilita fonte de luz nº 1;
glColor4f(1.0, 1.0, 1.0, 0.5); // Brilho total, mistura alfa de 50% (novo)
glBlendFunc(GL_SRC_ALPHA, GL_ONE); // Função de mesclagem translúcida baseada no valor do canal alfa do pixel de origem (novo)
Fim;
{Encontre o seguinte trecho de código próximo ao final da Lição 7.
If keys[VK_LEFT] Then //A tecla de direção Esquerda está pressionada?
yspeed := yspeed - 0.01; //Se sim, reduza yspeed
Seguindo o código acima, adicionamos o seguinte código.
Estas linhas monitoram se a tecla B está pressionada.
Nesse caso, o computador verifica se a opção de mesclagem está ativada.
Em seguida, defina-o para o estado oposto.
}
If (keys[ord('B')] And Not bp) Then //A tecla B está pressionada e bp é FALSE?
Começar
bp := TRUE; // Se sim, bp é definido como TRUE;
blend := Não blend; // Muda as opções de mesclagem para TRUE / FALSE
If (blend) Then // A mistura está ativada?
Começar
glEnable(GL_BLEND); //Ativa a mesclagem
glDisable(GL_DEPTH_TEST); // Desativa o teste de profundidade
Fim
Senão // mais
Começar
glDisable(GL_BLEND); //Desativa a mesclagem
glEnable(GL_DEPTH_TEST); //Ativa o teste de profundidade
Fim;
Fim;
If (Not keys[ord('B')]) Then // A tecla B foi liberada?
Começar
bp := FALSE; // Se sim, defina bp como FALSE;
Fim;
{
Mas como você pode especificar a cor da mistura ao usar o mapeamento de textura? É muito simples.
Ao ajustar o modo de textura, a cor de cada pixel da textura da textura é determinada pelo parâmetro do canal alfa.
Obtido multiplicando a cor do pixel atual.
Por exemplo, a cor desenhada é (0,5, 0,6, 0,4),
Multiplicaremos as cores para obter (0,5, 0,6, 0,4, 0,2)
(Quando o parâmetro alfa não é especificado, o padrão é zero).
É isso! Implementar a combinação Alpha no OpenGL é realmente muito simples!
}
{
Nota original (13/11/99)
Meu código de mistura de cores (NeHe) foi modificado para tornar os objetos exibidos mais realistas.
Usar o parâmetro alfa para mesclar os pixels de origem e de destino ao mesmo tempo fará com que os traços artificiais do objeto pareçam óbvios.
Isso fará com que a parte de trás do objeto pareça mais escura nas laterais.
Basicamente, o objeto parecerá estranho.
O método de mistura de cores que usei pode não ser o melhor, mas funciona.
Com as luzes ativadas, os objetos parecem realistas.
Obrigado ao Tom por fornecer o código original. O método de mistura de cores que ele usou está correto.
Mas o objeto não parece tão atraente quanto esperado :)
O código foi modificado novamente devido a problemas com a função glDepthMask() em algumas placas gráficas.
Este comando não parece ser muito eficaz ao ativar ou desativar testes de buffer de profundidade em algumas placas,
Portanto, converti o código para ativar ou desativar o teste de buffer de profundidade nos antigos glEnable e glDisable.
Mistura alfa de mapas de textura
O parâmetro alfa usado para o mapa de textura pode ser lido no mapa do problema assim como a cor.
O método é o seguinte: você precisa carregar o material necessário e obter seu parâmetro alfa ao mesmo tempo.
Em seguida, use o formato de cor GL_RGBA ao chamar glTexImage2D().
}