publicclassMyGLSurfaceViewextendsGLSurfaceView {

privatefinalfloatTOUCH_SCALE_FACTOR =180.0f /320;

/**

* 具体实现的渲染器

*/

privateOPhoneOglesDevRenderer mRenderer;

/**

* 记录上次触屏位置的坐标

*/

privatefloatmPreviousX, mPreviousY;

publicMyGLSurfaceView(Context context) {

super(context);

// 设置渲染器

mRenderer =newOPhoneOglesDevRenderer(context);

setRenderer(mRenderer);

// 设置渲染模式为主动渲染

setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);

}

publicvoidonPause() {

super.onPause();

}

publicvoidonResume() {

super.onResume();

}

/**

* 响应触屏事件

*/

@Override

publicbooleanonTouchEvent(MotionEvent e) {

floatx = e.getX();

floaty = e.getY();

switch(e.getAction()) {

caseMotionEvent.ACTION_MOVE:

floatdx = x - mPreviousX;

floatdy = y - mPreviousY;

mRenderer.mAngleX += dx * TOUCH_SCALE_FACTOR;

mRenderer.mAngleY += dy * TOUCH_SCALE_FACTOR;

requestRender();

}

mPreviousX = x;

mPreviousY = y;

returntrue;

}

}

OpenGL ES开发简要框架

开发OpenGL ES程序,首要做的就是设置视口,设置投影矩阵,设置模型视图矩阵等。对于设置模型视图矩阵,我们通常会分别设置相机矩阵和模型矩阵。对于一些全局性的设置,我们通常只需要执行一次;而对于那些需要动态改变的属性,则应该在相应事件发生时或者逐帧进行动态更新。GLSurfaceView.Renderer接口提供了监视绘图表面创建、改变以及逐帧更新的方法,分别是:

/**

* 创建绘图表面时调用

*/

@Override

publicvoidonSurfaceCreated(GL10 gl, EGLConfig config)

/**

* 当绘图表面尺寸发生改变时调用

*/

@Override

publicvoidonSurfaceChanged(GL10 gl,intwidth,intheight)

/**

* 逐帧渲染

*/

@Override

publicvoidonDrawFrame(GL10 gl)

/** * 创建绘图表面时调用 */ @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) /** * 当绘图表面尺寸发生改变时调用 */ @Override public void onSurfaceChanged(GL10 gl, int width, int height) /** * 逐帧渲染 */ @Override public void onDrawFrame(GL10 gl)

通常,我们在onSurfaceCreated()中通过调用glHint()函数来设置渲染质量与速度的平衡,设置清屏颜色,着色模型,启用背面剪裁和深度测试,以及禁用光照和混合等全局性设置。相关代码如下:

publicvoidonSurfaceCreated(GL10 gl, EGLConfig config) {

//全局性设置

gl.glDisable(GL10.GL_DITHER);

gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);

//设置清屏背景颜色

gl.glClearColor(0.5f,0.5f,0.5f,1);

//设置着色模型为平滑着色

gl.glShadeModel(GL10.GL_SMOOTH);

//启用背面剪裁

gl.glEnable(GL10.GL_CULL_FACE);

gl.glCullFace(GL10.GL_BACK);

//启用深度测试

gl.glEnable(GL10.GL_DEPTH_TEST);

//禁用光照和混合

gl.glDisable(GL10.GL_LIGHTING);

gl.glDisable(GL10.GL_BLEND);

}

在onSurfaceChanged中,我们会根据绘图表面尺寸的改变,来即时改变视口大小,以及重新设置投影矩阵。相关代码如下:

publicvoidonSurfaceChanged(GL10 gl,intwidth,intheight) {

//设置视口

gl.glViewport(0,0, width, height);

//设置投影矩阵

floatratio = (float) width / height;//屏幕宽高比

gl.glMatrixMode(GL10.GL_PROJECTION);

gl.glLoadIdentity();

GLU.gluPerspective(gl,45.0f, ratio,1,5000);

//每次修改完GL_PROJECTION后,最好将当前矩阵模型设置回GL_MODELVIEW

gl.glMatrixMode(GL10.GL_MODELVIEW);

}

}

