Sign in to follow this  
Conoktra

OpenGL OpenGL color interpolation not linear?

Recommended Posts

Conoktra    144

I have a rather simple problem that I am positive has a simple solution.  I am rendering a quad twice as two layers, each with a color.  The first is green, the second is red.  I am using the alpha channel of the color component for the quad's vertices to blend the two colors together across the quads.

 

Attached bellow are two images.  Image A is how it looks when rendered with OpenGL, image B is how it should look.  The black color in image A is the background bleeding through.  If OpenGL interpolated the color values linearly there would be no bleeding, it would be a nice transition from red to green and no black would show.  But that's obviously not the case.

 

I've tried using a GLSL program and setting the color variable to noperspective but it makes no difference.  Is there a way to force OpenGL to do plain linear interpolation of my vertex colors, so that the red and green blend evenly across the quad like in image B?

 

Additional information:

Red layer alpha values:
1.0 -------- 0.0
|             |
|             |
|             |
0.0 -------- 1.0

Green layer alpha values:
0.0 -------- 1.0
|              |
|              |
|              |
1.0 -------- 0.0

.

Thanks!

Share this post


Link to post
Share on other sites
Hodgman    51339
In 'a' your colours have completely faded out before even the half way point... Something is definitely wrong there -- I don't think this is a feature/design of GL.
Maybe post some more code/explanation of what you're doing?

Also, are you actually rendering a quad, or is it 2 triangles?

Share this post


Link to post
Share on other sites
ReaperSMS    1537

What are the vertex colors at each of the 4 corners of the two quads?

What blend mode are you using?

Are you rendering to sRGB?

 

Off the wall initial guesses, likely one of these or a combination of the two, though some quick envelope math doesn't match up directly:

 

Gamma is getting misunderstood.

 

Your vertex colors are (1, 0, 0, 1), and (0, 0, 0, 0) for the red quad, (0, 1, 0, 1) and (0, 0, 0, 0) for the green quad, and you're using alpha blending, so your color ramps drop off faster than you would expect.

 

For diagnosing, I suggest trying vertex colors of (1, 0, 0, 1) and (1, 0, 0, 0) for red, (0, 1, 0, 1) and (0, 1, 0, 0) for green. Might also use additive blending instead of src/inv_src. Also try a simple vertical gradient, as both two composited quads, and as a single quad going from (1, 0, 0, 1) at the top to (0, 1, 0, 1) at the bottom.

Share this post


Link to post
Share on other sites
Conoktra    144

Thanks for the help!

 


Also, are you actually rendering a quad, or is it 2 triangles?

It's being rendered as two triangles.  I've read that OpenGL uses the "Barycentric coordinate system" which might cause the issue as seen here.  But that individual was rendering in 2D, so he was able to bypass the problem by generating his texture coordinates from screen space (rather then interpolating them from the vertices).

 


Maybe post some more code/explanation of what you're doing?

Drawing two quads (one red and one green) that overlay and blend together to create a linear fade from red to green (as is seen in image B).  Somehow the interpolation of the color channel is non-linear, resulting in the background bleeding through as is seen in image A.  Code:

// Draw the red quad
glBegin(GL_TRIANGLES);

glVertex3f(0, 1, 0);
glColor4f(1, 0, 0, 0);

glVertex3f(1, 1, 1);
glColor4f(1, 0, 0, 0);

glVertex3f(1, 1, 0);
glColor4f(1, 0, 0, 1);

glVertex3f(0, 1, 1);
glColor4f(1, 0, 0, 1);

glVertex3f(1, 1, 1);
glColor4f(1, 0, 0, 0);

glVertex3f(0, 1, 0);
glColor4f(1, 0, 0, 0);

glEnd();

// Draw the green quad
glBegin(GL_TRIANGLES);

glVertex3f(0, 1, 0);
glColor4f(0, 1, 0, 1);

glVertex3f(1, 1, 1);
glColor4f(0, 1, 0, 1);

glVertex3f(1, 1, 0);
glColor4f(0, 1, 0, 0);

glVertex3f(0, 1, 1);
glColor4f(0, 1, 0, 0);

glVertex3f(1, 1, 1);
glColor4f(0, 1, 0, 1);

glVertex3f(0, 1, 0);
glColor4f(0, 1, 0, 1);

glEnd();


What are the vertex colors at each of the 4 corners of the two quads?
What blend mode are you using?
Are you rendering to sRGB?

See the above for vertex colors.  The blend mode is glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA). I am using sRGB. I am using Ogre3D so I can't verify that gamma correction isn't happening for sure.

 

I got Googling and added "fragColour.a = pow(outColour.a, 1.0 / 5.0);" to my shader rather then "fragColour.a = outColor.a;" and it seems to have done the trick!  Reading the OpenGL registry though says gamma correction shouldn't happen on alpha values for textures.  What about vertex colors?  That and a gamma factor of 5 is a lot bigger then the standard 2.2.

Share this post


Link to post
Share on other sites
haegarr    7372


