繁体   English   中英

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

[英]Drawing 2D bitmap in OpenGL ES (iOS)

我一直在挣扎了几个小时试图渲染的OpenGL ES(IOS)一个简单的2D位图。 虽然在OpenGL中我可以简单地使用glDrawPixels,但它在OpenGL ES中不存在,glBegin也不存在。 好像glVertexPointer现在也已被弃用。

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

我找不到使用现有API绘制位图的任何文档示例代码。

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

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

如何渲染纹理四边形

首先,您需要使用四边形的顶点位置构建一个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的页面

最后,着色器:

顶点

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

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

片段

varying vec2 uv;
uniform sampler2D image;

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

在没有其他GL状态更改的情况下,这将呈现以下内容:

纹理四边形

注意:由于我无权访问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与它进行通信。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM