openglgradientvertex-array

Triangle gradient on OpenGL


I'm trying to make a triangle like the one in the right in the following picture:

triangles

The problem is that what I want to achieve is a gradient of color from vertexes 1 and 2 proyected from C.

As far as I know this is not possible since vertex C must have a color on it's own, which will also blend into 1 and 2's colors, like in the left triangle of the picture. If I set C to a middle point color, this generates an undesired result, since the taller the triangle is made, the less noticiable are the other vertex's colors.

Line C1 should be black, and line C2 should be white.

Is there any way to achieve this in OpenGL?


Solution

  • There are two ways, but I don't know which makes most sense for your application. At a very high level:

    1. Map a texture to the triangle. As the gradient is very smooth, it doesn't need to be very high resolution, and you can let linear filtering do the work for you.

    2. Use a shader. More work to set up, but also more flexible, and gives you a 'perfect' result at any scale/resolution.


    Update: if you're going to use a shader, the idea is the following.

    Pass a varying vec2 coords from the vertex shader to the fragment shader. Set the value for point 1 to 0,0, for point 2 to 1,0 and for point C to 0,1. To get these values into the vertex shader, use an attribute. Varying values will be interpolated across the triangle, much like texture coordinates and colours would. So the coords variable is mapped to your triangle like this:

    y
    1 +-----+
      |\    |
      |#\   |
      |##\  |
      |###\ |
      |####\|
    0 +-----+ x
      0     1
    

    The fragment shader receives a coords value somewhere inside the hashed area. To figure out how much of each colour you need to blend, compute the line through coords and 0,1, and find its intersection with the x axis. Thanks to the coordinate system of coords, this is a simple operation: simply divide coords.x by coords.y. Call this f. (Note that this will give division by zero at point C, but this is expected as you never defined the colour there. You can check for that explicitly in the shader if you want.)

    Indicating coords with c and representing the line with . characters, f ends up somewhere between 0 and 1:

    y
    1 +-----+
      |\    |
      |.\   |
      |#c\  |
      |#.#\ |
      |##.#\|
    0 +--f--+ x
      0     1
    

    Now let's say you have uniform vec4 colour1 and uniform vec4 colour2 to define the colour at point 1 and 2, respectively. Then it's a simple matter of blending these: taking f fraction of colour2 and 1-f fraction of colour1 and adding them together. The GLSL mix function does exactly this.