在QGLFramebufferObject中使用sRGB颜色进行多重采样 [英] Using sRGB colour in QGLFramebufferObject with multisampling

查看:697
本文介绍了在QGLFramebufferObject中使用sRGB颜色进行多重采样的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

出于性能原因,我已经分离了我的2D和3D渲染。我有两个QGLFramebufferObjects为每个类型,因为QGLFramebuffer不支持多采样与 GL_TEXTURE_2D 作为目标,所以一旦绘图完成多采样缓冲区,它被分割成'正常' QGLFramebufferObject,其中像素值被解析。一旦这两个渲染类型都已经完成,缓冲区就被用作着色器的纹理输入,将2D'层'融合到3D上。



我应该提到,我锁定使用QGLFramebufferObjects而不是纯OpenGL对象,因为我使用QPainter所有2D工作,而QPainter只能绘制到Qt类型。



这个过程很好,除了抗锯齿太暗,它几乎看起来像一个黑暗的轮廓:





=http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=242491 =nofollow>此处和这里)。所以我为我的FBO blitting启用了 GL_FRAMEBUFFER_SRGB ,将我所有FBO的纹理目标内部类型设置为 GL_SRGB8_ALPHA8 sRGB-> Linear在我的着色器中的混合计算之前(并且在最终输出之前再次返回)。



但是它不工作;它看起来太亮,太暗,或完全相同。每当整个框架太暗/太亮,我知道这是因为我错过了一个色彩空间的转换。



我真的可以用一个解释操作顺序的方法来启用 GL_FRAMEBUFFER_SRGB 状态,如果blitting将影响颜色空间,并且哪些FBO需要在sRGB中,以使抗锯齿看起来正确。

解决方案


因此我为我的FBO blitting启用了GL_FRAMEBUFFER_SRGB,将所有FBO的纹理目标内部类型设置为GL_SRGB8_ALPHA8,并在我的着色器中混合计算之前执行sRGB-> Linear(并在最终输出之前再次执行)。


这是有意义的,直到最后一步。



使用sRGB色彩空间的图片格式表示从该纹理访问的纹理会自动 从sRGB色彩空间转换成线性色彩空间。当你从纹理中获取texels时,它自身就会发生。 。所以你不应该做任何sRGB->线性计算。



同样,当你启用 GL_FRAMEBUFFER_SRGB 当渲染到使用sRGB颜色空间的图像时,写入该图像的值假定为线性。通过启用 GL_FRAMEBUFFER_SRGB ,您要告诉OpenGL要做的是将您写入的线性值转换为sRGB色彩空间值。这又是免费的 ,和混合和抗锯齿工作正常。所以再次,你不应该做任何手动转换。



真的,你需要做的是确保一个正确的线性颜色管道。在sRGB色彩空间中创建的任何纹理都应使用sRGB色彩空间中的图像格式。这将确保您在着色器中从它们获得的值是线性的,因此照明数学实际上可以工作。当您编写颜色值时,需要将它们写入sRGB颜色空间framebuffer,并启用 GL_FRAMEBUFFER_SRGB 。这将确保您从着色器写入的线性值正确地转换为sRGB以便显示。



最后一部分是您需要确保您的显示也是sRGB图像。我不知道Qt OpenGL上下文初始化,但除非他们在过去4年左右忽略OpenGL,应该有一些设置,你可以使用它来强制它创建一个上下文与sRGB色彩空间缓冲区。


For performance reasons I have separated my 2D and 3D rendering. I have two QGLFramebufferObjects for each type because QGLFramebuffer does not support multisampling with GL_TEXTURE_2D as a target, so once drawing is done into the multisampled buffer, it is blitted into a 'normal' QGLFramebufferObject where the pixel values are resolved. Once this has been done for one/both of the render types, the buffers are used as texture inputs to a shader that blends the 2D 'layer' onto the 3D one.

I should mention that I'm locked into using QGLFramebufferObjects instead of pure OpenGL objects because I use QPainter for all 2D work, and QPainter can only paint onto Qt types.

This process works fine, except the anti-aliasing is too dark, it almost looks like a dark outline:

After doing some research I discovered this was down to using linear colour space instead sRGB (here and here). So I enabled GL_FRAMEBUFFER_SRGB for my FBO blitting, set the texture target internal type for my all FBOs to GL_SRGB8_ALPHA8, and performed sRGB->Linear before the blending calculations in my shader (and back again before the final output).

But it is isn't working; it either looks too bright, too dark, or exactly the same. Whenever the whole frame is too dark/light, I know it's because I've missed a colour-space conversion. But when it looks exactly the same - what is going on!?

I could really do with someone explaining the order of operations for enabling the GL_FRAMEBUFFER_SRGB state, if blitting will affect the colour space, and which FBOs need to be in sRGB for the anti-aliasing to look correct. Or am I totally wrong, and is it something else entirely that is causing these multisampling artifacts?

解决方案

So I enabled GL_FRAMEBUFFER_SRGB for my FBO blitting, set the texture target internal type for my all FBOs to GL_SRGB8_ALPHA8, and performed sRGB->Linear before the blending calculations in my shader (and back again before the final output).

That made sense right up until the final step.

An image format that uses the sRGB colorspace means that texture accesses from that texture will automatically be converted from the sRGB colorspace into a linear colorspace. This happens by itself when you fetch texels from the texture. It's free. So you shouldn't have to do any "sRGB->Linear" computations at all.

Similarly, when you have enabled GL_FRAMEBUFFER_SRGB when rendering to an image that uses the sRGB colorspace, values you write to that image are assumed to be linear. By enabling GL_FRAMEBUFFER_SRGB, what you are telling OpenGL to do is to convert the linear values you write to sRGB colorspace values. This is again free, and works just fine with blending and antialiasing. So again, you shouldn't have to do any manual conversion.

So really, what you need to do is ensure a properly linear color pipeline. Any textures of yours that were created in the sRGB colorspace should use image formats in the sRGB colorspace. This will ensure that values you get from them in the shader are linear, so lighting math actually works. When you write color values, you need to write them to an sRGB colorspace framebuffer, with GL_FRAMEBUFFER_SRGB enabled. This will ensure that the linear values you write from your shader are properly converted to sRGB for display.

The last part is that you need to make sure that your display is an sRGB image as well. I know nothing about Qt OpenGL context initialization, but unless they've been ignoring OpenGL for the last 4 years or so, there should be some setting you can use to force it to create a context with sRGB colorspace buffers.

这篇关于在QGLFramebufferObject中使用sRGB颜色进行多重采样的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