Passing data from several vertex shaders

A usual way to pass data from a vertex to a fragment shader is to use “varying” qualifier. However it works only in the case when the data is common for all vertices in a primitive.

Let’s say I am rendering a line and want to paint ends in different colors. So I declare

varying vec4 color1;
varying vec4 color2;

In the vertex shader I would:

if( vertex in the left corner )
color = red
else color = blue;

The idea is that each vertex would write only one value and by the time the processing comes to the fragment shader both vertices are processed and both color1 and color2 are initialized.

However it does not work that way. Even though the vertex shader only writes one of the variables the other variable gets overwritten anyway and usually contains garbage.

So how would I pass data from different vertices to the fragment shader under conditions that each vertex knows nothing about the other one.

Use geometry shader. It may know the four vertices of the line.
Lines with adjacency just needed for such tasks.
If you can not use the geometry shader, then use an additional buffer color.

Thanks Yar,
However I cannot use geometry shaders for portability reasons.
As for the buffer color: Is it just an varying variable ? If that the case it is not going to work - see OP.

However it does not work that way.

That’s because shaders don’t work that way.

Vertex shaders compute a series of values for vertices within a primitive. The hardware scan converter then takes these vertices and generates a series of fragments. So if you have a triangle (made from 3 vertices), the scan converter generates one fragment for every pixel on the viewable surface of the triangle.

Fragment shaders operate on these fragments. A fragment contains the interpolated values from the vertex shader. So if you have one vertex that puts 1.0 in a value, and one vertex that puts 0.0 in the same value, the fragments between the two vertices will get a varying number between 1.0 and 0.0, depending on how close it is to each vertex. Hence the term “varying.”

Multiple executions of a vertex shader do not affect each other. Multiple executions of a fragment shader do not affect each other.

Let’s say I am rendering a line and want to paint ends in different colors.

What goes in the middle? Do you want to blend between the different colors, or something else?

That is all understandable. The question is HOW TO…
It if cannot be done the usability of shaders is severely limited. There is a lot of situations when a fragment shader wants to know values at each vertex of the fragment not just interpolated values.

That is all understandable. The question is HOW TO…

How to do what? You haven’t explained

It if cannot be done the usability of shaders is severely limited. There is a lot of situations when a fragment shader wants to know values at each vertex of the fragment not just interpolated values.

No, there aren’t. You’re either formulating the problem incorrectly, doing GPGPU-stuff (in which case, you should be using OpenCL), or trying to do something extraordinarily different from normal rendering. There is almost always a way to restate the problem such that it isn’t necessary for your fragment program to do this.

Fragment programs operate on interpolated values. That’s how they’re intended to work. If you need to do the interpolation yourself or something, then each vertex must pass both its data and the opposing vertex’s data. That means each vertex must get, as an attribute, both its own color and the color of the other vertex. And then you have to use gl_VertexID to determine which vertex you are, so that you can write the same colors to the same outputs as the previous vertex.

Alternatively, you can use a geometry shader to do this. That one’s actually quite easy. You just output each line primitive, where each vertex has a pair of colors that is the same.

Yes that’s what I ended up doing. The same value is calculated for each vertex of the primitive. The code grows significantly,
The volume of communication with CPU increases, plus there is extra if/else statements for each vertex in the primitive. As the result in case of quads the performance slows down at least 4 times.
Example of why it is needed ? Let’s say you are implementing an oscilloscope and want to highlight the maximum point on the curve specified via GL_LINE_STRIP. A very simple task that is not straightforward to implement in a shader.
If the vertex shader was allowed to write to something similar to uniform variables that would be very easy to do.

Let’s say you are implementing an oscilloscope and want to highlight the maximum point on the curve specified via GL_LINE_STRIP. A very simple task that is not straightforward to implement in a shader.

Or you could pass the highest point in the curve to the fragment shader as a uniform, and it could decide to color that point in based on its window-space location relative to that point.

Or you could do something much simpler. After drawing the line, simply draw a point at the highest point in the curve. Problem solved.

Like I said: reformulating the problem will almost always give you a more reasonable solution. Just because you have shaders doesn’t mean you should use them to solve every problem.

If the vertex shader was allowed to write to something similar to uniform variables that would be very easy to do.

But then the uniform values wouldn’t be uniform, would they? :wink:

Example of why it is needed ? Let’s say you are implementing an oscilloscope and want to highlight the maximum point on the curve specified via GL_LINE_STRIP. A very simple task that is not straightforward to implement in a shader.

Either I am dumb or your problem is not clear but I don’t see any problem in doing this with or without shaders as Alfonse said in his last post.
Could we have a picture of the required result, to better understand your concern?

Or you could pass the highest point in the curve to the fragment shader as a uniform, and it could decide to color that point in based on its window-space location relative to that point.

In other words - sort all data points in CPU. You understand that this is not always desirable or even possible due to performance consideration.

Or you could do something much simpler. After drawing the line, simply draw a point at the highest point in the curve. Problem solved.

Same as above.

[quote]If the vertex shader was allowed to write to something similar to uniform variables that would be very easy to do.

But then the uniform values wouldn’t be uniform, would they? :wink: [/QUOTE]

In other words - sort all data points in CPU. You understand that this is not always desirable or even possible due to performance consideration.

GPUs aren’t exactly good at sorting operations either.

And if you’re getting your data points from the GPU, then your algorithm should output the highest value (or other points of interest) as part of that data point generation.