效果图:

核心看 顶点 shader的实现

uniform mat4 uMVPMatrix; //总变换矩阵
attribute vec3 aPosition;  //顶点位置 来自1号关键帧
attribute vec3 bPosition;  //顶点位置 来自2号关键帧
attribute vec3 cPosition;  //顶点位置 来自3号关键帧
attribute vec2 aTexCoor;    //顶点纹理坐标
uniform float uBfb;//融合比例
varying vec2 vTextureCoord;void main()
{vec3 tv;if(uBfb<=1.0)//若融合比例小于1,则需要执行的是1,2号关键帧的融合{tv=mix(aPosition,bPosition,uBfb);//mix(x,y,z) x,y的线性混叠,x(1-a)+y*a;}else //若融合比例大于1,则需要执行的是2,3号关键帧的融合{tv=mix(bPosition,cPosition,uBfb-1.0);}gl_Position = uMVPMatrix * vec4(tv,1);vTextureCoord = aTexCoor;//将接收的纹理坐标传递给片元着色器
}
package test.com.opengles_zcfxdxy;import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import android.opengl.GLES20;
/*** Created by hbin on 2016/11/3.* //加载后的物体——仅携带顶点信息,颜色随机*/public class GledeForDraw {int mProgram;//自定义渲染管线着色器程序idint muMVPMatrixHandle;//总变换矩阵引用int maPositionHandle1; //顶点位置属性引用int maPositionHandle2; //顶点位置属性引用int maPositionHandle3; //顶点位置属性引用int maTexCoorHandle; //顶点纹理坐标属性引用int muBfbHandle;//变化百分比引用String mVertexShader;//顶点着色器代码脚本String mFragmentShader;//片元着色器代码脚本FloatBuffer   mVertexBuffer1;//顶点坐标数据缓冲FloatBuffer   mVertexBuffer2;//顶点坐标数据缓冲FloatBuffer   mVertexBuffer3;//顶点坐标数据缓冲FloatBuffer   mTexCoorBuffer;//顶点纹理坐标数据缓冲float[][] glede_one;float[] glede_two;float[] glede_three;int vCount=0;int operator=1;float span=0.15f;float bfbCurr=0f;public GledeForDraw(MySurfaceView mv){//初始化顶点坐标与着色数据initVertexData(mv);//初始化shaderintShader(mv);new Thread(){@Overridepublic void run(){while(true){bfbCurr=bfbCurr+operator*span;if(bfbCurr>2.0f){bfbCurr=2.0f;operator=-operator;}else if(bfbCurr<0){bfbCurr=0;operator=-operator;}try{Thread.sleep(50);}catch(Exception e){e.printStackTrace();}}}}.start();}//初始化顶点坐标与着色数据的方法public void initVertexData(MySurfaceView mv){glede_one=LoadUtil.loadFromFileVertexOnly("laoying01.obj",mv);glede_two=LoadUtil.loadFromFileVertexOnly("laoying02.obj",mv)[0];glede_three=LoadUtil.loadFromFileVertexOnly("laoying03.obj",mv)[0];//========================1=========================================vCount=glede_one.length/3;//创建顶点坐标数据缓冲//vertices.length*4是因为一个整数四个字节ByteBuffer vbb = ByteBuffer.allocateDirect(glede_one[0].length*4);vbb.order(ByteOrder.nativeOrder());//设置字节顺序mVertexBuffer1 = vbb.asFloatBuffer();//转换为Float型缓冲mVertexBuffer1.put(glede_one[0]);//向缓冲区中放入顶点坐标数据mVertexBuffer1.position(0);//设置缓冲区起始位置//====================2==========================vCount=glede_two.length/3;//创建顶点坐标数据缓冲//vertices.length*4是因为一个整数四个字节vbb = ByteBuffer.allocateDirect(glede_two.length*4);vbb.order(ByteOrder.nativeOrder());//设置字节顺序mVertexBuffer2 = vbb.asFloatBuffer();//转换为Float型缓冲mVertexBuffer2.put(glede_two);//向缓冲区中放入顶点坐标数据mVertexBuffer2.position(0);//设置缓冲区起始位置//---------------------------------3-----------------------------vCount=glede_three.length/3;//创建顶点坐标数据缓冲//vertices.length*4是因为一个整数四个字节vbb = ByteBuffer.allocateDirect(glede_three.length*4);vbb.order(ByteOrder.nativeOrder());//设置字节顺序mVertexBuffer3 = vbb.asFloatBuffer();//转换为Float型缓冲mVertexBuffer3.put(glede_three);//向缓冲区中放入顶点坐标数据mVertexBuffer3.position(0);//设置缓冲区起始位置//------------------纹理-----------------------------------------ByteBuffer tbb = ByteBuffer.allocateDirect(glede_one[1].length*4);tbb.order(ByteOrder.nativeOrder());//设置字节顺序mTexCoorBuffer = tbb.asFloatBuffer();//转换为Float型缓冲mTexCoorBuffer.put(glede_one[1]);//向缓冲区中放入顶点纹理坐标数据mTexCoorBuffer.position(0);//设置缓冲区起始位置//特别提示:由于不同平台字节顺序不同数据单元不是字节的一定要经过ByteBuffer//转换,关键是要通过ByteOrder设置nativeOrder(),否则有可能会出问题//顶点纹理坐标数据的初始化================end============================}//初始化shaderpublic void intShader(MySurfaceView mv){//加载顶点着色器的脚本内容mVertexShader=ShaderUtil.loadFromAssetsFile("vertex.sh", mv.getResources());//加载片元着色器的脚本内容mFragmentShader=ShaderUtil.loadFromAssetsFile("frag.sh", mv.getResources());//基于顶点着色器与片元着色器创建程序mProgram = ShaderUtil.createProgram(mVertexShader, mFragmentShader);//获取程序中顶点位置属性引用maPositionHandle1 = GLES20.glGetAttribLocation(mProgram, "aPosition");maPositionHandle2 = GLES20.glGetAttribLocation(mProgram, "bPosition");maPositionHandle3 = GLES20.glGetAttribLocation(mProgram, "cPosition");//获取程序中总变换矩阵引用muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");//获取程序中顶点纹理坐标属性引用maTexCoorHandle= GLES20.glGetAttribLocation(mProgram, "aTexCoor");//变化百分比引用muBfbHandle= GLES20.glGetUniformLocation(mProgram, "uBfb");}public void drawSelf(int texId){//制定使用某套shader程序GLES20.glUseProgram(mProgram);//将最终变换矩阵传入shader程序GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);//将变化百分比传入shader程序GLES20.glUniform1f(muBfbHandle, bfbCurr);System.out.println(bfbCurr);//将顶点位置数据GLES20.glVertexAttribPointer(maPositionHandle1,3,GLES20.GL_FLOAT,false,3*4,mVertexBuffer1);//将顶点位置数据GLES20.glVertexAttribPointer(maPositionHandle2,3,GLES20.GL_FLOAT,false,3*4,mVertexBuffer2);//将顶点位置数据传入渲染管线GLES20.glVertexAttribPointer(maPositionHandle3,3,GLES20.GL_FLOAT,false,3*4,mVertexBuffer3);//将顶点纹理坐标数据传入渲染管线GLES20.glVertexAttribPointer(maTexCoorHandle,2,GLES20.GL_FLOAT,false,2*4,mTexCoorBuffer);//启用顶点位置、法向量、纹理坐标数据GLES20.glEnableVertexAttribArray(maPositionHandle1);GLES20.glEnableVertexAttribArray(maPositionHandle2);GLES20.glEnableVertexAttribArray(maPositionHandle3);GLES20.glEnableVertexAttribArray(maTexCoorHandle);//绑定纹理GLES20.glActiveTexture(GLES20.GL_TEXTURE0);GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);//绘制加载的物体GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);}
}
package test.com.opengles_zcfxdxy;
import java.io.IOException;
import java.io.InputStream;import android.opengl.GLSurfaceView;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import android.view.MotionEvent;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
/*** Created by hbin on 2016/11/3.*/public class MySurfaceView extends GLSurfaceView{private final float TOUCH_SCALE_FACTOR = 180.0f/320;//角度缩放比例private SceneRenderer mRenderer;//场景渲染器private float mPreviousY;//上次的触控位置Y坐标private float mPreviousX;//上次的触控位置X坐标int textureId;//系统分配的纹理idpublic MySurfaceView(Context context) {super(context);this.setEGLContextClientVersion(2); //设置使用OPENGL ES2.0mRenderer = new SceneRenderer();   //创建场景渲染器setRenderer(mRenderer);                //设置渲染器setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);//设置渲染模式为主动渲染this.setKeepScreenOn(true);}//触摸事件回调方法@Overridepublic boolean onTouchEvent(MotionEvent e){float y=e.getY();float x=e.getX();switch (e.getAction()){case MotionEvent.ACTION_MOVE:float dy=y-mPreviousY;float dx=x-mPreviousX;mRenderer.yAngle+=dy*TOUCH_SCALE_FACTOR;mRenderer.zAngle+=dx*TOUCH_SCALE_FACTOR;requestRender();}mPreviousX=x;mPreviousY=y;return  true;}private class SceneRenderer implements  GLSurfaceView.Renderer{float yAngle;//绕Y轴旋转的角度float zAngle; //绕Z轴旋转的角度//从指定的obj文件中加载对象GledeForDraw glede1;@Overridepublic void onSurfaceCreated(GL10 gl, EGLConfig config) {//设置屏幕背景色RGBAGLES20.glClearColor(1.0f,1.0f,1.0f,1.0f);//打开深度检测GLES20.glEnable(GLES20.GL_DEPTH_TEST);//关闭背面剪裁GLES20.glDisable(GLES20.GL_CULL_FACE);//初始化变换矩阵MatrixState.setInitStack();glede1=new GledeForDraw(MySurfaceView.this);//创建雄鹰//加载纹理textureId=initTexture(R.mipmap.ttt);}@Overridepublic void onSurfaceChanged(GL10 gl, int width, int height) {//设置视窗大小及位置GLES20.glViewport(0, 0, width, height);//计算GLSurfaceView的宽高比float ratio = (float) width / height;//调用此方法计算产生透视投影矩阵MatrixState.setProjectFrustum(-ratio, ratio, -1, 1, 2, 100);//调用此方法产生摄像机9参数位置矩阵MatrixState.setCamera(0,0,0,0f,0f,-1f,0f,1.0f,0.0f);}@Overridepublic void onDrawFrame(GL10 gl) {//清除深度缓冲与颜色缓冲GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);//坐标系推远MatrixState.pushMatrix();MatrixState.translate(0, -5f, -40f);//绕Y轴、Z轴旋转MatrixState.rotate(yAngle, 0, 1, 0);MatrixState.rotate(zAngle, 1, 0, 0);//若加载的物体部位空则绘制物体if(glede1!=null){glede1.drawSelf(textureId);}MatrixState.popMatrix();}}public int initTexture(int drawableId)//textureId{//生成纹理IDint[] textures = new int[1];GLES20.glGenTextures(1,          //产生的纹理id的数量textures,   //纹理id的数组0           //偏移量);int textureId=textures[0];GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_NEAREST);GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_LINEAR);GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,GLES20.GL_REPEAT);GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,GLES20.GL_REPEAT);//通过输入流加载图片===============begin===================InputStream is = this.getResources().openRawResource(drawableId);Bitmap bitmapTmp;try{bitmapTmp = BitmapFactory.decodeStream(is);}finally{try{is.close();}catch(IOException e){e.printStackTrace();}}//通过输入流加载图片===============end=====================//实际加载纹理GLUtils.texImage2D(GLES20.GL_TEXTURE_2D,   //纹理类型,在OpenGL ES中必须为GL10.GL_TEXTURE_2D0,                    //纹理的层次,0表示基本图像层,可以理解为直接贴图bitmapTmp,              //纹理图像0                     //纹理边框尺寸);bitmapTmp.recycle();          //纹理加载成功后释放图片return textureId;}
}

