我有两个表面。
一个作为背景(先渲染)。
另一个作为我的“画布”(最后渲染)。
我在尝试使用混合来实现透明效果的时候发现了一个很奇怪的问题!
虽然我按照“推荐”的渲染顺序渲染了,还是出不了透明效果……
我不得不使用一些“技巧”来达到我想要的效果。
我现在的妥协是要么使用
glDepthFunc(GL_LEQUAL)
,要么稍微调整第二个表面的Z(加上0.001f
)...
glDepthFunc(GL_LEQUAL);
quad.Draw();//the background
glDepthFunc(GL_LESS);
或
std::vector<GLfloat> Vtx = {
1.0f, 1.0f, 0.0f, // top right
1.0f, -1.0f, 0.0f, // bottom right
-1.0f, -1.0f, 0.0f, // bottom left
-1.0f, 1.0f, 0.0f // top left
};
std::vector<GLfloat> Vtx2 = {
1.0f, 1.0f, 0.001f, // top right
1.0f, -1.0f, 0.001f, // bottom right
-1.0f, -1.0f, 0.001f, // bottom left
-1.0f, 1.0f, 0.001f // top left
};
我想知道为什么会这样。它不是遵循正确的渲染顺序来正确混合每个对象吗?
有没有更好的方法可以在这两个表面上实现透明效果?
我意识到这其实是一个很复杂的问题...
首先,你必须把
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
放在正确的位置。
而且我一开始放错了地方(我什至把
glClear(GL_COLOR_BUFFER_BIT)
和glClear(GL_DEPTH_BUFFER_BIT)
放在了两个不同的地方),导致后面所有的结果都乱了!
然后关于NDC的Z轴... 是的,NDC的Z轴的-z是指向我的眼睛,只有整个场景变成3D后+z才指向我的眼睛...
使用普通投影矩阵后
但是还有一个问题……如果我真的把两个平面重叠了(两个z都是0) 会有z-fighting(至少在3D场景中)
下图是没有
glDepthFunc(GL_LEQUAL)
的2D场景(也是两个面完全重叠)
我目前的解决方案是:
直接在2D场景中的代码中添加
glDepthFunc(GL_LEQUAL)
(是的,我不知道为什么,但是在没有投影矩阵的情况下z-fighting就消失了)...
或者在所有z坐标上加上
-0.001f
(glClear
一定要放对地方)
std::vector<GLfloat> Vtx2 = {
1.0f, 1.0f, -0.001f, // top right
1.0f, -1.0f, -0.001f, // bottom right
-1.0f, -1.0f, -0.001f, // bottom left
-1.0f, 1.0f, -0.001f // top left
}.