Android OpenGL教程-第六课【转】
来源:互联网 发布:沙巴克传奇有哪些端口 编辑:程序博客网 时间:2024/05/22 13:25
第六课 纹理映射:
(在转之前 一开始没有弄明白,查阅资料,看了各路大神的逻辑后整明白了,最后附上自己的心得体会 以及代码!)
在这一课里,我将教会你如何把纹理映射到立方体的六个面。
激动的时刻来了,加载图片了。
复习一下android加载图片的知识。放一个png到drawable里面。
添加一个工具类,方便我们使用。
package top.wuqianling.opengl.lesson;import android.content.res.Resources;import android.graphics.Bitmap;import android.graphics.BitmapFactory;public class DataManage { private static Bitmap mBitmap; public static void init(Resources res) { mBitmap = BitmapFactory.decodeResource(res, R.drawable.nehe); } public static Bitmap getBitmap() { return mBitmap; }}
这样我们是不是可以直接用
Bitmap mBitmap = DataManage.getBitmap();
来获得这个bitmap了,当然需要在activity里面初始化这个DataManage。
DataManage.init(this.getResources());
( 注意:先使用该语句启用纹理 gl.glEnable(GL10.GL_TEXTURE_2D); )
好了,开始把bitmap放到opengl里的纹理里面。
IntBuffer intBuffer = IntBuffer.allocate(1);gl.glGenTextures(1, intBuffer);
首先让opengl准备些纹理,这里我们准备1个。glGenTextures第二个参数要求是IntBuffer,实际上就是一个int数组的变形,allocate几个就有几个纹理。
texture = intBuffer.get();
取得opengl准备的纹理,为了后面把图片绑定到这个纹理里面
gl.glBindTexture(GL10.GL_TEXTURE_2D, texture);
开始绑定这个2D纹理
Bitmap mBitmap = DataManage.getBitmap();GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, mBitmap, 0);
这一句才重要,此纹理是一个2D纹理 ( GL_TEXTURE_2D )。参数二代表图像的详细程度,通常就由它为零去了。参数三是数据的成分数。参数四是边框的值,一般就是“0”。据说openggl_es不支持纹理边界,所以必须设置为0。
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
下面的两行告诉OpenGL在显示图像时,当它比放大得原始的纹理大 ( GL_TEXTURE_MAG_FILTER )或缩小得比原始得纹理小( GL_TEXTURE_MIN_FILTER )时OpenGL采用的滤波方式。通常这两种情况下我都采用 GL_LINEAR。这使得纹理从很远处到离屏幕很近时都平滑显示。使用 GL_LINEAR 需要CPU和显卡做更多的运算。如果您的机器很慢,您也许应该采用 GL_NEAREST 。过滤的纹理在放大的时候,看起来马赛克的很。您也可以结合这两种滤波方式。在近处时使用 GL_LINEAR ,远处时 GL_NEAREST 。
有了纹理咋样弄的立方体上去呢,这里要用到纹理坐标:
先看纹理坐标数组
// 纹理数组private float[] mTextCoordArray = { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0f, 0f, 0f, 0f, 1.0f, 0, 1.0f, 1.0f, 1.0f, 1.0f, 0f, 0f, 0f, 0f, 0f, 0f, 1.0f, 1.0f, 1.0f, 1.0f, 0f, 1.0f, 0f, 0f, 0f, 0f, 1.0f, 1.0f, 1.0f};private FloatBuffer mTextCoordBuffer;
纹理的坐标就是用了把纹理贴到面上的坐标的对应关系
纹理的坐标是
左下角 0,0
左上角 0,1
右下角 1,0
右上角 1,1
这里面弄了12个面,表示六变形的12个面都画纹理。
OnDrawFrame里面添加的代码如下
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
//设置使用纹理数组
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mQuadsBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTextCoordBuffer);
//把纹理数组指定到纹理buffer
(注:转自:http://www.cnblogs.com/wuqianling/p/6612846.html)
下面是自己在写的代码:
package xxq.com.opengldemo;import android.app.Activity;import android.os.Bundle;import android.view.Window;import android.view.WindowManager;public class Lesson extends Activity { private OpenGLView mOpenGLView; private DataManage dataManage; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //去标题栏 requestWindowFeature(Window.FEATURE_NO_TITLE); //设置全屏 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); mOpenGLView = new OpenGLView(this); dataManage = new DataManage(); dataManage.init(this.getResources()); setContentView(mOpenGLView); }}
package xxq.com.opengldemo;import android.graphics.Bitmap;import android.opengl.GLSurfaceView;import android.opengl.GLUtils;import java.nio.FloatBuffer;import java.nio.IntBuffer;import javax.microedition.khronos.egl.EGLConfig;import javax.microedition.khronos.opengles.GL10;/** * 渲染器类,实现了GLSurfaceView.Renderer接口,实现这个接口,需要实现3个方法:OnSurfaceCreated(), * OnSurfaceChanged(),OnDrawFrame()。 */public class OpenGLRenderer implements GLSurfaceView.Renderer { private float cr, cg, cb; private float rtri, rquad; // (这是附加的)设置RGB颜色的方法 public void setColor(float r, float g, float b) { cr = r; cg = g; cb = b; } /** * 三棱锥 */ private float[] mTriangleArray = { 0.0f,1.0f,0.0f, -1.0f,-1.0f,1.0f, 1.0f,-1.0f,1.0f, 0.0f,1.0f,0.0f, 1.0f,-1.0f,1.0f, 1.0f,-1.0f,-1.0f, 0.0f,1.0f,0.0f, 1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f, 0.0f,1.0f,0.0f, -1.0f,-1.0f,-1.0f, -1.0f,-1.0f,1.0f }; private FloatBuffer mTriangleBuffer; /** * 正方体定点数组 */ private float[] mQuadsArray = { // 前 1f, 1f, 1f, // 右上 -1f, 1f, 1f, // 左上 -1f, -1f, 1f, // 左下 1f, -1f, 1f,// 右下 // 右 1f, 1f, -1f, // 右上 1f, 1f, 1f, // 左上 1f, -1f, 1f, // 左下 1f, -1f, -1f,// 右下 // 后 -1f, 1f, -1f, // 右上 1f, 1f, -1f, // 左上 1f, -1f, -1f, // 左下 -1f, -1f, -1f,// 右下 // 左 -1f, 1f, 1f, // 右上 -1f, 1f, -1f, // 左上 -1f, -1f, -1f, // 左下 -1f, -1f, 1f, // 右下 // 顶 1f, 1f, -1f, // 右上 -1f, 1f, -1f, // 左上 -1f, 1f, 1f, // 左下 1f, 1f, 1f, // 右下 // 底 1f, -1f, 1f, // 右上 -1f, -1f, 1f, // 左上 -1f, -1f, -1f, // 左下 1f, -1f, -1f // 右下 }; // 从这里可以看出,我们按照逆时针的方向画图 private FloatBuffer mQuadsBuffer; // 纹理数组 private float[] mTextCoordArray = { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0f, 0f, 0f, 0f, 1.0f, 0, 1.0f, 1.0f, 1.0f, 1.0f, 0f, 0f, 0f, 0f, 0f, 0f, 1.0f, 1.0f, 1.0f, 1.0f, 0f, 1.0f, 0f, 0f, 0f, 0f, 1.0f, 1.0f, 1.0f }; private FloatBuffer mTextCoordBuffer; /** * 该方法是画图方法,类似于View类的OnDraw(),一般所有的画图操作都在这里实现。 */ @Override public void onDrawFrame(GL10 gl) { rtri+=0.2f; rquad-=0.15f; // 启动纹理坐标数据 gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); //打开纹理 gl.glEnable(GL10.GL_TEXTURE_2D); IntBuffer intBuffer = IntBuffer.allocate(1); //创建纹理 gl.glGenTextures(1, intBuffer); //纹理名称数组 int texture = intBuffer.get(); //绑定纹理 gl.glBindTexture(GL10.GL_TEXTURE_2D, texture); Bitmap mBitmap = DataManage.getBitmap(); // 生成纹理 GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, mBitmap, 0); gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST); gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST); // 清除屏幕和深度缓存。 gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); gl.glMatrixMode(GL10.GL_MODELVIEW); // 利用数组模型来画模型,要加此句(原文中没有)(没有这句画不出大三角形) gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTextCoordBuffer); /** * 三棱锥 */ // 重置当前的模型观察矩阵。 gl.glLoadIdentity(); // 沿着X轴左移1.5个单位,Y轴不动(0.0f),最后移入屏幕6.0f个单位 gl.glTranslatef(-1.5f, 0.0f, -6.0f); // 设置顶点,第一个参数是坐标的维数,这里是3维,第二个参数,表示buffer里面放的是float,第三个参数是0, // 是因为我们的坐标在数组中是紧凑的排列的,没有使用offset,最后的参数放的是存放顶点坐标的buffer gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mTriangleBuffer); gl.glRotatef(rtri, 0.0f, 1.0f, 0.0f); //绕Y轴旋转 //依次画4个面 for (int i=0; i<4; i++){ gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, i*3, 4); } /** * 正方体 */ gl.glLoadIdentity(); // 坐标向右移1.5个单位 gl.glTranslatef(1.5f, 0.0f, -6.0f); //设置使用纹理数组 gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mQuadsBuffer); gl.glRotatef(rquad, 1.0f, 0.0f, 0.0f);//绕X轴旋转 for (int i=0; i<6; i++){ gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, i*4, 4); } gl.glClearColor(cr, cg, cb, 0.0f); } /** * 在Surface发生改变的时候调用,例如从竖屏切换到横屏的时候 */ @Override public void onSurfaceChanged(GL10 gl, int width, int height) { // 设置输出屏幕大小 gl.glViewport(0, 0, width, height); float ratio = (float) width / height; gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadIdentity(); gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10); } /** * 在Surface创建的时候调用,一般在这里做一个初始化openggl的操作 */ @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { // 启用smooth shading(阴影平滑)。阴影平滑通过多边形精细的混合色彩,并对外部光进行平滑。 gl.glShadeModel(GL10.GL_SMOOTH); // 设置清除屏幕时所用的颜色,参数对应(红,绿,蓝,Alpha值)。色彩值的范围从0.0f到1.0f。0.0f代表最黑的情况,1.0f就是最亮的情况。 gl.glClearColor(0f, 0f, 0f, 0f); // 下面三行是关于depth buffer(深度缓存)的。将深度缓存设想为屏幕后面的层。深度缓存不断的对物体进入屏幕内部有多深进行跟踪。 gl.glClearDepthf(1.0f); gl.glEnable(GL10.GL_DEPTH_TEST); gl.glDepthFunc(GL10.GL_LEQUAL); // 这里告诉OpenGL我们希望进行最好的透视修正。这会十分轻微的影响性能。但使得透视图看起来好一点。 gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); mTriangleBuffer = BufferUtil.floatToBuffer(mTriangleArray); mQuadsBuffer = BufferUtil.floatToBuffer(mQuadsArray); mTextCoordBuffer = BufferUtil.floatToBuffer(mTextCoordArray); }}
- Android OpenGL教程-第六课【转】
- Android OpenGL教程-第六课
- Android OpenGL教程-第六课
- Android OpenGL 教程 第六课
- NeHe OpenGL教程 第六课 纹理映射
- OpenGL教程翻译 第六课 平移变换
- 【OpenGL】nehe教程第六课学习笔记
- Android OpenGL教程-第一课【转】
- Android OpenGL教程-第二课【转】
- Android OpenGL教程-第三课【转】
- Android OpenGL教程-第四课【转】
- Android OpenGL教程-第五课【转】
- 纹理映射:Jeff Molofee(NeHe) 的 OPENGL 教程-第六课
- 用OpenInventor实现的NeHe OpenGL教程-第六课
- 用OpenInventor实现的NeHe OpenGL教程-第六课
- ArchieOpenGL教程第六课:对OpenGL进行设置
- 用OpenInventor实现的NeHe OpenGL教程-第六课
- 用OpenSceneGraph实现的NeHe OpenGL教程 - 第六课
- js学习
- dataguard日常操作
- mysql命令大全(速成版)
- DNX SDK版本 “dnx-clr-win-x86.1.0.0-beta5”无法安装
- 欢迎使用CSDN-markdown编辑器
- Android OpenGL教程-第六课【转】
- clearfix清除浮动的几种方法
- Go错误处理
- Java学习11:ArrayList常见题型
- 好久不用代码实现自定义UItableViewCell
- tst、cmp、bne、beq指令
- 1041. 考试座位号(15)——C语言
- Vue学习小结-1
- CentOS 6.X系统安装