Невозможно нарисовать 3D (Frustum) поверх 2D (Орто) в OpenGL - PullRequest
3 голосов
/ 16 марта 2011

Я пытаюсь визуализировать некоторые сетки с проекцией Frustum поверх фонового изображения (ортографическая проекция).Независимо от того, что я делаю, фоновое изображение остается на вершине сцены (скрывая сетки).

Я попробовал небольшой тест - когда я рендерил их обоих с одинаковой проекционной матрицей, былив правильном порядке - фоновое изображение было за сетками.

Это матрицы проекций и инициализация Depth-Buffer:

glEnable(GL_DEPTH_TEST);
glClearDepthf( 1.0f );
glDepthFunc( GL_LEQUAL );
glDepthMask (GL_TRUE);

EGLConfig eglconfig;
EGLint const attrib_list[] = {
    EGL_DEPTH_SIZE, 16,
    EGL_NONE
};
EGLint numreturned;
CHECK(eglChooseConfig(esContext.eglDisplay, attrib_list, &eglconfig, 1, &numreturned) != EGL_FALSE);

float fieldOfView = 60.0;
float znear = 0.1f;
float zfar = 100000;
float size = (float)(znear * tanf((fieldOfView * M_PI /180.0f) / 2.0f)); 

m_orthoProjMatrix.loadOrtho(0, 
                            screenWidth, 
                            0, 
                            screenHeight, 
                            znear, 
                            zfar);

m_frustProjMatrix.loadFrustum(-size, 
                               size, 
                              -size / (screenWidth / screenHeight), 
                               size / (screenWidth / screenHeight), 
                               znear, 
                               zfar);

Я очищаю буферы с помощью: glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

И последнее. Когда я отключаю GL_DEPTH_TEST, сетки рисуются перед фоновым изображением, поскольку фон вызывается первым ..

Я могуСкажите, какие матрицы глубины или буфера проецирования вызывают эту проблему. Значения матриц с screenWidth = 960 и screenHeight = 640:

Orthographic Proj Matrix:
0.00208 0.00000 0.00000 -1.00000
0.00000 0.00313 0.00000 -1.00000
0.00000 0.00000 0.00000 -1.00000
0.00000 0.00000 0.00000  1.00000

Frustum Proj Matrix:
1.73205 0.00000  0.00000  0.00000
0.00000 2.59808  0.00000  0.00000
0.00000 0.00000 -1.00000 -0.20000
0.00000 0.00000 -1.00000  0.00000

Camera Settings:
Vector3 pos(0,10,50);
Vector3 at(0,0,0);
Vector3 up(0,1,0);
LookAt(pos,at,up);

Scene Settings:
Vector3 BackgroundImagePosition (0,0, -430);
Vector3 SomeMesh(0,0,0);

Что я делаю не так?Амир.

Редактировать: Вот как я рисую изображения с ортогональной проекцией:

GLfloat verts[] = { 
image->x + image->width  , image->y                , image->z,
image->x + image->width  , image->y + image->height, image->z,
image->x                 , image->y + image->height, image->z,
image->x                 , image->y                , image->z};
Matrix4s mv(m_camera->getCameraViewMatrix());
Matrix4f proj(ResManPtr->getOrthoProjMatrix() * mv);
glUniformMatrix4fv(prog->getUniformLocation("u_projMatrix"), 1, GL_FALSE, &(*proj));
glActiveTexture(GL_TEXTURE0);
image->tex->bind();
glUniform1i(prog->getUniformLocation("s_texture"), 0);
glEnableVertexAttribArray(prog->getAttribLocation("a_position")); 
glVertexAttribPointer(prog->getAttribLocation("a_position"), 3, GL_FLOAT, GL_FALSE, 0, verts); 
glEnableVertexAttribArray(prog->getAttribLocation("a_texCoord"));
glVertexAttribPointer(prog->getAttribLocation("a_texCoord"), 2, GL_FLOAT, GL_FALSE, 0, m_texcoord);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