在onDrawFrame中,需要编写的是每帧实际渲染的代码,包括清屏,设置模型视图矩阵,渲染模型,以及相应的update函数。相关代码如下:

publicvoidonDrawFrame(GL10 gl) {

//一般的opengl程序,首先要做的就是清屏

gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

//紧接着设置模型视图矩阵

setUpCamera(gl);

//渲染物体

drawModel(gl);

//更新时间

updateTime();

}

设置模型视图矩阵(即GL_MODELVIEW矩阵)时,我们通常分别设置相机和物体矩阵。在设置相机矩阵时,我们可以通过调用

GLU.gluLookAt (GL10 gl, float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ) 传入视点位置(eyeX, eyeY, eyeZ)、被观察体的中心位置(centerX, centerY, centerZ)以及相机向上方向的向量(upX, upY, upZ)。相关代码如下:

/**

* 设置相机矩阵

* @param gl

*/

privatevoidsetUpCamera(GL10 gl) {

gl.glMatrixMode(GL10.GL_MODELVIEW);

gl.glLoadIdentity();

GLU.gluLookAt(gl, mfEyeX, mfEyeY, mfEyeZ, mfCenterX, mfCenterY, mfCenterZ,0,1,0);

}

OpenGL ES中采用的是矩阵堆栈体系。对于模型视图矩阵,堆栈深度至少为16;对于投影矩阵或者纹理矩阵,则至少为2。由于OpenGL ES中的矩阵操作,都是针对当前栈顶的矩阵,因此很多时候需要配对使用glPushMatrix()和glPopMatrix()来进行保存和恢复矩阵现场。在本例中,渲染模型之前,我们首先使用glPushMatrix()来复制当前模型视图矩阵,并将其推入到栈顶,之后所有的矩阵操作均针对该矩阵。然后我们通过调用glRotate()函数,进行适当的旋转,在渲染模型完毕之后,通过调用glPopMatrix()将当前矩阵弹出,恢复之前的矩阵现场。相关代码如下:

/**

* 渲染模型

* @param gl

*/

privatevoiddrawModel(GL10 gl) {

gl.glPushMatrix();

{

//首先对模型进行旋转

gl.glRotatef(mfAngleX,1,0,0);//绕X轴旋转

gl.glRotatef(mfAngleY,0,1,0);//绕Y轴旋转

if(mModel.containsAnimation()) {

//如果模型有动画,那么按时间就更新动画

if(mMsPerFrame >0) {

mModel.animate(mMsPerFrame *0.001f);//将毫秒数转化为秒, /1000

}

mModel.fillRenderBuffer();//更新顶点缓存

}

mModel.render(gl);//渲染模型

mModel.renderJoints(gl);//渲染关节,骨骼

}

gl.glPopMatrix();

}

OpenGL ES中支持三种渲染图元:点(GL_POINTS)、线(GL_LINES)和三角形(GL_TRIANGLES)。在本例子中,模型实体采用三角形渲染(对应函数mModel.render(gl)),而对于有骨骼信息的模型,会使用点和线来渲染骨骼辅助信息(对应函数mModel.renderJoints(gl))。OpenGL ES抛弃了OpenGL中传统但低效的glBegin()、glEnd()的渲染方式,采用了更为高效的批量渲染模式,使用java.nio.Buffer对象来存储渲染数据,之后通过调用glVertexPointer()、glNormalPointer()、glColorPointer()以及glTextureCoordPointer()传入Buffer对象来分别设置顶点位置、法线、颜色和纹理坐标渲染数据。在设置渲染数据的同时,需要通过调用glEnableClientState()函数,分别传入GL_VERTEX_ARRAY、GL_NORMAL_ARRAY、GL_COLOR_ARRAY和GL_TEXTURE_COORD_ARRAY来通知底层引擎启用相应渲染属性数据。这四个渲染属性并非要全部设置,而是可以根据需要只是启用其中的某几个。在本例中,渲染模型实体时,仅启用了顶点位置数据和纹理坐标数据;在渲染点线的骨骼辅助信息时,则仅仅启用了顶点位置数据。对于那些没有被启用的渲染属性,必须要确保其当前处于为非活动状态(即调用glDisableClientState()),否则就可能会对渲染结果造成一定影响,或者白白加重底层管线运算负担。

