笔者学到光源这一节,遇到的问题就比较多了,收集了一些如下所述:

  • (1) 导入的3ds模型,如果没有材质光照效果很奇怪.
    如下图
  • (2) 导入的3ds模型,有材质,灯光效果发暗,材质偏色,效果也很奇怪.

    下图中是有灯光的,但效果惨不忍睹.

  • (3) 场景引入灯光后,场景中的物体的颜色就全部消失了,即合引入颜色材质,效果也是怪怪的.

    如下图中的栅格,它原本应该是蓝色的.

  • (4) 场景中有物体引入材质后,整个场景的颜色就变得很奇怪

    下图中球体引入材质后,整个场景的颜色就变得很奇怪了.

  • (5) 导入的3ds模型,贴图颜色失真。

  • 下图中的茶壶,柱体,地板的贴图分别对应上图材质图片,可以看到经过纹理映射后,贴图颜色失真。
    这种问题并不是光源的问题,但是我也在这里一并列出来。

像这些问题,因为不好形容,网上也找不到合适的答案.群里的高手们也不屑回答这些菜鸟问题,因此只好自力更生了.

我先上一段演示场景的代码:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Windows.Forms;
  9. using SharpGL;
  10.  
  11. namespace SharpGLWinformsApplication1
  12. {
  13. /// <summary>
  14. /// 原创文章,出自"博客园, 猪悟能'S博客" : http://www.cnblogs.com/hackpig/
  15. /// </summary>
  16. public partial class SharpGLForm : Form
  17. {
  18. private float rotation = 0.0f,rotation2=0f,rotation3=0f;
  19. SharpGL.SceneGraph.Assets.Texture textureBox = new SharpGL.SceneGraph.Assets.Texture();
  20.  
  21. float[] fLightPosition = new float[] { 16f, 9f, -18f, 0f };// 光源位置
  22. float[] fLightAmbient = new float[] { 1f, 1f, 1f, 0f };// 环境光参数
  23. float[] fLightDiffuse = new float[] { 1f, 1f, 1f,0f };// 漫射光参数
  24.  
  25. float[] fLightPosition2 = new float[] { -7f, 5f, 2f, 0f };// 光源位置
  26. float[] fLightAmbient2 = new float[] { 0f, 0f, 1f, 0f };// 环境光参数
  27. float[] fLightDiffuse2 = new float[] { 0f, 0f, 1f, 0f };// 漫射光参数
  28.  
  29. bool f1 = false;
  30.  
  31. public SharpGLForm()
  32. {
  33. InitializeComponent();
  34. }
  35.  
  36. private void openGLControl_OpenGLDraw(object sender, PaintEventArgs e)
  37. {
  38. OpenGL gl = openGLControl.OpenGL;
  39. gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);
  40. gl.LoadIdentity();
  41. gl.Rotate(rotation3, , , );
  42. drawGrid(gl);
  43. drawLightPT(gl);
  44. drawLightPT2(gl);
  45. drawTextrueBox(gl, , , );
  46. drawSphere(gl, , , , false);
  47.  
  48. moveLightA(gl);
  49. rotation3+=0.1f;
  50. }
  51.  
  52. private void moveLightA(OpenGL gl)
  53. {
  54. if (!f1)
  55. --fLightPosition[];
  56. else
  57. ++fLightPosition[];
  58. if (fLightPosition[] > 15f)
  59. {
  60. f1 = !f1;
  61. }
  62. else if (fLightPosition[] < -25f)
  63. {
  64. f1 = !f1;
  65. }
  66. gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_POSITION, fLightPosition);//光源位置
  67. }
  68.  
  69. private void drawLightPT(OpenGL gl)
  70. {
  71. gl.PushMatrix();
  72. {
  73. gl.Disable(OpenGL.GL_TEXTURE_2D);
  74. gl.Color(0f,1f, 1f);
  75. gl.Scale(0.2, 0.2, 0.2);
  76. gl.Translate(fLightPosition[]- , fLightPosition[]+, fLightPosition[]);
  77. drawBox(gl, , , );
  78. }
  79. gl.PopMatrix();
  80. }
  81.  
  82. private void drawLightPT2(OpenGL gl)
  83. {
  84.  
  85. rotation2+=4f;
  86. gl.PushMatrix();
  87. {
  88. gl.LoadIdentity();
  89. gl.Disable(OpenGL.GL_TEXTURE_2D);
  90. gl.Color(0f, 1f, 1f);
  91. gl.Scale(0.2, 0.2, 0.2);
  92. gl.Rotate(rotation2, , , );
  93. gl.Translate(- , , );
  94.  
  95. drawBox(gl, , , );
  96. }
  97. gl.PopMatrix();
  98. }
  99.  
  100. private void drawTextrueBox(OpenGL gl, float xPos, float yPos, float zPos)
  101. {
  102. rotation += 3.0f;
  103. gl.PushMatrix();
  104. {
  105. textureBox.Bind(gl);
  106. gl.Enable(OpenGL.GL_TEXTURE_2D);
  107. gl.Rotate(rotation, , , );
  108. gl.Translate(-, , -);
  109. gl.Scale(, , );
  110. drawBox(gl,xPos, yPos, zPos);
  111. }
  112. gl.PopMatrix();
  113. }
  114.  
  115. private void drawBox(OpenGL gl, float xPos, float yPos, float zPos)
  116. {
  117. gl.PushMatrix();
  118. gl.Translate(xPos, yPos, zPos);
  119.  
  120. gl.Begin(OpenGL.GL_QUADS);
  121.  
  122. //前
  123. gl.TexCoord(, ); gl.Vertex(, , );
  124. gl.TexCoord(, ); gl.Vertex(-, , );
  125. gl.TexCoord(, ); gl.Vertex(-, -, );
  126. gl.TexCoord(, ); gl.Vertex(, -, );
  127.  
  128. //底
  129. gl.TexCoord(, ); gl.Vertex(, , );
  130. gl.TexCoord(, ); gl.Vertex(, , -);
  131. gl.TexCoord(, ); gl.Vertex(-, , -);
  132. gl.TexCoord(, ); gl.Vertex(-, , );
  133.  
  134. //左
  135. gl.TexCoord(, ); gl.Vertex(-, , );
  136. gl.TexCoord(, ); gl.Vertex(-, , -);
  137. gl.TexCoord(, ); gl.Vertex(-, -, -);
  138. gl.TexCoord(, ); gl.Vertex(-, -, );
  139.  
  140. //右
  141. gl.TexCoord(, ); gl.Vertex(, , );
  142. gl.TexCoord(, ); gl.Vertex(, , -);
  143. gl.TexCoord(, ); gl.Vertex(, -, -);
  144. gl.TexCoord(, ); gl.Vertex(, -, );
  145.  
  146. //后
  147. gl.TexCoord(, ); gl.Vertex(, , -);
  148. gl.TexCoord(, ); gl.Vertex(-, , -);
  149. gl.TexCoord(, ); gl.Vertex(-, -, -);
  150. gl.TexCoord(, ); gl.Vertex(, -, -);
  151.  
  152. //顶
  153. gl.TexCoord(, ); gl.Vertex(, -, );
  154. gl.TexCoord(, ); gl.Vertex(, -, -);
  155. gl.TexCoord(, ); gl.Vertex(-, -, -);
  156. gl.TexCoord(, ); gl.Vertex(-, -, );
  157.  
  158. gl.End();
  159. gl.PopMatrix();
  160.  
  161. }
  162.  
  163. void drawSphere(OpenGL gl, double radius, int segx, int segy, bool isLines)
  164. {
  165.  
  166. gl.PushMatrix();
  167. gl.Disable(OpenGL.GL_TEXTURE_2D);
  168. gl.Translate(-7f, -1f, 2f);
  169. var sphere = gl.NewQuadric();
  170.  
  171. if (isLines)
  172. gl.QuadricDrawStyle(sphere, OpenGL.GL_LINES);
  173. else
  174. gl.QuadricDrawStyle(sphere, OpenGL.GL_QUADS);
  175. gl.QuadricNormals(sphere, OpenGL.GLU_SMOOTH);
  176. gl.QuadricOrientation(sphere, (int)OpenGL.GLU_OUTSIDE);
  177. gl.QuadricTexture(sphere, (int)OpenGL.GLU_FALSE);
  178. gl.Sphere(sphere, radius, segx, segy);
  179. gl.DeleteQuadric(sphere);
  180. gl.PopMatrix();
  181.  
  182. }
  183.  
  184. void drawGrid(OpenGL gl)
  185. {
  186. //关闭纹理和光照
  187. gl.Disable(OpenGL.GL_TEXTURE_2D);
  188. gl.Disable(OpenGL.GL_LIGHTING);

  189. //绘制过程
  190. gl.PushAttrib(OpenGL.GL_CURRENT_BIT); //保存当前属性
  191. gl.PushMatrix(); //压入堆栈
  192. gl.Translate(0f, -2f, 0f);
  193. gl.Color(0f, 0f, 1f);
  194.  
  195. //在X,Z平面上绘制网格
  196. for (float i = -; i <= ; i += )
  197. {
  198. //绘制线
  199. gl.Begin(OpenGL.GL_LINES);
  200. {
  201. if (i == )
  202. gl.Color(0f, 1f, 0f);
  203. else
  204. gl.Color(0f, 0f, 1f);
  205.  
  206. //X轴方向
  207. gl.Vertex(-50f, 0f, i);
  208. gl.Vertex(50f, 0f, i);
  209. //Z轴方向
  210. gl.Vertex(i, 0f, -50f);
  211. gl.Vertex(i, 0f, 50f);
  212.  
  213. }
  214. gl.End();
  215. }
  216. gl.PopMatrix();
  217. gl.PopAttrib();
  218. gl.Enable(OpenGL.GL_LIGHTING);
  219. }
  220.  
  221. private void openGLControl_OpenGLInitialized(object sender, EventArgs e)
  222. {
  223. OpenGL gl = openGLControl.OpenGL;
  224. textureBox.Create(gl, "image.bmp");
  225.  
  226. gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_AMBIENT, fLightAmbient);//环境光源
  227. gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_DIFFUSE, fLightDiffuse);//漫射光源
  228. gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_POSITION, fLightPosition);//光源位置
  229.  
  230. gl.Light(OpenGL.GL_LIGHT1, OpenGL.GL_AMBIENT, fLightAmbient2);//环境光源
  231. gl.Light(OpenGL.GL_LIGHT1, OpenGL.GL_DIFFUSE, fLightDiffuse2);//漫射光源
  232. gl.Light(OpenGL.GL_LIGHT1, OpenGL.GL_POSITION, fLightPosition2);//光源位置
  233.  
  234. gl.Enable(OpenGL.GL_LIGHTING);//开启光照
  235. gl.Enable(OpenGL.GL_LIGHT0);
  236. gl.Enable(OpenGL.GL_LIGHT1);
  237.  
  238. gl.Enable(OpenGL.GL_NORMALIZE);
  239. gl.ClearColor(, , , );
  240.  
  241. }
  242.  
  243. private void openGLControl_Resized(object sender, EventArgs e)
  244. {
  245. OpenGL gl = openGLControl.OpenGL;
  246. gl.MatrixMode(OpenGL.GL_PROJECTION);
  247. gl.LoadIdentity();
  248. gl.Perspective(60.0f, (double)Width / (double)Height, 0.01, 100.0);
  249. gl.LookAt(-, , -, -, , , , , );
  250. gl.MatrixMode(OpenGL.GL_MODELVIEW);
  251. }
  252.  
  253. }
  254. }

