OpenGL ES Light Question
Я новичок в OpenGL ES и развиваюсь в Objective-C для iPhone.
Что я пытаюсь понять, так это то, как свет расположен в моем усечённом месте. Вот как я это делаю:
Я создаю квадрат и помещаю его как "пол" в моем усеченном контуре. Я помещаю свет прямо над серединой пола и указываю направление света прямо вниз. Теперь я ожидаю, что круг света на полу будет посередине. Но это не так, это больше назад (дальше). Как так?
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},
Разве это не должно сделать круг света таким, чтобы он находился посередине пола и не располагался немного назад?
Вот мой важный код:
Настройка вида:
-(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);
}
И рисунок:
-(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); }
Кроме того, я пересматриваю изменения
static const Vertex3D light0Position[] = {{0.0, 0.473, -10.0}};
в
static const Vertex3D light0Position[] = {{0.0, 0.473, -8.0}};
борд темнеет, на нем нет света. Почему я только подвинул свет на два шага ближе...? То же самое происходит, если я переместлю его на два шага дальше, вот так:
static const Vertex3D light0Position[] = {{0.0, 0.473, -12.0}};
Любая помощь, чтобы "пролить свет" на мою проблему, очень ценится! (Ничего не мог поделать...;))
Заранее спасибо!
2 ответа
Я предлагаю вам сделать большую сетку с большим количеством вершин, предпочтительно n на n квадратов. Старайтесь не иметь слишком длинных тонких треугольников. Это поможет увидеть, где находится свет, так как свет рассчитывается для каждой вершины, а не на пиксель для поверхности.
http://www.opengl.org/resources/features/KilgardTechniques/oglpitfall/
2. Плохая тесселяция больно освещает
Расчеты освещения OpenGL выполняются для каждой вершины. Это означает, что вычисления затенения из-за источников света, взаимодействующих с поверхностным материалом трехмерного объекта, рассчитываются только по вершинам объекта. Как правило, OpenGL просто интерполирует или сглаживает тени между цветами вершин. Освещение на каждой вершине в OpenGL работает довольно хорошо, за исключением случаев, когда эффект освещения, такой как зеркальная подсветка или прожектор, теряется или размыт, потому что эффект недостаточно сглаживается вершинами объекта. Такая недостаточная выборка световых эффектов происходит, когда объекты грубо моделируются для использования минимального количества вершин.
:
Начинающие программисты OpenGL часто испытывают желание включить функцию прожектора OpenGL и освещать прожектор на стене, смоделированной как один огромный многоугольник. К сожалению, никакой резкой картины прожектора не появится, как задумал новичок; вы, вероятно, не увидите никакого эффекта прожектора вообще. Проблема в том, что отсечение прожектора означает, что крайние углы стены, где указаны вершины, не получают вклада от прожектора, и, поскольку это единственные вершины, которые имеет стена, на стене не будет рисунка прожектора.
GL_POSITION
указывается в однородных координатах, что означает, что для него требуется четыре значения, а не три. Вам нужно указать w = 1.0 для вашего источника света, но вместо этого ваш w- компонент прибывает из того, что находится рядом с light0Position
в памяти.
(Часть причины того, что GL_POSITION
находится в однородных координатах, чтобы позволить вам определять направленное освещение, устанавливая положение с w = 0.0.)