简体   繁体   English

具有深度测试的OpenGL点精灵-混合问题?

[英]OpenGL point sprites with depth testing - a blending issue?

I am rendering point sprites (using OpenGL ES 2.0 on iOS) as a user's drawing strokes. 我正在渲染点精灵(在iOS上使用OpenGL ES 2.0)作为用户的绘画笔触。 I am storing these points in vertex buffer objects such that I need to perform depth testing in order for the sprites to appear in the correct order when they're submitted for drawing. 我将这些点存储在顶点缓冲对象中,这样我就需要进行深度测试,以使精灵在提交进行绘制时以正确的顺序出现。

I'm seeing an odd effect when rendering these drawing strokes, as shown by the following screenshot: 渲染这些笔触时,我看到一个奇怪的效果,如以下屏幕截图所示:

点精灵混合问题

Note the background-coloured 'border' around the edge of the blue stroke, where it is drawn over the green. 注意蓝色笔触边缘周围的背景色“边框”,在绿色上绘制该边框。 The user drew the blue stroke after the green stroke, but when the VBOs are redrawn the blue stroke gets drawn first. 用户在绿色笔划之后绘制了蓝色笔划,但是重新绘制VBO时,首先绘制了蓝色笔划。 When it comes to draw the green stroke, depth testing kicks in and sees that it should be behind the blue stroke, and so does this, with some success. 绘制绿色笔划时,深度测试开始进行,发现它应位于蓝色笔划的后面,并且这样做取得了一些成功。 It appears to me to be some kind of blending issue, or to do with incorrectly calculating the colour in the fragment shader? 在我看来,这是某种混合问题,还是与错误计算片段着色器中的颜色有关? The edges of all strokes should be transparent, however it appears that the fragment shader combines it with the background texture when processing those fragments. 所有笔触的边缘应该是透明的,但是在处理这些片段时,片段着色器似乎将其与背景纹理结合在一起。

In my app I have created a depth renderbuffer and called glEnable(GL_DEPTH_TEST) using glDepthFunc(GL_LEQUAL) . 在我的应用中,我创建了一个深度渲染缓冲区,并使用glDepthFunc(GL_LEQUAL)调用了glEnable(GL_DEPTH_TEST) glDepthFunc(GL_LEQUAL) I have experimented with glDepthMask() to no avail. 我已经尝试过glDepthMask()无效。 Blending is set to glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA) , and the point sprite colour uses premultiplied alpha values. 混合设置为glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA) ,点精灵颜色使用预乘的alpha值。 The drawing routine is very simple: 绘制例程非常简单:

  • Bind render-to-texture FBO. 绑定渲染到纹理的FBO。
  • Draw background texture. 绘制背景纹理。
  • Draw point sprites (from a number of VBOs). 绘制点精灵(来自多个VBO)。
  • Draw this FBO's texture to the main framebuffer. 将此FBO的纹理绘制到主帧缓冲区。
  • Present the main framebuffer. 呈现主帧缓冲区。


EDIT 编辑

Here is some code from the drawing routine. 这是绘图例程中的一些代码。

Setup state prior to drawing: 绘制前的设置状态:

glDisable(GL_DITHER);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);

Drawing routine: 绘图程序:

[drawingView setFramebuffer:drawingView.scratchFramebuffer andClear:YES];
glUseProgram(programs[PROGRAM_TEXTURE]);
[self drawTexture:[self textureForBackgroundType:self.backgroundType]];

glUseProgram(programs[PROGRAM_POINT_SPRITE]);

// ...
// Draw all VBOs containing point sprite data
// ...

[drawingView setFramebuffer:drawingView.defaultFramebuffer andClear:YES];
glUseProgram(programs[PROGRAM_TEXTURE]);
[self drawTexture:drawingView.scratchTexture];

[drawingView presentFramebuffer:drawingView.defaultFramebuffer];

Thanks for any help. 谢谢你的帮助。

If you want to draw non opaque geometries you have to z-sort them from back to front. 如果要绘制不透明的几何图形,则必须从后到前对它们进行Z排序。 This has been the only way to get a proper blending for many years. 多年来,这是获得正确混合的唯一方法。 These days there are some algorithms for order independent transparency like Dual Depth Peeling but they are not applicable to iOS. 如今,有一些用于顺序无关透明度的算法,例如“双重深度剥离”,但它们不适用于iOS。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM