Android OpenGL ES - я не могу заставить gluLookAt / gluPerspective работать

1

следующий текст немного длиннее, поскольку я хотел удостовериться, что люди с аналогичными проблемами, например, Google на этой странице легко справляется с конкретной проблемой и ее решениями. Но теперь по моей проблеме:

Недавно я начал программировать OpenGL ES на Android-смартфоне и столкнулся с проблемами понимания того, как используются gluPerspective и gluLookAt. Думаю, я понимаю, что они делают, но я не вижу треугольника, который я рисую. Я запускаю следующий код в методе onDrawFrame моей деятельности. Указанная активность реализует GLSurfaceView.Renderer с onDrawFrame, отмеченным с помощью @Override. Мой код:

gl.glViewport(0, 0, screen_width, screen_height);
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); //set background to black
gl.glClearDepthf(1.0f); 

gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

gl.glMatrixMode(GL10.GL_PROJECTION); // Change PROJECTION matrix
gl.glLoadIdentity();

float aspect_ratio = (float) screen_width / screen_height;
GLU.gluPerspective(gl, 67, aspect_ratio, 1, 100);

gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glMatrixMode(GL10.GL_MODELVIEW); // Change MODELVIEW matrix
gl.glLoadIdentity();

GLU.gluLookAt(gl, 0, 0, 20, 0, 0, 0, 0, 1, 0);

// make triangle with vertices (-2,0,0), (2,0,0), and (0,.5,0)
float[] vertices = { -2f, 0, 0, 2f, 0, 0, 0, .5f, 0 };
ByteBuffer buffer = ByteBuffer.allocateDirect(vertices.length * 4);
buffer.order(ByteOrder.nativeOrder());
FloatBuffer vertex_buffer = buffer.asFloatBuffer();
for (int i = 0; i < 9; i++) {
    vertex_buffer.put(vertices[i]);
}

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertex_buffer);
gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisable(GL10.GL_DEPTH_TEST);

Следующие моменты - это короткие заметки о том, что я знаю о настройках камеры в приведенном выше коде. ПОЖАЛУЙСТА, исправьте меня, если я получу что-то не так в следующих объяснениях, поскольку это может решить все мои проблемы!

  • glMatrixMode (GL10.GL_PROJECTION) переключает на изменение матрицы камеры (для которой я сразу же загружаю идентификационную матрицу)
  • GLU.gluPerspective(gl, 67, aspect_ratio, 1, 100) устанавливает перспективную проекцию с углом обзора 67 градусов в y-размерности. Использование "aspect_ration = (float) width/height" OpenGL вычисляет угол обзора в x-размерности. Далее "1" - это плоскость ближнего отсечения, тогда как "100" - это значение плоскости отсечения в этом случае.
  • Насколько я знаю, это не имеет значения, где в коде gluLookAt вызывается, если это делается до фактического рисования (я не уверен в этом, хотя). В этом примере сначала меняем матрицу MODELVIEW, загружаю идентификационную матрицу, а затем вызывается gluLookAt. 3.
  • "GLU.gluLookAt(gl, 0, 0, 20, 0, 0, 0, 0, 1, 0)" фактически состоит из трех трехэлементных векторов. Начальный ((0,0,20) в этом примере) устанавливает положение камеры в мировых координатах (т.е. 20 единиц на положительной оси Z, что означает, что она "торчит" спереди экрана телефона). Второй вектор определяет точку в мировой системе координат, на которую смотрит камера (в этом примере происхождение системы координат, т.е. Камера смотрит вдоль отрицательной оси z). Третий вектор - это верхний вектор, который определяет направление оси y системы координат камер (и, следовательно, также ось x через поперечное произведение с вектором от положения камеры до точки, на которую он смотрит).

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

Насколько я понял, камера теперь позиционируется на (0,0,20) и смотрит в начало координат системы координат. Его рисунок frustrum начинается с z-значения 19 и доходит до -80 (камера находится в точке 20 оси z и смотрит вдоль отрицательной оси z, а ее обзорный угол имеет ближнюю и дальнюю плоскость на 1 и 100 (оба выглядят вдоль отрицательной оси z в этом случае) соответственно). Поэтому треугольник должен быть виден, так как его вершины располагаются вокруг начала координат на плоскости z = 0 (например, плоскости xy), что явно находится в пределах обзора. Далее вытянутые вершины расположены в порядке против часовой стрелки; по умолчанию в OpenGL.

Итак, после этого длительного введения в проблему мой простой вопрос: что я испортил, чтобы этот код не выполнял то, что я ожидаю?

  • 0
    Вы пытались полностью отключить тест глубины? Вы устанавливаете цвета вершин или освещение где-нибудь, то есть могли бы вы нарисовать черный треугольник на черном фоне?
  • 2
    Как gluPerspective, так и gluLookAt умножают текущую матрицу (устанавливается с помощью glMatrixMode). Вы получили их в нужном месте, хотя
