使用GLKit在OpenGL中使用glBlendFunc透明度

时间:2022-09-07 09:12:26

I'm using GLKit for an iPad app. With this code I setup blending:

我正在使用GLKit作为iPad应用程序。使用此代码我设置混合:

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

It works fine, but when I try to get a screenshot the blend mode seems wrong. It doesn't matter if I use GLKit's snapshot or glReadPixels.

它工作正常,但当我尝试获取屏幕截图时,混合模式似乎是错误的。如果我使用GLKit的快照或glReadPixels并不重要。

This is what I get when working with the app: 使用GLKit在OpenGL中使用glBlendFunc透明度

这是我在使用应用程序时得到的结果:

And this is the screenshot: 使用GLKit在OpenGL中使用glBlendFunc透明度

这是截图:

Do I have to change the Blend Mode or something before I make the screenshot? And if so, to what?

在制作屏幕截图之前,我是否需要更改混合模式?如果是这样,到底是什么?

1 个解决方案

#1


3  

The problem you are having lies most likely in how the image is generated from the RGBA data. To solve this you will need to skip the alpha channel when creating CGImage with kCGImageAlphaNoneSkipLast or have the correct alpha values in the buffer in the first place.

您遇到的问题很可能在于如何从RGBA数据生成图像。要解决此问题,您需要在使用kCGImageAlphaNoneSkipLast创建CGImage时跳过alpha通道,或者首先在缓冲区中使用正确的alpha值。

To explain what is going. Your GL buffer consists of RGBA values but only RGB part is used to present it but when you create the image you use the alpha channel as well, thus the difference. How it comes to this is very simple, lets take a single pixel somewhere in the middle of the screen and go through its events:

解释发生了什么。您的GL缓冲区由RGBA值组成,但只有RGB部分用于显示它,但是当您创建图像时,您也使用Alpha通道,因此存在差异。它是如何实现这一点非常简单,让我们在屏幕中间的某个位置拍摄一个像素并完成其事件:

  1. You clear the pixel to any color you want
  2. 您可以将像素清除为所需的任何颜色

  3. You overwrite the pixel (all 4 channels RGBA) with a solid color received from the texture for instance (.8, .8, .8, 1.0)
  4. 您可以使用从纹理接收的纯色覆盖像素(所有4个通道RGBA)(.8,.8,.8,1.0)

  5. You draw a color over that pixel with some smaller alpha value and try to blend it, for instance (.4, .4, .4, .25). Your blend function says to multiply the source color with the source alpha and the destination with 1 - source alpha. That results in (.4, .4, .4, .25)*.25 + (.8, .8, .8, 1.0)*.75 = (.7, .7, .7, .76)
  6. 您可以使用较小的alpha值在该像素上绘制颜色,并尝试将其混合,例如(.4,.4,.4,.25)。您的混合函数表示将源颜色与源alpha相乘,目标与1 - 源alpha相乘。这导致(.4,.4,.4,.25)*。25 +(。8,.8,.8,1.0)*。75 =(。7,.7,.7,.76)

Now the result (.7, .7, .7, .76) is displayed nicely because your buffer only presents the RGB part resulting in seeing (.7, .7, .7, 1.0) but when you use all 4 components to create the image you also use the .76 alpha value which is further used to blend the image itself. Therefor you need to skip the alpha part at some point.

现在结果(.7,.7,.7,.76)很好地显示,因为你的缓冲区只显示RGB部分,导致看到(.7,.7,.7,1.0),但当你使用所有4个组件时创建图像时,您还使用.76 alpha值,该值进一步用于混合图像本身。因此,您需要在某些时候跳过alpha部分。

There is another way: As you can see in your case there is really no need to store the alpha value to the render buffer at all as you never use it, in your blend function you only use source alpha. Therefore you may just disable it using glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE), this also means you need to clear the alpha value to 1.0 (glClearColor(x,x,x,1.0))

还有另一种方法:正如你所看到的那样,你根本不需要将alpha值存储到渲染缓冲区,因为你从不使用它,在你的混合函数中你只使用源alpha。因此,您可以使用glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_FALSE)禁用它,这也意味着您需要将alpha值清除为1.0(glClearColor(x,x,x,1.0))

#1


3  

The problem you are having lies most likely in how the image is generated from the RGBA data. To solve this you will need to skip the alpha channel when creating CGImage with kCGImageAlphaNoneSkipLast or have the correct alpha values in the buffer in the first place.

您遇到的问题很可能在于如何从RGBA数据生成图像。要解决此问题,您需要在使用kCGImageAlphaNoneSkipLast创建CGImage时跳过alpha通道,或者首先在缓冲区中使用正确的alpha值。

To explain what is going. Your GL buffer consists of RGBA values but only RGB part is used to present it but when you create the image you use the alpha channel as well, thus the difference. How it comes to this is very simple, lets take a single pixel somewhere in the middle of the screen and go through its events:

解释发生了什么。您的GL缓冲区由RGBA值组成,但只有RGB部分用于显示它,但是当您创建图像时,您也使用Alpha通道,因此存在差异。它是如何实现这一点非常简单,让我们在屏幕中间的某个位置拍摄一个像素并完成其事件:

  1. You clear the pixel to any color you want
  2. 您可以将像素清除为所需的任何颜色

  3. You overwrite the pixel (all 4 channels RGBA) with a solid color received from the texture for instance (.8, .8, .8, 1.0)
  4. 您可以使用从纹理接收的纯色覆盖像素(所有4个通道RGBA)(.8,.8,.8,1.0)

  5. You draw a color over that pixel with some smaller alpha value and try to blend it, for instance (.4, .4, .4, .25). Your blend function says to multiply the source color with the source alpha and the destination with 1 - source alpha. That results in (.4, .4, .4, .25)*.25 + (.8, .8, .8, 1.0)*.75 = (.7, .7, .7, .76)
  6. 您可以使用较小的alpha值在该像素上绘制颜色,并尝试将其混合,例如(.4,.4,.4,.25)。您的混合函数表示将源颜色与源alpha相乘,目标与1 - 源alpha相乘。这导致(.4,.4,.4,.25)*。25 +(。8,.8,.8,1.0)*。75 =(。7,.7,.7,.76)

Now the result (.7, .7, .7, .76) is displayed nicely because your buffer only presents the RGB part resulting in seeing (.7, .7, .7, 1.0) but when you use all 4 components to create the image you also use the .76 alpha value which is further used to blend the image itself. Therefor you need to skip the alpha part at some point.

现在结果(.7,.7,.7,.76)很好地显示,因为你的缓冲区只显示RGB部分,导致看到(.7,.7,.7,1.0),但当你使用所有4个组件时创建图像时,您还使用.76 alpha值,该值进一步用于混合图像本身。因此,您需要在某些时候跳过alpha部分。

There is another way: As you can see in your case there is really no need to store the alpha value to the render buffer at all as you never use it, in your blend function you only use source alpha. Therefore you may just disable it using glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE), this also means you need to clear the alpha value to 1.0 (glClearColor(x,x,x,1.0))

还有另一种方法:正如你所看到的那样,你根本不需要将alpha值存储到渲染缓冲区,因为你从不使用它,在你的混合函数中你只使用源alpha。因此,您可以使用glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_FALSE)禁用它,这也意味着您需要将alpha值清除为1.0(glClearColor(x,x,x,1.0))