Problems with layers, depth and blending in openGL
I need to overlay some textures onto a video in a layered fashion (i.e. the first texture should appear under, the second texture when they are both semi-transparent etc). The textures all have different Z values so there should be no conflicts there. Images speak a thousand words so I have attached one below:
As you can see, the arrows are semi-transparent are cross over each other. Only the blue and red arrows seem to interact however. For arguments sake, lets say the red arrows have a z (vertical in this case) value of 4, the blue of 6 and the white of 10. The blend function I am using is:gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
and GL_DEPTH_TEST
is enabled.
I am looking for all the overlaid textures to interact the same as the red and blue ones do. i.e. You can see the red arrow beneath the white arrow and for a darker red to be shown where the darker 2 red arrows cross over. Can anyone point me in the right direction?
EDIT: Below is the code used to setup openGL for each frame render.
public void display(final GL gl, final GLProjection projection, final FieldMask fieldMask)
{
layerTextureShader.updateShader(gl, projection, fieldMask);
if (useMask)
{
layerMaskShader.updateShader(gl, projection, fieldMask);
}
gl.glTexEnvf(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_MODULATE);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, getVertexBufferObject());
gl.glBufferData(GL.GL_ARRAY_BUFFER, getNoOfVertices() * 3 * 4, getVertices(), GL.GL_STREAM_DRAW);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, getTexCoordBufferObject());
gl.glBufferData(GL.GL_ARRAY_BUFFER, getNoOfVertices() * 2 * 4, getTexCoords(), GL.GL_STREAM_DRAW);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, getIndicesBufferObject());
gl.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, getNoOfIndices() * 4, getIndices(), GL.GL_STREAM_DRAW);
gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, 0);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, getColorBufferObject());
gl.glBufferData(GL.GL_ARRAY_BUFFER, getNoOfVertices() * 4 * 4, getColors(), GL.GL_STREAM_DRAW);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
if (useMask)
{
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, getMaskColorBufferObject());
gl.glBufferData(GL.GL_ARRAY_BUFFER, getNoOfVertices() * 4 * 4, getMaskColors(), GL.GL_STREAM_DRAW);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
}
gl.glEnable(GL.GL_TEXTURE_2D);
gl.glActiveTexture(GL.GL_TEXTURE0);
gl.glBindTexture(GL.GL_TEXTURE_2D, textureId);
gl.glEnable(GL.GL_BLEND);
gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
if (useMask)
{
gl.glBlendEquation(GL.GL_MIN);
layerMaskShader.use(gl);
display(gl, true);
layerMaskShader.release(gl);
}
gl.glBlendEquat开发者_StackOverflow中文版ion(GL.GL_MAX);
layerTextureShader.use(gl);
display(gl, false);
layerTextureShader.release(gl);
gl.glDisable(GL.GL_TEXTURE_2D);
gl.glDepthMask(true);
gl.glDisable(GL.GL_BLEND);
}
For alpha blending you need to ensure you're drawing them in the correct order or draw them with additive blending.
A common approach to do this is to separate your alpha blended items from the non-alpha blended items. Render all your standard items, sort your alpha-blended ones from back to front and render them in that order. If framerates are an issue (say if you have many items to sort) you can sort across multiple frames.
精彩评论