OpenGL ReadPixels(屏幕截图)Alpha
我正在使用平铺渲染(使用glReadPixels)设置来拍摄场景的屏幕截图。我的输出看起来正确: 但观察alpha通道,即使透明纹理在不透明纹理上渲染,像素仍然是透明的 尤其是在我们看到天花板的地方,汽车的“内部”应该是完全不透明的,但在穿过后窗时,部分是透明的 是否有一种方法可以在像素处测试每个纹理的alpha分量,而不仅仅是最近的一个 是否有一种方法可以在像素处测试每个纹理的alpha分量,而不仅仅是最近的一个 否。OpenGL为每个像素存储一个RGBA值;无法获取以前的值(因为这需要大量RAM)OpenGL ReadPixels(屏幕截图)Alpha,opengl,rendering,screenshot,alpha,Opengl,Rendering,Screenshot,Alpha,我正在使用平铺渲染(使用glReadPixels)设置来拍摄场景的屏幕截图。我的输出看起来正确: 但观察alpha通道,即使透明纹理在不透明纹理上渲染,像素仍然是透明的 尤其是在我们看到天花板的地方,汽车的“内部”应该是完全不透明的,但在穿过后窗时,部分是透明的 是否有一种方法可以在像素处测试每个纹理的alpha分量,而不仅仅是最近的一个 是否有一种方法可以在像素处测试每个纹理的alpha分量,而不仅仅是最近的一个 否。OpenGL为每个像素存储一个RGBA值;无法获取以前的值(因为这需要大
写入帧缓冲区的alpha值取决于alpha混合方程,您可以使用
glBlendFunc
或glBlendFuncSeparate
进行设置。有关更多信息,请参见OpenGL wiki上的,并让您查看各种混合模式的效果。我认为您从评论和其他答案中获得了一些有用的指导,但没有获得完整的详细解决方案。与其只是给出结果,不如让我来看看,这样你就知道下一次你自己怎么弄清楚了
我假设您使用GL_SRC_ALPHA,GL_ONE_减去
blend函数将半透明对象向后绘制。你没有直接提到这一点,但它相当标准,并且与你所看到的一致。正确的解决方案还需要帧缓冲区中的alpha组件,但您已经有了,否则在读取alpha时将一无所获
为了说明整个过程,我将在此过程中使用两个示例。我只列出颜色的(R,A)
组件,G
和B
的行为就像R
(R1,1.0)
的图层,然后在其顶部绘制一个带有(R2,0.4)
的图层(R1,0.5)
的图层,然后在上面绘制一个带有(R2,0.4)
的图层(Rb,0.0)
,对于这种混合,您总是希望使用0.0的alpha值进行清除
首先,让我们计算我们想要实现的颜色结果:
- 对于情况1,绘制第一层完全覆盖背景,因为它的alpha=1.0。然后我们在上面混合第二层。因为它的alpha=0.4,所以我们保留了第一层的60%,并添加了第二层的40%。所以我们想要的颜色是
0.6*R1+0.4*R2
- 对于案例1,绘制第一层保留50%的背景,因为它的alpha=0.5。那么目前为止的颜色是
然后我们在上面混合第二层。同样,我们保留了前一层颜色的60%,并添加了第二层颜色的40%。所以我们想要的颜色是0.5*Rb+0.5*R1
0.6*(0.5*Rb+0.5*R1)+0.4*R2 =0.3*Rb+0.3*R1+0.4*R2
- 对于案例1,我们的第一层是完全不透明的。观察不透明度的一种方法是测量物体吸收的光的比例。一旦我们有了一个吸收所有光线的层,我们渲染的任何其他东西都不会改变这一点。我们的总阿尔法应该是
1.0
- 对于案例2,我们有一层吸收50%的光,另一层吸收40%的剩余光。由于50%中的40%是20%,因此总共有70%被吸收。我们的总阿尔法应该是
0.7
GL_SRC_ALPHA,GL_ONE_减去_SRC_ALPHA
进行混合可以获得所需的颜色效果。但正如你所注意到的,不是阿尔法。对示例执行计算:
- 案例1:绘图层1,
为1.0,源值为SRC_ALPHA
,目标值为S=(R1,1.0)
。因此,blend函数的计算结果为D=(Rb,0.0)
这将写入帧缓冲区,并成为图形图层2的目标值。第2层的源代码是SRC_ALPHA*S+1_减去SRC_ALPHA*D =1.0*(R1,1.0)+0.0*(Rb,0.0) =(R1,1.0)
。对于(R2,0.4)
SRC_ALPHA
SRC_ALPHA*S+1_减去SRC_ALPHA*D =0.4*(R2,0.4)+0.6*(R1,1.0) =(0.4*R2+0.6*R1,0.76)
- 案例2:绘图层1,
为0.5,源值为SRC_ALPHA
,目标值为S=(R1,0.5)
。因此,blend函数的计算结果为D=(Rb,0.0)
这将写入帧缓冲区,并成为图形图层2的目标值。第2层的源代码是SRC_ALPHA*S+1_减去SRC_ALPHA*D =0.5*(R1,0.5)+0.5*(Rb,0.0) =(0.5*R1+0.5*Rb,0.25)
。对于(R2,0.4)
SRC_ALPHA
SRC_ALPHA*S+1_减去SRC_ALPHA*D =0.4*(R2,0.4)+0.6*(0.5*R1+0.5*Rb,0.25) =(0.4*R2+0.3*R1+0.3*Rb,0.31)
glBlendFuncSeparate()
,这使我们能够做到这一点。我们需要弄清楚的是alpha使用什么混合函数。以下是思考过程:
假设我们已经渲染了一些半透明对象,其总alpha值为A1
,存储在帧缓冲区中。到目前为止,我们渲染的内容吸收了总光的一部分A1
,并让一部分1.0-A1
通过。我们用alphaA2渲染另一层
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
GL_ONE_MINUS_DST_ALPHA, GL_ONE);