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

android, java, opengl-es-2.0

Solution

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;
}

Problem

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?

Original source