完整代码下载地址:

http://download.csdn.net/detail/hb707934728/9672038

opengles之展翅飞翔的雄鹰相关推荐

  1. 《OpenGL ES 3.x游戏开发(下卷)》一2.4 展翅飞翔的雄鹰

    本节书摘来异步社区<OpenGL ES 3.x游戏开发(下卷)>一书中的第2章,第2.4节,作者: 吴亚峰 责编: 张涛,更多章节内容可以访问云栖社区"异步社区"公众号 ...

  2. 做一只展翅翱翔的雄鹰

    给青春一个梦想,用梦想点亮青春.--题记 湛蓝的天空,属于展翅翱翔的雄鹰. 青春是多梦的年龄. 当日历一张张地撕去,大学生活款款走向我们.告别了中学时期的放纵与自由,大学将我们领进知识的殿堂.在过去的 ...

  3. 当拓普遇上SAP,展翅翱翔的雄鹰飞向了更高的天空

    伴随着汽车工业的发展,汽配逐渐成为了生产链的核心环节. 在汽车行业高速发展与国家产业政策的大力推动下,汽配行业的规模已迅速扩大. 但是作为汽配行业的主要特点,层层分销渠道这种模式已经开始对企业的运营产 ...

  4. 积攒力量,终会展翅飞翔。Linux学习记录

    带着对linux的兴趣,我来到了兄弟连!来此学习已一月有余,也该写点东西记录一下在兄弟连的点滴. 上了这么多年学,我感觉学习的过程是枯燥的,这个问题应该是很难避免的!甚至可能在我们大家的潜意识里就觉得 ...

  5. 18款帝豪gl车机升级_好看又实用的2018款帝豪GL分享,感受它的魅力

    帝豪GL于2016年9月20日,在G20峰会主会场--杭州国际博览中心正式上市.是吉利汽车精品3.0代的第四款车型.上市至今,也有两年了,这两年里,风里来雨里去的,非常之不容易.同时,在刚刚上市的时候 ...

  6. python保留四位小数_保留四位有效数字python

    信息举报 时间:2020-11-29 本页为您甄选多篇描写保留四位有效数字python,保留四位有效数字python精选,保留四位有效数字python大全,有议论,叙事 ,想象等形式.文章字数有400 ...

  7. 《Android 3D游戏开发技术宝典——OpenGL ES 2.0》.(吴亚峰).[PDF]ckook

    图书作者: 吴亚峰 图书编号: 9787115277701 图书格式: PDF 出 版 社: 人民邮电出版社 出版年份: 2012 图书页数: 700-800 [内容简介] 随着智能手机移动嵌入式平台 ...

  8. 关于计算机老师的话,关于赞美老师的话

    导语:老师,您就是滋润我们心田的春雨,我们将永远感谢您.下面是小编给大家整理的赞美老师的话的内容,希望能给你带来帮助! 1.您是大桥,为我们连接被割断的山峦,让我们走向收获的峰巅:您是青藤,坚韧而修长 ...

  9. 计算机学院毕业生祝福6,用数学知识写给毕业生祝福语6

    用数学知识写给毕业生祝福语6篇1 1.默默地分手,正如当初默默地相遇.愿这温馨的微风,给你捎去我深情的祝福和祈祷! 2.你的天赋好比一朵火花,假如你用勤勉辛劳去助燃,它一定会变成熊熊烈火,放出无比的光 ...

