以分层方式缓慢替换颜色

以分层方式缓慢替换颜色

本文介绍了OPENGL混合功能-以分层方式缓慢替换颜色的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要执行的操作是在鲜红色(1,0,0,1)的顶部添加带有alpha(0.1,0,0,0.2)的暗红色.对于第一层,它工作正常,结果为(0.9,0,0,1);但是,当红色值达到0.5时,它不会降到该值以下.

What I am trying to do is add a darker red color with alpha (0.1,0,0,0.2) on top of a bright red (1,0,0,1). For the first layer it works fine, the result is (0.9 ,0 ,0, 1); However when the red value gets to 0.5 it cannot drop below that value.

第一层通过以下方程式演示,并且运行良好:

The first layer is demonstrated with the following equation, and works fine:

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
ColorBuffer color = (1,0,0,1)      Bright Red
SourceColor color = (0.1,0,0,0.2)  Dark Red

GL_ONE = 1   ,  GL_ONE_MINUS_SRC_ALPHA = 1 - 0.2 = 0.8

Cf = (ColorSource * One) + (ColorBuffer * One Minus Src Alpha);
Cf = ((0.1,0,0)*1 )   +  ((1,0,0) * 0.8);
Cf =   0.1,0,0        +     0.8,0,0;
Cf =   0.9,0,0  // Here is the result

现在经过多层之后,它将到达目标颜色更暗的点:0.5,现在该颜色再也不会变得更暗了,如下所示,它以0.5,0,0开头,但结果为0.5 ,0,0:

Now further down the line after many layers, it will get to a point where the destination color is darker : 0.5, now the color never gets any darker as demonstrated below it starts with 0.5,0,0 , but results in 0.5,0,0:

Cf = ((0.1,0,0)*1 )   +  ((0.5,0,0) * 0.8);
Cf =    0.1,0,0       +       0.4,0,0;
Cf =    0.5,0,0

这是结果,这意味着颜色缓冲区没有更改,并且我叠加的颜色不再起作用.

Here is the result which means the color buffer has not changed and the color I am overlaying no longer has any effect.

在将深红色替换为鲜红色之前,如何使它变成深红色?

How do I get my dark red to layer until it replaces the bright red?

简单处理草图演示问题-您将在这里注意到我正在尝试GL_SRC_ALPHA,它仍然存在该问题:

SIMPLE PROCESSING SKETCH DEMONSTRATING THE PROBLEM - you will notice here I am trying GL_SRC_ALPHA and it still has that problem:

http://studionu.net/files/OPENGL_test.zip

下图描述了在LEFT上的问题,在RIGHT上是所希望的效果.

The image below describes the problem on the LEFT on the RIGHT is the desired effect.

在此处编辑代码

这是我的代码:

我设置了一个纹理缓冲区对象并附加到FBO:

I set up a texture buffer object and attach to a FBO:

 'gl.glGenTextures(1, drawTex, 0);
  gl.glBindTexture(GL.GL_TEXTURE_2D, drawTex[0]);
  gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
  gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
  gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE);
  gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE);
  gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA8, 1000, 500, 0, GL.GL_BGRA,    GL.GL_UNSIGNED_BYTE, null);  '

' // Creating FBO.
  gl.glGenFramebuffersEXT(1, drawFBO, 0);
  gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, drawFBO[0]);
  gl.glFramebufferTexture2DEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_COLOR_ATTACHMENT0_EXT, GL.GL_TEXTURE_2D, drawTex[0], 0);
  int stat = gl.glCheckFramebufferStatusEXT(GL.GL_FRAMEBUFFER_EXT);
  if (stat != GL.GL_FRAMEBUFFER_COMPLETE_EXT) System.out.println("FBO error");
  gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, 0);'

然后我清除帧缓冲区:

' gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, drawFBO[0]);

  // Drawing to the first color attachement of drawFBO (this is where drawTex is attached to).
  gl.glDrawBuffer(GL.GL_COLOR_ATTACHMENT0_EXT);
  gl.glViewport(0, 0, 1000, 500);

    gl.glColor4f(0.0, 0.0, 0.0, 0.0);

  gl.glClear(gl.GL_COLOR_BUFFER_BIT);

  // Unbinding drawFBO. Now drawing to screen again.
  gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, 0);   '

