位置: 编程技术 - 正文
推荐整理分享Android OpenGL ES 入门,希望有所帮助,仅作参考,欢迎阅读内容。
文章相关热门搜索词:,内容如对您有帮助,希望把文章链接给更多的朋友!
原创: ES View】
1.关于GLSurfaceView
Android平台提供的OpenGL ES API主要定义在包android.opengl ,javax.microedition.khronos.egl ,javax.microedition.khronos.opengles,java.nio等几个包中,其中类GLSurfaceView为这些包中的核心类:
* 起到连接OpenGL ES与Android 的View层次结构之间的桥梁作用。
* 使得Open GL ES库适应于Anndroid系统的Activity生命周期。
* 使得选择合适的Frame buffer像素式变得容易。
* 创建和管理单独绘图线程以达到平滑动画效果。
* 提供了方便使用的调试工具来跟踪OpenGL ES函数调用以帮助检查错误。
——因此编写OpenGL ES应用的起始是从类GLSurfaceView开始,设置GLSurfaceView只需调用一个方法来设置OpenGLView用到的Renderer。一般的android程序主Activity中用setContentView来设置程序用到的layout布局,即程序的界面效果,opengl只需要构造好Renderer,将其添加入GlSurfaceView,再setContentView将activity设置为用这个gl的view作为显示就行了。
2.关于GLSurfaceView.Renderer
定义了一个统一图形绘制的接口,它定义了如下三个接口函数:
* onSurfaceCreated:在这个方法中主要用来设置一些绘制时不常变化的参数,比如:背景色,是否打开z-buffer等。
* onDrawFrame:定义实际的绘图操作。
* onSurfaceChanged:如果设备支持屏幕横向和纵向切换,这个方法将发生在横向<->纵向互换时.此时可以重新设置绘制的纵横比率。
~~~~~~~则得到一个OpenGl应用的基本框架模板~~~~~~~~~~
* TutorialPartI.java (主Activity)
public class TutorialPartI extends Activity {
// Called when the activity is first created.
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE); // (NEW)
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN); // (NEW)
GLSurfaceView view = new GLSurfaceView(this);//构造view
view.setRenderer(new OpenGLRenderer());
setContentView(view);
}
}
* OpenGLRenderer.java(关键)
public class OpenGLRenderer implements Renderer {
public void onSurfaceCreated(GL gl, EGLConfig config) {
// Set the background color to black ( rgba ).
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // OpenGL docs.
// Enable Smooth Shading, default not really needed.
gl.glShadeModel(GL.GL_SMOOTH);// OpenGL docs.
// Depth buffer setup.
gl.glClearDepthf(1.0f);// OpenGL docs.
// Enables depth testing.
gl.glEnable(GL.GL_DEPTH_TEST);// OpenGL docs.
// The type of depth testing to do.
gl.glDepthFunc(GL.GL_LEQUAL);// OpenGL docs.
// Really nice perspective calculations.
gl.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, // OpenGL docs.
GL.GL_NICEST);
}
public void onDrawFrame(GL gl) {
// Clears the screen and depth buffer.
gl.glClear(GL.GL_COLOR_BUFFER_BIT | // OpenGL docs.
GL.GL_DEPTH_BUFFER_BIT);
}
public void onSurfaceChanged(GL gl, int width, int height) {
// Sets the current view port to the new size.
gl.glViewport(0, 0, width, height);// OpenGL docs.
// Select the projection matrix
gl.glMatrixMode(GL.GL_PROJECTION);// OpenGL docs.
// Reset the projection matrix
gl.glLoadIdentity();// OpenGL docs.
// Calculate the aspect ratio of the window
GLU.gluPerspective(gl, .0f,
(float) width / (float) height,
0.1f, .0f);
// Select the modelview matrix
gl.glMatrixMode(GL.GL_MODELVIEW);// OpenGL docs.
// Reset the modelview matrix
gl.glLoadIdentity();// OpenGL docs.
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
二:【3D绘图基本概念】
一个3D图形通常是由一些小的基本元素(顶点,边,面,多边形)构成,每个基本元素都可以单独来操作。
1.Vertex(顶点):3D建模的最小单位
一个顶点也可以代表一个点光源或是Camera的位置。
* 通常的顶点定义方式,数组形式:
private float vertices[] = {
-1.0f, 1.0f, 0.0f, // 0, Top Left
-1.0f, -1.0f, 0.0f, // 1, Bottom Left
1.0f, -1.0f, 0.0f, // 2, Bottom Right
1.0f, 1.0f, 0.0f, // 3, Top Right
};//定义了4个顶点,分别是x,y,z轴坐标,相对于原点o .
定义的效果是:
0 3
o点
1 2
* 与Android的View类canvas绘图不用,canvas用的屏幕坐标系,即屏幕左上角为原点(0,0),向右正x,向下正y,坐标点的单位1为1像素。opengl用的世界坐标系,以屏幕中心为(0,0,0),单位可自行决定,绘制时是按比例的
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* 为了3D绘图的性能,通常用buffer类存放顶点颜色等等信息:
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length* 4); //一个float等于4个byte,因此要*4
vbb.order(ByteOrder.nativeOrder());//设置字节序
FloatBuffer vertexBuffer = vbb.asFloatBuffer();//不同buf转换
vertexBuffer.put(vertices); //即将以上的数组放入buffer
vertexBuffer.position(0);//这个position表示下一个可以读写的字节的缺省位置,相当于一个指针~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* 有了顶点的定义,下面一步就是如何将它们传给OpenGL ES库。OpenGl使用管道机制,来开关某些功能
gl.glEnableClientState(GL.GL_VERTEX_ARRAY);//打开传递buf功能
gl.glVertexPointer(3, GL.GL_FLOAT, 0, vertexBuffer);//将定义点的数组buf传递到opengl
gl.glDisableClientState(GL.GL_VERTEX_ARRAY);//关闭传递buf功能
2.Edge(边)
在OpenGL中,通常无需直接来定义一个边,而是通过顶点定义一个面,从而又面定义了这个面所拥有的边。修改两端点,从而可以修改一条边
3.Face(面)
在OpenGL ES中,面特指一个三角形,由三个顶点和三条边构成,对一个面所做的变化影响到连接面的所有顶点和边,面多边形
* 定义面的顶点的顺序很重要,在拼接曲面的时候,顶点的顺序定义了面的朝向(前向或是后向),为了获取绘制的高性能,一般情况不会绘制面的前面和后面,只绘制面的“前面”。虽然“前面”“后面”的定义可以应人而易,但一般为所有的“前面”定义统一的顶点顺序(顺时针或是逆时针方向)。
~~~~~~~~~~~~~~设置面的三种操作~~~~~~~~~~
* gl.glFrontFace(GL.GL_CCW); //设置逆时针方法为面的"前面"。顺时针为CW
* gl.glEnable(GL.GL_CULL_FACE);//打开忽略"后面"设置
* gl.glCullFace(GL.GL_BACK);//明确指明“忽略“哪个面
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4.Polygon (多边形)
多边形由多个面(三角形)拼接而成,在三维空间上,多边形不一定表示这个Polygon在同一平面上
~~~~~~实例:~~~~~
private short[] indices = {0,1,2,0,2,3}; //顶点连接顺序
ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2); //indices为short型,要*2 。(byte 8位,short 位)
ibb.order(ByteOrder.nativeOrder());
ShortBuffer indexBuffer = ibb.asShortBuffer();
indexBuffer.put(indices); //放入数据
indexBuffer.position(0);
~~~~~~~~~~~~~~~~~~~~~~~~~~~
5.Render (渲染)
定义好了多边形,下面是如何使用OpenGL ES的API来绘制(渲染)这个多边形。OpenGL ES提供了两类方法来绘制一个空间几何图形:
* public abstract void glDrawArrays(int mode, int first, int count)//使用VetexBuffer来绘制,顶点的顺序由vertexBuffer中的顺序指定。若没定义indices就用这个函数
* public abstract void glDrawElements(int mode, int count, int type, Buffer indices) //可以重新定义顶点的顺序,顶点的顺序由indices指定。
* 上面两方法中的mode分类:GL_POINTS(独立的点)、GL_LINE_STRIP(按顺序不间断的一条线)、GL_LINE_LOOP(首尾封闭)、GL_LINES(两两相连的多条线段)、GL_TRIANGLES(三三组成的分离的三角形)、GL_TRIANGLE_STRIP(相连的三角形)、GL_TRIANGLE_FAN(以起点为公共顶点的相连多个三角形)
~~~~~~~~~~举例,下面是绘制一个正方形~~~~~~~~~~~
* Square.java
public class Square {
private float vertices[] = {
-1.0f, 1.0f, 0.0f, // 0, Top Left
-1.0f, -1.0f, 0.0f, // 1, Bottom Left
1.0f, -1.0f, 0.0f, // 2, Bottom Right
1.0f, 1.0f, 0.0f, // 3, Top Right
};
private short[] indices = { 0, 1, 2, 0, 2, 3 };
private FloatBuffer vertexBuffer;
private ShortBuffer indexBuffer;
public Square() {
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
vbb.order(ByteOrder.nativeOrder());
vertexBuffer = vbb.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2);
ibb.order(ByteOrder.nativeOrder());
indexBuffer = ibb.asShortBuffer();
indexBuffer.put(indices);
indexBuffer.position(0);
}
public void draw(GL gl) {
gl.glFrontFace(GL.GL_CCW);
gl.glEnable(GL.GL_CULL_FACE);
gl.glCullFace(GL.GL_BACK);
gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL.GL_FLOAT, 0,vertexBuffer);
gl.glDrawElements(GL.GL_TRIANGLES, indices.length,
GL.GL_UNSIGNED_SHORT, indexBuffer);
gl.glDisableClientState(GL.GL_VERTEX_ARRAY);
gl.glDisable(GL.GL_CULL_FACE); //一般有enable必对应一个disable函数
}
}
* 相应的在OpenGlRenderer中加入Square对象的实例化,并在其onDrawFrame函数中调用square.draw(gl);
* 这时,并不能看到画面,还需要在draw之前调用
gl.glLoadIdentity();//每次调用onDrawFrame时重置,防止每次都后移4单位
gl.glTranslatef(0, 0, -4);//由于OpenGl Es渲染时,默认坐标是(0,0,0),其中Z轴为0,这个0的基准为屏幕,即绘制时贴着屏幕画的。所以要后平移4个单位,从立体的视角“向屏幕里面去一点”
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
三:【3D坐标变换】
1.Coordinate System(坐标系)
OpenGl使用右手坐标系:右手拇指指x轴正向,中指y轴正向,着z轴正向为掌心向外
2.Translate (平移)
之前的glTranslatef(float x,float y,float z)即为平移变换函数,可以进行多次平移变换,其结果为多个平移矩阵的累计结果,矩阵的顺序不重要,可以互换
3.Rotate(旋转)
glRotatef(float angle,float x,float y,float z)函数,除了xyz,还有一个旋转变换角度angle,定义旋转的参照矢量方向。多次旋转次序很重要。glRotatef(angle,-x,-y,-z)和glRotatef(-angle,x,y,z)等价的。
~~~~~~~~~~~示例~~~~~~~~~~~
gl.glRotatef(f, 1.0f, 0.0f, 0.0f);//拇指指x,向四指方向旋转
gl.glRotatef(f, 0.0f, 1.0f, 0.0f);//下同
gl.glRotatef(f, 0.0f, 0.0f, 1.0f);
//***多次旋转的话坐标轴是跟随着几何体一起旋转的,下一次旋转是在前一次旋转得到的坐标轴基础上转的
~~~~~~~~~~~~~~~~~~~~~~~~~~~
4.Translate & Rotate (平移和旋转组合变换)
就是上面那句话:坐标变换都是相对于变换的Mesh本身的坐标系而进行的
5.Scale(缩放)
方法public abstract void glScalef (float x, float y, float z)用于缩放变换。
gl.glScalef(2f, 2f, 2f)即xyz均乘以二
6.Translate & Scale(平移和缩放组合变换)
同样当需要平移和缩放时,变换的顺序也会影响最终结果,因为这时候单位“1”发生了变化
7.矩阵操作,单位矩阵
如果需要将当前矩阵回复最初的无变换的矩阵,可以使用单位矩阵(无平移,缩放,旋转),使用public abstract void glLoadIdentity()
在栈中保存当前矩阵和从栈中恢复所存矩阵,可以使用
public abstract void glPushMatrix();
public abstract void glPopMatrix();
~~~~~~~~~~~~~~~~~~~~举例~~~~~~~~~~~``~~~~~~~~
~~~绘制3个正方形A,B,C,使的B比A小%,C比B小%。 然后以屏幕中心逆时针旋转A,B以A为中心顺时针旋转,C以B为中心顺时针旋转同时以自己中心高速逆时针旋转
gl.glTranslatef(0, 0, -);//得到原始矩阵
gl.glPushMatrix();//存储原始矩阵
gl.glRotatef(angle, 0, 0, 1);//变换原始矩阵,得到A
square.draw(gl);//画出A
gl.glPopMatrix();//回归原始矩阵
gl.glPushMatrix();//存储原始矩阵
gl.glRotatef(-angle, 0, 0, 1);//绕原始矩阵中心旋转
gl.glTranslatef(2, 0, 0);//右移
gl.glScalef(.5f, .5f, .5f);//缩小,得到B
square.draw(gl);//画出B
gl.glPushMatrix();//存储B
gl.glRotatef(-angle, 0, 0, 1);//绕B的中心旋转
gl.glTranslatef(2, 0, 0);//右移
gl.glScalef(.5f, .5f, .5f);//缩小
gl.glRotatef(angle*, 0, 0, 1);//绕右移且缩小后的中心转,得到C
square.draw(gl);//画出C
gl.glPopMatrix();
gl.glPopMatrix();
angle;//角度自增
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
四:【给图形上色】
OpenGL ES使用颜色是RGBA模式(红,绿,蓝,透明度).
不同于一般情况下的进制的RGB,即三原色均为0~.OpenGl中三种颜色使用0.0f~1.0f的浮点数。1相当于。
1.Flat coloring(单色)
通知OpenGL使用单一的颜色来渲染,OpenGL将一直使用指定的颜色来渲染直到你指定其它的颜色,具体方法public abstract void glColor4f(float red, float green, float blue, float alpha)
缺省均为1,即为白色不透明
2.Smooth coloring(平滑颜色过渡)
当给每个顶点定义一个颜色时,OpenGL自动为不同顶点颜色之间生成中间过渡颜色(渐变色)
* 颜色同顶点一样,也是用数组 buffer的方式定义的,例如下:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
float[] colors = {
1f, 0f, 0f, 1f, // vertex 0 red
0f, 1f, 0f, 1f, // vertex 1 green
0f, 0f, 1f, 1f, // vertex 2 blue
1f, 0f, 1f, 1f, // vertex 3 magenta
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length * 4);
cbb.order(ByteOrder.nativeOrder());
colorBuffer = cbb.asFloatBuffer();
colorBuffer.put(colors);
colorBuffer.position(0);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
然后在draw方法中加入
gl.glEnableClientState(GL.GL_COLOR_ARRAY);
gl.glColorPointer(4, GL.GL_FLOAT, 0, colorBuffer);
//然后要记得disable
gl.glDisableClientState(GL.GL_COLOR_ARRAY);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
五.【从平面到立体,绘制真正的3D图形】
设计原则,创建并使用一个Mesh(网)类来构造各种不同的3D图形。
* Mesh.java ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public class Mesh {
private FloatBuffer verticesBuffer = null;
private ShortBuffer indicesBuffer = null;
private int numOfIndices = -1;
private float[] rgba
= new float[] { 1.0f, 1.0f, 1.0f, 1.0f };
private FloatBuffer colorBuffer = null;
public float x = 0;
public float y = 0;
public float z = 0;
public float rx = 0;
public float ry = 0;
public float rz = 0;
public void draw(GL gl) {
gl.glFrontFace(GL.GL_CCW);
gl.glEnable(GL.GL_CULL_FACE);
gl.glCullFace(GL.GL_BACK);
gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL.GL_FLOAT, 0, verticesBuffer);
gl.glColor4f(rgba[0], rgba[1], rgba[2], rgba[3]);//渲染单色
if (colorBuffer != null) { //若colorbuffer不为空则再渲染渐变色
gl.glEnableClientState(GL.GL_COLOR_ARRAY);
gl.glColorPointer(4, GL.GL_FLOAT, 0, colorBuffer);
}
gl.glTranslatef(x, y, z);
gl.glRotatef(rx, 1, 0, 0);
gl.glRotatef(ry, 0, 1, 0);
gl.glRotatef(rz, 0, 0, 1);
gl.glDrawElements(GL.GL_TRIANGLES, numOfIndices,
GL.GL_UNSIGNED_SHORT, indicesBuffer);
gl.glDisableClientState(GL.GL_VERTEX_ARRAY);
gl.glDisable(GL.GL_CULL_FACE);
}
protected void setVertices(float[] vertices) {
ByteBuffer vbb
= ByteBuffer.allocateDirect(vertices.length * 4);
vbb.order(ByteOrder.nativeOrder());
verticesBuffer = vbb.asFloatBuffer();
verticesBuffer.put(vertices);
verticesBuffer.position(0);
}
protected void setIndices(short[] indices) {
ByteBuffer ibb
= ByteBuffer.allocateDirect(indices.length * 2);
ibb.order(ByteOrder.nativeOrder());
indicesBuffer = ibb.asShortBuffer();
indicesBuffer.put(indices);
indicesBuffer.position(0);
numOfIndices = indices.length;
}
protected void setColor(float red, float green,
float blue, float alpha) {
rgba[0] = red;
rgba[1] = green;
rgba[2] = blue;
rgba[3] = alpha;
}
protected void setColors(float[] colors) {
ByteBuffer cbb
= ByteBuffer.allocateDirect(colors.length * 4);
cbb.order(ByteOrder.nativeOrder());
colorBuffer = cbb.asFloatBuffer();
colorBuffer.put(colors);
colorBuffer.position(0);
}
}
//在这个Mesh类中,定义有ver(点)和ind(路径),并有相应的set方法来生成Buffer,还有颜色的set,旋转与平移的xyz定义。在使用时,只需要定义一个图形类从Mesh派生,然后按顺序加入顶点与连接路径,或颜色,即可得到一个自定的3D图形。例如一个Cube正方体:
* Cube.java~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`
public class Cube extends Mesh {
public Cube(float width, float height, float depth) {
width /= 2;
height /= 2;
depth /= 2;
float vertices[] = { -width, -height, -depth, // 0
width, -height, -depth, // 1
width, height, -depth, // 2
-width, height, -depth, // 3
-width, -height, depth, // 4
width, -height, depth, // 5
width, height, depth, // 6
-width, height, depth, // 7
}; //8个顶点定义好后
short indices[] = { 0, 4, 5,
0, 5, 1,
1, 5, 6,
1, 6, 2,
2, 6, 7,
2, 7, 3,
3, 7, 4,
3, 4, 0,
4, 7, 6,
4, 6, 5,
3, 0, 1,
3, 1, 2, }; //按一定顺序把8个点连起来
setIndices(indices);
setVertices(vertices); //两个set,就得到了一个单色正方体。
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
六:【材质渲染】
前面是用颜色给图形上色,这里讲的是用bitmap位图来渲染
1.创建Bitmap对象
方法同android中的获取bitmap的方法,即:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~·
Bitmap bitmap = BitmapFactory.decodeResource(contect.getResources(),R.drawable.icon);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* 要注意的是,有些设备对使用的Bitmap的大小有要求,要求Bitmap的宽度和长度为2的几次幂(1,2,4,8,,,.。。。),如果使用不和要求的Bitmap来渲染,可能只会显示白色。
2.创建材质(Generating a texture)
* 首先,获取一个texture 的id
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int[] textures = new int[1];
// Tell OpenGL to generate textures.
gl.glGenTextures(1, textures, 0);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~·
* textures中存放了创建的Texture ID,使用同样的Texture Id ,也可以删除一个Texture,调用方法gl.glDeleteTextures(1, textures, 0);
* 然后调用这个函数时通知opengl使用这个textures:gl.glBindTexture(GL.GL_TEXTURE_2D, textures[0]);
*下一步需要给Texture填充设置参数,用来渲染的Texture可能比要渲染的区域大或者小,这时需要设置Texture需要放大或是缩小时OpenGL的模式
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~·
gl.glTexParameterf(GL.GL_TEXTURE_2D,
GL.GL_TEXTURE_MAG_FILTER,
GL.GL_LINEAR);//当texures小了,需要放大
gl.glTexParameterf(GL.GL_TEXTURE_2D,
GL.GL_TEXTURE_MIN_FILTER,
GL.GL_LINEAR);//当texures需要缩小
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~·
参数GL.GL_LINEAR和GL.GL_NEAREST,前者是模糊处理的,后者清晰
3.UV Mapping
告知OpenGL库如何将Bitmap的像素映射到Mesh上,分两步
* <1>定义UV坐标
UV Mapping指将Bitmap的像素映射到Mesh上的顶点。UV坐标定义image左上角(0,0),右下角(1,1)(因为使用的2D Texture),即映射这两个点到vertics坐标上即可。
例如~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
float textureCoordinates[] = {0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f };//应该也相当于一个路径,染色顺序是左下右下左上右上
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
float textureCoordinates[] = {0.0f, 0.5f,
0.5f, 0.5f,
0.0f, 0.0f,
0.5f, 0.0f };//这样会得到image左上四分之一图来渲染
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
float textureCoordinates[] = {0.0f, 2.0f,
2.0f, 2.0f,
0.0f, 0.0f,
2.0f, 0.0f };//这样超出Texture的边界了,这时有两种设置方法
* GL_REPEAT 重复Texture。
* GL_CLAMP_TO_EDGE 只靠边线绘制一次
例如:
gl.glTexParameterf(GL.GL_TEXTURE_2D,
GL.GL_TEXTURE_WRAP_S,
GL.GL_REPEAT);
gl.glTexParameterf(GL.GL_TEXTURE_2D,
GL.GL_TEXTURE_WRAP_T,
GL.GL_REPEAT);
//这样设置的结果是UV坐标系x方向一直重复,y方向也一直重复填充
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* <2>绑定Texture与图片
GLUtils.texImage2D(GL.GL_TEXTURE_2D, 0, bitmap, 0);
4.使用Texture
为了能够使用上面定义的Texture,需要创建一Buffer来存储UV坐标:
FloatBuffer byteBuf = ByteBuffer.allocateDirect(texture.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
textureBuffer = byteBuf.asFloatBuffer();
textureBuffer.put(textureCoordinates);
textureBuffer.position(0);
5.最后是渲染
gl.glEnable(GL.GL_TEXTURE_2D);
// Tell OpenGL where our texture is located.
gl.glBindTexture(GL.GL_TEXTURE_2D, textures[0]);
// Tell OpenGL to enable the use of UV coordinates.
gl.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY);
// Telling OpenGL where our UV coordinates are.
gl.glTexCoordPointer(2, GL.GL_FLOAT, 0, textureBuffer);
// ... here goes the rendering of the mesh ...
// Disable the use of UV coordinates.
gl.glDisableClientState(GL.GL_TEXTURE_COORD_ARRAY);
// Disable the use of textures.
gl.glDisable(GL.GL_TEXTURE_2D);
* * 这里有非常重要的一点,我在构造一个旋转三棱锥并往上贴图时就遇到过一个问题,图形在模拟器上运行正常,但是到了手机上就贴不上图。百度才知出现这个问题原因有很多种,首先图片的大小必须得是2的幂次。还有网友是用png式图时,要将PNG改成PNG8-色解决的,另外还有人是通过建立三种dpi的drawable文件夹解决的。
一个简单的Demo用来打开存放在assets文件夹中的.obj文件,点击下载
OpenGl函数说明 glAccum操作累加缓冲区glAddSwapHintRectWIN定义一组被SwapBuffers拷贝的三角形glAlphaFunc允许设置alpha检测功能glAreTexturesResident决定特定的纹理对象是否常驻在纹
mac xcode运行opengl 初次接触opengl,就只说说配置运行的步骤吧!希望多指教!1.新建项目,new-project-OSX中选择CommandLineTool;2.导入OpenGlFrame,右键项目-AddFilesToXXXXX选中/System
[OpenGL ES ]3D变换实践篇:平移,旋转,缩放 [OpenGLES]3D变换实践篇:平移,旋转,缩放罗朝辉(
上一篇:OpenGL ES常用API(opengl es programming guide)
友情链接: 武汉网站建设