I got Googling and added "fragColour.a = pow(outColour.a, 1.0 / 5.0);" to my shader rather then "fragColour.a = outColor.a;" and it seems to have done the trick!  Reading the OpenGL registry though says gamma correction shouldn't happen on alpha values for textures.  What about vertex colors?  That and a gamma factor of 5 is a lot bigger then the standard 2.2.

IMHO there must be a problem elsewhere! First, fragment alpha is not needed at all when you use glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA). Let fragment's alpha be at 1. Second, alpha is never meaningfully targeted by gamma correction, neither in textures nor in vertices nor elsewhere.

 

How do you do the 2 steps w.r.t. the blend operation? it is done with glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) in both cases? If so, then it is clear that the background has an effect onto the result.

Share this post


Link to post
Share on other sites
ReaperSMS    1537

You should be using glBlendFunc(GL_SRC_ALPHA, GL_ONE).

 

At a point where both of them are interpolated to 50% alpha, using SRC_ALPHA, ONE_MINUS_SRC_ALPHA, you will get 0.5 green, 0.25 red, 0.25 background, because you're doing this:

 

Output = 0.5 * Green + (1-0.5) * ( 0.5 * red + (1-0.5) * background );

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Partner Spotlight

  • Similar Content

    • By pseudomarvin
      I assumed that if a shader is computationally expensive then the execution is just slower. But running the following GLSL FS instead just crashes
      void main() { float x = 0; float y = 0; int sum = 0; for (float x = 0; x < 10; x += 0.00005) { for (float y = 0; y < 10; y += 0.00005) { sum++; } } fragColor = vec4(1, 1, 1 , 1.0); } with unhandled exception in nvoglv32.dll. Are there any hard limits on the number of steps/time that a shader can take before it is shut down? I was thinking about implementing some time intensive computation in shaders where it would take on the order of seconds to compute a frame, is that possible? Thanks.
    • By Arulbabu Donbosco
      There are studios selling applications which is just copying any 3Dgraphic content and regenerating into another new window. especially for CAVE Virtual reality experience. so that the user opens REvite or CAD or any other 3D applications and opens a model. then when the user selects the rendered window the VR application copies the 3D model information from the OpenGL window. 
      I got the clue that the VR application replaces the windows opengl32.dll file. how this is possible ... how can we copy the 3d content from the current OpenGL window.
      anyone, please help me .. how to go further... to create an application like VR CAVE. 
       
      Thanks
    • By cebugdev
      hi all,

      i am trying to build an OpenGL 2D GUI system, (yeah yeah, i know i should not be re inventing the wheel, but this is for educational and some other purpose only),
      i have built GUI system before using 2D systems such as that of HTML/JS canvas, but in 2D system, i can directly match a mouse coordinates to the actual graphic coordinates with additional computation for screen size/ratio/scale ofcourse.
      now i want to port it to OpenGL, i know that to render a 2D object in OpenGL we specify coordiantes in Clip space or use the orthographic projection, now heres what i need help about.
      1. what is the right way of rendering the GUI? is it thru drawing in clip space or switching to ortho projection?
      2. from screen coordinates (top left is 0,0 nd bottom right is width height), how can i map the mouse coordinates to OpenGL 2D so that mouse events such as button click works? In consideration ofcourse to the current screen/size dimension.
      3. when let say if the screen size/dimension is different, how to handle this? in my previous javascript 2D engine using canvas, i just have my working coordinates and then just perform the bitblk or copying my working canvas to screen canvas and scale the mouse coordinates from there, in OpenGL how to work on a multiple screen sizes (more like an OpenGL ES question).
      lastly, if you guys know any books, resources, links or tutorials that handle or discuss this, i found one with marekknows opengl game engine website but its not free,
      Just let me know. Did not have any luck finding resource in google for writing our own OpenGL GUI framework.
      IF there are no any available online, just let me know, what things do i need to look into for OpenGL and i will study them one by one to make it work.
      thank you, and looking forward to positive replies.
    • By fllwr0491
      I have a few beginner questions about tesselation that I really have no clue.
      The opengl wiki doesn't seem to talk anything about the details.
       
      What is the relationship between TCS layout out and TES layout in?
      How does the tesselator know how control points are organized?
          e.g. If TES input requests triangles, but TCS can output N vertices.
             What happens in this case?
      In this article,
      http://www.informit.com/articles/article.aspx?p=2120983
      the isoline example TCS out=4, but TES in=isoline.
      And gl_TessCoord is only a single one.
      So which ones are the control points?
      How are tesselator building primitives?
    • By Orella
      I've been developing a 2D Engine using SFML + ImGui.
      Here you can see an image
      The editor is rendered using ImGui and the scene window is a sf::RenderTexture where I draw the GameObjects and then is converted to ImGui::Image to render it in the editor.
      Now I need to create a 3D Engine during this year in my Bachelor Degree but using SDL2 + ImGui and I want to recreate what I did with the 2D Engine. 
      I've managed to render the editor like I did in the 2D Engine using this example that comes with ImGui. 
      3D Editor preview
      But I don't know how to create an equivalent of sf::RenderTexture in SDL2, so I can draw the 3D scene there and convert it to ImGui::Image to show it in the editor.
      If you can provide code will be better. And if you want me to provide any specific code tell me.
      Thanks!
  • Popular Now