点法向量和面法向量(1)

6.4 点法向量和面法向量(1)

2012-06-08 15:54 吴亚峰 译 人民邮电出版社  字号: T |  T
一键收藏,随时查看,分享好友!

《Android 3D游戏开发技术宝典——OpenGL ES 2.0》第6章光照,本章将向读者介绍光照效果的开发,通过本章的学习,读者可以为场景中的物体增加逼真的光照效果,大大提升了场景的真实感。本节为大家介绍点法向量和面法向量。

AD:【线下活动】三大新锐HTML 5企业汇聚51CTO—大话移动前端技术

6.4  点法向量和面法向量(1)

本章前面几节的案例都是基于球面开发的,球面属于连续、平滑的曲面,因此面上的每个顶点都有确定的法向量。但现实世界中的物体表面并不都是连续、平滑的,此时对于面上的某些点的法向量计算就并不那么直观了,图6-18说明了这个问题。

从图6-18中可以看出,顶点A位于长方体左、上、前3个面的交界处,此处是不光滑的。这种情况下顶点A的法向量有两种处理策略,具体如下所列。

 
图6-18  两种法向量示意图

在顶点A的位置放置3个不同的顶点,每个顶点看作是仅属于一个面。各个顶点的法向量即为其属于的面的法向量,这种策略就是面法向量的策略,比较适合棱角分明的物体。

顶点A的位置仅认为存在一个顶点,其法向量取其所属的所有面法向量的平均值。这种策略就是点法向量策略,比较适合用多个平面搭建平滑曲面的情况。

提示 前面球体的案例采用的就是此策略,只不过由于球面上顶点的法向量可以直接计算,因此相当于直接得到了点平均法向量,而略去了计算平均值的过程。但很多情况下是需要进行平均法向量的计算的,尤其是在加载预制3D模型的时候,这一点在后面的章节会有专门的介绍。

了解了点法向量和面法向量的基本知识后,下面将通过两个基本相同的绘制立方体的案例(Sample6_7和Sample6_8)对这两种策略进行比较。这两个案例的运行效果如图6-19和图6-20所示,其中图6-19来自采用面法向量策略的案例Sample6_7,图6-20来自采用点法向量策略的案例Sample6_8。

 
图6-19  案例Sample6_7的运行效果图
 
图6-20  案例Sample6_8的运行效果图

说明 从图6-19与图6-20的比较中可以看出,对于棱角分明的物体适合采用面法向量策略。若采用点法向量策略渲染真实感就会差很多了,实际开发中读者应该根据所绘制物体表面的特点来选用合适的策略。

了解了两个案例的运行效果后,就可以进行案例的开发了。由于这两个案例中大部分的代码与前面6.2.5小节中案例Sample6_5里的完全相同,主要的区别就在立方体顶点与法向量初始化的部分,所以下面仅给出Sample6_7与Sample6_8中初始化立方体顶点与法向量的部分代码,具体内容如下所列。

(1)首先介绍采用面法向量策略的案例Sample6_7中初始化立方体顶点及法向量数据的initVertexData方法,其代码如下。

代码位置:见随书光盘中源代码/第6章/Sample6_7/com/bn/Sample6_7目录下的Cube.java。

   
   
  1. 1   public void initVertexData() {          //初始化顶点数据的方法  
  2. 2         vCount=6*6;                   //顶点数(6个面,每个面两个三角形,6个顶点)  
  3. 3         float vertices[]=new float[]{  
  4. 4           Constant.UNIT_SIZE,Constant.UNIT_SIZE,Constant.UNIT_SIZE,   //立方体前面  
  5. 5           -Constant.UNIT_SIZE,Constant.UNIT_SIZE,Constant.UNIT_SIZE,  //两个三角形  
  6. 6           -Constant.UNIT_SIZE,-Constant.UNIT_SIZE,Constant.UNIT_SIZE, //中6个顶点  
  7. 7           Constant.UNIT_SIZE,Constant.UNIT_SIZE,Constant.UNIT_SIZE,   //的X、Y、Z坐标  
  8. 8           -Constant.UNIT_SIZE,-Constant.UNIT_SIZE,Constant.UNIT_SIZE,  
  9. 9           Constant.UNIT_SIZE,-Constant.UNIT_SIZE,Constant.UNIT_SIZE,  
  10. 10          ……//此处省略了其他5个面顶点坐标产生的代码,  
  11. 11          ……//需要的读者请自行查看随书光盘中的源代码  
  12. 12        };  
  13. 13      ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);                                                                    //创建顶点坐标数据缓冲  
  14. 14      vbb.order(ByteOrder.nativeOrder());         //设置字节顺序  
  15. 15      mVertexBuffer = vbb.asFloatBuffer();            //转换为float型缓冲  
  16. 16      mVertexBuffer.put(vertices);                    //向缓冲区中放入顶点坐标数据  
  17. 17      mVertexBuffer.position(0);                      //设置缓冲区起始位置  
  18. 18      float normals[]=new float[]{  
  19. 19          0,0,1,  0,0,1,  0,0,1,  0,0,1,  0,0,1,  0,0,1,  //前面上6个顶点的法向量  
  20. 20          0,0,-1,  0,0,-1,  0,0,-1,  0,0,-1,  0,0,-1,  0,0,-1, //后面上6个顶点的法向量  
  21. 21          -1,0,0,  -1,0,0,  -1,0,0,  -1,0,0,  -1,0,0,  -1,0,0, //左面上6个顶点的法向量  
  22. 22          1,0,0,  1,0,0,  1,0,0,  1,0,0,  1,0,0,  1,0,0,  //右面上6个顶点的法向量  
  23. 23          0,1,0,  0,1,0,  0,1,0,  0,1,0,  0,1,0,  0,1,0,  //上面上6个顶点的法向量  
  24. 24          0,-1,0,  0,-1,0,  0,-1,0,  0,-1,0,  0,-1,0,  0,-1,0, //下面上6个顶点的法向量  
  25. 25      };  
  26. 26       ByteBuffer nbb = ByteBuffer.allocateDirect(normals.length*4);                                                                      //创建绘制顶点法向量缓冲  
  27. 27       nbb.order(ByteOrder.nativeOrder());                //设置字节顺序  
  28. 28       mNormalBuffer = nbb.asFloatBuffer();           //转换为float型缓冲  
  29. 29       mNormalBuffer.put(normals);                    //向缓冲区中放入顶点法向量数据  
  30. 30       mNormalBuffer.position(0);                     //设置缓冲区起始位置  
  31. 31  }  

【责任编辑: book TEL:(010)68476606
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值