How to avoid transparency overlap using OpenGL?

旧城冷巷雨未停 提交于 2021-02-07 13:41:20

问题


I am working on a handwriting application on iOS. I found the sample project "GLPaint" from iOS documentation which is implemented by OpenGL ES, and I did something modification on it.

I track the touch points and calculate the curves between the points and draw particle images alone the curve to make it looks like where the finger passby.

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];

What I got is a solid line which looks quite good. But now I want to draw semi-transparent highlight instead of solid line. So I replace the particle image with a 50% transparency one without changing code.

Result of 50% transparency particle image

Result of 50% transparency particle image

There is something wrong with blend.

What I need

What I need

I draw three points using the semi-transparency particle image, and the intersection area should keep 50% transparency.

What's the solution?


回答1:


Im maybe two years later answering that question, but i hope it helps somebody who comes here looking for a solution to this problem, like it happened to me.

You are going to need to assign to each cirle a different z value. It doesn't matter how big or small this difference is, we only need them to not be strictly equal.

First, you disable writing in the color buffer glColorMask(false,false,false,false) , and then draw the circles normally. The Z-buffer will be updated as desired, but no circles will be drawn yet.

Then, you enable writing in the color buffer (glColorMask(true,true,true,true) ) and set the depthFunc to LEQUAL ( glDepthFunc(GL_LEQUAL) ). Only the nearest circle pixels will pass the depth test (Setting it to LEQUAL instead of EQUAL deals with some rare but possible floating point approximation errors). Enabling blending and drawing them again will produce the image you wanted, with no transparency overlap.




回答2:


You have to change the blend function. You can play around it with:

glBlendFunc(GL_SRC_ALPHA,GL_ONE);

Maybe (GL_ONE, GL_ONE), forgot how to handle your case, but the solution is in that function.

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




回答3:


Late reply but hopefully useful for others.

Another way to avoid that effect is to grab the color buffer before transparent circles are drawn (ie. do a GrabPass) and then read and blend manually with the opaque buffer in the fragment shader of your circles.



来源:https://stackoverflow.com/questions/14154704/how-to-avoid-transparency-overlap-using-opengl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!