OpenGL纹理映射和光照效果

 在前面我们已经可以绘制出一个带有颜色的立方体了,但是这些颜色是系统自带的黄色,绿色等,有时候这并不能满足我们的要求,这时候就需要将纹理映射到立方体上去了。

      为使用纹理,我们需要打开OpenGL的一些开关以启动我们需要的一些功能:

     gl.glEnable(GL10.GL_TEXTURE_2D);

     这个调用是必不可缺的;如果你没有打开此功能,那么你就无法将图像映射到多边形上。它可以在需要时打开和关闭,通常在初始化时打开。   

生成纹理

OpenGL 中的纹理通过一个唯一号引用,通过函数 glBindTexture() 实现。你 可以自己指定这个唯一号,或者通过调用 glGenTextures () 函数生成一个唯一 号。

[html]  view plain copy
  1. // 2.生成纹理ID    
  2.        int[] tmp_tex = new int[1];//尽管只有一个纹理,但使用一个元素的数组    
  3.        //glGenTextures(申请个数,存放数组,偏移值)    
  4.        gl.glGenTextures(1, tmp_tex, 0); //向系统申请可用的,用于标示纹理的ID    
  5.        int texture = tmp_tex[0];    

纹理绑定

在为纹理生成名称后,在为纹理提供图像数据之前,我们必须绑定纹理。绑定使得指定纹理处于活动状态。一次只能激活一个纹理。活动的或“被绑定”的纹理是绘制多边形时使用的纹理,也是新纹理数据将加载其上纹理,所以在提供图像数据前必须绑定纹理。

 gl.glBindTexture(GL10.GL_TEXTURE_2D, texture);

绑定纹理数据,传入指定图片
   GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0);   

下面看一下完整代码:

 

