我一直在努力小时尝试在OpenGL ES(iOS)中渲染简单的2D位图。虽然在OpenGL中我可以简单地使用glDrawPixels,但它并不存在于OpenGL ES中,glBegin也不存在。似乎glVertexPointer现在也被弃用了。
(注意:我的渲染位图在60 FPS时不断变化,因此glDrawPixels 比使用纹理更好的解决方案)
我未能找到任何使用当前API绘制位图的文档示例代码。
简而言之:给定一个像素数组(例如RGBX格式),如何渲染它,可能使用最近邻居进行缩放,使用OpenGL ES?
答案 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状态更改,这将呈现以下内容:
注意:由于我目前无法访问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);
创建后,您将通过glVertexAttribPointer
和glUniform
与其进行通信。