另外需要注意的是OPhone中要传入gl*Pointer()函数的Buffer对象必须要为direct模式申请的,这样可以确保缓存对象放置在Native的堆中,以免受到Java端的垃圾回收机制的影响。对于FloatBuffer、ShortBuffer和IntBuffer等多字节的缓存对象,它们的字节顺序必须设置为nativeOrder,否则会极大降低程序执行效率。

在设置好各个渲染属性的数据之后,就要通过调用glDrawArrays()或者glDrawElements()来进行数据的最终提交渲染。前者表示传入的数据是最终要渲染的数据,可以直接渲染,而后者会根据传入的索引,由底层重组最终要真正渲染的数据。相比之下,后者可以节省更多的内存。下面的代码展示了以三角形来渲染模型实体,启用顶点位置数据和纹理坐标数据,未启用法线和颜色数据:

/**

* 渲染实体模型

* @param gl

*/

publicvoidrender(GL10 gl) {

gl.glPushMatrix();

{

//设置默认颜色

gl.glColor4f(1.0f,0.5f,0.5f,1.0f);

//启用客户端状态

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

//遍历所有的MS3D Group,渲染每一个Group

for(inti =0; i

if(mpGroups[i].getTriangleCount() ==0) {

//如果该Group包含的三角形个数为零,则直接跳过

continue;

}

//得到相应纹理

TextureInfo tex = mpTexInfo[i % mpTexInfo.length];

if(tex !=null) {

//如果纹理不为空,则绑定相应纹理

gl.glBindTexture(GL10.GL_TEXTURE_2D, tex.mTexID);

//启用纹理贴图

gl.glEnable(GL10.GL_TEXTURE_2D);

//绑定纹理坐标数据

gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

gl.glTexCoordPointer(2, GL10.GL_FLOAT,0,

mpBufTextureCoords[i]);

}else{

//如果纹理为空,禁用纹理贴图

//禁用纹理客户端状态

gl.glDisable(GL10.GL_TEXTURE_2D);

gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

}

//绑定顶点数据

gl.glVertexPointer(3, GL10.GL_FLOAT,0, mpBufVertices[i]);

//提交渲染

gl.glDrawArrays(GL10.GL_TRIANGLES,0, mpGroups[i]

.getTriangleCount() *3);

}

//渲染完毕,重置客户端状态

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

gl.glDisable(GL10.GL_TEXTURE_2D);

}

gl.glPopMatrix();

}

程序中渲染骨骼关节辅助信息的部分,就是以点和线的模型进行渲染,相关代码如下

/**

* 渲染骨骼帮助信息

* @param gl

*/

publicvoidrenderJoints(GL10 gl) {

if(!containsJoint()) {

return;

}

//为保证骨骼始终可见,暂时禁用深度测试

gl.glDisable(GL10.GL_DEPTH_TEST);

//设置点和线的宽度

gl.glPointSize(4.0f);

gl.glLineWidth(2.0f);

//仅仅启用顶点数据

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

//渲染骨骼连线

gl.glColor4f(1.0f,0.0f,0.0f,1.0f);//设置颜色

gl.glVertexPointer(3, GL10.GL_FLOAT,0, mBufJointLinePosition);

//提交渲染

gl.glDrawArrays(GL10.GL_LINES,0, mJointLineCount);

//渲染关节点

gl.glColor4f(1.0f,1.0f,0.0f,1.0f);//设置颜色

gl.glVertexPointer(3, GL10.GL_FLOAT,0, mBufJointPointPosition);

//提交渲染

gl.glDrawArrays(GL10.GL_POINTS,0, mJointPointCount);

//重置回默认状态

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

gl.glPointSize(1.0f);

gl.glLineWidth(1.0f);

gl.glEnable(GL10.GL_DEPTH_TEST);

}