效果如下图:

场景中有两个光源,一个在X方向左右运行,一个绕点点在转圈.

Box上了材质贴图,球体没有材质.

从效果上看,已经解决了开头所述的问题(3),(4),我们提下关键点在哪里:

1. 第194,195行必须有,否则画栅格时会受到场景中的灯光,或者材质设定的影响,栅格原来颜色就没有了.

  这个其实就是因为OpenGL是个状态机,其它部分代码改变了某些状态,画栅格时就会继承改变.

2. 同样原道理,第171行必须关闭纹理,否会受到Box材质设置状态的影响,球就不会是白色的了.

3. 第246行必须有,它用来自动归一化法线方向,因为光照效果由顶点和法线方向决定.

  这就是问题(1),(2)之所以有问题的原因.

  而导入的3ds模型,其画三角形的函数中也需要注意Normal()函数的向量值有没有方向问题.
  下图是修正了法线后的光照效果,可以看到是正常的.

   

4.  对于问题5,因为在检查了灯光与贴图后都是正常的, 所以问题只会在出现在贴图的时候。

经检测,是在导入3ds模形的代码中,关于读取贴图的一个函数Build2DMipmaps()中,把RGB换BGR即可。

GL.Build2DMipmaps(OpenGL.GL_TEXTURE_2D, 3, image.Width, image.Height, OpenGL.GL_BGR, OpenGL.GL_UNSIGNED_BYTE, bitmapdata.Scan0);

