使用透视投影时,低分辨率渲染纹理结果
我目前正在为摄像头输入iPhone摄像头应用程序,将其转换为OpenGL纹理,然后将其映射到3D对象(为了简单起见,目前为透视投影平面)。 在将相机输入映射到此3D平面之后,我将该3D场景渲染为纹理,然后将纹理用作正交空间中平面的新纹理(在片段着色器中应用其他过滤器)。
只要我把所有东西放在正交投影中,我的渲染纹理的分辨率就非常高。 但从我投影透视投影机的那一刻起,我的渲染纹理的分辨率就非常低。
比较:
正如你所看到的,最后一张图像与另外两张图像相比分辨率很低。 所以我猜测我做错了什么。
我目前没有在我的任何帧缓冲区上使用多重采样,而且我仍然怀疑,无论如何我会需要它来解决我的问题,因为正交场景完美运行。
我渲染的纹理是2048x2048(最终将作为图像输出到iPhone相机胶卷中)。
以下是我认为可能相关的源代码的一些部分:
创建输出到屏幕的帧缓冲区的代码:
// Color renderbuffer
glGenRenderbuffers(1, &colorRenderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, colorRenderBuffer);
[context renderbufferStorage:GL_RENDERBUFFER
fromDrawable:(CAEAGLLayer*)glView.layer];
// Depth renderbuffer
glGenRenderbuffers(1, &depthRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
// Framebuffer
glGenFramebuffers(1, &defaultFrameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, defaultFrameBuffer);
// Associate renderbuffers with framebuffer
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_RENDERBUFFER, colorRenderBuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, depthRenderbuffer);
TextureRenderTarget类:
void TextureRenderTarget::init()
{
// Color renderbuffer
glGenRenderbuffers(1, &colorRenderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, colorRenderBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB8_OES,
width, height);
// Depth renderbuffer
glGenRenderbuffers(1, &depthRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16,
width, height);
// Framebuffer
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
// Associate renderbuffers with framebuffer
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_RENDERBUFFER, colorRenderBuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, depthRenderbuffer);
// Texture and associate with framebuffer
texture = new RenderTexture(width, height);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, texture->getHandle(), 0);
// Check for errors
checkStatus();
}
void TextureRenderTarget::bind() const
{
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glBindRenderbuffer(GL_RENDERBUFFER, colorRenderBuffer);
}
void TextureRenderTarget::unbind() const
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
}
最后,关于如何创建渲染纹理和填充像素的片段:
void Texture::generate()
{
// Create texture to render into
glActiveTexture(unit);
glGenTextures(1, &handle);
glBindTexture(GL_TEXTURE_2D, handle);
// Configure texture
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
void Texture::setPixels(const GLvoid* pixels)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
GL_UNSIGNED_BYTE, pixels);
updateMipMaps();
}
void Texture::updateMipMaps() const
{
glBindTexture(GL_TEXTURE_2D, handle);
glGenerateMipmap(GL_TEXTURE_2D);
}
void Texture::bind(GLenum unit)
{
this->unit = unit;
if(unit != -1)
{
glActiveTexture(unit);
glBindTexture(GL_TEXTURE_2D, handle);
}
else
{
cout << "Texture::bind -> Couldn't activate unit -1" << endl;
}
}
void Texture::unbind()
{
glBindTexture(GL_TEXTURE_2D, 0);
}
我会假设纹理映射与透视投影不完全一致。
你可以通过检查器(1象素单元格的棋格)替换相机胶卷图像吗? 然后比较正交投影和透视投影中的渲染棋子 - 网格应该不会模糊。 如果是这样,那么问题出现在投影矩阵中 - 它需要一些直接纹理到像素映射的偏差。
如果您有设备,您可以通过XCode中的OpenGL frame capture
功能查看渲染步骤 - 您将看到图像何时变得模糊。
至于mipmapping,将它用于即时创建的纹理并不好。
模糊可能由平面位于屏幕坐标中的半个像素引起。 由于从正交变换到透视变换会改变平面的位置,因此平面可能不会位于两次变换之间的同一屏幕坐标处。
当您将UIImageView从帧原点(0.0,0.0)移动到标准分辨率显示上的(0.5,0.5)和视网膜显示上的(0.25,0.25)时,会出现类似的模糊现象。
由于实际采样的像素数量是有限的,因此您的纹理非常高的事实可能无助于此情况。
尝试在屏幕x,y坐标中移动飞机一小段距离,并查看模糊是否消失。
我最终通过合并渲染过程的第一步和第二步来解决了我的问题。
第一步用于裁剪和翻转相机的纹理并将其渲染为新的纹理。 然后将这个新渲染的纹理映射到3D平面上,并将结果渲染为新的纹理。
我通过改变3D平面的纹理坐标来合并这两个步骤,以便我可以直接在这个平面上使用原始相机纹理。
我不知道究竟是什么原因造成了这两个渲染纹理之间的质量损失,而是作为未来的暗示:不渲染纹理并重新使用该结果来渲染纹理。 将所有这些融合在一起对性能更好,同时也避免了色彩偏移问题。
链接地址: http://www.djcxy.com/p/33879.html上一篇: Low resolution render to texture result when using perspective projection
下一篇: Rendering to texture on iOS OpenGL ES—works on simulator, but not on device