Displaying Graphics with OpenGL ES(三)——Drawing Shapes
2016-04-15 18:33
411 查看
Drawing Shapes
在用OpenGl定义shapes后,就要画出他们了。画出形状需要大量的代码,因为API提供了强大的图形渲染通道。1.初始化 Shapes
在你画之前,必须初始化和加载shape。除非执行程序期间改变shapes的构造( 原始坐标),你应该初始化他们在onSurfaceCreate()方法里为了渲染消耗内存和执行效率。public class MyGLRenderer implements GLSurfaceView.Renderer { ... private Triangle mTriangle; private Square mSquare; public void onSurfaceCreated(GL10 unused, EGLConfig config) { ... // initialize a triangle mTriangle = new Triangle(); // initialize a square mSquare = new Square(); } ... }
2.Draw a Shape
通过绘制OpenGL ES 2.0的定义shape需要的代码量较大,因为你必须提供很多细节的图形渲染通道。具体而言,您必须定义如下:~Vertex Shader:为渲染图形顶点的OpenGL ES图形代码。
~Fragment Shader:渲染shape正面的颜色和纹理的OpenGL ES 代码。
~Program:一个OpenGL ES对象,其中包含要用于绘制一个或多个shapes的着色器。
至少需要一个vertex shader 和 一个fragment shader。这些shaders必须被编译和添加到OpenGL ES program。下面是一个最基本的三角形shaders,你可以在Triangle.class里定义:
public class Triangle { private final String vertexShaderCode = "attribute vec4 vPosition;" + "void main() {" + " gl_Position = vPosition;" + "}"; private final String fragmentShaderCode = "precision mediump float;" + "uniform vec4 vColor;" + "void main() {" + " gl_FragColor = vColor;" + "}"; ... }
包含着色器,必须先在OpenGL ES的环境中使用该编译OpenGL着色语言(GLSL)代码。编译这段代码,在你的渲染器类创建一个实用方法:
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; }
为了绘制shape,您必须编译shader代码,将其添加到OpenGL ES的程序对象,然后链接程序。这是绘制的对象的构造函数,所以只进行一次。
Note: 编译的OpenGL ES着色器和链接程序在CPU周期和处理时间方面的代价较大,所以你应该避免做更多的操作在这里。如果你不知道你的着色器在运行时的内容,你应该建立你的代码,他们只获得创建一次,然后缓存以备后用。
public class Triangle() { ... private final int mProgram; public Triangle() { ... int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode); int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode); // create empty OpenGL ES Program mProgram = GLES20.glCreateProgram(); // add the vertex shader to program GLES20.glAttachShader(mProgram, vertexShader); // add the fragment shader to program GLES20.glAttachShader(mProgram, fragmentShader); // creates OpenGL ES program executables GLES20.glLinkProgram(mProgram); } }
下面,你就可以添加绘制shape的实际调用。绘制形状与OpenGL ES需要您指定几个参数来告诉画什么渲染通道以及如何绘制它。由于绘图选项可以通过形状有所不同,所以在你的形状类包含自己的绘画逻辑是个好想法。
创建绘制形状的draw()方法。此代码设置形状的顶点着色器颜色值和fragment着色器的位置,然后执行绘图功能。
private int mPositionHandle; private int mColorHandle; private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX; private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex public void draw() { // Add program to OpenGL ES environment GLES20.glUseProgram(mProgram); // get handle to vertex shader's vPosition member mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition"); // Enable a handle to the triangle vertices GLES20.glEnableVertexAttribArray(mPositionHandle); // Prepare the triangle coordinate data GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer); // get handle to fragment shader's vColor member mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor"); // Set color for drawing the triangle GLES20.glUniform4fv(mColorHandle, 1, color, 0); // Draw the triangle GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount); // Disable vertex array GLES20.glDisableVertexAttribArray(mPositionHandle); }
一但你有了所有到位的代码,绘制这个对象只需要调用draw()方法从渲染的onDrawFrame()方法里:
public void onDrawFrame(GL10 unused) { ... mTriangle.draw(); }
然后运行程序,可以看到:
Figure 1. Triangle绘制没有用到Projection或Camera View。
此代码示例的一些问题。首先,它不会打动你的朋友。其次,三角形是有点压扁,并改变形状,当您更改设备的屏幕方向。形状歪斜的原因是由于对象的顶点未针对其中显示GLSurfaceView屏幕区域的比例校正。可以使用在下一章的投影和相机视图解决这个问题。
最后,三角形是固定的,这是一个有点无聊。在Add Motion 章节里,可以使这种形状旋转,做更多有趣的使用的OpenGL ES图形通道。
相关文章推荐
- copy与mutableCopy
- Displaying Graphics with OpenGL ES(二)——定义形状Defining Shapes
- golang 走起(九) linux 下 go语言 vim设置
- Linux默认目录介绍
- 配置Opencv出现0x000007b错误的解决方法
- EmguCV学习(三)
- EmguCV学习(二)
- EmguCV学习(一)
- 正则表达式
- 关于Handler和Looper
- Centos7安装nginx
- linux监控程序-程序自动重启方法
- linux 创建新用户并增加管理员权限
- 如何让popuwindow在指定的位置显示
- Linux下驱动调试方法
- Tomcat之虚拟主机配置以及web应用配置
- linux inotify+rsync
- Android官方MVP架构示例项目解析
- Tomcat的JVM设置和连接数设置
- 03搭建docker私有仓库