可以看到,效果正常了。

5. 最后一个困绕笔者的问题是物体旋转中心点的问题.这个话题跟灯光无关,在这个场景中恰好碰到了这个问题,发现原来是知识上的一个盲点.

  演示场景中,你会看到Box并不是绕世界坐标系的原点(绿色线的交汇点)在转,而是沿指定位置为轴心在转.

  是绕世界坐标原点转,还是绕你指定的坐标为轴转动,关键在于你是先Translate(),还是先Rotate().  读者可以参考下演示代码,然后自己尝试一下就知道了.

本节源代码下载

原创文章,出自"博客园, 猪悟能'S博客" : http://www.cnblogs.com/hackpig/

SharpGL学习笔记(十二) 光源例子:解决光源场景中的常见问题的更多相关文章

  1. ROS学习笔记十二:使用gazebo在ROS中仿真

    想要在ROS系统中对我们的机器人进行仿真,需要使用gazebo. gazebo是一种适用于复杂室内多机器人和室外环境的仿真环境.它能够在三维环境中对多个机器人.传感器及物体进行仿真,产生实际传感器反馈 ...

  2. python3.4学习笔记(十二) python正则表达式的使用,使用pyspider匹配输出带.html结尾的URL

    python3.4学习笔记(十二) python正则表达式的使用,使用pyspider匹配输出带.html结尾的URL实战例子:使用pyspider匹配输出带.html结尾的URL:@config(a ...

  3. Go语言学习笔记十二: 范围(Range)

    Go语言学习笔记十二: 范围(Range) rang这个关键字主要用来遍历数组,切片,通道或Map.在数组和切片中返回索引值,在Map中返回key. 这个特别像python的方式.不过写法上比较怪异使 ...

  4. SharpGL学习笔记(十四) 材质:十二个材质球

    材质颜色 OpenGL用材料对光的红.绿.蓝三原色的反射率来近似定义材料的颜色.象光源一样,材料颜色也分成环境.漫反射和镜面反射成分,它们决定了材料对环境光.漫反射光和镜面反射光的反射程度.在进行光照 ...

  5. SharpGL学习笔记(十) 常见的光源类型,创建光源

    在OpenGL中,使用光源的特性组合,如颜色,位置,方向等等,可以创建多种不同类型的灯光. 常见的几种灯光类型有: 定向光源(directonal) 定位光源(positional) 衰减光源 聚光灯 ...

  6. java jvm学习笔记十二(访问控制器的栈校验机制)

    欢迎装载请说明出处:http://blog.csdn.net/yfqnihao 本节源码:http://download.csdn.net/detail/yfqnihao/4863854 这一节,我们 ...

  7. SharpGL学习笔记(十九) 摄像机漫游

    所谓的摄像机漫游,就是可以在场景中来回走动. 现实中,我们通过眼睛观察东西,身体移动带动眼睛移动观察身边的事物,这也是在漫游. 在OpenGL中我们使用函数LookAt()来操作摄像机在三维场景中进行 ...

  8. (C/C++学习笔记) 十二. 指针

    十二. 指针 ● 基本概念 位系统下为4字节(8位十六进制数),在64位系统下为8字节(16位十六进制数) 进制表示的, 内存地址不占用内存空间 指针本身是一种数据类型, 它可以指向int, char ...

  9. SharpGL学习笔记(十五) 纹理映射

    纹理映射非常实用,在游戏场景中已经无所不在了. 一个较少的多边形构成的模形,配合好的纹理贴图进行映射,可以得到逼真的效果.游戏中的天空,地面,墙面,和植物都是纹理贴图进行映射的. 例如最终幻想8的男女 ...

随机推荐

  1. 介绍几个工作开发中封装的好用的android自定义控件

    首先看效果图, 看下这两个界面,第一个中用到了一个自定义的FlowRadioGroup,支持复合子控件,自定义布局: 第二个界面中看到了输入的数字 自动4位分割了吧:也用到了自定义的DivisionE ...

  2. 安装cvxpy遇到的问题与解决方案(ubuntu14.10,python 2.7.8)

    应该说,cvxpy的安装说明是很棒的,一步一步非常清楚,www.cvxpy.org/en/latest/install/index.html 可是,我照着做完之后,还是不能import cvxpy,不 ...

  3. Chart 点击获取坐标

    private void chart2_MouseMove(object sender, MouseEventArgs e) { if (!this.DesignMode) { ].AxisX.Sca ...

  4. java中Finally块的执行

    在try{}catch{}finally{}块中,都知道finally子块是肯定会执行的.当然也有个别情况,当在try{}或者catch{}块中出现强制退出System.exti(int)时,fina ...

  5. Git--用git建立code库

    利用点时间,把自己这段时间使用git的工具的内容,使用过程中遇到的问题都梳理下.首先我们建立一个文件库(基于Ubuntu系统): 1.必须要安装: [html]  view plain copy   ...

  6. 托管调试助手“NonComVisibleBaseClass”检测到问题

    最近 一次在研究 自动化测试框架White ,程序总是报   “托管调试助手“NonComVisibleBaseClass”在“d:\xxxxxxxxxx.vshost.exe”中检测到问题.” 其他 ...

  7. lettuce webdriver 自动化测试---玩转BDD

    行为驱动开发(BDD),依然高大上的矗立在远方,很少被人问津,一方面是BDD的思想不太容易理解,别一方面BDD的资料并不多.中文的资料就更少了. 之前增写过一篇<python BDD 框架之le ...

  8. 扁平化设计的最新趋势 – 长阴影(Long Shadow)

    随着互联网的发展,网页设计变得越来越复杂,如今设计的外观和感觉实现网站功能说使用的开发技术一样重要.互联网的功能远远不只是基本的信息共享,现在人们对网站的期望是远远大于几年前的. 如今,HTML5 & ...

  9. .NET ORM 哪家强

    ORM到底哪家强? 很多人都想知道这个问题,自已也没测试过,只能道听途说. 闲的无聊就将几个ORM拿出来比一比,假如怀疑测试代码有问题可以将它下载下来慢慢研究. 参赛ORM 1.SqlSugar:是一 ...

  10. Django--上传文件

    需求 Django中forms表单上传文件处理​ 速查 views.py 1 2 3 4 5 6 7 8 9 def upload(request):     if request.method==' ...