locka
locka

Reputation: 6029

How do I use a shader to colour lines drawn with GL_LINES and OpenGL ES 2.0

I have an Android app using OpenGL ES 2.0. I need to draw 10 lines from an array each of which are described by a start point and an end point. So there are 10 lines = 20 points = 60 floats values. None of the points are connected so each pair of points in the array is unrelated to the others, hence I draw with GL_LINES.

I draw them by putting the values into a float buffer and calling some helper code like this:

public void drawLines(FloatBuffer vertexBuffer, float lineWidth,
        int numPoints, float colour[]) {
    GLES20.glLineWidth(lineWidth);
    drawShape(vertexBuffer, GLES20.GL_LINES, numPoints, colour);
}

protected void drawShape(FloatBuffer vertexBuffer, int drawType,
        int numPoints, float colour[]) {
    // ... set shader ...
    GLES20.glDrawArrays(drawType, 0, numPoints);
}

The drawLines takes the float buffer (60 floats), a linewidth, the number of points (20) and a 4 float colour value array. I haven't shown the shader setting code but it basically exposes the colour variable to uniform uColour value.

The fragment shader that picks up uColour just plugs it straight into the output.

/* Fragment */
precision mediump float;

uniform vec4 uColour;
uniform float uTime;

void main() {
    gl_FragColor = uColour;
}

The vertex shader:

uniform mat4 uMVPMatrix;

attribute vec4 vPosition;

void main() {
    gl_Position = uMVPMatrix * vPosition;
}

But now I want to do something different. I want every line in my buffer to have a different colour. The colours are a function of the position of the line in the array. I want to shade the beginning line white, the last dark gray and lines between a gradation between the two, e.g. #ffffff, #eeeeee, #dddddd etc.

I could obviously just draw each line individually plugging a new value into uColour each time but that is inefficient. I don't want to call GL 10 times when I could call it once and modify the value in a shader each time around.

Perhaps I could declare a uniform value called uVertexCount in my vertex shader? Prior to the draw I set uVertexCount to 0 and for each time the vertex shader is called I increment this value. The fragment shader could determine the line index by looking at uVertexCount. It could then interpolate a value for the colour between some start and end value or some other means. But this depends if every line or point is considered a primitive or the whole array of lines is a single primitive.

Is this feasible? I don't know how many times the vertex shader is called per fragment shader. Are the calls interleaved in a way such as this to make it viable, i.e. vertex 0, vertex 1, x * fragment, vertex 2, vertex 3, x * fragment etc.

Does anyone know of some reasonable sample code that might demonstrate the concept or point me to some other way of doing something similar?

Upvotes: 6

Views: 6988

Answers (1)

pearcoding
pearcoding

Reputation: 1149

Add color information into your Vertexbuffer (Floatbuffer) and use the attribute in your shader.

Example vertexbuffer:

uniform mat4 uMVPMatrix;

attribute vec4 vPosition;
attribute vec3 vColor;

varying vec3 color;

void main() {
    gl_Position = uMVPMatrix * vPosition;
    color = vColor;
}

Example fragmentshader:

precision mediump float;

varying vec3 color;

void main() {
    gl_FragColor = color;
}

Upvotes: 6

Related Questions