简体   繁体   English

OpenGL - 具有多个纹理的蒙版

[英]OpenGL - mask with multiple textures

I have implemented masking in OpenGL according to the following concept:我已经根据以下概念在 OpenGL 中实现了遮罩:

  • The mask is composed of black and white colors.面具由黑色和白色组成。
  • A foreground texture should only be visible in the white parts of the mask.前景纹理应该只在蒙版的白色部分可见。
  • A background texture should only be visible in the black parts of the mask.背景纹理应该只在遮罩的黑色部分可见。

I can make the white part or the black part work as supposed by using glBlendFunc(), but not the two at the same time, because the foreground layer not only blends onto the mask, but also onto the background layer.我可以通过使用 glBlendFunc() 使白色部分或黑色部分按预期工作,但不能同时使用两者,因为前景层不仅混合到蒙版上,还混合到背景层上。

Is there anyone who knows how to accomplish this in the best way?有没有人知道如何以最佳方式实现这一目标? I have been searching the net and read something about fragment shaders.我一直在网上搜索并阅读有关片段着色器的内容。 Is this the way to go?这是要走的路吗?

This should work:这应该有效:

glEnable(GL_BLEND);
// Use a simple blendfunc for drawing the background
glBlendFunc(GL_ONE, GL_ZERO);
// Draw entire background without masking
drawQuad(backgroundTexture);
// Next, we want a blendfunc that doesn't change the color of any pixels,
// but rather replaces the framebuffer alpha values with values based
// on the whiteness of the mask. In other words, if a pixel is white in the mask,
// then the corresponding framebuffer pixel's alpha will be set to 1.
glBlendFuncSeparate(GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ZERO);
// Now "draw" the mask (again, this doesn't produce a visible result, it just
// changes the alpha values in the framebuffer)
drawQuad(maskTexture);
// Finally, we want a blendfunc that makes the foreground visible only in
// areas with high alpha.
glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA);
drawQuad(foregroundTexture);

This is fairly tricky, so tell me if anything is unclear.这相当棘手,所以如果有任何不清楚的地方,请告诉我。

Don't forget to request an alpha buffer when creating the GL context.在创建 GL 上下文时不要忘记请求一个 alpha 缓冲区 Otherwise it's possible to get a context without an alpha buffer.否则有可能在没有 alpha 缓冲区的情况下获得上下文。

Edit: Here, I made an illustration.编辑:在这里,我做了一个插图。插图

Edit: Since writing this answer, I've learned that there are better ways to do this:编辑:自从写了这个答案,我了解到有更好的方法来做到这一点:

  • If you're limited to OpenGL's fixed-function pipeline, use texture environments如果您仅限于 OpenGL 的固定功能管道,请使用纹理环境
  • If you can use shaders, use a fragment shader.如果您可以使用着色器,请使用片段着色器。

The way described in this answer works and is not particularly worse in performance than these 2 better options, but is less elegant and less flexible.此答案中描述的方式有效,并且在性能上并不比这 2 个更好的选项差,但不太优雅且不太灵活。

Stefan Monov's is great answer! Stefan Monov 的回答很好! But for those who still have issues to get his answer working:但是对于那些仍然有问题无法让他的答案起作用的人:

  1. you need to check GLES20.glGetIntegerv(GLES20.GL_ALPHA_BITS, ib) - you need non zero result.您需要检查 GLES20.glGetIntegerv(GLES20.GL_ALPHA_BITS, ib) - 您需要非零结果。
  2. if you got 0 - goto EGLConfig and ensure that you pass alpha bits如果你得到 0 - 转到 EGLConfig 并确保你传递了 alpha 位

    EGL14.EGL_RED_SIZE, 8, EGL14.EGL_GREEN_SIZE, 8, EGL14.EGL_BLUE_SIZE, 8, EGL14.EGL_ALPHA_SIZE, 8, <- i havn't this and spent a much of time EGL14.EGL_DEPTH_SIZE, 16,

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

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