在这里我将帧缓冲区绑定并绘制到其中,然后在此处设置颜色膨胀:

Here I Bind the framebuffer and draw into it and I set the color here swell:

'  gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, drawFBO[0]);
  // Drawing to the first color attachement of drawFBO (this is where drawTex is attached to).
  gl.glDrawBuffer(GL.GL_COLOR_ATTACHMENT0_EXT);

 // Setting orthographic projection.
  gl.glMatrixMode(GL.GL_PROJECTION);
  gl.glPushMatrix();
  gl.glLoadIdentity();
  gl.glOrtho(0.0, 1000, 0.0, 500, -100.0, +100.0);
  gl.glMatrixMode(GL.GL_MODELVIEW);
 gl.glPushMatrix();
 gl.glLoadIdentity();

  gl.glViewport(0, 0, 1000, 500);

  gl.glDisable(GL.GL_TEXTURE_2D);


 gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
 gl.glVertexPointer(2, GL.GL_FLOAT, 0, paintBuffer);
 // gl.glHint (gl.GL_POINT_SMOOTH_HINT, gl.GL_NICEST);
 // gl.glEnable(gl.GL_POINT_SMOOTH);
 gl.glEnable(gl.GL_VERTEX_PROGRAM_POINT_SIZE);

 gl.glEnable(gl.GL_BLEND);
 gl.glEnable(gl.GL_DEPTH_TEST);
 gl.glDepthFunc(gl.GL_NICEST);
 gl.glDisable(gl.GL_ALPHA_TEST);
 gl.glAlphaFunc(gl.GL_LESS, 0.01);

 gl.glPointSize(35.0);

  float kBrushOpacity = 0.05/3.0;

  println(kBrushOpacity);

  float  colorchange = 1.0;



 if (timer>200) {
   colorchange = 0.5; //////COLOR GETS DARKER
  }

 if (timer>400) {
   //colorchange = 0.2; //////COLOR GETS DARKER AGAIN
 }

  timer++;
 gl.glDisableClientState( gl.GL_COLOR_ARRAY );
  gl.glColor4f(colorchange, 0, 0.0, kBrushOpacity);
  gl.glBlendFuncSeparate(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA,gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_DST_ALPHA);////////THIS IS THE OPENGL BLEND EQUATION FOR PREMULTIPLIED COLORS



  gl.glDrawArrays(GL.GL_POINTS, 0, count); //Count tells us how many point exist to be drawn.
 gl.glDisable(gl.GL_BLEND);     //Dont use blend when drawing the texture to screen. Just draw it.

 gl.glDisableClientState(GL.GL_VERTEX_ARRAY);
  gl.glMatrixMode(GL.GL_PROJECTION);
  gl.glPopMatrix();
 gl.glMatrixMode(GL.GL_MODELVIEW);
 gl.glPopMatrix();
 // Unbinding drawFBO. Now drawing to screen again.
  gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, 0);   '

在这里我将纹理绘制到屏幕上

Here I Draw texture to screen:

' gl.glDrawArrays(GL.GL_POINTS, 0, count); //Count tells us how many point exist to be drawn.
gl.glDisable(gl.GL_BLEND);      //Dont use blend when drawing the texture to screen. Just draw it.

gl.glDisableClientState(GL.GL_VERTEX_ARRAY);
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glPopMatrix();
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glPopMatrix();
// Unbinding drawFBO. Now drawing to screen again.
gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, 0);

// Setting orthographic projection.
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glPushMatrix();
gl.glLoadIdentity();
gl.glOrtho(0.0, width, 0.0, height, -100.0, +100.0);
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glPushMatrix();
gl.glLoadIdentity();

 gl.glViewport(0, 0, width, height);

 // Drawing texture to screen.
 gl.glEnable(GL.GL_TEXTURE_2D);
 gl.glActiveTexture(GL.GL_TEXTURE0);
  gl.glBindTexture(GL.GL_TEXTURE_2D, drawTex[0]);
 gl.glTexEnvf(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_REPLACE);
 gl.glBegin(GL.GL_QUADS);
