• 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/ !!!
  • 相关阅读:
    装饰器
    目录和文件操作
    网络通信过程
    epoll并发
    laravel(包含lumen)框架中的跨域函数实例
    windows使用nginx
    nginx反向代理配置 其实很简单
    前端html页面使用marked点亮你的代码
    PHPWAMP开启SSL,PHPWAMP配置ssl证书
    php接收并存储base64位字符串图片
  • 原文地址:https://www.cnblogs.com/klcf0220/p/3111567.html
Copyright © 2020-2023  润新知