Android NDK GL ES 2.0 渲染到纹理(通过帧缓冲区)导致模糊/低分辨率图像

标签 android android-ndk opengl-es-2.0 galaxy texture2d

编辑:弄清楚了,请参阅下面的答案。

我在尝试在三星 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 的屏幕截图

Screensshot of 1024x1024

屏幕截图 og 512x512

Screenshot og 512x512

在两个图像上,上面的 4 个项目首先被绘制到纹理,然后从那里绘制到后缓冲区(黑色的缺陷也是 Galaxy S 唯一的问题,但我不认为它相关)

我可以加载一个 1024x1024 纹理并从中进行渲染,而且如果我在纹理的渲染缓冲区上使用 glReadPixels 它看起来也很好(不幸的是,GL ES 不支持直接从底层纹理读取像素)

Saved framebuffer at 1024x1024

正如您可能注意到的那样,即使是 512x512 版本的轻型版本,它也不会出现任何模糊现象。

为了进一步迷惑我,我有一个运行 OpenGL ES 1.1 的 Java 旧项目,可以在同一个 Galaxy S 设备上毫无问题地渲染到 1024x1024 纹理,我还没有绝望到用 Java 编写完整的 ES 2.0 渲染来看看这是否有所作为,我还没有尝试使用 NDK 的 ES 1.1,因为帧缓冲区的 OES 扩展方法会创建链接器错误(可能有一个可以链接的库,如果没有人有更好的,我可能会去那里想法)

不过,我曾尝试在 java 中创建帧缓冲区和纹理,并将句柄传递给 native 代码,但这没有任何区别。

Google 的任何指示、猜测、直觉、神奇关键字,任何东西都非常感谢我今天连续花了 12 个小时试图解决这个问题,但我一直没有取得任何进展,我快绝望了。

以下是可能相关的代码 fragment ,不要犹豫,要求更多(此时整个项目有数千行跨越 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);

最佳答案

我偶然发现了一个让我找到答案的小提示,问题是我从样本中简单复制的纹理坐标的精度:

varying lowp vec2 TextureCoordsOut;

不知道 lowp 是什么意思我只是忽略了它 - 大错 - 我把它改成了

varying highp vec2 TextureCoordsOut;

现在它可以完美地工作了,为什么它在所有其他设备上都能工作,尽管 lowp 超出了我的理解

它可能的 mediump 也可以工作,但我想我只是为了 go highp 来测试它。

关于Android NDK GL ES 2.0 渲染到纹理(通过帧缓冲区)导致模糊/低分辨率图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15580446/

相关文章:

java - 如何在android中解析列表?

Android Studio 将 libapp.so 添加到生成的 apk 中,它是什么以及如何关闭它?

iphone - 编写 GLKBaseEffect 替代品

android - SpriteBatch.setBlendFunction() 对 Android 没有影响

c++ - QT 找不到要使用的正确 OpenGL api

android - 无法使用 NotificationListenerService 取消通知

android - 条件链单一且可完成

java - 更新行时 SQLite 中没有这样的列错误

c++ - Android NDK 中有异步文件 I/O 吗?

Android ndk构建无法构建32位可执行文件