最新文章

  1. JVM基础面试题及原理讲解
  2. 在eclipse里jsp编译后的java和class文件的位置
  3. 三星T5 SSD制作ubuntu18.04随身携带即插即用与win10共享文件真爽~(简单粗暴安装大法一步到位)
  4. 即时通讯音视频开发(八):常见的实时语音通讯编码标准
  5. [LeetCode] Reverse Linked List I II - 链表翻转问题
  6. 苹果CMS小俊XG013主题模板
  7. Exadata中最有用的功能-存储索引
  8. Windows 10部署与管理指南(1)之环境准备篇
  9. 2021-2027全球与中国兽医临床试验业务市场现状及未来发展趋势
  10. 数字经济时代,企业的核心竞争力究竟是什么?
  11. 微信小程序学习笔记③——wxml+wxss+js基础入门[样例+解析]
  12. Minecraft 1.12.2 彩色渐变字体0.5 RGB光束+光影效果
  13. 计算机网络体系批判,基于批判性思维的计算机网络概论课程改革.pdf
  14. shell脚本编程100例
  15. windows配置DNS
  16. 数据处理方法-算术编码(香农算法、java编码实现)
  17. SSH不能传输文件问题
  18. python 翻译模块 翻译API使用(百度、有道、谷歌)
  19. 给小仙女讲什么是javascript(一)
  20. 嵌入式系统原理与接口技术

热门文章

  1. java uuid 类型_什么是UUID,Java中怎么产生UUID?
  2. 面部表情识别3:Android实现表情识别(含源码,可实时检测)
  3. 品牌国际传播第一步:谁是最重要的人?| 直播活动预告
  4. linux内存占用过高怎么解决,centos7内存占用过高处理方法
  5. 学习代码中的英文单词
  6. 虚拟服务器设置虚拟内存,vmware虚拟机关于内存的一项设置,可以提高你的虚拟机运行效能-虚拟内存怎么设置最好...
  7. supervisor控制台运行出错,BACKOFF Exited too quickly
  8. 基于springboot+vue的戒毒所人员管理系统 毕业设计-附源码251514
  9. Cocos技术派 | 3d人物渲染详细教程
  10. Android集成GMS服务及GMS认证方案