Android OpenGL ES - 我无法使gluLookAt / gluPerspective工作

时间:2010-09-21 20:23:44

标签: java android opengl-es 3d

以下文字有点长,因为我想确保有类似问题的人,例如谷歌此页面可以轻松地轻松地遵循确切的问题及其解决方案。但现在我的问题是:

我最近开始在Android智能手机上编程OpenGL ES,并且遇到了解如何使用gluPerspective和gluLookAt的问题。我我明白他们做了什么,但我看不到我画的三角形。我在我的活动的onDrawFrame方法中运行以下代码。所述活动使用标记为@Override的onDrawFrame实现GLSurfaceView.Renderer。我的代码是:

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);

接下来的几点是关于我在上面的代码中对相机设置的推定知识的简短说明。如果我在以下解释中出错了,请纠正我,因为这可能已经解决了我的所有问题!

  1. glMatrixMode(GL10.GL_PROJECTION)切换到更改相机矩阵(我之后直接加载了单位矩阵)
  2. GLU.gluPerspective(gl,67,aspect_ratio,1,100)在y维度中设置具有67度视角的视图截面的透视投影。使用“aspect_ration =(float)width / height”OpenGL计算x维度中的视角。此外,“1”是近剪裁平面,而“100”是这种情况下远剪裁平面的值。
  3. 据我所知,无论如何,只要在实际绘图之前完成,就会调用gluLookAt代码(尽管我不确定)。在这个例子中,我首先更改为MODELVIEW矩阵,加载一个单位矩阵,然后调用gluLookAt。 3。
  4. “GLU.gluLookAt(gl,0,0,20,0,0,0,0,1,0)”实际上由三个3元素向量组成。初始值(本例中为(0,0,20))设置摄像机在世界坐标中的位置(即正Z轴上的20个单位,这意味着它“伸出”手机屏幕的正面)。第二矢量确定摄像机看到的世界坐标系中的点(在该示例中,坐标系的原点,即摄像机沿负z轴看)。第三个向量是向上矢量,它定义了摄像机坐标系的y轴方向(因此也是x轴通过交叉积与从摄像机位置到它所看到的点的矢量)。
  5. 三角绘图代码是从教程中复制的(但我在其他教程中也发现了类似的代码,所以我认为这不是问题)。

    据我所知,相机现在位于(0,0,20)并朝向坐标系的原点。它的绘图截头从z值19开始,一直到-80(相机在z轴点20处,沿着负z轴看;它的观察截头体有近和远的平面在1和100(都看着在这种情况下,沿着负z轴),分别)。因此,三角形应该是可见的,因为其顶点位于z轴= 0平面(即xy平面)上的原点周围,这明显位于观察截头体内。此外,绘制的顶点以逆时针顺序排列; OpenGL中的默认值。

    所以在对这个问题进行了长时间的介绍之后,我的一个简单的问题是:我搞砸了什么,以至于这段代码不符合我的预期呢?

3 个答案:

答案 0 :(得分:6)

我只在PC,Mac和iOS上使用OpenGL,但据我所知,代码看起来很好。然后,我也一直这样做,但我仍然得到空屏幕一段时间,几乎任何时候我从头开始任何3D(无论API)...所以这里有一些事情要尝试,几乎在尝试它们的顺序。希望至少其中一个是你尚未尝试过的东西!

  • 最后添加glFlush,因为你实际上并没有那么多。当你进行缓冲交换时,你会认为驱动程序会为你做这件事,但似乎并不能保证 - 例如Mac OS X似乎并不总是如此。
  • 将背景设置为非黑色。如果有东西是黑色的,你想看到它。
  • 禁用GL_LIGHTING。如果这个被启用(我认为这是默认情况?)但你没有提供法线,一切都会变黑。 (见上文。)
  • 禁用GL_CULL_FACE。无论你怎么仔细考虑绕线顺序,你仍然有可能犯错。但如果GL_CULL_FACE关闭,则无法实现。
  • 禁用GL_DEPTH_TEST。当我偶然输入glClearDepth(0)时,这已经节省了我几次。看起来你在这方面还不错,但它仍然值得一试。
  • 在每次API调用之后,以宗教的方式检查glGetError以防万一。 (assert(glGetError()==GL_NO_ERROR)会为初学者做,但你真的想要一个小的循环,同时打印gluErrorString的结果,这样一眼就能看出什么可能是错的。)
  • 确保执行glBindBufferARRAY_BUFFERARRAY_ELEMENT_BUFFER绑定设置为0.要初始化VBO,您必须将其绑定,所以如果您在某处有某些内容设置一个它可能只是让它绑定。这将填满您的glVertexPointer
  • 沿着最后几行 - 明确地设置更多状态。例如,在这种情况下,您可能希望glDisableClientState其他数组类型,以防万一。根据文档,GL启动时顶点阵列被禁用,但这是一种值得消除的可能性。

答案 1 :(得分:2)

在查看了进一步的教程之后我找到了答案(然后在之前使用的那些教程中也注意到了它)!感谢大家的答案,他们在诊断OpenGL问题方面非常有帮助,并且肯定会在将来帮助我!

我的问题的解决方案是...... 问题不是glulookat或gluperspective,而是在我的情况下,FloatBuffer的内部位置。在for(0&lt; i&lt; 9&gt;)循环之后,我没有将变量vertex_buffer的位置设置为0。将缓冲区的位置设置为0可以通过至少两个命令完成:

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

据我所知,他们做同样的事情。我快速测试了位置重置属于代码的位置,在我的示例代码中我可以在gl.glEnableClientState(GL10.GL_VERTEX_ARRAY)之后调用它,但是我必须在gl.glVertexPointer(3,GL10.GL_FLOAT,0,vertex_buffer)之前调用它。 ),否则返回初始问题。

我希望这可以帮助其他有类似问题的人,或者只是缺少glulookat和gluperspective;)

再次感谢您的建议!

答案 2 :(得分:0)

对于OpenGL ES用户

就我而言,我不得不写

gl.glMatrixMode(gl.GL_PROJECTION);
gl.glLoadIdentity();
GLU.gluPerspective(gl,45,1,1.5f,50);
gl.glMatrixMode(gl.GL_MODELVIEW);
gl.glLoadIdentity();

不只是

GLU.gluPerspective(gl,45,1,1.5f,50);

采用onSurfaceChanged方法。