转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼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通过计算纹理坐标来显示一张图片相关推荐

  1. Android 开发使用OpenGL ES绘制三棱锥并进行纹理贴图

    效果图: 直接上代码 MainActivity.java的代码 package com.zzu.shiyan3;import androidx.appcompat.app.AppCompatActiv ...

  2. OpenGL ES实现三棱锥纹理贴图

    这是老师布置的课后作业,闲来无事分享出来,也加深一遍自己的印象~ 自己定义一个MyRenderer.java类: package com.example.shiyan3_2;import androi ...

  3. Android Studio OpenGL ES绘制三棱锥/四面体的多纹理贴图 每个面使用一张图片渲染

    本文参考了王刚的<疯狂Android讲义(第3版)>P554-P559 要求:利用OpenGL ES绘制一个三棱锥,并对每个面进行纹理贴图,每个面使用不同的图片进行渲染. 环境:Andro ...

  4. android OpenGL ES实现渲染到透明的纹理 render to transparent texture

    PC上OpenGL渲染到纹理,很容易得到透明背景,但是在android上OpenGL ES渲染出来是黑色背景,对于这个问题,想了两个解决办法. 1> 让android的OpenGL ES环境支持 ...

  5. OpenGL ES 3.0(五)纹理

    我们可以为每个顶点添加颜色来增加图形的细节,从而创建出有趣的图像.但是,如果想让图形看起来更真实,我们就必须有足够多的顶点,从而指定足够多的颜色.这将会产生很多额外开销,因为每个模型都会需求更多的顶点 ...

  6. 【Android OpenGL ES 开发 (四)】纹理相关(一)

    纹理贴图的原理 1.作用:可以用来渲染视频. 2.纹理坐标 生成OpenGL中的纹理对象 1.像素数据想要绘制出来需要先变成纹理 2.创建纹理放在GPU上 GLuint CreateTexture2D ...

  7. OpenGL ES (三)着色器和程序

    OpenGL ES学习系列文章: 上一篇:OpenGL ES (二)EGL介绍和使用 下一篇:OpenGL ES (二)EGL介绍和使用 着色器和程序 前言 1.创建Shader 2.加载Shader ...

  8. 笔谈OpenGL ES(三)

    昨天下午以及今天一天,公司安排了新员工培训课程,占用了自己的一些时间,但是也了解到一些新的有利于自身的东西.进公司就要进有完善公司体系和制度的公司,小公司真的是没搞头的,我体验过,反正小公司以后是不会 ...

  9. 【Android OpenGL ES 开发 (五)】纹理相关(二)

    纹理放大和缩小的过滤参数 1.使用线性插值效果最佳 2.通过修改 float maxscale = 4.0f  //放大 float  minscale = 0.5f //缩小 vertices[0] ...

  10. 【OpenGL ES】 Android OpenGL ES -- 透视投影 和 正交投影

    博客地址 : http://blog.csdn.net/shulianghan/article/details/46680803 源码下载 : http://download.csdn.net/det ...

最新文章

  1. 数据库收缩(sql2008)
  2. 在OperaMasks中使用ELite和JRuby动态语言的秘笈
  3. Spring MVC之异常处理
  4. vue 父组件与子组件之间的传值(普通传值)
  5. VS2008和VS2010水晶报表版本冲突的问题解决
  6. linux下安装配置svn独立服务器
  7. JavaScript语法详解:运算符和表达式
  8. resample函数_使用Pandas的resample函数处理时间序列数据的技巧
  9. 使用generator自动生成Mybatis映射配置文件
  10. 宜宾学院教务系统(金智教务系统)成绩爬虫
  11. 银行保险机构信息科技外包风险管理办法学习笔记
  12. Shottr 免费好用的Mac 截屏软件
  13. JZOJ5773 简单数学题
  14. Spring Cloud Alibaba Sentinel(七)受权规则 黑白名单
  15. MongoDB学习总结四(详细记录使用MongoTemplate操作MongoDB数据库)
  16. 超市仓库商品库存管理系统
  17. python终端界面分屏输出_linux命令 - screen/终端分屏命令
  18. ueditor粘贴word图片无法显示的问题
  19. html5 ios keychain,iOS10适配之Keychain读写失败
  20. 夏季来临,警惕蜱虫叮咬感染疾病——莱姆病

热门文章

  1. Spring Boot + Spring-Kafka 异步配置
  2. bootstrap-select 插件使用详解
  3. MySQL数据库索引优化实战分析
  4. CUDA实现QuickSortr排序算法(一)
  5. 机器学习_回归和分类的区别
  6. C++_CopyConstructor(副本构造器 防止指针重复释放)
  7. 分布式存储系统学习笔记(一)—什么是分布式系统(6)—2PC和Paxos协议
  8. 学生成绩管理系统V3.0链表版
  9. IEnumerable,IQueryable之前世今生
  10. NYOJ 7-街区最短路径问题(曼哈顿距离)