OPENGL Blend Function - Slow color swap at layer level

What I'm trying to do is add a dark red color with alpha (0,1,0,0,0,2,2) over 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 reaches 0.5, it cannot fall below this 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 

Now, dropping below the line after many layers, it will reach the point where the destination color is darker: 0.5, now the color never becomes darker, as shown below, it starts with 0.5.0.0, but leads to 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 that the color buffer has not changed, and the color that I apply no longer has any effect.

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

SIMPLE PROCESSED GASKET PROBLEM DEMONSTRATION - You will notice that I am trying to use GL_SRC_ALPHA, and it still has this problem:

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

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

red on red issue

CHANGE HERE CODE

So here is my code:

I set the texture buffer object and connected to 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);' 

Then I clear the frame buffer:

 ' 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 snap the framebuffer and draw into it, and I set the color here:

 ' 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 a texture for the 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(); ' 
+4
source share
2 answers

May I ask why you chose GL_ONE as the source? The fact that your mixing formula has a total multiplication value greater than one means that just mixing the same color with yourself to lighten it, which you see when you reach equilibrium, trying to darken it.

If you used the more common source source GL_SRC_ALPHA, I think it should behave as you expect. Is there a reason you didn't choose her?

If you use GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA as source / dest blending coefficients, you will not get an offset to increase the brightness of the image from performing the combination because the multiplication ratios are 1.

EDIT: I do not agree that using GL_SRC_ALPHA will still have the same problem. I made a quick formula layout in excel, as you can see below. The mix value ultimately converges to the color of the source (0.1f). If you want to converge faster, use a larger src alpha value.

Parameters:

 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 

Result:

Columns:

 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 
+2
source

The answer is to use the same method as paint programs like GIMP or Photoshop or SKetchbook. They never mix anything new painted on canvas; they simply paint it at the end of each call as a texture quad. So fast that you will never see it ... Anyway, it worked for me, hope this helps others.

+1
source

Source: https://habr.com/ru/post/1414304/


All Articles