(转)使用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绘制各种形体,并在上一 ...
随机推荐
- Yii2.0 for update 行级锁
当我们遇到存在高并发并且对于数据的准确性有要求的场景,需要了解和使用for update 需要注意的点: 1.InnoDB默认是行级别的锁,当有明确指定的主键时候,是行级锁.否则是表级别 2.for ...
- 【GDAL】聊聊GDAL的数据模型
GDAL是个非常优秀的GIS数据操作库,最近在和实习生介绍GDAL的简单使用,顺手写下记录 本篇记录栅格数据,代码环境为C# 在GDAL中,栅格数据大致是以一个Dataset对应一个栅格数据文件(.T ...
- How to show out three rows from the same databand On A4?
How to show out three rows from the same databand On A4? Quote Post by DoraHuang » Tue Mar 13, 2018 ...
- Java并发AtomicLongArray类
java.util.concurrent.atomic.AtomicLongArray类提供了可以原子读取和写入的底层long类型数组的操作,并且还包含高级原子操作. AtomicLongArray支 ...
- java中封装的使用方法(工具myeclipse)
封装可以实现属性私有化,将类的属性修饰符由public改为private,如此做者,其他类就无法访问该类中被private修饰的对象,一般我们会使用setter/getter()方法实现对这些对象的访 ...
- mysql 性能调优 参数随写
set global innodb_buffer_pool_size = 12*1024*1024*1024;set global bulk_insert_buffer_size = 12582912 ...
- luoguP1313 计算系数 题解(NOIP2011)
P1313 计算系数 题目 #include<iostream> #include<cstdlib> #include<cstdio> #include<cm ...
- ubuntu16.04安装LNMP(ubuntu+Nginx+mysql+PHP7.0)
系统环境: Ubuntu 16.04.2 LTS nginx version: nginx/1.10.3 (Ubuntu) PHP 7.0.22-0ubuntu0.16.04.1 mysql Ver ...
- cmd 编码格式
相当于编辑器的声明为gbk格式编码,输出格式也是gbka = '中文' 就会以gbk编码为str,也只能以gbk解码. reload sys修改默认编码 在不指定编码的时候充当默认解码或者编码格式
- rgba转化为16进制在线工具
https://www.sioe.cn/yingyong/yanse-rgb-16/