(转)使用OpenGL显示图像(三)绘制Shapes
绘制形状
编写:jdneo - 原文:http://developer.android.com/training/graphics/opengl/draw.html
在定义了使用OpenGL绘制的形状之后,你可能希望绘制出它们。使用OpenGL ES 2.0绘制图形可能会比你想象当中更复杂一些,因为API中提供了大量对于图形渲染流程的控制。
这节课将解释如何使用OpenGL ES 2.0接口画出在上一节课中定义的形状。
初始化形状
在你开始绘画之前,你需要初始化并加载你期望绘制的图形。除非你所使用的形状结构(原始坐标)在执行过程中发生了变化,不然的话你应该在渲染器的onSurfaceCreated()方法中初始化它们,这样做是出于内存和执行效率的考量。
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();
}
...
}
画一个形状
使用OpenGL ES 2.0画一个定义好的形状需要较多代码,因为你需要提供很多图形渲染流程的细节。具体而言,你必须定义如下几项:
- 顶点着色器(Vertex Shader):用来渲染形状顶点的OpenGL ES代码。
- 片段着色器(Fragment Shader):使用颜色或纹理渲染形状表面的OpenGL ES代码。
- 程式(Program):一个OpenGL ES对象,包含了你希望用来绘制一个或更多图形所要用到的着色器。
你需要至少一个顶点着色器来绘制一个形状,以及一个片段着色器为该形状上色。这些着色器必须被编译然后添加到一个OpenGL ES Program当中,并利用它来绘制形状。下面的代码在Triangle类中定义了基本的着色器,我们可以利用它们绘制出一个图形:
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 Shading Language(GLSL)代码,它必须先被编译然后才能在OpenGL环境中使用。要编译这些代码,需要在你的渲染器类中创建一个辅助方法:
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;
}
为了绘制你的图形,你必须编译着色器代码,将它们添加至一个OpenGL ES Program对象中,然后执行链接。在你的绘制对象的构造函数里做这些事情,这样上述步骤就只用执行一次。
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);
}
}
至此,你已经完全准备好添加实际的调用语句来绘制你的图形了。使用OpenGL ES绘制图形需要你定义一些变量来告诉渲染流程你需要绘制的内容以及如何绘制。既然绘制属性会根据形状的不同而发生变化,把绘制逻辑包含在形状类里面将是一个不错的主意。
创建一个draw()
方法来绘制图形。下面的代码为形状的顶点着色器和形状着色器设置了位置和颜色值,然后执行绘制函数:
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);
}
一旦你完成了上述所有代码,仅需要在你渲染器的onDrawFrame()方法中调用draw()
方法就可以画出我们想要画的对象了:
public void onDrawFrame(GL10 unused) {
...
mTriangle.draw();
}
当你运行这个应用时,它看上去会像是这样:
在这个代码样例中,还存在一些问题。首先,它无法给用户带来什么深刻的印象。其次,这个三角形看上去有一些扁,另外当你改变屏幕方向时,它的形状也会随之改变。发生形变的原因是因为对象的顶点没有根据显示GLSurfaceView的屏幕区域的长宽比进行修正。你可以在下一节课中使用投影(Projection)或者相机视角(Camera View)来解决这个问题。
最后,这个三角形是静止的,这看上去有些无聊。在添加移动课程当中(后续课程),你会让这个形状发生旋转,并使用一些OpenGL ES图形处理流程中更加新奇的用法。
(转)使用OpenGL显示图像(三)绘制Shapes的更多相关文章
- iOS OpenGL ES简单绘制三角形
OpenGL 是用于2D/3D图形编程的一套基于C语言的统一接口. windows,Linux,Unix上均可兼容. OpenGL ES 是在OpenGL嵌入式设备上的版本, android/iOS ...
- OpenGL入门学习 课程 (三) 绘制几何图形的一些细节问题
http://oulehui.blog.163.com/blog/static/79614698201191832753312/ 先回顾一下我们都学习了些什么: 第一课,编写第一个OpenGL程序第二 ...
- (转)使用OpenGL显示图像(二)定义Shapes
定义形状 编写:jdneo - 原文:http://developer.android.com/training/graphics/opengl/shapes.html 在一个OpenGL ES Vi ...
- Android OpenGL ES(三)----编程框架
首先当然是创建Android项目,你可以选择最新的Android Studio也可以选择eclipse都是一样的.我们重点讲解开发OpenGL ES的流程 1.定义顶点着色器和片段着色器 第一节我们讲 ...
- Android OpenGL 入门示例----绘制三角形和正方形
Android上对OpenGl的支持是无缝的,所以才有众多3D效果如此逼真的游戏,在Camera的一些流程中也有用到GLSurfaceView的情况.本文记录OpenGL在Android上的入门级示例 ...
- OpenGL实现多层绘制(Layered Rendering) [转]
http://blog.csdn.net/u010462297/article/details/50589991 引言 在某些情况下会需要用到多层绘制.FBO下有多个颜色挂接点(Color Attac ...
- <opengl>使用glu绘制二次曲面
绘制二次曲面通常要以下四步: 1.首先我们创建一个二次方程状态对象 GLUquadricObj *m_pObj; //保存绘图模式.法线模式.法线朝向.纹理等信息 //创建二次方程状态对象 ...
- OpenGL(三) RGBA颜色设置
OpenGL支持两种颜色模式:一种是RGBA,一种是颜色索引模式. 像素点附加颜色信息之后,就必须为每一个像素点额外分配一个内存空间保存该点的颜色信息,对于RGBA颜色模式,保存的数据直接代表了颜色, ...
- (转)使用OpenGL显示图像(七)Android OpenGLES2.0——纹理贴图之显示图片
转:http://blog.csdn.net/junzia/article/details/52842816 前面几篇博客,我们将了Android中利用OpenGL ES 2.0绘制各种形体,并在上一 ...
随机推荐
- HTTP协议之-URL
一.URL url统一资源定位符 1.URL格式: 方案.就是指所使用的协议,类似http:// 服务器的地址,类似i.cnblogs.com/ 制定web服务器的某个资源路径 方案://服务器位置/ ...
- 【Java架构:持续交付】一篇文章搞掂:持续交付理论
一.持续集成.持续交付.DevOps概念,关系等 持续集成(Continuous integration/CI) 持续交付(Continuous delivery/CD) 持续部署() 持续 (Con ...
- (转)Docker network命令
转:https://blog.csdn.net/gezhonglei2007/article/details/51627821 原文地址:https://docs.docker.com/engine/ ...
- 使用ajax前必须了解的知识
ajax的全称: asynchronous javascript and xml (异步的javascript和xml) ajax不是某种编程语言 是一种在无需重新加载整个页面的情况下能够更新部分网页 ...
- php开发面试题---日常面试题1
php开发面试题---日常面试题1 一.总结 一句话总结: 实战确定学习方向,然后去网上找视频资源,非常多,然后看书 1.什么样的数据存在memcache里面? 要去数据库里面查询的那些数据,数据库查 ...
- 学会如何使用,pycharm,和gitlanb
好好看,好好学.这才是正确的. 1 在pycharm 里面选择checkout as 切换分支 2 选择自己提交的,然后选择审核人.是强哥
- https中引用http
https里引用http不安全,会报错 解决方案 1.可以部署在http中,http中引用https不会存在安全问题报错 2.https中引用https,把需要引用的http部署成https
- 如何在列表,字典,集合中,根据条件筛选数据 -- Python数据结构与算法相关问题与解决技巧
实际案例: 1.过滤掉列表 [3,9,-1,10,20,-2..]的负数 2.筛出字典{'LiLei':79,'Jim':88,'Lucy':92...}中值高于90的项 3.筛出集合 {77,89, ...
- Unity获取Android和iOS手机系统电量及网络状况
最开始考虑使用中间静态链接库来调用手机系统自带的API,但是在研究的过程中发现Android系统将电量等信息记录在了固定的文件中,所以只需要在C#中直接读取就可以而不需要中间库. a.Android版 ...
- select的限制与poll的使用
select的限制 select的并发数受到两个限制:1.一个进程能打开的最大描述符数量;2.select中fd_set集合容量的限制(FD_SETSIZE) 关于进程的最大描述符数量: ulimit ...