我需要将球体渲染到纹理(使用帧缓冲区对象(FBO)完成),然后将该纹理与后台缓冲区进行 alpha 混合。到目前为止,除了在每一帧开始时清除它之外,我还没有对纹理进行任何处理。
我应该说我的场景只包含一个空旷空间中的行星,球体应该出现在行星旁边或周围(现在有点像月亮)。当我将球体直接渲染到后台缓冲区时,它会正确显示;但是当我执行将其渲染为纹理然后将该纹理与后台缓冲区混合的中间步骤时,球体仅在它位于行星前面时才会显示,不在前面的部分只是“切断” “:
我使用glutSolidSphere
绑定到 FBO 的 RGBA8 全屏纹理渲染球体,确保每个球体像素接收 1.0 的 alpha 值。然后,我将纹理传递给片段着色器程序,并使用此代码在 alpha 混合时将全屏四边形(纹理映射到其上)渲染到后缓冲区:
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glBegin(GL_QUADS);
glTexCoord2i(0, 1);
glVertex3i(-1, 1, -1); // TOP LEFT
glTexCoord2i(0, 0);
glVertex3i(-1, -1, -1); // BOTTOM LEFT
glTexCoord2i(1, 0);
glVertex3i( 1, -1, -1); // BOTTOM RIGHT
glTexCoord2i(1, 1);
glVertex3i( 1, 1, -1); // TOP RIGHT
glEnd();
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
这是着色器代码(取自用 Cg 编写的 FX 文件):
sampler2D BlitSamp = sampler_state
{
MinFilter = LINEAR;
MagFilter = LINEAR;
MipFilter = LINEAR;
AddressU = Clamp;
AddressV = Clamp;
};
float4 blendPS(float2 texcoords : TEXCOORD0) : COLOR
{
float4 outColor = tex2D(BlitSamp, texcoords);
return outColor;
}
我什至不知道这是深度缓冲区的问题还是 alpha 混合的问题,我尝试了很多启用和禁用深度测试(将深度缓冲区附加到 FBO)和 alpha 混合的组合。
编辑:我尝试将一个空白的全屏四边形直接渲染到后台缓冲区,甚至在地球边缘裁剪。出于某种原因,启用渲染四边形的深度测试(即删除线glDisable(GL_DEPTH_TEST)
和glEnable(GL_DEPTH_TEST) in the code above
)解决了这个问题,但是现在除了行星和球体之外的所有东西都显示为白色:
我确保(并且可以确认)纹理的 alpha 通道在每个像素上都是 0,但球体除外,所以我不明白可以在哪里引入白度。(也仍然有兴趣解释为什么启用深度测试会产生这种效果。)