我已经在这个问题上工作了一段时间,现在是时候向更大的社区寻求帮助了。我已经阅读了关于这个主题的许多其他StackOverflow问题,但还没有找到相关的解决方案。
我有一个完善的Android OpenGL项目渲染到纹理,然后再将纹理渲染到屏幕上。这种机制对我的应用至关重要,我有很多历史和信心。我最近添加了新功能,以在内部拍摄渲染的屏幕截图;也就是说,我的应用程序也能够将渲染的纹理保存到文件中。传统上这些图像与显示器的大小完全相同。
现在,我想要生成大于屏幕尺寸的图像,以便生成的屏幕截图反映较大的图像尺寸,但在屏幕上显示时也会缩放到屏幕尺寸。这应该是一个简单易行的过程,但是,我得到了意想不到的结果。生成的屏幕截图是正确的大小,但除了屏幕大小的区域外,它是空的。例如,如果渲染的纹理和结果屏幕截图的目标是屏幕显示大小的4倍(每个维度X和Y的屏幕大小的两倍),屏幕截图图像文件将是预期的大小,但只有左上角将绘制图像的象限。在此示例中,这是resulting generated screenshot。我的视口是768x887,结果屏幕截图正确1536x1774,在屏幕截图中,唯一的彩色区域是768x887。出于我们的目的,我的片段着色器用于渲染到纹理是对坐标映射到屏幕的测试......
gl_FragColor = vec4(uv.x, 0.0, uv.y, 1.0); // during render to texture
请注意,当我们在执行期间将相同的纹理绘制到屏幕时,整个屏幕的颜色与该着色器一致。为什么屏幕截图只有一个象限,而不是整个?为什么,当这个纹理在屏幕上绘制时,它只显示屏幕大小的部分,而不是三个空象限的整个部分?
我从GLSurfaceView.Renderer.onSurfaceChanged()
获取视口的原始大小,并将其存储到_viewportWidth
和_viewportHeight
。当我创建帧缓冲区纹理时,我传统上直接从_viewportWidth
和_viewportHeight
创建它。现在,我有一个例子......
float quality = 2f;
_frameBufferWidth = (int)((float)_viewportWidth * quality);
_frameBufferHeight = (int)((float)_viewportHeight * quality);
...并按_frameBufferWidth
生成大小为_frameBufferHeight
的帧缓冲区。
我也打电话给glViewport()
两次。在我第一次调用glBindframebuffer()
渲染到纹理而不是屏幕之后,在进行相关的错误处理之后,我调用glViewport(0, 0, _frameBufferWidth, _frameBufferHeight)
,它会毫无错误地传递。当我后来想要将此纹理绘制到屏幕上时,我会进行第二次glBindframebuffer()
调用,然后立即调用glViewport(0, 0, _viewportWidth, _viewportHeight)
。我们的想法是,对纹理的原始渲染将进入_frameBufferWidth
_frameBufferHeight
尺寸的图像,当我们在屏幕上显示时,我们需要_viewportWidth
到_viewportHeight
尺寸。
我可能缺少什么想法?提前谢谢。
编辑(2016年3月10日):
我刚试过quality=0.5f
并得到了不寻常的结果。我更愿意分享更多图片来澄清这种情况,但我是一名新成员,我只允许两名。当我们使用quality=0.5f
绘制到屏幕时,屏幕会根据上面的GLSL代码正确着色:显示与上面链接的屏幕截图的768x887左上象限相对应(对应quality=2f
)。但是,quality=0.5f
screenshot that is generated的颜色与屏幕不同。这个截图正确地具有预期的384x443大小,但仍然被渲染为好像它的768x887并且刚刚裁剪出384x443部分。
即使代码另有说明,似乎我们总是在_viewportWidth
区域内呈现_viewportHeight
,而不是_frameBufferWidth
到_frameBufferHeight
区域。
对于两个渲染过程,我基本上都有一个全屏四边形,并且习惯了那个正常工作。当我渲染到屏幕时,我将刚渲染的纹理采样到:
gl_FragColor = texture2D(u_sampler, uv); // during render to screen
u_sampler
访问我们渲染的纹理,uv
对于两个维度都在[0,1]中。因此,要使屏幕显示任何内容,必须进行纹理查找以获取其颜色信息。因此,屏幕上显示的鲜红色和蓝色最初必须存在于帧缓冲区中,即使它从正确大小的屏幕截图中丢失了。
答案 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);
因为glViewport会将标准化坐标转换为像素坐标。
另外要提到的是,在iOS视图中,视图的大小不在像素中,而是在点上,所以我需要将它乘以3.您可以查看是否在Android上获得了实际的像素坐标。