Android OpenGL:渲染为大于屏幕大小和GLVIEW的纹理

Android OpenGL:渲染为大于屏幕大小和GLVIEW的纹理,android,opengl-es,framebuffer,fbo,Android,Opengl Es,Framebuffer,Fbo,我已经在这个问题上工作了一段时间,是时候向更大的社区寻求帮助了。我已经阅读了许多关于这个主题的其他StackOverflow问题,但还没有找到相关的解决方案 我有一个完善的Android OpenGL项目,它先渲染纹理,然后再将纹理渲染到屏幕上。这个机制是我应用的基础,我对它有很多历史和信心。我最近添加了新功能,在内部拍摄了渲染的屏幕截图;也就是说,我的应用程序也能够将渲染纹理保存到文件中。传统上,这些图像的大小与显示屏的大小完全相同 现在,我想生成大于屏幕大小的图像,这样生成的屏幕截图可以反映

我已经在这个问题上工作了一段时间,是时候向更大的社区寻求帮助了。我已经阅读了许多关于这个主题的其他StackOverflow问题,但还没有找到相关的解决方案

我有一个完善的Android OpenGL项目,它先渲染纹理,然后再将纹理渲染到屏幕上。这个机制是我应用的基础,我对它有很多历史和信心。我最近添加了新功能,在内部拍摄了渲染的屏幕截图;也就是说,我的应用程序也能够将渲染纹理保存到文件中。传统上,这些图像的大小与显示屏的大小完全相同

现在,我想生成大于屏幕大小的图像,这样生成的屏幕截图可以反映更大的图像大小,但在屏幕上显示时也会缩放到屏幕大小。这应该是一个简单明了的过程,然而,我得到了意想不到的结果。生成的屏幕截图大小正确,但除了屏幕大小的区域外,其余区域为空。例如,如果渲染纹理和生成的屏幕截图是屏幕显示大小的4倍(每个维度X和Y的屏幕大小的两倍),则屏幕截图图像文件将是预期大小,但仅绘制了图像的左上象限。在本例中,下面是。我的视口是768x887,生成的屏幕截图正确为1536x1774,在屏幕截图中,唯一的彩色区域是768x887。出于我们在这里的目的,我的渲染到纹理的片段着色器是对屏幕坐标映射的测试

gl_FragColor = vec4(uv.x, 0.0, uv.y, 1.0);  // during render to texture
请注意,当我们在执行期间将此相同纹理绘制到屏幕时,整个屏幕的颜色与该着色器一致。为什么只有屏幕截图的一个象限被填充,而不是整个屏幕?为什么,当这个纹理在屏幕上绘制时,它只显示屏幕大小的一部分,而不是整个屏幕的三个空象限

我从
GLSurfaceView.Renderer.onSurfaceChanged()
获取视口的原始大小,并将其存储到
\u viewportWidth
\u viewportHeight
中。当我创建帧缓冲区纹理时,我通常直接从
\u viewportWidth
\u viewportHeight
创建它。现在,我举个例子

float quality = 2f;
_frameBufferWidth = (int)((float)_viewportWidth * quality);
_frameBufferHeight = (int)((float)_viewportHeight * quality);
。。。并通过
\u frameBufferHeight
生成大小为
\u frameBufferWidth
的帧缓冲区

我还调用了
glViewport()
两次。在我第一次调用
glBindframebuffer()
渲染到纹理而不是屏幕之后,在执行相关的错误处理之后,我调用
glViewport(0,0,_frameBufferWidth,_frameBufferHeight)
,它会毫无错误地通过。当我以后要在屏幕上绘制此纹理时,我会进行第二次调用
glBindframebuffer()
并在调用之后立即调用
glViewport(0,0,_viewportWidth,_viewportHeight)
。其思想是,原始渲染到纹理将进入一个
\u frameBufferWidth
by
\u frameBufferHeight
大小的图像,当我们在屏幕上显示它时,我们需要一个
\u viewportWidth
by
\u viewportHeight
大小的图像

你知道我遗漏了什么吗?提前谢谢

编辑(2016年3月10日): 我刚试过
quality=0.5f
,结果很不寻常。我更愿意分享更多的图片来澄清这个场景,但我是一个新成员,只允许两个。当我们以
质量=0.5f
绘制屏幕时,屏幕根据上面的GLSL代码正确着色:显示与上面链接的屏幕截图的768x887左上象限相同(对应于
质量=2f
)。但是,
质量=0.5f
的颜色与屏幕不同。此屏幕截图正确地具有预期的384x443大小,但仍呈现为768x887,只是裁剪出384x443部分

即使代码建议相反,似乎我们总是通过
\u viewportHeight
区域渲染到
\u viewportWidth
区域,而不是通过
\u frameBufferHeight
区域渲染到预期的
\u frameBufferWidth
区域

我基本上有一个用于渲染过程的全屏四元组,我已经习惯了这种工作方式。当我渲染到屏幕时,我对刚刚渲染到的纹理进行采样:

gl_FragColor = texture2D(u_sampler, uv);  // during render to screen

u_采样器
访问我们渲染到的纹理,
uv
在[0,1]中用于两个维度。因此,为了让屏幕显示任何内容,它必须进行纹理查找以获取其颜色信息。因此,屏幕上显示的鲜红色和蓝色最初必须存在于帧缓冲区中,即使它在大小正确的屏幕截图中丢失。

我以前遇到过与iOS相同的问题,也遇到过openGL ES。我尝试渲染到4096*4096的帧缓冲区,它位于左上角

我找到的解决办法是添加

glViewport(0, 0, 4096, 4096)
在任何其他功能之前,例如

glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
在主渲染函数中

后来我可以用

glViewport(0, 0, view.bounds.width*3, view.bounds.height*3);
as glViewport将标准化坐标转换为像素坐标


另一件需要提及的事情是,在iOS上,视图的大小不是像素而是点,所以我需要将它乘以3。您可以查看Android上是否有实际的像素坐标。

这听起来很合理。您有其他设备可以测试它吗?理想情况下,来自不同的供应商,具有不同的GPU?Hi-Reto。我刚刚在另一台设备上测试了这个,得到了同样的结果。我从三星Galaxy Tab a开始,刚试过LG G2。根据我的OpenGL查询,两者都使用高通Adreno渲染器,并允许最大纹理大小和视口尺寸为4096。我想我是从你的另一个人那里得到了多个电话的想法。任何补充