OpenGL 渲染篇
前面讨论了如何给3D图形染色,更一般的情况是使用位图来给Mesh上色(渲染材质)。主要步骤如下:
创建Bitmap对象
使用材质渲染,首先需要构造用来渲染的Bitmap对象,Bitmap对象可以从资源文件中读取或是从网络下载或是使用代码构造。为简单起见,本例从资源中读取:
1
2
|
Bitmap bitmap = BitmapFactory.decodeResource(contect.getResources(),
R.drawable.icon);
|
要注意的是,有些设备对使用的Bitmap的大小有要求,要求Bitmap的宽度和长度为2的几次幂(1,2,4,8,16,32,64.。。。),如果使用不和要求的Bitmap来渲染,可能只会显示白色。
创建材质(Generating a texture)
下一步使用OpenGL库创建一个材质(Texture),首先是获取一个Texture Id。
1
2
3
4
5
|
// Create an int array with the number of textures we want,
// in this case 1.
int [] textures = new int [ 1 ];
// Tell OpenGL to generate textures.
gl.glGenTextures( 1 , textures, 0 );
|
textures中存放了创建的Texture ID,使用同样的Texture Id ,也可以来删除一个Texture:
1
2
|
// Delete a texture.
gl.glDeleteTextures( 1 , textures, 0 )
|
有了Texture Id之后,就可以通知OpenGL库使用这个Texture:
1
|
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[ 0 ]);
|
设置Texture参数glTexParameter
下一步需要给Texture填充设置参数,用来渲染的Texture可能比要渲染的区域大或者小,这是需要设置Texture需要放大或是缩小时OpenGL的模式:
1
2
3
4
5
6
7
8
9
|
// Scale up if the texture if smaller.
gl.glTexParameterf(GL10.GL_TEXTURE_2D,
GL10.GL_TEXTURE_MAG_FILTER,
GL10.GL_LINEAR);
// scale linearly when image smalled than texture
gl.glTexParameterf(GL10.GL_TEXTURE_2D,
GL10.GL_TEXTURE_MIN_FILTER,
GL10.GL_LINEAR);
|
常用的两种模式为GL10.GL_LINEAR和GL10.GL_NEAREST。
需要比较清晰的图像使用GL10.GL_NEAREST:
而使用GL10.GL_LINEAR则会得到一个较模糊的图像:
UV Mapping
下一步要告知OpenGL库如何将Bitmap的像素映射到Mesh上。这可以分为两步来完成:
定义UV坐标
UV Mapping指将Bitmap的像素映射到Mesh上的顶点。UV坐标定义为左上角(0,0),右下角(1,1)(因为使用的2D Texture),下图坐标显示了UV坐标,右边为我们需要染色的平面的顶点顺序:
为了能正确的匹配,需要把UV坐标中的(0,1)映射到顶点0,(1,1)映射到顶点2等等。
1
2
3
4
|
float textureCoordinates[] = { 0 .0f, 1 .0f,
1 .0f, 1 .0f,
0 .0f, 0 .0f,
1 .0f, 0 .0f };
|
如果使用如下坐标定义:
1
2
3
4
|
float textureCoordinates[] = { 0 .0f, 0 .5f,
0 .5f, 0 .5f,
0 .0f, 0 .0f,
0 .5f, 0 .0f };
|
Texture匹配到Plane的左上角部分。
而
1
2
3
4
|
float textureCoordinates[] = { 0 .0f, 2 .0f,
2 .0f, 2 .0f,
0 .0f, 0 .0f,
2 .0f, 0 .0f };
|
将使用一些不存在的Texture去渲染平面(UV坐标为0,0-1,1 而 (0,0)-(2,2)定义超过UV定义的大小),这时需要告诉OpenGL库如何去渲染这些不存在的Texture部分。
有两种设置
- GL_REPEAT重复Texture。
- GL_CLAMP_TO_EDGE只靠边线绘制一次。
下面有四种不同组合:
本例使用如下配置:
1
2
3
4
5
6
|
gl.glTexParameterf(GL10.GL_TEXTURE_2D,
GL10.GL_TEXTURE_WRAP_S,
GL10.GL_REPEAT);
gl.glTexParameterf(GL10.GL_TEXTURE_2D,
GL10.GL_TEXTURE_WRAP_T,
GL10.GL_REPEAT);
|
然后是将Bitmap资源和Texture绑定起来:
1
|
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0 , bitmap, 0 );
|
使用Texture
为了能够使用上面定义的Texture,需要创建一Buffer来存储UV坐标:
1
2
3
4
5
|
FloatBuffer byteBuf = ByteBuffer.allocateDirect(texture.length * 4 );
byteBuf.order(ByteOrder.nativeOrder());
textureBuffer = byteBuf.asFloatBuffer();
textureBuffer.put(textureCoordinates);
textureBuffer.position( 0 );
|
渲染
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
// Telling OpenGL to enable textures.
gl.glEnable(GL10.GL_TEXTURE_2D);
// Tell OpenGL where our texture is located.
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[ 0 ]);
// Tell OpenGL to enable the use of UV coordinates.
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
// Telling OpenGL where our UV coordinates are.
gl.glTexCoordPointer( 2 , GL10.GL_FLOAT, 0 , textureBuffer);
// ... here goes the rendering of the mesh ...
// Disable the use of UV coordinates.
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
// Disable the use of textures.
gl.glDisable(GL10.GL_TEXTURE_2D);
|
本例代码是在一个平面上(SimplePlane)下使用Texture来渲染,首先是修改Mesh基类,使它能够支持定义UV 坐标:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
// Our UV texture buffer.
private FloatBuffer mTextureBuffer;
/**
* Set the texture coordinates.
*
* @param textureCoords
*/
protected void setTextureCoordinates( float [] textureCoords) {
// float is 4 bytes, therefore we multiply the number if
// vertices with 4.
ByteBuffer byteBuf = ByteBuffer.allocateDirect(
textureCoords.length * 4 );
byteBuf.order(ByteOrder.nativeOrder());
mTextureBuffer = byteBuf.asFloatBuffer();
mTextureBuffer.put(textureCoords);
mTextureBuffer.position( 0 );
}
|
并添加设置Bitmap和创建Texture的方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
// Our texture id.
private int mTextureId = - 1 ;
// The bitmap we want to load as a texture.
private Bitmap mBitmap;
/**
* Set the bitmap to load into a texture.
*
* @param bitmap
*/
public void loadBitmap(Bitmap bitmap) {
this .mBitmap = bitmap;
mShouldLoadTexture = true ;
}
/**
* Loads the texture.
*
* @param gl
*/
private void loadGLTexture(GL10 gl) {
// Generate one texture pointer...
int [] textures = new int [ 1 ];
gl.glGenTextures( 1 , textures, 0 );
mTextureId = textures[ 0 ];
// ...and bind it to our array
gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureId);
// Create Nearest Filtered Texture
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
GL10.GL_LINEAR);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,
GL10.GL_LINEAR);
// Different possible texture parameters, e.g. GL10.GL_CLAMP_TO_EDGE
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
GL10.GL_CLAMP_TO_EDGE);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
GL10.GL_REPEAT);
// Use theAndroidGLUtils to specify a two-dimensional texture image
// from our bitmap
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0 , mBitmap, 0 );
}
|
最后修改draw方法来渲染材质:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
// Indicates if we need to load the texture.
private boolean mShouldLoadTexture = false ;
/**
* Render the mesh.
*
* @param gl
* the OpenGL context to render to.
*/
public void draw(GL10 gl) {
...
// Smooth color
if (mColorBuffer != null ) {
// Enable the color array buffer to be used during rendering.
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
gl.glColorPointer( 4 , GL10.GL_FLOAT, 0 , mColorBuffer);
}
if (mShouldLoadTexture) {
loadGLTexture(gl);
mShouldLoadTexture = false ;
}
if (mTextureId != - 1 && mTextureBuffer != null ) {
gl.glEnable(GL10.GL_TEXTURE_2D);
// Enable the texture state
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
// Point to our buffers
gl.glTexCoordPointer( 2 , GL10.GL_FLOAT, 0 , mTextureBuffer);
gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureId);
}
gl.glTranslatef(x, y, z);
...
// Point out the where the color buffer is.
gl.glDrawElements(GL10.GL_TRIANGLES, mNumOfIndices,
GL10.GL_UNSIGNED_SHORT, mIndicesBuffer);
...
if (mTextureId != - 1 && mTextureBuffer != null ) {
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
}
...
}
|
本例使用的SimplePlane定义如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
package se.jayway.opengl.tutorial.mesh;
/**
* SimplePlane is a setup class for Mesh that creates a plane mesh.
*
* @author Per-Erik Bergman (per-erik.bergman@jayway.com)
*
*/
public class SimplePlane extends Mesh {
/**
* Create a plane with a default with and height of 1 unit.
*/
public SimplePlane() {
this ( 1 , 1 );
}
/**
* Create a plane.
*
* @param width
* the width of the plane.
* @param height
* the height of the plane.
*/
public SimplePlane( float width, float height) {
// Mapping coordinates for the vertices
float textureCoordinates[] = { 0 .0f, 2 .0f, //
2 .0f, 2 .0f, //
0 .0f, 0 .0f, //
2 .0f, 0 .0f, //
};
short [] indices = new short [] { 0 , 1 , 2 , 1 , 3 , 2 };
float [] vertices = new float [] { - 0 .5f, - 0 .5f, 0 .0f,
0 .5f, - 0 .5f, 0 .0f,
- 0 .5f, 0 .5f, 0 .0f,
0 .5f, 0 .5f, 0 .0f };
setIndices(indices);
setVertices(vertices);
setTextureCoordinates(textureCoordinates);
}
}
|
本例示例代码下载见http://www.linuxidc.com/Linux/2011-10/45756p8.htm,到本篇为止介绍了OpenGL ES开发的基本方法,更详细的教程将在以后发布,后面先回到AndroidApiDemos中OpenGL ES的示例。
前面简单介绍了OpenGL ES的开发:
- AndroidOpenGL ES 简明开发教程一:概述
- AndroidOpenGL ES 简明开发教程二:构造OpenGL ES View
- AndroidOpenGL ES 简明开发教程三:3D绘图基本概念
- AndroidOpenGL ES 简明开发教程四:3D 坐标变换
- AndroidOpenGL ES 简明开发教程五:添加颜色
- AndroidOpenGL ES 简明开发教程六: 真正的3D图形
- AndroidOpenGL ES 简明开发教程七:材质渲染
和2D图形相比,3D绘图要复杂的多,Android提供了OpenGL ES 3D 图形开发包,对应熟悉OpenGL开发的不会很难,但如果一直没有从事3D开发过,一时还不容易上手,因此暂时跳过Android ApiDemos 中后OpenGL相关的例子,计划将在后面详细介绍Android OpenGL ES开发,之后补上这部分例子。
ApiDemo 中 OpenGL ES 示例解析
Graphics/OpenGL ES/Compressed Texture
Graphics/OpenGL ES/Cube Map
Graphics/OpenGL ES/Frame Buffer Object
Graphics/OpenGL ES/GLSurfaceView
Graphics/OpenGL ES/Kube
Graphics/OpenGL ES/Matrix Palette Skinning
Graphics/OpenGL ES/OpenGL ES 2.0
Graphics/OpenGL ES/Sprite Text
Graphics/OpenGL ES/Textured Triangle
Graphics/OpenGL ES/Touch Rotate
Graphics/OpenGL ES/Translucent GLSurfaceView
Graphics/SurfaceView Overlay
本文全部源码下载:
免费下载地址在http://linux.linuxidc.com/
用户名与密码都是www.linuxidc.com
具体下载目录在/pub/Android源码集锦/2011年/10月/Android OpenGL ES 简明开发教程相关源码/
OpenGL 渲染篇相关推荐
- 教你实现GPUImage【OpenGL渲染原理】
原文出处: 袁峥Seemygo(@袁峥Seemygo) 一.前言 本篇主要讲解GPUImage底层是如何渲染的,GPUImage底层使用的是OPENGL,操控GPU来实现屏幕展示 由于网上Ope ...
- Android性能系列-渲染篇
Google近期在Udacity上发布了Android性能优化的在线课程,分别从渲染,运算与内存,电量几个方面介绍了如何去优化性能,这些课程是Google之前在Youtube上发布的Android性能 ...
- 【OpenGL】八、初始化 OpenGL 渲染环境 ( 导入 OpenGL 头文件 | 链接 OpenGL 库 | 将窗口设置为 OpenGL 窗口 | 设置像素格式描述符 | 渲染绘制 ) ★
文章目录 一.导入 OpenGL 的两个头文件 二.链接 OpenGL 库 三.将 Windows 桌面窗口改成 OpenGL 窗口 四.获取窗口设备 五.设置像素格式描述符 六.设置像素格式 七.创 ...
- [转贴]Cocos2d-x3.2与OpenGL渲染总结(一)Cocos2d-x3.2的渲染流程
看了opengles有一段时间了,算是了解了一下下.然后,就在基本要决定还是回归cocos2dx 3.2的,看了这篇好文章,欣喜转之~ 推荐看原帖: Cocos2d-x3.2与OpenGL渲染总结(一 ...
- android OpenGL渲染3D模型文件
码字不易,转载请注明出处喔 https://blog.csdn.net/newchenxf/article/details/121402859 1 前言 大部分OpenGL示例代码,要么播放个视频,要 ...
- Android平台上基于OpenGl渲染yuv视频
本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 更多音视频开发文章,请看:音视频开发专栏 介绍一个自己刚出炉的音视频播放录制开源项目 前言 这是我音视频专栏的第一篇实例解析,也算是 ...
- Android JNI利用opengl渲染文字 (二)
上篇文章准备了opengl渲染图像的环境.这片文章要做的是把freetype加载到程序中,并可以从路径中加载字体. 编译Android平台上的freetype https://www.cnblogs. ...
- 使用OpenGL渲染一个三角形
OplenGL的功能是什么?这里文中给出了介绍:In OpenGL everything is in 3D space, but the screen and window are a 2D arra ...
- 六、OpenGL 渲染技巧:深度测试、多边形偏移、 混合
OpenGL + OpenGL ES +Metal 系列文章汇总 深度测试 在上一篇五.OpenGL 渲染技巧:正背面剔除中,文末还遗留一个问题未解决,在解决之前,先说说这种现象产生的原因 甜甜圈缺口 ...
最新文章
- Android中怎样使用Navicat可视化查看sqllite的数据库(查看db文件)
- HDU1226 搜索 bfs xingxing在努力
- iamond operator is not supported in -source 1.5
- 本机在合成图片经常提示内存不足
- 通过SVD求解单应矩阵
- 微信小程序 后端返回数据为字符串,转json方法
- 行业下行,丧失亮点的OPPO慢人一步
- idea 中 maven Process terminated
- 在 Windows Service 服务上部署 AutoVue_EMP_21_0_2 的操作手册
- 5V转3V的降压芯片和LDO
- 【JZOJ6360】最大菱形和(rhombus)
- App地推营销成为趋势,破局增长数据赋能是关键
- 小程序之 一个方法中的值怎么传递到另一个方法中
- c++笔记(class)练手项目:暗网杀手排名系统
- 小觅双目摄像头标准彩色版发布 为移动机器人视觉导航避障优化设计
- 我们分析了GitHub上5.46 亿条日志,发现中国开源虽然贡献大但还有这些不足......
- 面试官让你说说你的缺点,你该怎么回答
- 直接上干货!关于Android开发的面试经验总结,含小米、腾讯、阿里
- mongodb 基本介绍
- java 二叉树第n层节点数及层序遍历
热门文章
- matlab显示灰度值的概率,求Matlab统计灰度值的代码
- 芒果文件服务器,芒果云服务器
- 设计模式 可复用面向对象软件的基础_面向对象的可复用设计模式之简单工厂模式(1/24)...
- strrev php_PHP使用strrev翻转中文乱码问题的解决方法
- php java memcached_php-memcached详解
- php验证码一直验证错误,织梦输入正确验证码登录却一直显示错误的解决方法
- 如果项目上线在上线期间出现BUG改怎么办?
- Postman:ResponseHeader存在多个Set-Cookie时,教你获取Cookie值
- ubuntu 16.04 终端命令太长,换行输入方法
- 21天Jenkins打卡Day7-打包git代码