OpenGL ES总结(三)OpenGL通过计算纹理坐标来显示一张图片
转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/62444395
通过OpenGL来显示一张汽车图片,图片可以看做一个矩形,所以我们先来画一个矩形
OpenGL的基本形状是三角形,一个矩形可以看成由4个三角形构成,如果我们一个一个画,那需要12个顶点,36个坐标,效率不高,所以我们采用另外一种方式——顶点索引与glDrawElements配合使用。
什么是顶点索引呢?顶点索引就是给出顶点的下标而不给出具体的顶点坐标,如下声明:
private final float[] mVertexData = {0f,0f,0f,1f,1f,0f,-1f,1f,0f,-1f,-1f,0f,1f,-1f,0f
};private final short[] mIndexData = {0,1,2,0,2,3,0,3,4,0,4,1
};
我们的绘制区域是(-1,-1)到(1,1)的平面区域,mVertexData给出了5个顶点,mIndexData给出了4个三角形的【号位点,如打球时,有1号位,2号位】描述,如下图所示:
声明一个ShortBuffer ,用来存放顶点的索引数据
private ShortBuffer mIndexBuffer;mIndexBuffer= ByteBuffer.allocateDirect(mIndexData.length * 2).order(ByteOrder.nativeOrder()).asShortBuffer().put(indexData);
mIndexBuffer.position(0);
这个就是开始站好位置。
然后,使用GLES30.glDrawElements把三角形画出来
GLE30.glDrawElements(GLES30.GL_TRIANGLES,mIndexData.length,GLES30.GL_UNSIGNED_SHORT,mIndexBuffer);
接着创建一个纹理
public class CustomTexture {private static final String TAG = CustomTexture.class.getSimpleName();public static int loadTexture(Context context, int resourceId) {final int[] textureObjectIds = new int[1];GLES30.glGenTextures(1, textureObjectIds, 0);if (textureObjectIds[0] == 0) {Log.d(TAG, ">> create texture fail");return 0;}BitmapFactory.Options options = new BitmapFactory.Options();options.inScaled = false;Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options);if (bitmap == null) {Log.d(TAG, ">> load bitmap fail");GLES30.glDeleteTextures(1, textureObjectIds, 0);return 0;}GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureObjectIds[0]);GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR_MIPMAP_LINEAR);GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);GLUtils.texImage2D(GLES30.GL_TEXTURE_2D, 0, bitmap, 0);bitmap.recycle();//与target相关联的纹理图像生成一组完整的mipmapGLES30.glGenerateMipmap(GLES30.GL_TEXTURE_2D);GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, 0);return textureObjectIds[0];}
}
一张图,看清纹理坐标及OpenGL坐标
配置顶点shader(着色器)
vertex_shader.glsl
attribute vec4 aPosition;
attribute vec2 aTexCoord;
varying vec2 vTexCoord;
uniform mat4 uMatrix;
void main() {vTexCoord=aTexCoord;gl_Position = uMatrix*aPosition;
}
aTexCoord是一个二维向量,表示纹理的坐标,
varying这个变量是用来在vertex_shader和fragment_shader之间传递值用的,所以名称要相同,我们把aTexCoord赋值给vTexCoord,然后来看car_shader的配置
car_shader.glsl
precision mediump float;
varying vec2 vTexCoord;
uniform sampler2D sTexture;
void main() {gl_FragColor = texture2D(sTexture,vTexCoord);
}
在car_shader中,我们声明了一个uniform常量,类型是sampler2D,这个类型是指一个二维的纹理数据数组 ,使用texture2D来处理被插值的纹理坐标vTexCoord和纹理数据sTexture,得到的颜色值就是要显示的颜色,交给gl_FragColor
然后通过glAttachShader,link到program.
一般进程获取一个链接的着色器对象包括6个步骤
- 1、创建顶点着色器和片段着色器
- 2、将源码附加在每个着色器对象中
- 3、编译着色器对象
- 4、创建程序对象
- 5、将编译的着色器对象附加到程序对象中
- 6、链接程序对象
如果链接成功,我们就可以随时绘制。下面详细介绍执行这些进程的API
创建并编译着色器
GLuint glCreareShader(GLenum type) type :着色器类型【GL_VERTEX_SHADER,GL_FRAGMENT_SHADER】,返回对象为新着色器对象的句柄
void glDeleteShader(GLuint shader): shader 删除该着色器对象(如果一个着色器对象在删除前已经链接到程序对象中,那么当执行glDeleteShader函数时不会立即被删除,而是该着色器对象将被标记为删除,器内存被释放一次,它不再链接到其他任何程序对象)。
GLES30.glAttachShader(program, vertexShader);
checkGlError("glAttachShader");
GLES30.glAttachShader(program, pixelShader);
checkGlError("glAttachShader");
GLES30.glLinkProgram(program);
int[] linkStatus = new int[1];
GLES30.glGetProgramiv(program, GLES30.GL_LINK_STATUS, linkStatus, 0);
if (linkStatus[0] != GLES30.GL_TRUE) {Log.e(TAG, "Could not link program: ");Log.e(TAG, GLES30.glGetProgramInfoLog(program));GLES30.glDeleteProgram(program);program = 0;
}
当我要显示一张1072*768的图示,由于它不是正方形,需要重新对其计算坐标
如图,红色就是对应的纹理坐标
于是我们有
// 5个点,三角形显示区域private final float[] mVertexData = {0f, 0f, 0f,1.0f, 0.75f, 0f,-1.0f, 0.75f, 0f,-1.0f, -0.75f, 0f,1.0f, -0.75f, 0f};private final short[] mIndexData = {0, 1, 2, // 0号点,1号点,2号点组成一个三角形0, 2, 3, // 0号点,2号点,3号点组成一个三角形0, 3, 4, // 0号点,3号点,4号点组成一个三角形0, 4, 1 // 0号点, 4号点,1号点组成一个三角形};//纹理坐标private final float[] mTextureVertexData = {0.5f,0.375f,1f,0f,0f,0f,0f,0.75f,1f,0.75f};
最后在onDrawFrame中
public void onDrawFrame(GL10 gl) {GLES30.glClear(GLES30.GL_DEPTH_BUFFER_BIT | GLES30.GL_COLOR_BUFFER_BIT);GLES30.glUseProgram(mProgramId);GLES30.glUniformMatrix4fv(mMatrix, 1, false, projectionMatrix, 0);GLES30.glEnableVertexAttribArray(mPosition);GLES30.glVertexAttribPointer(mPosition, 3, GLES30.GL_FLOAT, false,12, mVertexBuffer);GLES30.glEnableVertexAttribArray(aTextureCoordHandle);GLES30.glVertexAttribPointer(aTextureCoordHandle, 2, GLES30.GL_FLOAT, false, 8, mTextureVertexBuffer);GLES30.glActiveTexture(GLES30.GL_TEXTURE0);GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureId);GLES30.glUniform1i(uTextureSamplerHandle, 0);GLES30.glDrawElements(GLES30.GL_TRIANGLES, mIndexData.length, GLES30.GL_UNSIGNED_SHORT, mIndexBuffer);}
实现效果如图:
第一时间获得博客更新提醒,以及更多android干货,源码分析,欢迎关注我的微信公众号,扫一扫下方二维码或者长按识别二维码,即可关注。
如果你觉得好,随手点赞,也是对笔者的肯定,也可以分享此公众号给你更多的人,原创不易
OpenGL ES总结(三)OpenGL通过计算纹理坐标来显示一张图片相关推荐
- Android 开发使用OpenGL ES绘制三棱锥并进行纹理贴图
效果图: 直接上代码 MainActivity.java的代码 package com.zzu.shiyan3;import androidx.appcompat.app.AppCompatActiv ...
- OpenGL ES实现三棱锥纹理贴图
这是老师布置的课后作业,闲来无事分享出来,也加深一遍自己的印象~ 自己定义一个MyRenderer.java类: package com.example.shiyan3_2;import androi ...
- Android Studio OpenGL ES绘制三棱锥/四面体的多纹理贴图 每个面使用一张图片渲染
本文参考了王刚的<疯狂Android讲义(第3版)>P554-P559 要求:利用OpenGL ES绘制一个三棱锥,并对每个面进行纹理贴图,每个面使用不同的图片进行渲染. 环境:Andro ...
- android OpenGL ES实现渲染到透明的纹理 render to transparent texture
PC上OpenGL渲染到纹理,很容易得到透明背景,但是在android上OpenGL ES渲染出来是黑色背景,对于这个问题,想了两个解决办法. 1> 让android的OpenGL ES环境支持 ...
- OpenGL ES 3.0(五)纹理
我们可以为每个顶点添加颜色来增加图形的细节,从而创建出有趣的图像.但是,如果想让图形看起来更真实,我们就必须有足够多的顶点,从而指定足够多的颜色.这将会产生很多额外开销,因为每个模型都会需求更多的顶点 ...
- 【Android OpenGL ES 开发 (四)】纹理相关(一)
纹理贴图的原理 1.作用:可以用来渲染视频. 2.纹理坐标 生成OpenGL中的纹理对象 1.像素数据想要绘制出来需要先变成纹理 2.创建纹理放在GPU上 GLuint CreateTexture2D ...
- OpenGL ES (三)着色器和程序
OpenGL ES学习系列文章: 上一篇:OpenGL ES (二)EGL介绍和使用 下一篇:OpenGL ES (二)EGL介绍和使用 着色器和程序 前言 1.创建Shader 2.加载Shader ...
- 笔谈OpenGL ES(三)
昨天下午以及今天一天,公司安排了新员工培训课程,占用了自己的一些时间,但是也了解到一些新的有利于自身的东西.进公司就要进有完善公司体系和制度的公司,小公司真的是没搞头的,我体验过,反正小公司以后是不会 ...
- 【Android OpenGL ES 开发 (五)】纹理相关(二)
纹理放大和缩小的过滤参数 1.使用线性插值效果最佳 2.通过修改 float maxscale = 4.0f //放大 float minscale = 0.5f //缩小 vertices[0] ...
- 【OpenGL ES】 Android OpenGL ES -- 透视投影 和 正交投影
博客地址 : http://blog.csdn.net/shulianghan/article/details/46680803 源码下载 : http://download.csdn.net/det ...
最新文章
- 数据库收缩(sql2008)
- 在OperaMasks中使用ELite和JRuby动态语言的秘笈
- Spring MVC之异常处理
- vue 父组件与子组件之间的传值(普通传值)
- VS2008和VS2010水晶报表版本冲突的问题解决
- linux下安装配置svn独立服务器
- JavaScript语法详解:运算符和表达式
- resample函数_使用Pandas的resample函数处理时间序列数据的技巧
- 使用generator自动生成Mybatis映射配置文件
- 宜宾学院教务系统(金智教务系统)成绩爬虫
- 银行保险机构信息科技外包风险管理办法学习笔记
- Shottr 免费好用的Mac 截屏软件
- JZOJ5773 简单数学题
- Spring Cloud Alibaba Sentinel(七)受权规则 黑白名单
- MongoDB学习总结四(详细记录使用MongoTemplate操作MongoDB数据库)
- 超市仓库商品库存管理系统
- python终端界面分屏输出_linux命令 - screen/终端分屏命令
- ueditor粘贴word图片无法显示的问题
- html5 ios keychain,iOS10适配之Keychain读写失败
- 夏季来临,警惕蜱虫叮咬感染疾病——莱姆病
热门文章
- Spring Boot + Spring-Kafka 异步配置
- bootstrap-select 插件使用详解
- MySQL数据库索引优化实战分析
- CUDA实现QuickSortr排序算法(一)
- 机器学习_回归和分类的区别
- C++_CopyConstructor(副本构造器 防止指针重复释放)
- 分布式存储系统学习笔记(一)—什么是分布式系统(6)—2PC和Paxos协议
- 学生成绩管理系统V3.0链表版
- IEnumerable,IQueryable之前世今生
- NYOJ 7-街区最短路径问题(曼哈顿距离)