zoukankan      html  css  js  c++  java
  • Android OpenGL(2)

    OpenGL 3D 效果

    这一次主要说说3D效果吧,主要是纹理映射、光照和事件、混合颜色。

    通过上一次的介绍,3D空间创建对象的方法应该没问题啦。但是只有一些基本的集合体和一些颜色组成,大家看起来肯定不爽吧,所以我们可以将纹理映射到立方体上去,可以加上光照效果,也可以在纹理的基础上加上混合,使它看起来具有透明的效果。期待吧。。

    首先来看看MainActivity,

    /*MainActivity.java*/
    public class MainActivity extends Activity {
        DRender drender = new DRender();    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);        
            GLImage.load(this.getResources());        
            GLSurfaceView glView = new GLSurfaceView(this);//GLSurfaceView
            glView.setRenderer(drender);      //serRender  
            setContentView(glView);
        }
        //光照效果的处理事件
        public boolean onKeyUp(int keyCode, KeyEvent event)
        {
            drender.onKeyUp(keyCode, event);
            return true;
        }
        public boolean onKeyDown(int keyCode, KeyEvent event)
        {
            drender.onKeyDown(keyCode, event);
            return super.onKeyDown(keyCode, event);
        }
    }
    class GLImage
    {
        public static Bitmap mBitmap;
        public static void load(Resources resources)
        {
            mBitmap = BitmapFactory.decodeResource(resources, R.drawable.img);//在drawable里放一张图片img
        }
    }

    根据上一次的介绍,同样的我们需要构建一个自己的GLRender类,GLRender中也必须要实现下面的3个抽象方法:

    public void onDrawFrame(GL10 gl){}
    public void onSurfaceChanged(GL10 gl, int width, int height){}
    public void onSurfaceCreated(GL10 gl, EGLConfig config){}

    首先来讲讲纹理映射吧:
    为立方体的每一个面都贴上一张图,要创建一个纹理,并使用图片来生成纹理。代码如下:
            IntBuffer textureBuffer = IntBuffer.allocate(1);
            // 创建纹理
            gl.glGenTextures(1, textureBuffer);
            texture = textureBuffer.get();
        //绑定要使用的纹理
        gl.glBindTexture(GL10.GL_TEXTURE_2D, texture);
        //生成纹理
        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GLImage.mBitmap, 0);
        //线性滤波
        gl.glTexParameterx(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_LINEAR);
        gl.glTexParameterx(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_LINEAR);
        //开启or关闭纹理
        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
        gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    然后就是对立方体的每一个面设置纹理数据(见后面详细代码),设置好后通过
    gl.glTexCoordPointer(2, GL10.GL_FIXED, 0, texCoords); 将纹理映射到要绘制的物体上。
    最后,和绘制多边形一样将其绘制到屏幕上即可。
        //绘制四边形
        gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, 24,  GL10.GL_UNSIGNED_BYTE, indices);

    为了使效果更加美观,逼真,我就再加上了光照的效果。
    步骤如下:
        //定义环境光(r,g,b,a)
        FloatBuffer lightAmbient = FloatBuffer.wrap(new float[]{0.5f,0.5f,0.5f,1.0f});
        //定义漫射光
        FloatBuffer lightDiffuse = FloatBuffer.wrap(new float[]{1.0f,1.0f,1.0f,1.0f});
        //光源的位置
        FloatBuffer lightPosition = FloatBuffer.wrap(new float[]{0.0f,0.0f,2.0f,1.0f});
            //设置环境光
            gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_AMBIENT, lightAmbient);
            //设置漫射光
            gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_DIFFUSE, lightDiffuse);
    GL_AMBIENT为环境光,GL_DIFFUSE为漫射光,第三个参数为光源数组。
            //设置光源的位置
            gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_POSITION, lightPosition); 
    设置光源的位置,只需把第二个参数改为POSITION,然后第三个参数改为光源数组lightPosition。
            //启用一号光源
            gl.glEnable(GL10.GL_LIGHT1);
    不开启的话会看不到任何光源,所以一定要记得启用光源。当然,当不需要用光源的时候,也可以用关闭掉。
            //关闭一号光源
            gl.glDisable(GL10.GL_LIGHT1);
    至于按键事件的处理,可以详细参照后面的详细代码分析,也可以在后面的代码下载链接中下载你所需要的代码。此处将不详细展开。

    透明效果也是许多人喜欢的,下面就在纹理的基础上加上混合,使具有透明的效果。
    前面都是用GL_RGB来制定颜色的3个分量,其实还有一个分量,那就是alpha,这个分量可以指定透明度。
    当alpha为0.0时是完全透明的,1.0是完全不透明的。
    首先,在onSurfaceCreated方法中加入设置光线的代码:
        //设置光线,,1.0f为全光线,a=50%
        gl.glColor4f(1.0f,1.0f,1.0f,0.5f);   
        // 基于源象素alpha通道值的半透明混合函数
        gl.glBlendFunc(GL10.GL_SRC_ALPHA,GL10.GL_ONE);
    然后在程序中控制是否开启混合:
            //混合开关
            if (key)
            {
                    gl.glEnable(GL10.GL_BLEND);        // 打开混合
                    gl.glDisable(GL10.GL_DEPTH_TEST);    // 关闭深度测试
            }
            else
            {
                    gl.glDisable(GL10.GL_BLEND);        // 关闭混合
                    gl.glEnable(GL10.GL_DEPTH_TEST);    // 打开深度测试
            }

    详细代码如下:(代码需要相应的修改,不想修改的可以去下载链接中去下载代码,嘿嘿,但是代码是没有错的哈。)

    public class DRender implements Renderer
    {
        float xrot, yrot, zrot=-5.0f;
        float xspeed, yspeed;//旋转的速度
        float step = 0.4f;
        boolean key = true , light = true;;
        int one = 0x10000;
        
        //定义环境光(r,g,b,a)
        FloatBuffer lightAmbient = FloatBuffer.wrap(new float[]{0.5f,0.5f,0.5f,1.0f}); 
        //定义漫射光
        FloatBuffer lightDiffuse = FloatBuffer.wrap(new float[]{1.0f,1.0f,1.0f,1.0f});
        //光源的位置
        FloatBuffer lightPosition = FloatBuffer.wrap(new float[]{0.0f,0.0f,2.0f,1.0f}); 
        
        //过滤的类型
        int filter = 1;
        //纹理效果
        int [] texture;
        
        IntBuffer vertices = IntBuffer.wrap(new int[]{
                -one,-one,one,
                one,-one,one,
                one,one,one,
                -one,one,one,
                
                -one,-one,-one,
                -one,one,-one,
                one,one,-one,
                one,-one,-one,
                
                -one,one,-one,
                -one,one,one,
                one,one,one,
                one,one,-one,
                
                -one,-one,-one,
                one,-one,-one,
                one,-one,one,
                -one,-one,one,
                
                one,-one,-one,
                one,one,-one,
                one,one,one,
                one,-one,one,
                
                -one,-one,-one,
                -one,-one,one,
                -one,one,one,
                -one,one,-one,
                
        });
        IntBuffer normals = IntBuffer.wrap(new int[]{
            0,0,one,
            0,0,one,
            0,0,one,
            0,0,one,
            
            0,0,one,
            0,0,one,
            0,0,one,
            0,0,one,
            
            0,one,0,
            0,one,0,
            0,one,0,
            0,one,0,
            
            0,-one,0,
            0,-one,0,
            0,-one,0,
            0,-one,0,
            
            one,0,0,
            one,0,0,
            one,0,0,
            one,0,0,
            
            -one,0,0,
            -one,0,0,
            -one,0,0,
            -one,0,0,
        });
        IntBuffer texCoords = IntBuffer.wrap(new int[]{
            one,0,0,0,0,one,one,one,    
            0,0,0,one,one,one,one,0,
            one,one,one,0,0,0,0,one,
            0,one,one,one,one,0,0,0,
            0,0,0,one,one,one,one,0,
            one,0,0,0,0,one,one,one,
        });
        
        ByteBuffer indices = ByteBuffer.wrap(new byte[]{
                0,1,3,2,
                4,5,7,6,
                8,9,11,10,
                12,13,15,14,
                16,17,19,18,
                20,21,23,22,
        });
        @Override
        public void onDrawFrame(GL10 gl)
        {
            // 清除屏幕和深度缓存
            gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
            gl.glMatrixMode(GL10.GL_MODELVIEW);
            // 重置当前的模型观察矩阵
            gl.glLoadIdentity();
            //如果不启用GL_LIGHTING光就什么都看不见
            gl.glEnable(GL10.GL_LIGHTING);
            gl.glTranslatef(0.0f, 0.0f, zrot);
            
            //设置3个方向的旋转
            gl.glRotatef(xrot, 1.0f, 0.0f, 0.0f);
            gl.glRotatef(yrot, 0.0f, 1.0f, 0.0f);
            gl.glRotatef(zrot, 0.0f, 0.0f, 1.0f);
            // 绑定纹理
            gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[filter]);
            
            gl.glNormalPointer(GL10.GL_FIXED, 0, normals);
            gl.glVertexPointer(3, GL10.GL_FIXED, 0, vertices);
            gl.glTexCoordPointer(2, GL10.GL_FIXED, 0, texCoords);
            
            gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
            gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
            gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
            
            //纹理和四边形对应的顶点
            gl.glVertexPointer(3, GL10.GL_FIXED, 0, vertices);
            gl.glTexCoordPointer(2, GL10.GL_FIXED, 0, texCoords);
    
            //绘制四边形
            gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, 24,  GL10.GL_UNSIGNED_BYTE, indices);
    
            gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
            gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
            gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
            
            //旋转角度
            if ( key )
            {
                xrot+=xspeed; 
                yrot+=yspeed; 
            } 
            // 判断是否开始光源
            if (!light)                
            {
                gl.glDisable(GL10.GL_LIGHT1);        // 禁用一号光源
            }
            else                    // 否则
            {
                gl.glEnable(GL10.GL_LIGHT1);        // 启用一号光源
            }
            
            //混合开关
            if (key)
            {
                gl.glEnable(GL10.GL_BLEND);        // 打开混合
                gl.glDisable(GL10.GL_DEPTH_TEST);    // 关闭深度测试
            }
            else 
            {
                gl.glDisable(GL10.GL_BLEND);        // 关闭混合
                gl.glEnable(GL10.GL_DEPTH_TEST);    // 打开深度测试
            }
        }
    
        @Override
        public void onSurfaceChanged(GL10 gl, int width, int height)
        {
            float ratio = (float) width / height;
            //设置OpenGL场景的大小
            gl.glViewport(0, 0, width, height);
            //设置投影矩阵
            gl.glMatrixMode(GL10.GL_PROJECTION);
            //重置投影矩阵
            gl.glLoadIdentity();
            // 设置视口的大小
            gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
            // 选择模型观察矩阵
            gl.glMatrixMode(GL10.GL_MODELVIEW);    
            // 重置模型观察矩阵
            gl.glLoadIdentity();        
        }
    
        @Override
        public void onSurfaceCreated(GL10 gl, EGLConfig config)
        {
            // 黑色背景
            gl.glClearColor(0, 0, 0, 0);
            gl.glDisable(GL10.GL_DITHER);
            // 告诉系统对透视进行修正
            gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
            gl.glEnable(GL10.GL_CULL_FACE);
            // 启用阴影平滑
            gl.glShadeModel(GL10.GL_SMOOTH);
            // 启用深度测试
            gl.glEnable(GL10.GL_DEPTH_TEST);
            //设置光线,,1.0f为全光线,a=50%
            gl.glColor4f(1.0f,1.0f,1.0f,0.5f);    
            // 基于源象素alpha通道值的半透明混合函数
            gl.glBlendFunc(GL10.GL_SRC_ALPHA,GL10.GL_ONE);
            
            IntBuffer textureBuffer = IntBuffer.allocate(3);
            // 创建纹理
            gl.glGenTextures(3, textureBuffer);
            texture = textureBuffer.array();
            // 创建 Nearest 滤波贴图
            gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[0]);
            gl.glTexParameterx(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_NEAREST); // ( NEW )
            gl.glTexParameterx(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_NEAREST); // ( NEW )
            GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GLImage.mBitmap, 0);
            
            // 创建线性滤波纹理
             gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[1]);
            gl.glTexParameterx(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_LINEAR); // ( NEW )
            gl.glTexParameterx(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_LINEAR); // ( NEW )
            GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GLImage.mBitmap, 0);
            
            gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[2]);
            gl.glTexParameterx(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_NEAREST); // ( NEW )
            gl.glTexParameterx(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_LINEAR); // ( NEW )
            GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GLImage.mBitmap, 0);
            
            //深度测试相关
            gl.glClearDepthf(1.0f);
            gl.glDepthFunc(GL10.GL_LEQUAL);
            gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
            gl.glEnable(GL10.GL_TEXTURE_2D);
            
            //启用纹理映射
            gl.glClearDepthf(1.0f);
            //深度测试的类型
            gl.glDepthFunc(GL10.GL_LEQUAL);
            //精细的透视修正
            gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
            //允许2D贴图,纹理
            gl.glEnable(GL10.GL_TEXTURE_2D);
            
            //设置环境光
            gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_AMBIENT, lightAmbient);
            //设置漫射光
            gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_DIFFUSE, lightDiffuse);
            //设置光源的位置
            gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_POSITION, lightPosition);  
            //启用一号光源
            gl.glEnable(GL10.GL_LIGHT1);
            //开启混合
            gl.glEnable(GL10.GL_BLEND);
        }
        
        public boolean onKeyDown(int keyCode, KeyEvent event)
        {
            switch ( keyCode )
            {
                case KeyEvent.KEYCODE_DPAD_UP:
                    key = true;
                    xspeed=-step;
                    break;
                case KeyEvent.KEYCODE_DPAD_DOWN:
                    key = true;
                    xspeed=step;
                    break;
                case KeyEvent.KEYCODE_DPAD_LEFT:
                    key = true;
                    yspeed=-step;
                    break;
                case KeyEvent.KEYCODE_DPAD_RIGHT:
                    key = true;
                    yspeed=step;
                    break;
                case KeyEvent.KEYCODE_DPAD_CENTER:
                        light = !light;
                    break;
            }
            return false;
        }
        
        public boolean onKeyUp(int keyCode, KeyEvent event)
        {
            key = !key;
            return false;
        }
    }

    额。。就先写那么多吧。。还有一些更好的效果过几天才能够出来了。。

    因为。。明后天是周末啦。。嘿嘿,你们懂的哈。。

    代码下载链接:http://download.csdn.net/detail/klcf0220/5489181

    http://www.apkbus.com/android-121456-1-1.html

    喜欢开源,乐意分享的大神们,欢迎加入QQ群:176507146,你值的拥有哦!

    作者:快乐出发0220 ;Android群:151319601 ; Linux群:96394158 ;转载请注明出处 http://klcf0220.cnblogs.com/ !!!
  • 相关阅读:
    Data Base mysql备份与恢复
    java 乱码问题解决方案
    【知识强化】第二章 物理层 2.1 通信基础
    【知识强化】第二章 进程管理 2.2 处理机调度
    【知识强化】第二章 进程管理 2.1 进程与线程
    【知识强化】第一章 操作系统概述 1.3 操作系统的运行环境
    【知识强化】第一章 网络体系结构 1.1 数据结构的基本概念
    【知识强化】第一章 网络体系结构 1.2 计算机网络体系结构与参考模型
    【知识强化】第一章 网络体系结构 1.1 计算机网络概述
    【知识强化】第一章 操作系统概述 1.1 操作系统的基本概念
  • 原文地址:https://www.cnblogs.com/klcf0220/p/3111567.html
Copyright © 2011-2022 走看看