纹理操作        在前面的代码中,我们看到了启用、绑定纹理等操作。纹理映射是3D中非常重要的一块,如果没有纹理,整个3D世界就会只是一些单纯的色块。OPhone中目前支持2D纹理映射(贴图尺寸必须要为2的N次方),并支持2个以上的纹理贴图单元。由于纹理数据存储在OpenGL ES服务器端(可以理解为GPU端,即Graphics Process Unit,图形处理单元),因此需要我们从客户端(即外部的应用程序端)将像素数据传入,由底层将这些像素转换成更为高效的、对硬件更为友好的纹素格式。OpenGL ES中的每一个纹理都被当作一个纹理对象,它除了包括纹理像素数据之外,还包括该纹理的其他属性,比如名字、过滤模式、混合模式等。开发者需要首先向底层申请一个纹理名称,之后上传纹理像素数据,以及设置其他属性。下面的代码向我们展示了如何在OPhone中创建一个纹理对象:

/**

* 创建一个纹理对象

* @param context - 应用程序环境

* @param gl - opengl es对象

* @param resID - R.java中的资源ID

* @param wrap_s_mode - 纹理环绕S模式

* @param wrap_t_mode - 纹理环绕T模式

* @return 申请好的纹理ID

*/

publicstaticintgetTexture(Context context, GL10 gl,intresID,

intwrap_s_mode,intwrap_t_mode) {

//申请一个纹理对象ID

int[] textures =newint[1];

gl.glGenTextures(1, textures,0);

//绑定这个申请来的ID为当前纹理操作对象

inttextureID = textures[0];

gl.glBindTexture(GL10.GL_TEXTURE_2D, textureID);

//设置当前纹理对象的过滤模式

gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,

GL10.GL_NEAREST);

gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,

GL10.GL_LINEAR);

//设置环绕模式

gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,

wrap_s_mode);

gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,

wrap_t_mode);

//设置混合模式

gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,

GL10.GL_REPLACE);

//开始载入纹理

InputStream is = context.getResources().openRawResource(resID);

Bitmap bitmap;

try{

bitmap = BitmapFactory.decodeStream(is);

}finally{

try{

is.close();

}catch(IOException e) {

// Ignore.

}

}

//绑定像素数据到纹理对象

GLUtils.texImage2D(GL10.GL_TEXTURE_2D,0, bitmap,0);

bitmap.recycle();

returntextureID;

}

创建好纹理对象之后,在使用时,需要首先通过调用gl.glEnable(GL10.GL_TEXTURE_2D)来通知底层开启纹理贴图操作,之后绑定相应的纹理ID到当前纹理贴图单元,同时通过调用glTexCoordPointer()来设置好相应的纹理坐标信息,最终提交渲染时,底层就会自动进行纹理映射操作。当纹理不再被使用时,可以通过调用glDeleteTextures()来将其删除。

输入事件响应

我们可以重载GLSurfaceView的onTouchEvent()方法,从而监测用户对屏幕的触摸事件。本例中,我们根据触摸位置的改变,来对模型进行绕Y轴和X轴的旋转。如果有需要,开发者还可以重载键盘按键onKeyDown()方法。值得注意的是,由于这些事件和渲染线程是分别独立的线程,因此有些操作如果需要确保在渲染线程内部执行的话,可以调用queueEvent (Runnable)来将该操作附加到渲染线程操作队列中。相关代码如下:

/**

* 响应触屏事件

*/

@Override

publicbooleanonTouchEvent(MotionEvent e) {

floatx = e.getX();

floaty = e.getY();

switch(e.getAction()) {

caseMotionEvent.ACTION_MOVE:

floatdx = x - mPreviousX;

floatdy = y - mPreviousY;

mRenderer.mfAngleY += dx * TOUCH_SCALE_FACTOR;

mRenderer.mfAngleX += dy * TOUCH_SCALE_FACTOR;

requestRender();

}

mPreviousX = x;

mPreviousY = y;

returntrue;

}