[html]  view plain copy
  1. import java.nio.ByteBuffer;  
  2. import java.nio.ByteOrder;  
  3. import java.nio.FloatBuffer;  
  4.   
  5. import javax.microedition.khronos.egl.EGLConfig;  
  6. import javax.microedition.khronos.opengles.GL10;  
  7.   
  8. import android.content.Context;  
  9. import android.graphics.Bitmap;  
  10. import android.graphics.BitmapFactory;  
  11. import android.opengl.GLSurfaceView.Renderer;  
  12. import android.opengl.GLU;  
  13. import android.opengl.GLUtils;  
  14.   
  15. public class CubeRenderer implements Renderer {    
  16.       
  17.     Bitmap bmp;       
  18.     float box[] = new float[] {    
  19.             // FRONT    
  20.             -0.5f, -0.5f,  0.5f,    
  21.              0.5f, -0.5f,  0.5f,    
  22.             -0.5f,  0.5f,  0.5f,    
  23.              0.5f,  0.5f,  0.5f,    
  24.             // BACK    
  25.             -0.5f, -0.5f, -0.5f,    
  26.             -0.5f,  0.5f, -0.5f,    
  27.              0.5f, -0.5f, -0.5f,    
  28.              0.5f,  0.5f, -0.5f,    
  29.             // LEFT    
  30.             -0.5f, -0.5f,  0.5f,    
  31.             -0.5f,  0.5f,  0.5f,    
  32.             -0.5f, -0.5f, -0.5f,    
  33.             -0.5f,  0.5f, -0.5f,    
  34.             // RIGHT    
  35.              0.5f, -0.5f, -0.5f,    
  36.              0.5f,  0.5f, -0.5f,    
  37.              0.5f, -0.5f,  0.5f,    
  38.              0.5f,  0.5f,  0.5f,    
  39.             // TOP    
  40.             -0.5f,  0.5f,  0.5f,    
  41.              0.5f,  0.5f,  0.5f,    
  42.              -0.5f,  0.5f, -0.5f,    
  43.              0.5f,  0.5f, -0.5f,    
  44.             // BOTTOM    
  45.             -0.5f, -0.5f,  0.5f,    
  46.             -0.5f, -0.5f, -0.5f,    
  47.              0.5f, -0.5f,  0.5f,    
  48.              0.5f, -0.5f, -0.5f,    
  49.         };    
  50.         
  51.     float lightAmbient[] = new float[] { 0.5f, 0.5f, 0.6f, 1.0f };  //环境光    
  52.     float lightDiffuse[] = new float[] { 0.6f, 0.6f, 0.6f, 1.0f };//漫反射光    
  53.     float[] lightPos = new float[] {0,0,3,1};  //光源位置    
  54. /*   
  55.  * 因为进行光照处理,你必须告知系统你定义的模型各个面的方向,以便系统计算光影情况,方向的描述是通过向量点来描述的   
  56.  */     
  57.     float norms[] = new float[] { //法向量数组,用于描述个顶点的方向,以此说明各个面的方向    
  58.             // FRONT    
  59.             0f,  0f,  1f, //方向为(0,0,0)至(0,0,1)即Z轴正方向    
  60.             0f,  0f,  1f,    
  61.             0f,  0f,  1f,    
  62.             0f,  0f,  1f,    
  63.             // BACK    
  64.             0f,  0f,  -1f,    
  65.             0f,  0f,  -1f,    
  66.             0f,  0f,  -1f,    
  67.             0f,  0f,  -1f,    
  68.             // LEFT    
  69.             -1f,  0f,  0f,    
  70.             -1f,  0f,  0f,    
  71.             -1f,  0f,  0f,    
  72.             -1f,  0f,  0f,    
  73.             // RIGHT    
  74.             1f, 0f, 0f,    
  75.             1f, 0f, 0f,    
  76.             1f, 0f, 0f,    
  77.             1f, 0f, 0f,    
  78.             // TOP    
  79.             0f,  1f, 0f,    
  80.             0f,  1f, 0f,    
  81.             0f,  1f, 0f,    
  82.             0f,  1f, 0f,    
  83.             // BOTTOM    
  84.             0f,  -1f, 0f,    
  85.             0f,  -1f, 0f,    
  86.             0f,  -1f, 0f,    
  87.             0f,  -1f, 0f    
  88.         };    
  89.     
  90.         
  91.     float texCoords[] = new float[] { //纹理坐标对应数组    
  92.             // FRONT    
  93.              0.0f, 0.0f,    
  94.              1.0f, 0.0f,    
  95.              0.0f, 1.0f,    
  96.              1.0f, 1.0f,    
  97.             // BACK    
  98.              1.0f, 0.0f,    
  99.              1.0f, 1.0f,    
  100.              0.0f, 0.0f,    
  101.              0.0f, 1.0f,    
  102.             // LEFT    
  103.              1.0f, 0.0f,    
  104.              1.0f, 1.0f,    
  105.              0.0f, 0.0f,    
  106.              0.0f, 1.0f,    
  107.             // RIGHT    
  108.              1.0f, 0.0f,    
  109.              1.0f, 1.0f,    
  110.              0.0f, 0.0f,    
  111.              0.0f, 1.0f,    
  112.             // TOP    
  113.              0.0f, 0.0f,    
  114.              1.0f, 0.0f,    
  115.              0.0f, 1.0f,    
  116.              1.0f, 1.0f,    
  117.             // BOTTOM    
  118.              1.0f, 0.0f,    
  119.              1.0f, 1.0f,    
  120.              0.0f, 0.0f,    
  121.              0.0f, 1.0f    
  122.         };    
  123.     
  124.         
  125.     FloatBuffer cubeBuff;    
  126.     FloatBuffer normBuff;    
  127.     FloatBuffer texBuff;    
  128.         
  129.     float xrot = 0.0f;    
  130.     float yrot = 0.0f;    
  131.         
  132.     /**   
  133.      * 将float数组转换存储在字节缓冲数组   
  134.      * @param arr   
  135.      * @return   
  136.      */    
  137.     public FloatBuffer makeFloatBuffer(float[] arr) {    
  138.         ByteBuffer bb = ByteBuffer.allocateDirect(arr.length * 4);//分配缓冲空间,一个float占4个字节    
  139.         bb.order(ByteOrder.nativeOrder()); //设置字节顺序, 其中ByteOrder.nativeOrder()是获取本机字节顺序    
  140.         FloatBuffer fb = bb.asFloatBuffer(); //转换为float型    
  141.         fb.put(arr);        //添加数据    
  142.         fb.position(0);      //设置数组的起始位置    
  143.         return fb;    
  144.     }    
  145.         
  146.     public CubeRenderer(Context c) {    
  147.         // TODO Auto-generated constructor stub    
  148.         cubeBuff = makeFloatBuffer(box);//转换float数组    
  149.         normBuff = makeFloatBuffer(norms);    
  150.         texBuff = makeFloatBuffer(texCoords);       
  151.         bmp = BitmapFactory.decodeResource(c.getResources(), R.drawable.splash);    
  152.     }    
  153.         
  154.         
  155.     protected void init(GL10 gl) {    
  156.         gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);//设置清屏时背景的颜色,R,G,B,A    
  157.             
  158.         gl.glEnable(GL10.GL_LIGHTING); //启用光照    
  159.         gl.glEnable(GL10.GL_LIGHT0);  //开启光源0    
  160.         //设置光照参数,也可以使用默认的,不设置    
  161.         gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, lightAmbient, 0);    
  162.         gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, lightDiffuse, 0);    
  163.         gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lightPos, 0);    
  164.             
  165.         gl.glNormalPointer(GL10.GL_FLOAT, 0, normBuff);    
  166.         gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);    
  167.             
  168.         //使用纹理步骤:    
  169.         // 1.开启贴图    
  170.         gl.glEnable(GL10.GL_TEXTURE_2D);    
  171.             
  172.         // 2.生成纹理ID    
  173.         int[] tmp_tex = new int[1];//尽管只有一个纹理,但使用一个元素的数组    
  174.         //glGenTextures(申请个数,存放数组,偏移值)    
  175.         gl.glGenTextures(1, tmp_tex, 0); //向系统申请可用的,用于标示纹理的ID    
  176.         int texture = tmp_tex[0];    
  177.             
  178.         //3.绑定纹理,使得指定纹理处于活动状态。一次只能激活一个纹理    
  179.         gl.glBindTexture(GL10.GL_TEXTURE_2D, texture);    
  180.             
  181.         //4.绑定纹理数据,传入指定图片    
  182.         GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0);      
  183.             
  184.         //5.传递各个顶点对应的纹理坐标    
  185.         gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuff);    
  186.         gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); //开启纹理坐标数组    
  187.             
  188.         //6.设置纹理参数 (可选)    
  189.         /*下面的两行参数告诉OpenGL在显示图像时,当它比放大得原始的纹理大    
  190.         *( GL_TEXTURE_MAG_FILTER )或缩小得比原始得纹理小( GL_TEXTURE_MIN_FILTER )   
  191.         *时OpenGL采用的滤波方式。通常这两种情况下我都采用 GL_LINEAR 。这使得纹理从很远处   
  192.         *到离屏幕很近时都平滑显示。使用 GL_LINEAR 需要CPU和显卡做更多的运算。如果您的机器很慢,   
  193.         *您也许应该采用 GL_NEAREST 。过滤的纹理在放大的时候,看起来马赛克的很。您也可以结合这   
  194.         *两种滤波方式。在近处时使用 GL_LINEAR ,远处时 GL_NEAREST 。   
  195.         **/    
  196.         gl.glTexParameterx(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_LINEAR);       
  197.         gl.glTexParameterx(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_LINEAR);    
  198.                 
  199.             
  200.         gl.glEnable(GL10.GL_DEPTH_TEST); //启用深度缓存    
  201.         gl.glEnable(GL10.GL_CULL_FACE);  //启用背面剪裁    
  202.         gl.glClearDepthf(1.0f);    // 设置深度缓存值    
  203.         gl.glDepthFunc(GL10.GL_LEQUAL);  // 设置深度缓存比较函数,GL_LEQUAL表示新的像素的深度缓存值小于等于当前像素的深度缓存值(通过gl.glClearDepthf(1.0f)设置)时通过深度测试       
  204.         gl.glShadeModel(GL10.GL_SMOOTH);// 设置阴影模式GL_SMOOTH    
  205.     }    
  206.         
  207.     @Override    
  208.     public void onSurfaceCreated(GL10 gl, EGLConfig config) {    
  209.         // TODO Auto-generated method stub    
  210.         init(gl);    
  211.     }    
  212.         
  213.     @Override    
  214.     public void onSurfaceChanged(GL10 gl, int w, int h) {    
  215.         // TODO Auto-generated method stub    
  216.         gl.glViewport(0, 0, w, h); //设置视窗    
  217.         gl.glMatrixMode(GL10.GL_PROJECTION); // 设置投影矩阵    
  218.         gl.glLoadIdentity();  //设置矩阵为单位矩阵,相当于重置矩阵           
  219.         GLU.gluPerspective(gl, 45.0f, ((float) w) / h, 0.1f, 10f);//设置透视范围      
  220.     }    
  221.         
  222.     @Override    
  223.     public void onDrawFrame(GL10 gl) {    
  224.         // TODO Auto-generated method stub    
  225.         gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);// 清除屏幕和深度缓存    
  226.             
  227.         gl.glMatrixMode(GL10.GL_MODELVIEW);   //切换至模型观察矩阵    
  228.         gl.glLoadIdentity();// 重置当前的模型观察矩阵    
  229.         GLU.gluLookAt(gl, 0, 0, 3, 0, 0, 0, 0, 1, 0);//设置视点和模型中心位置    
  230.         
  231.         gl.glVertexPointer(3, GL10.GL_FLOAT, 0, cubeBuff);//设置顶点数据    
  232.         gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);    
  233.         
  234.         gl.glRotatef(xrot, 1, 0, 0);  //绕着(0,0,0)与(1,0,0)即x轴旋转    
  235.         gl.glRotatef(yrot, 0, 1, 0);    
  236.             
  237.         gl.glColor4f(1.0f, 0, 0, 1.0f);   //设置颜色,红色    
  238.         gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);  //绘制正方型FRONT面    
  239.         gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 4, 4);    
  240.         
  241.         gl.glColor4f(0, 1.0f, 0, 1.0f);    
  242.         gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 8, 4);    
  243.         gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 12, 4);    
  244.             
  245.         gl.glColor4f(0, 0, 1.0f, 1.0f);    
  246.         gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 16, 4);    
  247.         gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 20, 4);    
  248.         
  249.         xrot += 0.5f;    
  250.         yrot += 0.5f;    
  251.     }    
  252.     
  253. }    

上面重要的部分都已经做了注释,下面看一些运行后效果:

OpenGL纹理映射和光照效果_第1张图片


http://blog.csdn.net/wangkuifeng0118/article/details/7428406

你可能感兴趣的:(OpenGL)