следующий текст немного длиннее, поскольку я хотел удостовериться, что люди с аналогичными проблемами, например, 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);
Следующие моменты - это короткие заметки о том, что я знаю о настройках камеры в приведенном выше коде. ПОЖАЛУЙСТА, исправьте меня, если я получу что-то не так в следующих объяснениях, поскольку это может решить все мои проблемы!
Код чертежа треугольника был скопирован из учебника (но я нашел аналогичный код и в других учебниках, поэтому я предполагаю, что это не проблема).
Насколько я понял, камера теперь позиционируется на (0,0,20) и смотрит в начало координат системы координат. Его рисунок frustrum начинается с z-значения 19 и доходит до -80 (камера находится в точке 20 оси z и смотрит вдоль отрицательной оси z, а ее обзорный угол имеет ближнюю и дальнюю плоскость на 1 и 100 (оба выглядят вдоль отрицательной оси z в этом случае) соответственно). Поэтому треугольник должен быть виден, так как его вершины располагаются вокруг начала координат на плоскости z = 0 (например, плоскости xy), что явно находится в пределах обзора. Далее вытянутые вершины расположены в порядке против часовой стрелки; по умолчанию в OpenGL.
Итак, после этого длительного введения в проблему мой простой вопрос: что я испортил, чтобы этот код не выполнял то, что я ожидаю?
Я нашел ответ, посмотрев дальнейшие уроки (а затем также заметил его в тех, которые я использовал раньше)! Спасибо всем за ваши ответы, они были очень полезны в диагностике проблем OpenGL в целом и наверняка помогут мне в будущем!
Решение моей проблемы - это..., что проблема не является glulookat или gluperspective, но в моем случае является внутренней позицией FloatBuffer. Я не установил положение переменной vertex_buffer равным 0 после цикла for (0 < я < 9). Установка позиции буфера на 0 может выполняться по меньшей мере двумя командами:
Насколько я знаю, они делают то же самое. Я быстро проверил, где в коде находится позиция reset, и в моем примере кода я мог бы вызвать его после gl.glEnableClientState(GL10.GL_VERTEX_ARRAY), однако мне пришлось вызвать его перед gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertex_buffer), в противном случае возвращалась исходная проблема.
Я надеюсь, что это поможет другим людям с подобными проблемами или, может быть, это всего лишь недостаток glulookat и gluperspective;)
Еще раз спасибо за ваши предложения!
Я только использовал 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 запускается с отключенными массивами вершин, согласно документам, но это возможность исключить.