и вот как я рисую сетки с проекцией усеченного конуса:

Matrix4f mv(world->getCamera()->getCameraViewMatrix());
const btVector3& dir = getDirection();
Scalar xzAngle = atan2s(dir.x(), dir.z()) - (Scalar)M_PI_2;
btVector3 origin = getGhostObject()->getWorldTransform().getOrigin();
mv.applyTranslate(origin.x(), origin.y() - m_width/2, origin.z());
mv.applyRotateY(xzAngle);    
GLProgramPtr prog = ResManPtr->getProgramMap()[Consts::DEFAULT_PROGRAM_KEY];
Matrix4f proj(ResManPtr->getFrustProjMatrix() * mv);
glUniformMatrix4fv(prog->getUniformLocation("u_projMatrix"), 1, GL_FALSE, &(*proj));
glActiveTexture(GL_TEXTURE0);
m_texture->bind();  
glUniform1i(prog->getUniformLocation("s_texture") , 0);
m_model->render(frame_number);

1 Ответ

6 голосов
/ 16 марта 2011

Если я правильно понимаю, вы хотите сделать следующие отдельные вещи:

  • Нарисуйте полноэкранный квад с текстурой на нем
  • Сделайте что-нибудь, чтобы этот квад не был взятна счет в z-буфере
  • Затем нарисуйте поверх него сетку (с любой матрицей проекции, вида и модели).

"Когда я отключаю GL_DEPTH_TEST,сетки рисуются перед фоновым изображением, потому что фон вызывается первым .. "-> Я так понимаю, что вы можете нарисовать как ваш полноэкранный квад, так и нашу сетку по отдельности.Так что настройка VBO, матрицы, текстуры и прочее - все хорошо.Это только пункт № 2, который пропускает.

  • Решение 1:

Очистите все для нового кадра, как обычно.Z-буфер везде будет 1,0

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

Нарисуйте фон.Ваш цветовой буфер в порядке, но он отстой, потому что z-буфер будет содержать глубину вашего четырехугольника, скажем, 0,5.Поэтому, когда вы будете рендерить свою сетку, вам повезет, так что новые значения глубины будут меньше 0,5, иначе тест глубины не пройдёт.Но мы можем что-то с этим сделать: просто очистите z-буфер снова до 1.0:

glClear(GL_DEPTH_BUFFER_BIT);

Теперь нарисуйте другой меш как обычно.Матрица ModelViewProjection изменилась, но OpenGL не знает этого: все, что он знает, это то, что глубина равна 1,0 везде.Таким образом, тест глубины всегда будет успешным для вашей сетки.Таким образом, вы увидите свою сетку там, где она должна быть, с правильными z-значениями и квадратом фона повсюду.

  • Решение 2

Здесь вы предотвращаете значения глубиныот того, чтобы быть обновленным, когда нарисован полноэкранный квад.

Отключить запись в буфер глубины:

glDepthMask(GL_FALSE);

Нарисовать фон.Цветовой буфер будет в порядке, а z-буфер будет по-прежнему содержать 1.0 везде, как установлено glClear () несколькими строками выше.

Теперь снова включите запись в буфер глубины:

glDepthMask(GL_TRUE);

Нарисуй другую сетку.Как и прежде, z-буфер везде будет равен 1.0, как если бы вы только что вызвали glClear (), поэтому, если ваша сетка находится в усеченной области (это, очевидно, должно быть), ее z будет, скажем, 0,5, и она будетбыть нарисованным.

  • Решение 3

Просто нарисуйте фон далеко от камеры, возле дальней плоскости отсечения.(то есть с большим компонентом Z).Его z-компонент будет равен 0,9999 или что-то в этом роде, и, как и прежде, меш будет хорошо отображаться.

Я действительно, действительно, не могу объяснить более подробно.Извините, если все еще не ясно, я попытался переформулировать каждую идею несколькими способами, больше ничего не могу сделать.

...