【问题标题】:How to avoid transparency overlap using OpenGL?如何使用OpenGL避免透明度重叠?
【发布时间】:2012-12-18 17:56:38
【问题描述】:

我正在开发 iOS 上的手写应用程序。我从 iOS 文档中找到了由 OpenGL ES 实现的示例项目“GLPaint”,并对其进行了一些修改。

我跟踪触摸点并计算点之间的曲线并单独绘制粒子图像曲线使其看起来像手指经过的地方。

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% 的图像。

Result of 50% transparency particle image

混合有问题。

What I need

我用半透明粒子图画了三个点,相交区域要保持50%的透明度。

解决办法是什么?

【问题讨论】:

  • 问题是您需要消除过度绘制,对于一般情况“仅混合”是不可能的。您可以使用深度缓冲区(带有 alpha 测试),但这不会正确抗锯齿。如果您希望对此进行适当的抗锯齿处理,那么要做到这一点并非易事,至少在一般情况下并非如此。您需要先渲染到额外的帧缓冲区,然后在第二遍中进行合成。
  • 感谢您的回复。我是 OpenGL 的新手,我仍然不清楚 OpenGL 中的大多数概念。我认为抗锯齿不是问题。能否请您更详细地说明代码?

标签: ios opengl-es transparency alpha overlap


【解决方案1】:

您必须更改混合功能。你可以玩弄它:

glBlendFunc(GL_SRC_ALPHA,GL_ONE);

也许(GL_ONE, GL_ONE),忘记了如何处理你的情况,但解决方案就在那个函数中。

http://www.opengl.org/sdk/docs/man/xhtml/glBlendFunc.xml

【讨论】:

    【解决方案2】:

    我可能会在两年后回答这个问题,但我希望它可以帮助那些来这里寻找解决这个问题的人,就像它发生在我身上一样。

    您需要为每个圆圈分配不同的 z 值。不管这个差异有多大或多小,我们只需要它们不严格相等即可。

    首先,您禁用在颜色缓冲区glColorMask(false,false,false,false) 中的写入,然后正常绘制圆圈。 Z-buffer 将根据需要更新,但尚未绘制圆。

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

    【讨论】:

    • 非常感谢您的回答。还有一个问题。 “分配不同的z值”是什么意思。那是坐标的第三维还是 z 缓冲区值?对不起,如果这个问题没有意义,我是opengl的新手。
    • 两者同时!在着色器内部,X 和 Y 坐标控制每个顶点在屏幕中的位置(-1 到 1),Z 坐标控制深度(0 到 1,更接近 0)。此深度是与 Z 缓冲区相比的深度 - 如果该像素中的 Z 缓冲区具有较小的值,则意味着已经有一个像素靠近相机,因此该片段被丢弃。因此,如果每个圆都有不同的 Z 坐标,则每个像素只有一个片段不会被丢弃(离相机最近的片段),因此混合会成功。
    • 您可能会感到困惑,因为大多数时候我们使用变换矩阵在顶点着色器中应用坐标变换。因此,您有一个顶点的初始 X、Y、Z,它被转换到另一个位置以将其与相机或其他任何东西对齐,因此着色器使用的真实 Z 可能不是顶点的原始 Z。如果您是 OpenGL 新手,解释起来会有些复杂,所以我强烈建议您阅读本教程(直到“深度和模板”部分),open.gl,它在我开始时帮助了我很大。如果您需要,请随时问我!
    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多