帮我配置OpenGL for 2D

时间:2011-02-06 17:31:12

标签: android opengl-es 2d

我正在使用OpenGL为Android编写我的第一个2D应用程序。我正在写我的欲望,所以我的屏幕坐标在横向模式下应该是0到799,479。我试图让OpenGL在世界坐标中使用这个范围。

应用程序,比如它,到目前为止工作得很好,但是我不得不调整数字以便让屏幕上显示内容,而我对无法理解投影矩阵之间的关系感到沮丧,并且在这方面渲染纹理。

设置投影矩阵:

gl.glViewport(0, 0, width, height);
float ratio = (float) width / height;
float size = .01f * (float) Math.tan(Math.toRadians(45.0) / 2);             
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glFrustumf(-size, size, -size / ratio, size / ratio, 0.01f, 100.0f);
//    GLU.gluOrtho2D(gl, 0,width, 0, height);

我想在这里理解0.01f和100.0f。我用什么来描述0,0 - >的2D世界? 799,479,z值为零?

另外,我不确定什么是“最好” - 使用glFrustumF或GLU.gluOrtho2D后者有更简单的参数 - 只是视口的尺寸 - 但我没有任何地方。 (有些网站的高度和0相反,但没有区别。)但这不应该是2D使用OpenGL的自然选择吗?我是否必须在某个地方设置一些内容来对OpenGL说“我在2D中这样做 - 请为了速度而无视任何地方的第三个维度”?

绘制纹理

我正在使用2个纹理三角形绘制内容。我的init的相关部分(让我知道是否需要更详细地编辑我的问题)是:

gl.glMatrixMode(GL10.GL_MODELVIEW);                             
gl.glLoadIdentity();
gl.glTranslatex(nXpos, nYpos, nZoomin);         
gl.glRotatef(nRotZ, 0, 0, 1);               
gl.glScalef((float)nScaleup,(float)nScaleup, 0.0f);
...
...
gl.glVertexPointer(2, GL10.GL_FIXED, 0, mVertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTextureBuffer);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);      


mVertexBuffer is an IntBuffer and contains:
int  vertices[] =  
{
    -1,   -1,
    1,  -1,
    -1, 1,
    1,  1   
};

我最终不打算通过nZoomin - 我已经这样做了,因为这是我发现实际看到任何东西所需的“神奇数字”!目前我需要在那里使用-1000,数字越小,图像越小。我正确地认为,当投影矩阵设置正确时,nZoomin必须有某种方法使其值为零吗?

我的纹理目前是128x128(但最终可能会有不同的尺寸,但可能总是正方形)。我无法知道他们当前以实际尺寸显示的时间。我希望能够为nScaleup传递128的值,以便将其绘制为实际大小。这与投影矩阵有关,还是我有两个不同的问题?

2 个答案:

答案 0 :(得分:8)

如果您使用的是2D,则不需要glFrustum,只需使用glOrtho。像这样:

void glOrthof(0, 800, 0, 480, -1, 1);

那将原点放在左下角。如果您想要它在左上角,请使用:

void glOrthof(0, 800, 480, 0, -1, 1);

对于480和800,您显然应该替换视图的实际大小,以便您的应用程序可以移植到不同的屏幕尺寸和配置。

我为z范围传递-1和1,但这些并不重要,因为正交投影将(x,y,z)放在屏幕上的同一位置,无论z的值如何。 (但是,near和far必须不相等。)这是告诉OpenGL忽略z坐标的唯一方法;没有特定的“2D”模式,您的矩阵仍然是4x4,而2维顶点将获得z坐标为0。

请注意,您的坐标不是的范围是0到799,但实际上是0到800.原因是OpenGL将坐标解释为位于像素之间的,而不是< em> on 他们。可以把它想象成一个30厘米的尺子:它上面有30个厘米的间隔,刻度为0-30。

您正在使用的顶点缓冲区不起作用,因为您使用的是GL_FIXED格式。这意味着小数点前16位,后面16位,因此要在原点周围指定2x2方格,您需要将每个值乘以0x10000

int vertices[] =  
{
    -0x10000, -0x10000,
     0x10000, -0x10000,
    -0x10000,  0x10000,
     0x10000,  0x10000
};

这可能是您需要如此扩展它的原因。如果你使用这个数组,没有缩放,你应该得到一个2x2像素的正方形。把它变成一个1x1的正方形,所以尺寸可以直接用比例因子控制,留给读者练习;)

答案 1 :(得分:1)

  

我是否必须在某处设置某些内容以对OpenGL说“我在2D中这样做

我认为问题在于您使用投影矩阵进行透视投影。 相反,你应该使用平行投影。 要获得此矩阵,您可以使用glOrtho()函数。

gl.glMatrixMode(GL10.GL_PROJECTION);
...
gl.glOrtho(0, width, 0, height, 0, 128);

现在,z值不再影响对象的大小。


  

我想在这里理解0.01f和100.0f。我用什么来描述0,0 - >的2D世界? 799,479,z值为零?

在2D世界中,你并不真正拥有z值。但你必须决定 首先要绘制哪些对象。 有两种方法可以决定:

  1. 停用GL_DEPTH_TEST并按照您选择的顺序绘制所有内容
  2. 激活GL_DEPTH_TEST并让OpenGL决定