Android OpenGL ES 应用(二) 纹理
上一篇讲了基础入门 OpenGL (一) ,这一次主要学习OpenGL 纹理基本学习总结
要是做复杂的OpenGL应用程序,一定会用到纹理技术。纹理说白了就是把图片或者视频图像绘制到OpenGL空间中。
因此纹理也有坐标系,称ST坐标。或者UV
上面是纹理坐标空间。但没有固定的方向
以下演示载入一张image作为纹理贴图。
public class TextureUtils {
public static int createTexture(InputStream ins) {
int[] textures = new int[1];
GLES20.glGenTextures(1, textures, 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_CLAMP_TO_EDGE);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,GLES20.GL_CLAMP_TO_EDGE);
//上面是纹理贴图的取样方式,包含拉伸方式,取临近值和线性值
Bitmap bitmap = BitmapFactory.decodeStream(ins);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);//让图片和纹理关联起来。载入到OpenGl空间中
Log.d("OPENGL","bitmap:" + bitmap);
bitmap.recycle();//不须要。能够释放
return textureId;
}
}
public class MyRenderer implements Renderer {
public static float[] projMatrix = new float[16];// 投影
public static float[] viewMatrix = new float[16];// 相机
public static float[] mViewPjMatrix;// 总变换矩阵
public static float[] matrixs = new float[16];
public static int textureId = -1;
Context context;
MyDrawModel drawModel;
public MyRenderer(Context context) {
this.context = context;
}
@Override
public void onDrawFrame(GL10 arg0) {
GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
Log.e("", "textureId:" + textureId);
drawModel.drawFrame(textureId);
}
@Override
public void onSurfaceChanged(GL10 arg0, int w, int h) {
GLES20.glViewport(0, 0, w, h);
float ratio = (float) w / h;
Matrix.frustumM(projMatrix, 0, -ratio, ratio, -1, 1, 1, 10);//投影矩阵设置
Matrix.setLookAtM(viewMatrix, 0, 0, 0, 3, 0, 0, 0, 0.0f, 1.0f, 0.0f);//摄像机坐标设置
}
@Override
public void onSurfaceCreated(GL10 g, EGLConfig eglConfig) {
GLES20.glClearColor(0.5f,0.5f,0.5f, 1.0f);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
InputStream ins = null;
drawModel = new MyDrawModel();
drawModel.init();
try {
ins = context.getAssets().open("house.jpg");
textureId = TextureUtils.createTexture(ins);
Log.e("", "textureId:" + textureId);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
ins.close();
} catch (IOException e) {
e.printStackTrace();
}
}
GLES20.glDisable(GLES20.GL_CULL_FACE);
}
}
public class MyDrawModel {
private int programId;
private int mVPMatrixHandle; // 总变换矩阵引用id
private int positionHandle; // 顶点位置id
private int texCoorHandle; // 顶点纹理坐标id
private FloatBuffer vertexBuffer;
private FloatBuffer texCoorBuffer;
public MyDrawModel() {
}
public void init() {
initData();
int vertexsharder = GLHelper.compileScript(GLES20.GL_VERTEX_SHADER,
GLScript.vertex2);
int fragmentsharder = GLHelper.compileScript(GLES20.GL_FRAGMENT_SHADER,
GLScript.fragment2);
programId = GLHelper.linkAttach(vertexsharder, fragmentsharder);
boolean isOK = GLHelper.checkProgram(programId);
positionHandle = GLES20.glGetAttribLocation(programId, "aPosition");
texCoorHandle = GLES20.glGetAttribLocation(programId, "aTexCoor");
mVPMatrixHandle = GLES20.glGetUniformLocation(programId, "uMVPMatrix");
Log.d("OPENGL", "positionHandle:" + positionHandle + ";texCoorHandle:"
+ texCoorHandle + ";mVPMatrixHandle:" + mVPMatrixHandle + ";"
+ isOK);
}
private void initData() {
//X,Y,Z,绘画的顶点
float vertices[] = new float[] {
0, 0, 0,
-1.8f, -1f, 0,
1.8f, -1f, 0,
1.8f, 1f, 0,
-1.8f, 1f, 0,
-1.8f, -1f, 0
};
ByteBuffer vb = ByteBuffer.allocateDirect(vertices.length * 4);
vb.order(ByteOrder.nativeOrder());
vertexBuffer = vb.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
//纹理空间坐标 S,T
float texCoor[] = new float[] {
0.5f, 0.5f,
0f, 1f,
1f, 1f,
1f, 0f,
0f, 0f,
0f, 1f
};
ByteBuffer cb = ByteBuffer.allocateDirect(texCoor.length * 4);
cb.order(ByteOrder.nativeOrder());
texCoorBuffer = cb.asFloatBuffer();
texCoorBuffer.put(texCoor);
texCoorBuffer.position(0);
}
public void drawFrame(int textureId) {
GLES20.glUseProgram(programId);
// // 初始化矩阵
Matrix.setRotateM(MyRenderer.matrixs, 0, 0, 1, 0, 0);
Matrix.translateM(MyRenderer.matrixs, 0, 0, 0, 1);
//矩阵转换 ,投影矩阵,摄像机矩阵。模型矩阵
MyRenderer.mViewPjMatrix = new float[16];
Matrix.multiplyMM(MyRenderer.mViewPjMatrix, 0, MyRenderer.viewMatrix,0, MyRenderer.matrixs, 0);
Matrix.multiplyMM(MyRenderer.mViewPjMatrix, 0, MyRenderer.projMatrix,0, MyRenderer.mViewPjMatrix, 0);
GLES20.glUniformMatrix4fv(mVPMatrixHandle, 1, false, MyRenderer.mViewPjMatrix, 0);
GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 3 * 4, vertexBuffer);
GLES20.glVertexAttribPointer(texCoorHandle, 2, GLES20.GL_FLOAT, false, 2 * 4, texCoorBuffer);
GLES20.glEnableVertexAttribArray(positionHandle);
GLES20.glEnableVertexAttribArray(texCoorHandle);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, 6);//六个定点,绘制三角形
}
}
OpenGL须要把设备的坐标归一化到[-1,-1]空间中。所以这里涉及到矩阵相乘的理论,包含世界坐标,物体坐标,摄像机坐标的转换。以后会具体介绍。
public class GLScript {
public GLScript() {
}
public static final String vertex1 = "attribute vec4 mPosition;\n" +
"void main()\n" +
"{\n" +
"gl_Position=mPosition;\n " +
"}\n";
public static final String fragment1 = "precision mediump float;\n" +
"uniform vec4 mColor;\n" +
"void main(){ gl_FragColor=mColor;\n}";
public static final String vertex2 = "uniform mat4 uMVPMatrix;\n"
+ "attribute vec3 aPosition;\n"
+ "attribute vec2 aTexCoor;\n"
+ "varying vec2 vTextureCoord;\n"
+ "void main() { \n"
+ "gl_Position = uMVPMatrix * vec4(aPosition,1);\n"
+ "vTextureCoord = aTexCoor;\n"
+ "}\n"
;
public static final String fragment2 = "precision mediump float;\n"
+ "varying vec2 vTextureCoord;\n"
+ "uniform sampler2D sTexture;\n"
+ "void main() { \n"
+ "vec2 coord = vTextureCoord;\n"
+ "coord.s = coord.s * 0.5;\n" //事实上是去图像的一半,向量缩小了
+ "gl_FragColor = texture2D(sTexture, coord); \n"
+ "}\n"
;
}
coord.s = coord.s * 0.5;
这样是取纹理图像的一半,显示到界面上也就是图片的前半部分内容
其他的工具类和上一篇文章一样。
内容显示
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYmlyZHNhY3Rpb24=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
原图:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYmlyZHNhY3Rpb24=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
Android OpenGL ES 应用(二) 纹理的更多相关文章
- Android OpenGL ES 3.0 纹理应用
本文主要演示OpenGL ES 3.0 纹理演示.接口大部分和2.0没什么区别,脚本稍微有了点变化而已. 扩展GLSurfaceView package com.example.gles300; im ...
- Android OpenGL ES(七)----理解纹理与纹理过滤
1.理解纹理 OpenGL中的纹理能够用来表示图像.照片,甚至由一个数学算法生成的分形数据.每一个二维的纹理都由很多小的纹理元素组成.它们是小块的数据,类似于我们前面讨论过的片段和像素.要使用纹理,最 ...
- Android OpenGL ES(二)OpenGL ES管道(Pipeline) .
大部分图形系统都可以比作工厂中的装配线(Assemble line)或者称为管道(Pipeline).前一道的输出作为下道工序的输入.主CPU发出一个绘图指令,然后可能由硬件部件完成坐标变换,裁剪,添 ...
- Android OpenGL ES(七)基本几何图形定义 .
在前面Android OpenGL ES(六):创建实例应用OpenGLDemos程序框架 我们创建了示例程序的基本框架,并提供了一个“Hello World”示例,将屏幕显示为红色. 本例介绍Ope ...
- Android OpenGL ES(十二):三维坐标系及坐标变换初步 .
OpenGL ES图形库最终的结果是在二维平面上显示3D物体(常称作模型Model)这是因为目前的打部分显示器还只能显示二维图形.但我们在构造3D模型时必须要有空间现象能力,所有对模型的描述还是使用三 ...
- Android OpenGL ES 开发教程 从入门到精通
感谢,摘自:http://blog.csdn.net/mapdigit/article/details/7526556 Android OpenGL ES 简明开发教程 Android OpenGL ...
- Android OpenGL ES(十三)通用的矩阵变换指令 .
Android OpenGL ES 对于不同坐标系下坐标变换,大都使用矩阵运算的方法来定义和实现的.这里介绍对应指定的坐标系(比如viewmodel, projection或是viewport) An ...
- Android OpenGL ES(一)OpenGL ES介绍
在学习Android OpenGL ES开发之前,你必须具备Java 语言开发经验和一些Android开发的基本知识,但并不需要有图形开发的经验,本教程也会涉及到一些基本的线性几何知识,如矢量,矩阵运 ...
- [工作记录] Android OpenGL ES: non-square texture - continue
previous: [工作记录] Android OpenGL ES 2.0: square texture not supported on some device recently I found ...
随机推荐
- nest expression & Pyparsing
http://pyparsing.wikispaces.com/ http://bbs.csdn.net/topics/330052586 C++ boost "<([^<> ...
- 将258.369 double值转为内存表示(科学计数法)
前言 庖丁解牛 - <<庄子>> 庖丁为文惠君解牛,手之所触, 肩之所倚, 足之所履, 膝之所踦, 砉然向然, 奏刀騞然, 莫不中音, 合于<桑林>之舞, 乃中&l ...
- Cloudera Hadoop 4 实战课程(Hadoop 2.0、集群界面化管理、电商在线查询+日志离线分析)
课程大纲及内容简介: 每节课约35分钟,共不下40讲 第一章(11讲) ·分布式和传统单机模式 ·Hadoop背景和工作原理 ·Mapreduce工作原理剖析 ·第二代MR--YARN原理剖析 ·Cl ...
- Hadoop应用开发实战(flume应用开发、搜索引擎算法、Pipes、集群、PageRank算法)
Hadoop是2013年最热门的技术之一,通过北风网robby老师<深入浅出Hadoop实战开发>.<Hadoop应用开发实战>两套课程的学习,普通Java开发人员可以在最快的 ...
- MFC拆分窗口及它们之间的数据交换
源代码:http://download.csdn.net/detail/nuptboyzhb/4221531 CSplitterWnd类 CSplitterWnd类提供一个分隔器窗口的功能,分隔器窗口 ...
- 动静结合学内核:linux idle进程和init进程浅析
刘柳 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 + titer1@qq.com 退休的贵族进程 ...
- asp.net笔试题
1. 简述 private. protected. public. internal 修饰符的访问权限. 答 . private : 私有成员, 在类的内部才可以访问. protected : 保护成 ...
- Python 学习入门(21)—— 线程
本文介绍了Python对于线程的支持,包括“学会”多线程编程需要掌握的基础以及Python两个线程标准库的完整介绍及使用示例. 1. 线程基础 1.1. 线程状态 线程有5种状态,状态转换的过程如下图 ...
- Oracle Autonomous Transactions(自治事务)
Oracle Autonomous Transactions Autonomous transactions allow you to leave the context of the calling ...
- [置顶] MyEclipse显示中文界面,在线安装教程
准备工作 1,装好MyEclipse软件 2,可以上网 3,在线安装地址:http://download.eclipse.org/technology/babel/update-site/R0.11. ...