2012-05-25 34 views
4

我想要做的是在明亮的红色(1,0,0, 1)。对于第一层它工作正常,结果是(0.9,0,0,1);但是,当红色值达到0.5时,它不能低于该值。OPENGL混合功能 - 以分层方式缓慢替换颜色

第一层表现出以下等式,并且正常工作:进一步

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:

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 

下面是这意味着颜色缓冲区并没有改变结果和我的色彩覆盖不再有任何效果。

我怎样才能让我的深红色层,直到它取代明亮的红色?

简单加工SKETCH证明了问题 - 你会发现在这里我想GL_SRC_ALPHA,它仍然有一个问题:在所需

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

下图描述了右边的左边的问题影响。

red on red issue

编辑这里是代码

因此,这里是我的代码:

我成立了一个纹理缓冲对象和附加到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); ' 

在这里,我绑定帧缓冲区,并吸引到它,我设定的颜色在这里膨胀:

' 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); ' 

这里我绘制纹理屏幕:

' 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(); ' 

回答

2

请问为什么你选择GL_ONE作为源因素?事实上,您的混合公式的总乘法值大于1意味着只需将相同的颜色与自身混合并使其变亮,在您尝试将其变暗时达到平衡时您会看到它。

如果您使用了更常见的源因素GL_SRC_ALPHA,我认为它应该按照您的预期行事。你有没有选择使用它的原因?

如果使用GL_SRC_ALPHA和GL_ONE_MINUS_SRC_ALPHA作为源/目标的混合因素,你不会得到一个偏向从执行混合图像亮度的,因为倍增系数总和为1

编辑:我不同意使用GL_SRC_ALPHA仍然会有同样的问题。我在Excel中做了一个快速模型的公式,如下所示。混合的值最终收敛到源颜色(0.1f)。如果您想更快收敛,请使用较大的src alpha值。

参数:

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 
+0

我选择GL_ONE作为源的因素,因为我没有任何背景,所以抽取因为颜色缓冲区将不会出现第一个位基本上是0在各方面RGBA至少那它做什么对我来说,当我不有任何背景。如果背景不透明SRC_ALPHA在某种程度上起作用。 – Carson

+0

BTW蒂姆,你有处理,我可以给你一个复制问题的简单草图?这里是:http://studionu.net/files/OPENGL_test.zip尝试一下,让我知道。 SRC_ALPHA也会遇到这个问题,因为您会看到 – Carson

+0

我不同意SRC_ALPHA存在同样的问题,请参阅我的编辑(我没有该软件)。 – Tim

1

答案是使用同样的方法,绘图程序如GIMP或Photoshop或写生。他们从来没有将任何新绘制到画布上,而是在每次调用结束时将其绘制为纹理四边形。如此之快,你永远不会看到它......无论如何,这对我来说很有效,希望它对别人有帮助。