Показать ещё 1 комментарий
Теги:
opengl-es
3d

2 ответа

2
Лучший ответ

Я нашел ответ, посмотрев дальнейшие уроки (а затем также заметил его в тех, которые я использовал раньше)! Спасибо всем за ваши ответы, они были очень полезны в диагностике проблем OpenGL в целом и наверняка помогут мне в будущем!

Решение моей проблемы - это..., что проблема не является glulookat или gluperspective, но в моем случае является внутренней позицией FloatBuffer. Я не установил положение переменной vertex_buffer равным 0 после цикла for (0 < я < 9). Установка позиции буфера на 0 может выполняться по меньшей мере двумя командами:

  • vertex_buffer.rewind()
  • vertex_buffer.position(0)

Насколько я знаю, они делают то же самое. Я быстро проверил, где в коде находится позиция reset, и в моем примере кода я мог бы вызвать его после gl.glEnableClientState(GL10.GL_VERTEX_ARRAY), однако мне пришлось вызвать его перед gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertex_buffer), в противном случае возвращалась исходная проблема.

Я надеюсь, что это поможет другим людям с подобными проблемами или, может быть, это всего лишь недостаток glulookat и gluperspective;)

Еще раз спасибо за ваши предложения!

5

Я только использовал OpenGL на ПК, Mac и iOS, но из того, что я могу сказать, код выглядит отлично. Опять же, мой всегда делает это тоже, но я все равно получаю пустой экран на некоторое время, почти каждый раз, когда я начинаю с чего-либо 3D с нуля (независимо от API)... так вот некоторые вещи, чтобы попробовать, в значительной степени в порядок, в котором их можно попробовать. Надеюсь, хотя бы один из них будет тем, что вы еще не пробовали!

  • Добавьте в конец glFlush в конце, потому что вы на самом деле не рисуете все это. Вы могли бы подумать, что драйвер сделает это для вас, когда вы сделаете буферный обмен, но, похоже, нет никаких гарантий - Mac OS X не всегда выглядит, например.
  • Установите фон нечерным. Если что-то черное, вы хотите его увидеть.
  • Отключить GL_LIGHTING. Если это включено (по моему мнению, это по умолчанию?), Но вы не поставляете нормали, все будет черным. (См. Выше.)
  • Отключить GL_CULL_FACE. Неважно, насколько тщательно вы думаете об извилистом порядке, все еще есть вероятность, что вы, возможно, ошибаетесь. Но если GL_CULL_FACE выключено, это становится невозможным.
  • Отключить GL_DEPTH_TEST. Это спасло меня пару раз, когда я случайно набрал glClearDepth(0). Похоже, вы в порядке, но это все равно стоит.
  • Проверяйте glGetError религиозно, после каждого вызова API, на всякий случай. (assert(glGetError()==GL_NO_ERROR) будет делать для стартеров, но вы действительно хотите иметь небольшой цикл, который также выводит результат gluErrorString, чтобы было легче увидеть, что может быть неправильно.)
  • Убедитесь, что вы создали glBindBuffer, чтобы установить привязки ARRAY_BUFFER и ARRAY_ELEMENT_BUFFER в 0. Чтобы инициализировать VBO, вам необходимо связать его, поэтому, если у вас есть что-то где-то, что устанавливает его, просто оставьте его связанным. Это наполнит ваш glVertexPointer.
  • По строкам последних нескольких - настроить более явно. В этом случае, например, вы можете захотеть glDisableClientState другие типы массивов, на всякий случай. GL запускается с отключенными массивами вершин, согласно документам, но это возможность исключить.
  • 0
    Я тестировал добавление glFlush в конце, а также отключение CULL_FACE, DEPTH_TEST и LIGHTING. При этом я заметил кое-что странное: через пару секунд треугольник показывается белым цветом в верхнем правом углу экрана моего мобильного телефона (возможно, 1/3 его видима, не касаясь экрана). Странно то, что треугольник появляется только доли секунды и слегка мерцает и вибрирует (т. Е. Один край движется вверх и вниз), ни один из которых я не реализовал! Тогда треугольник снова исчезает. Я проверил свой оригинальный код, и это также происходит там, я просто никогда не видел его. Что бы это могло быть?
  • 0
    на самом деле я просто заметил, что треугольник, кажется, даже не всегда появляется в верхнем правом углу, но прыгает вокруг. Тем не менее, это очень трудно сказать, поскольку это показывает только на долю секунды. Я запустил код в эмуляторе (до этого на устройстве Samsung Galaxy S), просто чтобы проверить, и он также не показывает треугольник. Может быть, из-за того, что эмулятор был таким медленным, я даже не видел, чтобы он там мерцал.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню