A way to stop color interplation on GL_EDGES?

168 Views Asked by At

i am currently writing a glumpy based renderer in Python.

I am using glumpys OpenGl features for rendering a bunch of points and lines. My points are actually a graph so the lines are edges, multiple edges can have one shared point.

I implemented a picker, which enables me to draw a specific subgraph.

I have a alpha value stored on a buffer for each vertex. When i click, the alpha values are changed, so that only the points of the selected subgraph are drawn with alpha = 1. The shader is called twice:

# Draw Points
self.program_points.draw(gl.GL_POINTS)

# Draw Lines
self.program_points.draw(gl.GL_LINES, self.edge_buffer)

My problem is: The alpha values are set correctly, also the edges with both points alpha = 1 are rendered correctly but the edges that have one point with alpha = 1 and one with alpha = 0 fades out.

I want to don't color the fading edges at all. Is there a way to check on both nodes of an edge and always pick the lower alpha value or something equally useful.

My vertex shader:

uniform vec2 resolution;

attribute vec3 position;
attribute float radius;

attribute float  color;
attribute float color_alpha;
attribute float id;

// for AA
varying vec4 v_position;
varying float v_radius;
varying float v_color_alpha;


varying vec4  v_id;
varying float  v_color;

void main (void)
{
    // this is for the picker!
    v_id = vec4 (mod(floor(id / (256*256)), 256) / 255.0,
             mod(floor(id /     (256)), 256) / 255.0,
             mod(floor(id /       (1)), 256) / 255.0,
             1.0 );
    // values to the fragment shader
    v_color         = color;
    v_color_alpha   = color_alpha;
    v_radius        = radius;

    //two pixel for AA
    gl_PointSize = 2.0+ ceil(2.0*radius);

    // hook for the Cameramovement
    v_position = <transform(position)>;
    gl_Position = v_position;
} ```
1

There are 1 best solutions below

1
On

Well, basically, there are two options:

  • the value of a varying are interpolated across the whole primitive
  • the value of a varying is constant for the primitive, by using the flat interpolation qualifier. It the primitive is not just a point, this means the data has to come from one of the vertices only, which is called the proviking vertex. For GL_LINES, this is usually the first vertex of each line.

None of the two modes will solve your issue in the general case. Consider the Following case of two connected Edges AB and BC with attached alpha values 1, 1 and 0, respectively:

A      B      C 
|------+------|
1      1      0

What you really want here is a sharp transition from opaque to fully transparent, and the standard solution for that is to actually split the vertices:

A     B D     C 
|-----+++-----|
1     1 0     0

Now B and D have the same position, but different alpha values - and that is what GPU's model of a vertex really is: a set of attributes - not just position - and if a single attribute differs, it is technically a different vertex.

For your use case, you could probably remove the element buffer completely and always keep two distinct vertices per line.

Is there a way to check on both nodes of an edge and always pick the lower alpha value or something equally useful.

Not directly. There are some non-standard GL extensions which will give you access to the associated data of each vertex, like AMD_shader_explicit_vertex_parameter orNV_fragment_shader_barycentric, but none of these is generally supported and it is also way above the version of GL you seem to be using here.

However, for your use case, you could do some simple fragment shader hacks like:

gl_FragColor.a = step(0.99999, v_color_alpha);

which will basically set alpha to 0.0 if it is below 0.99999 so it will remove most part of the transition. Note that fragments with alpha=0 might still be written to the depth and stencil buffers, so you might want a conditional discard instead.