我正在进行一个测试项目,其中一个大的3D四边形与其他几个3D四边形相交(旋转方式不同)。所有四边形都具有透明度(从完全透明到完全透明)。小四边形永远不会重叠,好吧,它们可能会,但相机放置和Z缓冲区确保只有那些可能重叠的部分实际上重叠。
为了渲染这个,我首先将大四边形渲染到另一个rgba帧缓冲区以供稍后查找。 现在我开始渲染到屏幕。首先渲染天空盒,然后在启用了Alpha混合的情况下渲染小四边形:GL_SRC_ALHPA和GL_ONE_MINUS_SRC_ALPHA。之后我再次使用alpha混合渲染大四边形。当然,由于Z缓冲区,只会渲染四边形前面的像素。
这就是为什么,在小四边形的片段着色器中,我做了一个光线追踪来找到与大四边形的交点。如果交点是小四边形,我从最初创建的帧缓冲区中获取纹理元素,并手动将此纹理元素与计算出的小四边形纹理颜色混合。
但结果并不相同:前面的颜色正确呈现(GPU处理那里的混合),它们背后的颜色是“怪异的”。它们更亮或更暗但我从来没有得到相同的结果。在考虑之后,我认为这一定是因为我没有从我的小四边形着色器中发出正确的alpha值,因此GPU执行混合会更改颜色。
因此,当使用上述混合方法在GPU上进行混合时,计算的alpha值究竟是多少。在opengl手册中,我找到:A * Srgba +(1 - A)* Drgba。当我发出该结果时,混合是不一样的。我很确定这是因为结果再次通过GPU混合。
光线追踪是正确的,我很确定。
那么,手动混合应该怎么办? 或者,我应该使用其他方法来获得正确的效果吗?
我不相信,但这里有一些代码(优化适用于以后):
vec4 vRayOrg = vec4(0.0, 0.0, 0.0, 1.0);
vec4 vRayDir = vec4(normalize(vBBPosition.xyz), 0.0);
vec4 vPlaneOrg = mView * vec4(0.0, 0.0, 0.0, 1.0);
vec4 vPlaneNormal = mView * vec4(0.0, 1.0, 0.0, 0.0);
float div = dot(vRayDir.xyz, vPlaneNormal.xyz);
float t = dot(vPlaneOrg.xyz - vRayOrg.xyz, vPlaneNormal.xyz) / div;
vec4 pIntersection = vRayOrg + t * vRayDir;
vec3 normal = normalize(vec4(vCoord, 0.0, 0.0)).xyz;
vec3 vLight = normalize(vPosition.xyz / vPosition.w);
float distance = length(vCoord) - 1.0;
float distf = clamp(0.225 - distance, 0.0, 1.0);
float diffuse = clamp(0.25 + dot(-normal, vLight), 0.0, 1.0);
vec4 cOut = diffuse * 9.0 * distf * cGlow;
if (distance > 0.0 && t >= 0.0 && pIntersection.z <= vBBPosition.z)
{
vec2 vTexcoord = (vProjectedPosition.xy / vProjectedPosition.w) * 0.5 + 0.5;
vec4 cLookup = texture(tLookup, vTexcoord);
cOut = cLookup.a * cLookup + (1.0 - cLookup.a) * cOut;
}
vFragColor = cOut;