在OpenGL ES(iOS)中绘制2D位图

时间:2016-04-16 20:37:19

标签: ios opengl-es bitmap 2d

我一直在努力小时尝试在OpenGL ES(iOS)中渲染简单的2D位图。虽然在OpenGL中我可以简单地使用glDrawPixels,但它并不存在于OpenGL ES中,glBegin也不存在。似乎glVertexPointer现在也被弃用了。

(注意:我的渲染位图在60 FPS时不断变化,因此glDrawPixels 比使用纹理更好的解决方案)

我未能找到任何使用当前API绘制位图的文档示例代码。

简而言之:给定一个像素数组(例如RGBX格式),如何渲染它,可能使用最近邻居进行缩放,使用OpenGL ES?

1 个答案:

答案 0 :(得分:1)

简短的回答是渲染纹理四边形并实现模型矩阵以执行各种变换(例如缩放)。

如何渲染纹理四边形

首先,您需要使用四边形的顶点位置构建一个VBO:

float[] positions = {
        +0.5f, +0.5f, +0f,    // top right
        -0.5f, +0.5f, +0f,    // top left
        +0.5f, -0.5f, +0f,    // bottom right
        -0.5f, -0.5f, +0f     // bottom left
};

int positionVBO = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, positionVBO);
glBufferData(GL_ARRAY_BUFFER, floatBuffer(positions), GL_STATIC_DRAW);

然后将必要的信息传递给您的顶点着色器:

int positionAttribute = glGetAttribLocation(shader, "position");
glEnableVertexAttribArray(positionAttribute);
glVertexAttribPointer(positionAttribute, 3, GL_FLOAT, false, 0, 0);

现在我们将使用四边形的纹理坐标做同样的事情:

float[] texcoords = {
        1f, 0f,     // top right
        0f, 0f,     // top left
        1f, 1f,     // bottom right
        0f, 1f      // bottom left
};

int texcoordVBO = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, texcoordVBO);
glBufferData(GL_ARRAY_BUFFER, floatBuffer(texcoords), GL_STATIC_DRAW);
int textureAttribute = glGetAttribLocation(shader.getId(), "texcoord");
glEnableVertexAttribArray(textureAttribute);
glVertexAttribPointer(textureAttribute, 2, GL_FLOAT, false, 0, 0);

您可以将这些数据交错到单个VBO中,但我会将其留给读者。无论我们是否已将所有四边形顶点数据提交给GPU,并告诉着色器如何访问它。

接下来,我们构建纹理缓冲区,假设我们有一个名为image的对象:

int texture = glGenTextures();
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.getWidth(), image.getHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, image.getPixels());

将该信息传递给着色器:

int textureUniform = glGetUniformLocation(shader, "image");
glUniform1i(textureUniform, 0);

查看open.gl's page on Textures了解详情。

最后,着色器:

vertex.glsl

attribute vec3 position;
attribute vec2 texcoord;
varying vec2 uv;

void main()
{
    gl_Position = vec4(position, 1.0);
    uv = texcoord;
}

fragment.glsl

varying vec2 uv;
uniform sampler2D image;

void main()
{
    gl_FragColor = texture(image, uv);
}

如果没有其他GL状态更改,这将呈现以下内容:

textured quad

注意:由于我目前无法访问iOS开发环境,因此该示例是用Java编写的。但原则是相同的。

编辑:如何构建着色器程序

着色器程序由一系列着色器组成。最小的是顶点和片段着色器。这就是我们如何从上面的两个着色器构建着色器程序:

String vertexSource = loadShaderSource("vertex.glsl");
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, vertexSource);
glCompileShader(vertexShader);

String fragmentSource = loadFileAsString("fragment.glsl");
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, fragmentSource);
glCompileShader(fragmentShader);

GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);

创建后,您将通过glVertexAttribPointerglUniform与其进行通信。