php open gl,Open GL 资料 01相关推荐

  1. GL calls GL verts FPS

    写在前面:刚接触,运行demo 看到有这些字样信息.个人理解,如有不对,请指出,因为我也不太明白(这里写下,怕自己把这样的理解都忘了). GL calls(渲染次数) GL verts(显卡绘制的顶点 ...

  2. Spring Cloud学习资料01

    SpringCloud01 1.认识微服务 随着互联网行业的发展,对服务的要求也越来越高,服务架构也从单体架构逐渐演变为现在流行的微服务架构.这些架构之间有怎样的差别呢? 1.0.学习目标 了解微服务 ...

  3. 华为培训资料01 接入网

    主要目标: 1.了解接入网 2. 接入网的常见技术 3. 光纤接入的部署结构 1. 接入网 接入网(Access Network)是指本地交换机与用户终端之间的所有机.线设备,直接面对广大的用户和应用 ...

  4. OpenGL 各类库的解析 gl/glu/glut/freeglut/glfw/glew

    看了网上很多资料,讲的都不是很全,正好在学这一块,好好地总结一下吧 注:在windows中,对这些库的大小写是不作要求的 gl.h gl库是核心库,gl中包含了最基本的3D函数,可以再本地电脑中的: ...

  5. 运行时绘制Gizmo——关于unity3D的GL图像库的使用(非常详细)

    转载来源:https://www.cnblogs.com/JLZT1223/p/6094404.html ps: 想了解一下GL库,但是都没有什么好的资料. 好不容易找到一个详细的博客,格式还全乱,阅 ...

  6. Unity流水账14:GL、Graphics及CommandBuffer

    一.GL (1).描述   底层图形库.   使用此类可以处理激活转换矩阵,发出类似于OpenGL立即模式的渲染命令以及执行其他低级图形任务.注意:在几乎所有情况下,使用Graphics.DrawMe ...

  7. gl.getAttribLocation P41 获取name参数指定的attribute变量存储地址

    参数 program 指定包含顶点着色器和片元着色器的着色器程序对象 name 指定想要获取其存储地址的attribute变量名称 var VSHADER_SOURCE= 'attribute  ve ...

  8. unity, GL.TexCoord or GL.Color must put before GL.Vertex!!!

    GL.Begin(GL.QUADS);                  //in unity, should use left hand rule         //RU         GL.T ...

  9. OpenGL 各类库的解析gl glu glut freeglut glfw glew

    gl.h gl库是核心库,gl中包含了最基本的3D函数,可以再本地电脑中的: C:\Program Files (x86)\MicrosoftSDKs\Windows\v7.0A\Include\gl ...

最新文章

  1. 虚拟机cenos 重置密码
  2. atomic与nonatomic,assign,copy与retain的定义和区别
  3. TP-Link路由器下的多种接入模式
  4. linux之trap命令
  5. Android 功耗(11)---Android 功耗分析之wakelock
  6. rk3399_android7.1调试mipi转lvds转换IC总结
  7. Spring3之InternalResourceViewResolver
  8. 使用Arduino和水流传感器进行流速和流量测量
  9. java毕业设计(论文)答辩提纲,毕业论文答辩提纲模板.doc
  10. http://t.cn/xxx的短链接如何生成?(附15款新浪短链接生成器)
  11. unity塔防游戏怪物转向_英雄塔防物语手游下载-英雄塔防物语安卓版下载v2.3.8
  12. Visual Studio 2008 测试版 2 自述文件
  13. 程序员小灰2021年整理
  14. 【RFC2818 基于 TLS 的 HTTP】(翻译)
  15. Android:上海垃圾分类必备,图像识别垃圾分类app的制作
  16. PDF转换Word如何操作?用迅读PDF转换器,任意互转
  17. Mysql 的存储过程和存储函数
  18. Lisa美语发音教程——学习笔记
  19. PC偏振控制器、锁模激光器技术、AOM声光调制器、相位噪声、锁相环、光耦合器类型
  20. 网络爬虫的 “ 黑洞 ”

热门文章

  1. 浅谈智能电网的建设 软件开发
  2. 『震惊』秘密报告披露转基因食品危害
  3. 成员函数指针与高性能的C++委托(下篇)
  4. thinkphp 模板 php函数调用,thinkphp模版调用函数方法
  5. ​Cell:粟硕/施莽团队利用宏转录组揭示“野味”动物携带和人类疾病密切相关的多种病毒...
  6. Nat Biotechnol | 杨弋团队报道RNA光遗传学工具,可时空精确操纵活细胞RNA代谢与功能...
  7. 中国农业大学营养与健康研究院诚聘博士后
  8. 感知器原理及线性分类技术实现
  9. 在Mac上唤出「快速备忘录」的开启与关闭设置教程
  10. 算法学习入门书籍 -- 2022.02.13