如何使用OpenGL避免透明度重叠?

7
我正在iOS上开发手写应用程序。我在iOS文档中找到了一个名为“GLPaint”的示例项目,它是由OpenGL ES实现的,并对其进行了一些修改。
我跟踪触摸点并计算点之间的曲线,然后沿着曲线绘制粒子图像,使其看起来像手指经过的轨迹。
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, brushData); // burshData is from CGImage, it is 

// vertexBuffer is generated based on the calculated points, it's just a sequence of point where need to draw image.
glVertexPointer(2, GL_FLOAT, 0, vertexBuffer); 
glDrawArrays(GL_POINTS, 0, vertexCount);

glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER_OES];

我得到的是一条实线,看起来非常好。但现在我想画半透明的高亮线而不是实线。所以我用50%透明度的粒子图像替换了原来的图像,而没有改变代码。

50%透明度粒子图像的结果

Result of 50% transparency particle image

混合物有问题。

我需要什么

What I need

我使用半透明粒子图像绘制了三个点,交集区域应该保持50%的透明度。

有什么解决方案吗?


1
问题在于您需要消除过度绘制,这在“仅混合”情况下对于一般情况而言是不可能的。您可以使用深度缓冲区(带有alpha测试),但那样无法正确地进行反锯齿处理。如果您想要正确地进行反锯齿处理,至少在一般情况下,这并不是易于得到正确结果的。您需要先渲染到额外的帧缓冲区,然后在第二次传递中进行复合。 - Damon
感谢你的回复。我是OpenGL的新手,对其中大多数概念仍不清楚。我认为抗锯齿不是问题所在。你能否提供更详细的代码说明呢? - Joe Jia
3个回答

6

也许我回答这个问题已经晚了两年,但我希望它能帮助到像我一样寻找解决此问题的人。

您需要为每个圆分配不同的z值。无论这种差异大小如何,我们只需要它们不是严格相等的。

首先,禁用颜色缓冲区中的写入操作glColorMask(false,false,false,false),然后正常绘制圆形。Z缓冲区将按预期更新,但尚未绘制任何圆形。

然后,启用颜色缓冲区中的写入操作(glColorMask(true,true,true,true))并将depthFunc设置为LEQUAL (glDepthFunc(GL_LEQUAL))。只有最近的圆形像素会通过深度测试(将其设置为LEQUAL而不是EQUAL可以处理一些罕见但可能的浮点近似误差)。启用混合并再次绘制它们将产生所需的图像,没有透明重叠。


非常感谢您的回答。还有一个问题。您所说的“分配不同的z值”是什么意思?是指坐标系的第三维还是z缓冲区的值?如果这个问题有点不清楚,那是因为我是opengl的新手。 - Woody Huang
同时进行!在着色器内,X和Y坐标控制每个顶点在屏幕上的位置(-1到1),而Z坐标控制深度(0到1,其中0更近)。这个深度与Z缓冲区进行比较 - 如果该像素的Z缓冲区具有较小的值,则意味着已经绘制了一个更靠近相机的像素,因此片段将被丢弃。因此,如果每个圆都有不同的Z坐标,则每个像素只有一个片段不会被丢弃(最靠近相机的片段),因此混合将成功。 - Ivelate
你可能会感到困惑,因为大多数情况下我们使用变换矩阵在顶点着色器内应用坐标变换。因此,对于一个顶点,你有一个初始的X、Y、Z值,它被转换到另一个位置以与相机或其他物体对齐,所以着色器使用的实际Z值可能不是你的顶点的原始Z值。如果你是OpenGL新手,这有点复杂解释,所以我强烈建议你阅读这个教程(直到“深度和模板”部分)https://open.gl/,当我开始学习时,它对我帮助很大。如果你需要更多帮助,请随时问我! - Ivelate

0

0

回复晚了,但希望对其他人有用。

避免这种效果的另一种方法是在绘制透明圆之前获取颜色缓冲区(即进行GrabPass),然后在圆的片段着色器中手动读取和混合不透明缓冲区。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接