编辑:想通了,请参阅下面的答案。
我在尝试在三星 Galaxy S 上的 Android (NDK) 上渲染到 OpenGL ES 2.0 中的纹理时遇到问题
更具体地说,我使用帧缓冲区渲染到纹理,然后从该纹理绘制到后缓冲区 - 在模拟器(运行 4.2.2)和 Galaxy S2 上它完美渲染,同样适用于在数字上运行具有相同代码的 iOS 设备。
Galaxy S 正在运行 2.3.3(我无法说服模拟器在 2.3.3 中执行此操作)。
当我将纹理大小设置为 1024x1024 时,它看起来好像仍然存储在 512x512 纹理中,或者好像正在进行一些重度压缩,这仅发生在 Galaxy S、S2、模拟器和 iOS 设备上完美无缺。
如果我将纹理设置为 512x512,它似乎在 Galaxy S 上渲染得相当不错,没有什么明显的错误,但你会注意到一些相同的模糊,只是程度要小得多
1024x1024 截图
屏幕截图 og 512x512
在这两个图像上,上面的 4 个项目首先绘制到纹理,然后从那里绘制到后缓冲区(黑色的缺陷也是 Galaxy S 唯一的问题,但我不认为它相关)
我可以加载一个 1024x1024 纹理并从中渲染就好了,如果我在纹理的渲染缓冲区上使用 glReadPixels 它看起来也很好(不幸的是,GL ES 不支持直接从底层纹理读取像素)
您可能会注意到,即使是 512x512 版本的轻量级,它也不会出现任何模糊。
为了进一步让我感到困惑,我有一个运行 OpenGL ES 1.1 的 Java 旧项目,它在同一个 Galaxy S 设备上渲染为 1024x1024 纹理而没有任何问题,我还没有绝望到用 Java 编写一个完整的 ES 2.0 渲染看看是否有所作为,我还没有尝试使用 NDK 的 ES 1.1,因为帧缓冲区的 OES 扩展方法会创建链接器错误(可能有一个可以链接的库,如果没有人有更好的想法,我可能会去那里)
然而,我尝试在 java 中创建帧缓冲区和纹理并将句柄传递给本机代码,但这没有区别。
任何指针,猜测,预感,谷歌的神奇关键字,任何事情都非常感谢我今天连续花了 12 个小时试图弄清楚这一点,但我没有取得任何进展,我快要绝望了。
以下是可能相关的代码片段,不要犹豫要求更多(此时整个项目有数千行跨越 3 个平台,所以我尝试选择最相关的部分。)
创建帧缓冲区的代码:
glGenFramebuffers(1, &FFrameBufferID);
glBindFramebuffer(GL_FRAMEBUFFER, FFrameBufferID);
glGenRenderbuffers(1, &FDepthBufferID);
glBindRenderbuffer(GL_RENDERBUFFER, FDepthBufferID);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, FDepthBufferID);
glGenTextures(1, &FTextureID);
glBindTexture(GL_TEXTURE_2D, FTextureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//Tried both with and without:
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, FTextureID, 0);
GLenum OStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (OStatus != GL_FRAMEBUFFER_COMPLETE) {
Dev::Log(SGString("framebuffer creation failed: ") + (int) OStatus);
}
顶点着色器:
void main(void) {
gl_Position = Projection * vec4(Position, 1.0);
TextureCoordsOut = TextureCoords;
ParamOut = Param;
ColorOut = Color;
}
投影矩阵:
matrix[0] = 2.0 / (right - left);
matrix[1] = 0.0;
matrix[2] = 0.0;
matrix[3] = 0.0;
matrix[4] = 0.0;
matrix[5] = 2.0 / (top - bottom);
matrix[6] = 0.0;
matrix[7] = 0.0;
matrix[8] = 0.0;
matrix[9] = 0.0;
matrix[10] = -2.0 / (far - near);
matrix[11] = 0.0;
matrix[12] = -(right + left) / (right - left);
matrix[13] = -(top + bottom) / (top - bottom);
matrix[14] = -(far + near) / (far - near);
matrix[15] = 1.0;
渲染:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glVertexAttribPointer(FPositionSlot, 3, GL_FLOAT, GL_FALSE, sizeof(SGVertex), OVertextBuffer->Buffer());
glVertexAttribPointer(FTextureCoordsSlot, 2, GL_FLOAT, GL_FALSE, sizeof(SGVertex), OVertextBuffer->Buffer() + (sizeof(float) * 3));
glVertexAttribPointer(FParamSlot, 1, GL_FLOAT, GL_FALSE, sizeof(SGVertex), OVertextBuffer->Buffer()+ (sizeof(float) * 5));
glVertexAttribPointer(FColorSlot, 4, GL_FLOAT, GL_FALSE, sizeof(SGVertex), OVertextBuffer->Buffer()+ (sizeof(float) * 6));
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, OTexture->TextureID());
glUniform1i(FTextureUniform, 0);
glDrawArrays(GL_TRIANGLES, 0, count);