2 Framebuffer对象
当对附加到Framebuffer对象上的图像执行渲染操作时,试图通过纹理或图像获取从这些图像中访问像素将导致未定义的值。这种从图像中获取的信息是不一致的。注意,这只涉及到渲染操作的获取(fetch)操作;通过像素传输操作(即使是异步操作)读取图像也可以正常工作(尽管非异步读取会使CPU停止等待GPU完成渲染)。
OpenGL对于从附加纹理(attached texture)中获取数据是非常严格的。它指出,如果shader执行的任何纹理提取的图像的任何部分都是由渲染操作写入的,则被访问的纹理的值是未定义的,OpenGL对此相当保守。
如果一个图像被附加到一个framebuffer对象上,那么为了从读取纹理(或存储提供对该图像访问的任何纹理)中获得有意义的值,您必须使用纹理mipmap范围说明符(mipmap range specifier),使其不可能访问到已经attach的任何mipmap级别。或者,您可以使用Nearest的或Linear minification滤波器,并从其他attach的mipmap层获取。
当使用数组纹理或Cubemap纹理时,您同样将获得未定义的获取,即使只attach了其中一个纹理,并且仅从另一个纹理中获取。只要fetch和attach层都在相同的mipmap级别,就会得到未定义的行为。
纹理视图(texture view)可以帮助解决数组/面问题。例如,如果你想在相同的mipmap中从纹理数组0层中读取数据并写入纹理数组1层,你可以创建两个纹理视图,每个都只能访问特定的层。第0层的视图可以绑定为一个纹理,而第1层的视图可以附加到FBO。没有反馈回路会起作用。
注意:触发未定义的fetch操作所需要的只是被attach的纹理,即使您没有渲染它。与framebuffer的draw buffer状态是不相关的。如果它被attach到当前正在渲染的FBO上,并且您试图从中读取它,那么您将得到未定义的行为。类似地,使用写掩码(Write Mask)也不能防止未定义的行为。
一旦这些图像不再被写入,那么在更改之前执行的渲染命令所写入的值,将能够被在更改之后执行的渲染命令将能够读取到。改变渲染内容的操作包括:
因此,如果你想实现可编程的Blend(比OpenGL提供的更复杂的Blend函数)操作,你需要在两个纹理之间经常“ping-pong”,算法是这样的:
从纹理0读取,混合(blend)并写入纹理1。绑定纹理1用于读取。将FBO的attachment更改为纹理0(记住:仅仅调用glDrawBuffers是不够的)。从纹理1读取,混合(blend)并写入纹理0。绑定纹理0用于读取。将FBO的attachment更改为纹理1(请记住:仅仅调用glDrawBuffers是不够的)。根据需要对每个混合(blend)对象重复上述操作。
限 时 特 惠: 本站每日持续更新海量各大内部创业教程,一年会员只需98元,全站资源免费下载 点击查看详情
站 长 微 信: lzxmw777