Search code examples
androidopengl-es

What is the easiest way to draw line using OpenGL-ES (android)


If I have custom renderer in opengl-es prepared:

public void onDrawFrame(GL10 gl)
{
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
    // here i want to draw line from [0, 0, 0] to [1, 0, 0]
}

What is the easiest and shortest way to draw line?

In ordinary OpenGL it is:

glBegin(GL_LINES);
    glVertex3f(0, 0, 0);
    glVertex3f(1, 0, 0);
glEnd();

But how can i get the same effect with OpenGL ES?


Solution

  • I am new to new to OpenGL ES 2.0 but I created a line class.

    public class Line {
        private FloatBuffer VertexBuffer;
    
        private final String VertexShaderCode =
            // This matrix member variable provides a hook to manipulate
            // the coordinates of the objects that use this vertex shader
            "uniform mat4 uMVPMatrix;" +
    
            "attribute vec4 vPosition;" +
            "void main() {" +
            // the matrix must be included as a modifier of gl_Position
            "  gl_Position = uMVPMatrix * vPosition;" +
            "}";
    
        private final String FragmentShaderCode =
            "precision mediump float;" +
            "uniform vec4 vColor;" +
            "void main() {" +
            "  gl_FragColor = vColor;" +
            "}";
        
        protected int GlProgram;
        protected int PositionHandle;
        protected int ColorHandle;
        protected int MVPMatrixHandle;
    
        // number of coordinates per vertex in this array
        static final int COORDS_PER_VERTEX = 3;
        static float LineCoords[] = {
            0.0f, 0.0f, 0.0f,
            1.0f, 0.0f, 0.0f
        };
    
        private final int VertexCount = LineCoords.length / COORDS_PER_VERTEX;
        private final int VertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
    
        // Set color with red, green, blue and alpha (opacity) values
        float color[] = { 0.0f, 0.0f, 0.0f, 1.0f };
    
        public Line() {
            // initialize vertex byte buffer for shape coordinates
            ByteBuffer bb = ByteBuffer.allocateDirect(
                // (number of coordinate values * 4 bytes per float)
                LineCoords.length * 4);
            // use the device hardware's native byte order
            bb.order(ByteOrder.nativeOrder());
    
            // create a floating point buffer from the ByteBuffer
            VertexBuffer = bb.asFloatBuffer();
            // add the coordinates to the FloatBuffer
            VertexBuffer.put(LineCoords);
            // set the buffer to read the first coordinate
            VertexBuffer.position(0);
        
            int vertexShader = ArRenderer.loadShader(GLES20.GL_VERTEX_SHADER, VertexShaderCode);
            int fragmentShader = ArRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, FragmentShaderCode);
    
            GlProgram = GLES20.glCreateProgram();             // create empty OpenGL ES Program
            GLES20.glAttachShader(GlProgram, vertexShader);   // add the vertex shader to program
            GLES20.glAttachShader(GlProgram, fragmentShader); // add the fragment shader to program
            GLES20.glLinkProgram(GlProgram);                  // creates OpenGL ES program executables
        }
    
        public void SetVerts(float v0, float v1, float v2, float v3, float v4, float v5) {
            LineCoords[0] = v0;
            LineCoords[1] = v1;
            LineCoords[2] = v2;
            LineCoords[3] = v3;
            LineCoords[4] = v4;
            LineCoords[5] = v5;
        
            VertexBuffer.put(LineCoords);
            // set the buffer to read the first coordinate
            VertexBuffer.position(0);
        }
    
        public void SetColor(float red, float green, float blue, float alpha) {
            color[0] = red;
            color[1] = green;
            color[2] = blue;
            color[3] = alpha;
        }
    
        public void draw(float[] mvpMatrix) {
            // Add program to OpenGL ES environment
            GLES20.glUseProgram(GlProgram);
    
            // get handle to vertex shader's vPosition member
            PositionHandle = GLES20.glGetAttribLocation(GlProgram, "vPosition");
    
            // Enable a handle to the triangle vertices
            GLES20.glEnableVertexAttribArray(PositionHandle);
    
            // Prepare the triangle coordinate data
            GLES20.glVertexAttribPointer(PositionHandle, COORDS_PER_VERTEX,
                                     GLES20.GL_FLOAT, false,
                                     VertexStride, VertexBuffer);
    
            // get handle to fragment shader's vColor member
            ColorHandle = GLES20.glGetUniformLocation(GlProgram, "vColor");
    
            // Set color for drawing the triangle
            GLES20.glUniform4fv(ColorHandle, 1, color, 0);
        
            // get handle to shape's transformation matrix
            MVPMatrixHandle = GLES20.glGetUniformLocation(GlProgram, "uMVPMatrix");
            ArRenderer.checkGlError("glGetUniformLocation");
    
            // Apply the projection and view transformation
            GLES20.glUniformMatrix4fv(MVPMatrixHandle, 1, false, mvpMatrix, 0);
            ArRenderer.checkGlError("glUniformMatrix4fv");
    
            // Draw the triangle
            GLES20.glDrawArrays(GLES20.GL_LINES, 0, VertexCount);
    
            // Disable vertex array
            GLES20.glDisableVertexAttribArray(PositionHandle);
        }
     }
    

    And then in my Render class I create my line objects and to a container so the get draw in the by iterating over the items and calling the Line.draw method in onDrawFrame.

    Here are some lines I create to make a horizon:

        Line eastHorz = new Line();
        eastHorz.SetVerts(10f, 10f, 0f, 10f, -10f, 0f);
        eastHorz.SetColor(.8f, .8f, 0f, 1.0f);
        Line northHorz = new Line();
        northHorz.SetVerts(-10f, 10f, 0f, 10f, 10f, 0f);
        northHorz.SetColor(0.8f, 0.8f, 0f, 1.0f);
        Line westHorz = new Line();
        westHorz.SetVerts(-10f, -10f, 0f, -10f, 10f, 0f);
        westHorz.SetColor(0.8f, 0.8f, 0f, 1.0f);
        Line southHorz = new Line();
        southHorz.SetVerts(-10f, -10f, 0f, 10f, -10f, 0f);
        southHorz.SetColor(0.8f, 0.8f, 0f, 1.0f);
        Lines.add(eastHorz);
        Lines.add(northHorz);
        Lines.add(westHorz);
        Lines.add(southHorz);
    

    ArRenderer is my render class which holds the Lines, camera position etc and implements GLSurfaceView.Renderer. The loadShader method is:

    public static int loadShader(int type, String shaderCode) { 
        // create a vertex shader type (GLES20.GL_VERTEX_SHADER) 
        // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER) 
        int shader = GLES20.glCreateShader(type); 
        
        // add the source code to the shader and compile it 
        GLES20.glShaderSource(shader, shaderCode); 
        GLES20.glCompileShader(shader); 
        return shader; 
    }