2012-05-25 45 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或寫生。他們從來沒有將任何新繪製到畫布上,而是在每次調用結束時將其繪製爲紋理四邊形。如此之快,你永遠不會看到它......無論如何,這對我來說很有效,希望它對別人有幫助。