Tentando entender a luz no Opengl, como simular uma luz solar realista?


13

Não sei se estou fazendo algo errado ou faltando alguma coisa, mas quero simular a luz do sol, como em um dia ensolarado.

Quando o objeto está voltado para a luz direcional, está bem iluminado e não há problemas. Se eu der uma volta no objeto e olhar para ele de volta, está escuro. Não está muito escuro porque estou usando, GL_AMBIENTmas ainda está muito escuro para um dia ensolarado. Se eu aumentar o valor, ele nunca ficará melhor porque o lado do objeto voltado para a luz será muito brilhante.

E há outro problema irritante com a luz ambiente: ao olhar para a parte de trás do objeto, não consigo ver nenhuma forma, apenas uma cor lisa. Difícil de explicar, aqui estão algumas fotos:

Frente do objeto: http://i.stack.imgur.com/YW53X.png
Voltar ao objeto: http://i.stack.imgur.com/Qufha.png

Como você pode ver facilmente, a parte da frente está bonita, você pode ver a forma daquela coisa vermelha. No verso, é claro, você não pode ver a mesma forma.

Agora, eu sei que estou olhando para a parte de trás de um objeto e olhando na direção da luz e ela deve ser mais escura que a parte da frente. Mas não deve parecer tão simples assim. Não é isso que vemos ao ir contra a luz do sol olhando para algum objeto, vemos que os objetos formam alguma forma.

Como posso ter o mesmo efeito (ou similar) no OpenGL?

Minha luz está atualmente definida assim:

float posLight0[4] = {-1.0f, 1.0f, 1.0f, 0.0f};
float ambLight0[4] = {0.5f, 0.5f, 0.5f, 0.5f};

glLightfv(GL_LIGHT0, GL_POSITION, posLight0);
glLightfv(GL_LIGHT0, GL_AMBIENT, ambLight0);

Eu sugiro que você considere usar shaders, se possível. O pipeline de função fixa do OpenGL usa um modelo de iluminação bastante simples, enquanto os sombreadores oferecem controle total sobre a matemática.
Incredulous Monk

Respostas:


11

Com a luz ambiente, seus objetos parecem muito brilhantes porque a luz difusa é adicionada à luz ambiente e a luz difusa é padronizada como 1.0. Isso soma 1,5, e tudo acima de 1,0 é fixo. Defina a luz difusa para 0,5:

float difLight0[4] = {0.5f, 0.5f, 0.5f, 1.0f};
glLightfv(GL_LIGHT0, GL_DIFFUSE, difLight0);

O segundo problema é mais difícil de resolver. Você pode tentar adicionar alguns detalhes finos à superfície, como textura ou mapa de relevo. No OpenGL, a luz ambiente é constante, mas no mundo real esse nunca é o caso. Para simular o mundo real, é necessária alguma forma de solução de iluminação global . A oclusão ambiental ajuda muito aqui, mas é mais difícil de implementar do que apenas definir os estados do OpenGL. Você pode fazer a oclusão do ambiente nos vértices do seu modelo no seu software de modelagem 3D ou usar o SSAO , mas não vou detalhar os detalhes.

O que você pode facilmente fazer é adicionar outra fonte de luz mais fraca de alguma outra direção (por exemplo, direção oposta). Isso não será realista, mas pelo menos dará uma certa forma às partes traseiras dos seus objetos.

Considere também adicionar destaques especulares ao seu aplicativo. Tornará os objetos brilhantes.

float specLight0[4] = {0.5f, 0.5f, 0.5f, 1.0f};
glLightfv(GL_LIGHT0, GL_SPECULAR, specLight0);
glMaterialfv(GL_FRONT, GL_SHININESS, 10.0f); // Shininess between 0 and 128

Você também pode especificar cores claras e materiais separadamente, especialmente se os padrões não forem adequados para você.


Portanto, não há uma maneira simples e direta de fazer o que eu quero no OpengGL ... Que pena. Talvez eu tente adicionar outra fonte de luz, mas como exatamente especifico a intensidade da luz?
Rfgamaral

O GL_SPECULARe GL_SHININESSnão parece produzir nenhum efeito ... Eu mudei glMaterialfvpara glMaterialiporque não estava compilando. E também tentei um valor maior como 128. Parece o mesmo para mim ... Talvez o problema esteja no meu modelo carregado (obj / mtl), terá que dar uma olhada.
Rfgamaral

1
@Nazgulled Acabei de verificar se o spec0 light0 é padrão em 1.0, mas o specular material é padronizado em 0.0. Então mude glLightfv (GL_LIGHT0, GL_SPECULAR, specLight0); para glMaterialfv (GL_FRONT, GL_SPECULAR, specLight0); Também é bom definir glLightModeli (GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); ou o especular pode ser calculado incorretamente quando a câmera está girando.
msell

1
@Nazgulled Para a luz secundária, defina o ambiente e o especular para zero e algum valor pequeno como 0,2 para o difuso. Você também pode definir o ambiente de todas as luzes como zero e usar o ambiente global com GL_LIGHT_MODEL_AMBIENT.
msell

2

A luz ambiente do OpenGL é de uma única cor, mas a luz ambiente no mundo real geralmente é mais brilhante por cima e mais escura por baixo. Você pode aproximar isso no OpenGL configurando a luz ambiente para azul muito escuro e adicionando uma luz direcional azul escura apontando para baixo. Isso, além de uma luz direcional branca brilhante vinda de onde o sol está, pode aproximar muito bem a luz externa.

O que você realmente deve fazer é escrever um sombreador que calcule a luz por pixel, mas chegar de onde você está vai demorar um pouco.


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.