150e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainpage.title=Drawing Shapes
250e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainparent.title=Displaying Graphics with OpenGL ES
350e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainparent.link=index.html
450e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
550e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Maintrainingnavtop=true
650e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainprevious.title=Defining Shapes
750e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainprevious.link=environment.html
850e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainnext.title=Applying Projection and Camera Views
950e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainnext.link=projection.html
1050e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
1150e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main@jd:body
1250e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
1350e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main<div id="tb-wrapper">
1450e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main<div id="tb">
1550e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
1650e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main<h2>This lesson teaches you to</h2>
1750e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main<ol>
1850e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main  <li><a href="#initialize">Initialize Shapes</a></li>
1950e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main  <li><a href="#draw">Draw a Shape</a></li>
2050e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main</ol>
2150e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
2250e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main<h2>You should also read</h2>
2350e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main<ul>
2450e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main  <li><a href="{@docRoot}guide/topics/graphics/opengl.html">OpenGL</a></li>
2550e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main</ul>
2650e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
2750e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main<div class="download-box">
2850e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main <a href="{@docRoot}shareables/training/OpenGLES.zip"
2950e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainclass="button">Download the sample</a>
3050e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main <p class="filename">OpenGLES.zip</p>
3150e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main</div>
3250e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
3350e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main</div>
3450e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main</div>
3550e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
3650e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main<p>After you define shapes to be drawn with OpenGL, you probably want to draw them. Drawing shapes
3750e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainwith the OpenGL ES 2.0 takes a bit more code than you might imagine, because the API provides a
3850e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Maingreat deal of control over the graphics rendering pipeline.</p>
3950e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
4050e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main<p>This lesson explains how to draw the shapes you defined in the previous lesson using the OpenGL
4150e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott MainES 2.0 API.</p>
4250e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
4350e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
4450e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main<h2 id="initialize">Initialize Shapes</h2>
4550e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
4650e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main<p>Before you do any drawing, you must initialize and load the shapes you plan to draw. Unless the
4750e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainstructure (the original coordinates) of the shapes you use in your program change during the course
4850e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainof execution, you should initialize them in the {@link
4950e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainandroid.opengl.GLSurfaceView.Renderer#onSurfaceCreated onSurfaceCreated()} method of your renderer
5050e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainfor memory and processing efficiency.</p>
5150e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
5250e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main<pre>
53c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyenpublic class MyGLRenderer implements GLSurfaceView.Renderer {
54c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen
5550e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main    ...
56c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen    private Triangle mTriangle;
57c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen    private Square   mSquare;
58c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen
59c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen    public void onSurfaceCreated(GL10 unused, EGLConfig config) {
60c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen        ...
6150e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
62c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen        // initialize a triangle
63c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen        mTriangle = new Triangle();
64c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen        // initialize a square
65c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen        mSquare = new Square();
66c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen    }
67c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen    ...
6850e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main}
6950e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main</pre>
7050e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
7150e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
7250e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main<h2 id="draw">Draw a Shape</h2>
7350e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
7450e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main<p>Drawing a defined shape using OpenGL ES 2.0 requires a significant amount of code, because you
7550e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainmust provide a lot of details to the graphics rendering pipeline. Specifically, you must define the
7650e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainfollowing:</p>
7750e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
7850e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main<ul>
7950e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main  <li><em>Vertex Shader</em> - OpenGL ES graphics code for rendering the vertices of a shape.</li>
8050e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main  <li><em>Fragment Shader</em> - OpenGL ES code for rendering the face of a shape with colors or
8150e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Maintextures.</li>
8250e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main  <li><em>Program</em> - An OpenGL ES object that contains the shaders you want to use for drawing
8350e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainone or more shapes.</li>
8450e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main</ul>
8550e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
8650e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main<p>You need at least one vertex shader to draw a shape and one fragment shader to color that shape.
8750e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott MainThese shaders must be complied and then added to an OpenGL ES program, which is then used to draw
88c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyenthe shape. Here is an example of how to define basic shaders you can use to draw a shape in the
89c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen<code>Triangle</code> class:</p>
9050e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
9150e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main<pre>
92c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyenpublic class Triangle {
93c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen
94c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen    private final String vertexShaderCode =
95c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen        "attribute vec4 vPosition;" +
96c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen        "void main() {" +
97c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen        "  gl_Position = vPosition;" +
98c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen        "}";
99c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen
100c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen    private final String fragmentShaderCode =
101c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen        "precision mediump float;" +
102c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen        "uniform vec4 vColor;" +
103c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen        "void main() {" +
104c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen        "  gl_FragColor = vColor;" +
105c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen        "}";
106c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen
107c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen    ...
108c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen}
10950e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main</pre>
11050e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
11150e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main<p>Shaders contain OpenGL Shading Language (GLSL) code that must be compiled prior to using it in
11250e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainthe OpenGL ES environment. To compile this code, create a utility method in your renderer class:</p>
11350e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
11450e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main<pre>
11550e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainpublic static int loadShader(int type, String shaderCode){
11650e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
11750e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main    // create a vertex shader type (GLES20.GL_VERTEX_SHADER)
11850e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main    // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
11950e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main    int shader = GLES20.glCreateShader(type);
12050e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
12150e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main    // add the source code to the shader and compile it
12250e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main    GLES20.glShaderSource(shader, shaderCode);
12350e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main    GLES20.glCompileShader(shader);
12450e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
12550e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main    return shader;
12650e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main}
12750e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main</pre>
12850e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
12950e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main<p>In order to draw your shape, you must compile the shader code, add them to a OpenGL ES program
13050e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainobject and then link the program. Do this in your drawn object’s constructor, so it is only done
13150e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainonce.</p>
13250e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
13350e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main<p class="note"><strong>Note:</strong> Compiling OpenGL ES shaders and linking programs is expensive
13450e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainin terms of CPU cycles and processing time, so you should avoid doing this more than once. If you do
13550e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainnot know the content of your shaders at runtime, you should build your code such that they only
13650e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainget created once and then cached for later use.</p>
13750e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
13850e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main<pre>
139feaaea5b415283160f3255b75903be1df3b728e3Joe Fernandezpublic class Triangle() {
14050e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main    ...
14150e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
142c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen    private final int mProgram;
143c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen
144c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen    public Triangle() {
145c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen        ...
146c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen
147c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen        int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER,
148c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen                                        vertexShaderCode);
149c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen        int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER,
150c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen                                        fragmentShaderCode);
151c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen
152c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen        // create empty OpenGL ES Program
153c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen        mProgram = GLES20.glCreateProgram();
15450e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
155c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen        // add the vertex shader to program
156c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen        GLES20.glAttachShader(mProgram, vertexShader);
157c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen
158c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen        // add the fragment shader to program
159c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen        GLES20.glAttachShader(mProgram, fragmentShader);
160c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen
161c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen        // creates OpenGL ES program executables
162c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen        GLES20.glLinkProgram(mProgram);
163c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen    }
16450e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main}
16550e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main</pre>
16650e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
16750e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main<p>At this point, you are ready to add the actual calls that draw your shape. Drawing shapes with
16850e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott MainOpenGL ES requires that you specify several parameters to tell the rendering pipeline what you want
16950e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainto draw and how to draw it. Since drawing options can vary by shape, it's a good idea to have your
17050e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainshape classes contain their own drawing logic.</p>
17150e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
17250e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main<p>Create a {@code draw()} method for drawing the shape. This code sets the position and
17350e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Maincolor values to the shape’s vertex shader and fragment shader, and then executes the drawing
17450e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainfunction.</p>
17550e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
17650e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main<pre>
177c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyenprivate int mPositionHandle;
178c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyenprivate int mColorHandle;
179c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen
180c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyenprivate final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
181c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyenprivate final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
182c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen
18350e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainpublic void draw() {
18450e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main    // Add program to OpenGL ES environment
18550e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main    GLES20.glUseProgram(mProgram);
18650e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
18750e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main    // get handle to vertex shader's vPosition member
18850e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main    mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
18950e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
19050e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main    // Enable a handle to the triangle vertices
19150e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main    GLES20.glEnableVertexAttribArray(mPositionHandle);
19250e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
19350e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main    // Prepare the triangle coordinate data
19450e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main    GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
19550e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main                                 GLES20.GL_FLOAT, false,
19650e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main                                 vertexStride, vertexBuffer);
19750e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
19850e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main    // get handle to fragment shader's vColor member
19950e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main    mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
20050e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
20150e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main    // Set color for drawing the triangle
20250e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main    GLES20.glUniform4fv(mColorHandle, 1, color, 0);
20350e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
20450e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main    // Draw the triangle
20550e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
20650e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
20750e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main    // Disable vertex array
20850e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main    GLES20.glDisableVertexAttribArray(mPositionHandle);
20950e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main}
21050e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main</pre>
21150e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
21250e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main<p>Once you have all this code in place, drawing this object just requires a call to the
21350e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main{@code draw()} method from within your renderer’s {@link
214c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyenandroid.opengl.GLSurfaceView.Renderer#onDrawFrame onDrawFrame()} method:
215c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen
216c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen<pre>
217c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyenpublic void onDrawFrame(GL10 unused) {
218c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen    ...
219c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen
220c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen    mTriangle.draw();
221c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen}
222c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen</pre>
223c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen
224c25adda63603827f1799e0995edf286ac46f51f1Luan Nguyen<p>When you run the application, it should look something like this:</p>
22550e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
22650e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main<img src="{@docRoot}images/opengl/ogl-triangle.png">
22750e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main<p class="img-caption">
22850e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main<strong>Figure 1.</strong> Triangle drawn without a projection or camera view.</p>
22950e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
23050e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main<p>There are a few problems with this code example. First of all, it is not going to impress your
23150e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainfriends. Secondly, the triangle is a bit squashed and changes shape when you change the screen
23250e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainorientation of the device. The reason the shape is skewed is due to the fact that the object’s
23350e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainvertices have not been corrected for the proportions of the screen area where the {@link
23450e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainandroid.opengl.GLSurfaceView} is displayed. You can fix that problem using a projection and camera
23550e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Mainview in the next lesson.</p>
23650e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main
23750e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Main<p>Lastly, the triangle is stationary, which is a bit boring. In the <a href="motion.html">Adding
23850e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott MainMotion</a> lesson, you make this shape rotate and make more interesting use of the OpenGL ES
23950e990c64fa23ce94efa76b9e72df7f8ec3cee6aScott Maingraphics pipeline.</p>