gl.glTexCoord2f(0.0, 1.0);
gl.glVertex2f(0.0, 0.0);

 gl.glTexCoord2f(1.0, 1.0);
 gl.glVertex2f(width, 0.0);

 gl.glTexCoord2f(1.0, 0.0);
 gl.glVertex2f(width, height);

 gl.glTexCoord2f(0.0, 0.0);
 gl.glVertex2f(0.0, height);
  gl.glEnd();
  gl.glBindTexture(GL.GL_TEXTURE_2D, 0);

  gl.glMatrixMode(GL.GL_PROJECTION);
  gl.glPopMatrix();
 gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glPopMatrix();   '

推荐答案

请问为什么您选择GL_ONE作为源因子?您的混合公式的总乘法值大于1的事实意味着,将同一种颜色与其自身进行混合并使其变亮,这是您在尝试使它变暗时达到平衡时所看到的.

May I ask why you've chosen GL_ONE as the source factor? The fact that your blend formula has a total multiplication value greater than one means that just blending the same color with itself with brighten it, which you're seeing as you're reaching an equilibrium while trying to darken it.

如果您使用了更常见的源因子GL_SRC_ALPHA,我认为它应该表现出预期的效果.您没有选择使用它的原因吗?

If you used the more common source factor GL_SRC_ALPHA I think it should behave as you expect. Is there a reason you have not chosen to use it?

如果使用GL_SRC_ALPHA和GL_ONE_MINUS_SRC_ALPHA作为源/目标混合因子,则由于混合因子的总和为1,因此不会因进行混合而使图像变亮.

If you use GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA as your source/dest blend factors, you will not get a bias toward brightening the image from performing a blend, because the multiplication factors sum to 1.

我不同意使用GL_SRC_ALPHA仍然会有同样的问题.我在excel中对公式进行了快速建模,如下所示.混合的值最终收敛到源颜色(0.1f).如果要收敛更快,请使用更大的src alpha值.

I disagree that using GL_SRC_ALPHA would still have the same problem. I did a quick mockup of the formula in excel, as you can see below. The value of the blending eventually converges to the source color (0.1f). If you want to converge faster, use a larger src alpha value.

参数:

Source Red = 0.1
Source Alpha = 0.2
Dest Red = 1.0 (iteration==0), Result[iteration-1] (iteration != 0)
1-Src Alpha = 0.8
Result = Src Red * Src Alpha + Dest Red * One_Minus_Src_Alpha

结果:

列:

0: Iteration
1: Source Red
2: Source Alpha
3: Dest Red
4: 1-Src Alpha
5: Result

0   1   2   3       4   5
------------------------------------------------
0   0.1 0.2 1.00    0.8 0.82   (0.1 * 0.2 + 1.0  * 0.8 = 0.82)
1   0.1 0.2 0.82    0.8 0.68   (0.1 * 0.2 + 0.82 * 0.8 = 0.68)
2   0.1 0.2 0.68    0.8 0.56   (etc...)
3   0.1 0.2 0.56    0.8 0.47
4   0.1 0.2 0.47    0.8 0.39
5   0.1 0.2 0.39    0.8 0.34
6   0.1 0.2 0.34    0.8 0.29
7   0.1 0.2 0.29    0.8 0.25
8   0.1 0.2 0.25    0.8 0.22
9   0.1 0.2 0.22    0.8 0.20
10  0.1 0.2 0.20    0.8 0.18
11  0.1 0.2 0.18    0.8 0.16
12  0.1 0.2 0.16    0.8 0.15
13  0.1 0.2 0.15    0.8 0.14
14  0.1 0.2 0.14    0.8 0.13
15  0.1 0.2 0.13    0.8 0.13
16  0.1 0.2 0.13    0.8 0.12
17  0.1 0.2 0.12    0.8 0.12
18  0.1 0.2 0.12    0.8 0.11
19  0.1 0.2 0.11    0.8 0.11
20  0.1 0.2 0.11    0.8 0.11
21  0.1 0.2 0.11    0.8 0.11
22  0.1 0.2 0.11    0.8 0.11
23  0.1 0.2 0.11    0.8 0.10
24  0.1 0.2 0.10    0.8 0.10
25  0.1 0.2 0.10    0.8 0.10

这篇关于OPENGL混合功能-以分层方式缓慢替换颜色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-21 13:30