Pergunta de luz OpenG ES
-
22-09-2019 - |
Pergunta
Sou novo no OpenGL ES e estou desenvolvendo no Objective-C para iPhone.
O que estou tentando entender é como a luz está posicionada no meu frustum. É assim que eu faço:
Crio um quadrado e o coloco como "piso" no meu frustum. Estou colocando a luz, logo acima, no meio do chão e aponte a direção da luz para baixo. Agora, espero que o círculo leve no chão esteja no meio. Mas não é, é mais para as costas (fugir). Por quê?
near = 8.0
far = 28
light position = {0.0, 0.0, -10.0}
light direction = {0.0, -1.0, 0.0}
Floor coordinates = {-0.3153, -0.473, -20.0},
{-0.3153, -0.473, 0.0},
{0.3153, -0.473, -20.0},
{0.3153, -0.473, 0.0},
Isso juntos não deveria fazer o círculo de luz estar no meio do chão e não se posicionar um pouco para trás?
Aqui está meu código significativo:
Configurando a exibição:
-(void)setupView:(TDRoomView*)view
{
const GLfloat zNear = 8, zFar = 28, fieldOfView = 5;
GLfloat size;
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
size = zNear * tanf(DEGREES_TO_RADIANS(fieldOfView) / 2.0);
NSLog(@"tanf(DEGREES_TO_RADIANS(fieldOfView)/2.0); %f ", tanf(DEGREES_TO_RADIANS(fieldOfView)/2.0));
CGRect rect = view.bounds;
glFrustumf(-size, size, -size / (rect.size.width / rect.size.height), size /
(rect.size.width / rect.size.height), zNear, zFar);
glViewport(-size, size, rect.size.width, rect.size.height);
glMatrixMode(GL_MODELVIEW);
glShadeModel(GL_SMOOTH);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
static const Color3D light0Ambient[] = {{1.0, 1.0, 1.0, 1.0}};
glLightfv(GL_LIGHT0, GL_AMBIENT, (const GLfloat *)light0Ambient);
static const Color3D light0Diffuse[] = {{0.5, 0.5, 0.5, 1.0}};
glLightfv(GL_LIGHT0, GL_DIFFUSE, (const GLfloat *)light0Diffuse);
static const Color3D light0Specular[] = {{0.5, 0.5, 0.5, 1.0}};
glLightfv(GL_LIGHT0, GL_SPECULAR, (const GLfloat *)light0Specular);
static const Vertex3D light0Position[] = {{0.0, 0.473, -10.0}};
glLightfv(GL_LIGHT0, GL_POSITION, (const GLfloat *)light0Position);
static const Vertex3D lightVector= {0.0, -1.0, 0.0};
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, (GLfloat *)&lightVector);
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 85);
glLoadIdentity();
glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
}
E desenho:
-(void)drawView:(TDRoomView*)view
{
static const Vertex3D vertices[]= {
{-0.3153, -0.473, -20.0},
{-0.3153, -0.473, 0.0},
{0.3153, -0.473, -20.0},
{0.3153, -0.473, 0.0},
{-0.1, -0.25, -3.0},
{0.0, 0.0, -10.0},
{0.1, -0.25, -3.0}
};
static const Color3D colors[] = {
{0.7, 0.7, 0.7, 1.0},
{0.7, 0.7, 0.7, 1.0},
{0.7, 0.7, 0.7, 1.0},
{0.7, 0.7, 0.7, 1.0},
{1.0, 0.0, 0.0, 1.0},
{0.0, 1.0, 0.0, 1.0},
{0.0, 0.0, 1.0, 1.0}
};
static const GLubyte roomFaces[] = {
0, 1, 2,
1, 2, 3};
static const Vector3D normals[] = {
{0.000000, 1.000000, 0.000000},
{0.000000, 1.000000, 0.000000},
{0.000000, 1.000000, 0.000000},
{0.000000, 1.000000, 0.000000},
{0.000000, 1.000000, 0.000000},
{0.000000, 1.000000, 0.000000},
{0.000000, 1.000000, 0.000000}
};
glLoadIdentity();
glClearColor(0.7, 0.7, 0.7, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glColorPointer(4, GL_FLOAT, 0, colors);
glNormalPointer(GL_FLOAT, 0, normals);
glDrawElements(GL_TRIANGLE_STRIP, 8, GL_UNSIGNED_BYTE, roomFaces);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY); }
Além disso, eu reconava a alteração do
static const Vertex3D light0Position[] = {{0.0, 0.473, -10.0}};
para
static const Vertex3D light0Position[] = {{0.0, 0.473, -8.0}};
A Bord fica escura, nenhuma luz brilha nela. Por que, eu só movi a luz dois passos para mais perto ...? As mesmas coisas acontecem se eu mover dois passos mais longe assim:
static const Vertex3D light0Position[] = {{0.0, 0.473, -12.0}};
Qualquer ajuda para "lançar a luz da luz" do meu problema é muito apreciada! (Não pude evitar ...;)))
Desde já, obrigado!
Solução
Sugiro que você faça uma grade maior com mais vértices, de preferência n por n quadrados. Tente não ter triângulos finos muito longos. Isso tornará mais fácil ver onde a luz parece estar, pois a luz é calculada para cada vértice e não por pixel para a superfície.
http://www.opengl.org/resources/features/kilgardtechniques/oglpitfall/
2. Pobre piedade do dólar prejudica a iluminação
Os cálculos de iluminação do OpenGL são feitos por vertex. Isso significa que os cálculos de sombreamento devido a fontes de luz interagindo com o material da superfície de um objeto 3D são calculados apenas nos vértices do objeto. Normalmente, o OpenGL apenas interpola ou lisa tons entre as cores dos vértices. A iluminação per-vertex do OpenGL funciona muito bem, exceto quando um efeito de iluminação, como um destaque especular ou um holofote, é perdido ou borrado, porque o efeito não é suficientemente amostrado pelos vértices de um objeto. Esse sub-amostragem de efeitos de iluminação ocorre quando os objetos são modelados grosseiramente para usar um número mínimo de vértices.
:
Os programadores iniciantes do OpenGL são frequentemente tentados a permitir a funcionalidade de destaque do OpenGL e destacar um holofote em uma parede modelada como um único polígono enorme. Infelizmente, nenhum padrão de destaque nítido aparecerá como o novato pretendido; Você provavelmente não verá nenhum efeito de destaque. O problema é que o corte dos holofotes significa que os cantos extremos da parede onde os vértices são especificados não têm contribuição dos holofotes e, como esses são os únicos vértices que a parede possui, não haverá padrão de destaque na parede.
Outras dicas
GL_POSITION
é especificado em coordenadas homogêneas, o que significa que requer quatro valores, não três. Você precisa especificar W = 1.0 para sua fonte de luz, mas seu W O componente está vindo do que quer que aconteça ao lado de light0Position
em memória.
(Parte da razão pela qual GL_POSITION
está em coordenadas homogêneas é permitir que você defina luzes direcionais, definindo uma posição com W = 0.0.)