这是根据徐明亮《OpenGL游戏编程》书上光灯一节的一个例子改编的.

从这个例子可以学习到二次曲面的参数设置,程序中提供了两个画球的函数,一个是用三角形画出来的,一个是二次曲面构成的.

你会发现,跟三角形版本不同,二次曲面要做一些设定,否则画出来的球体无法接受光照.

先上代码:

  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 light2
  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;
  19. float m_bReadX, m_bReadY;
  20. float m_bGreenX, m_bGreenY;
  21. float m_bBlueX, m_bBlueY;
  22.  
  23. //3个光源位置
  24. float[] lightPosR = new float[] { 0f, 0f, 2f, 1f };
  25. float[] lightPosG = new float[] { 0f, 0f, 2f, 1f };
  26. float[] lightPosB = new float[] { 0f, 0f, 2f, 1f };
  27.  
  28. //3个光源漫射光
  29. float[] diffLightR = { 1f, 0f, 0f, 1f };
  30. float[] diffLightG = { 0f, 1f, 0f, 1f };
  31. float[] diffLightB = { 0f, 0f, 1f, 1f };
  32.  
  33. //定义3个光源我镜面光
  34. float[] specLightR = { 1f, 0f, 0f, 1f };
  35. float[] specLightG = { 0f, 1f, 0f, 1f };
  36. float[] specLightB = { 0f, 0f, 1f, 1f };
  37.  
  38. //默认的光源, 灰色光源,用于默认照明
  39. float[] defDiffLight = new float[] { 0.8f, 0.8f, 0.8f, 1f };
  40. float[] defSpecLight = new float[] { 1f, 1f, 1f, 1f };
  41. float[] defLightPos = new float[] { 0f, 0f, 10f, 1f };
  42.  
  43. public SharpGLForm()
  44. {
  45. InitializeComponent();
  46. }
  47.  
  48. private void openGLControl_OpenGLDraw(object sender, PaintEventArgs e)
  49. {
  50. OpenGL gl = openGLControl.OpenGL;
  51. gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);
  52. gl.LoadIdentity();
  53. gl.Rotate(rotation, 0.0f, 1.0f, 0.0f);
  54.  
  55. draw(gl);
  56. rotation += 3.0f;
  57.  
  58. update(gl);
  59. }
  60.  
  61. void update(OpenGL gl)
  62. {
  63. gl.Enable(OpenGL.GL_LIGHT1);
  64. m_bReadX += ;
  65. m_bReadY += ;
  66. gl.Enable(OpenGL.GL_LIGHT2);
  67. m_bGreenX += ;
  68. m_bGreenY += ;
  69. gl.Enable(OpenGL.GL_LIGHT3);
  70. m_bBlueX += ;
  71. m_bBlueY += ;
  72. }
  73.  
  74. void draw(OpenGL gl)
  75. {
  76. gl.PushMatrix();
  77. //旋转红光
  78. gl.Rotate(m_bReadX, 1f, 0f, 0f);
  79. gl.Rotate(m_bReadY, 0f, 1f, 0f);
  80. //设置红光的位置
  81. gl.Light(OpenGL.GL_LIGHT1, OpenGL.GL_POSITION, lightPosR);
  82. //绘制光球
  83. gl.Translate(lightPosR[], lightPosR[], lightPosR[]);
  84. gl.Color(1f, 0f, 0f);
  85. gl.PushAttrib(OpenGL.GL_LIGHTING_BIT);
  86. gl.Disable(OpenGL.GL_LIGHTING);
  87. drawSphere(gl,lightPosR[], lightPosR[], lightPosR[],0.2f,,,false);
  88. gl.Enable(OpenGL.GL_LIGHTING);
  89. gl.PopAttrib();
  90. gl.PopMatrix();
  91.  
  92. gl.PushMatrix();
  93. //旋转绿光
  94. gl.Rotate(m_bGreenX, 1f, 0f, 0f);
  95. gl.Rotate(m_bGreenY, 0f, 1f, 0f);
  96. //设置绿光的位置
  97. gl.Light(OpenGL.GL_LIGHT2, OpenGL.GL_POSITION, lightPosG);
  98. //绘制光球
  99. gl.Translate(lightPosG[], lightPosG[], lightPosG[]);
  100. gl.Color(0f, 1f, 0f);
  101. gl.PushAttrib(OpenGL.GL_LIGHTING_BIT);
  102. gl.Disable(OpenGL.GL_LIGHTING);
  103. drawSphere(gl, lightPosG[], lightPosG[], lightPosG[], 0.2f, , ,false);
  104. gl.Enable(OpenGL.GL_LIGHTING);
  105. gl.PopAttrib();
  106. gl.PopMatrix();
  107.  
  108. gl.PushMatrix();
  109. //旋转蓝光
  110. gl.Rotate(m_bBlueX, 1f, 0f, 0f);
  111. gl.Rotate(m_bBlueY, 0f, 1f, 0f);
  112. //设置蓝光的位置
  113. gl.Light(OpenGL.GL_LIGHT3, OpenGL.GL_POSITION, lightPosB);
  114. //绘制光球
  115. gl.Translate(lightPosB[], lightPosB[], lightPosB[]);
  116. gl.Color(0f, 0f, 1f);
  117. gl.PushAttrib(OpenGL.GL_LIGHTING_BIT);
  118. gl.Disable(OpenGL.GL_LIGHTING);
  119. drawSphere(gl, lightPosB[], lightPosB[], lightPosB[], 0.2f, , ,false);
  120. gl.Enable(OpenGL.GL_LIGHTING);
  121. gl.PopAttrib();
  122. gl.PopMatrix();
  123.  
  124. //绘制球体
  125. gl.PushMatrix();
  126. gl.Rotate(rotation, 1f, 0f, 0f);
  127. gl.Rotate(rotation, 0f, 1f, 0f);
  128. gl.Rotate(rotation, 0f, 0f, 1f);
  129. drawSphere(gl, , , , , , ,false);
  130.  
  131. gl.PopMatrix();
  132.  
  133. gl.Flush();
  134.  
  135. }
  136.  
  137. //二次曲面球体
  138. void drawSphere(OpenGL gl,float x,float y,float z, double radius, int segx, int segy, bool isLines)
  139. {
  140. gl.PushMatrix();
  141. gl.Translate(x, y, z);
  142. var sphere = gl.NewQuadric();
  143. if (isLines)
  144. gl.QuadricDrawStyle(sphere, OpenGL.GL_LINES);
  145. else
  146. gl.QuadricDrawStyle(sphere, OpenGL.GL_QUADS);
  147. gl.QuadricNormals(sphere, OpenGL.GLU_NONE); //GLU_NONE,GLU_FLAT,GLU_SMOOTH
  148. gl.QuadricOrientation(sphere, (int)OpenGL.GLU_OUTSIDE); //GLU_OUTSIDE,GLU_INSIDE
  149. gl.QuadricTexture(sphere, (int)OpenGL.GLU_FALSE); //GL_TRUE,GLU_FALSE
  150. gl.Sphere(sphere, radius, segx, segy);
  151. gl.DeleteQuadric(sphere);
  152. gl.PopMatrix();
  153. }
  154.  
  155. //球心坐标为(x,y,z),球的半径为radius,M,N分别表示球体的横纵向被分成多少份
  156. void drawSphere1(OpenGL gl, float xx, float yy, float zz, float radius, float M, float N,bool isLines)
  157. {
  158. const float PI = 3.1415926f;
  159. float step_z = (float)Math.PI / M;
  160. float step_xy = * PI / N;
  161. float[] x = new float[] { , , , };
  162. float[] y = new float[] { , , , };
  163. float[] z = new float[] { , , , };
  164.  
  165. float angle_z = 0.0f;
  166. float angle_xy = 0.0f;
  167. int i = , j = ;
  168. gl.Begin(OpenGL.GL_QUADS);
  169. for (i = ; i < M; i++)
  170. {
  171. angle_z = i * step_z;
  172. for (j = ; j < N; j++)
  173. {
  174. angle_xy = j * step_xy;
  175.  
  176. x[] = (float)(radius * Math.Sin(angle_z) * Math.Cos(angle_xy));
  177. y[] = (float)(radius * Math.Sin(angle_z) * Math.Sin(angle_xy));
  178. z[] = (float)(radius * Math.Cos(angle_z));
  179.  
  180. x[] = (float)(radius * Math.Sin(angle_z + step_z) * Math.Cos(angle_xy));
  181. y[] = (float)(radius * Math.Sin(angle_z + step_z) * Math.Sin(angle_xy));
  182. z[] = (float)(radius * Math.Cos(angle_z + step_z));
  183.  
  184. x[] = (float)(radius * Math.Sin(angle_z + step_z) * Math.Cos(angle_xy + step_xy));
  185. y[] = (float)(radius * Math.Sin(angle_z + step_z) * Math.Sin(angle_xy + step_xy));
  186. z[] = (float)(radius * Math.Cos(angle_z + step_z));
  187.  
  188. x[] = (float)(radius * Math.Sin(angle_z) * Math.Cos(angle_xy + step_xy));
  189. y[] = (float)(radius * Math.Sin(angle_z) * Math.Sin(angle_xy + step_xy));
  190. z[] = (float)(radius * Math.Cos(angle_z));
  191.  
  192. for (int k = ; k < ; k++)
  193. {
  194. gl.Vertex(xx + x[k], yy + y[k], zz + z[k]);
  195. }
  196. }
  197. }
  198. gl.End();
  199. }
  200.  
  201. private void openGLControl_OpenGLInitialized(object sender, EventArgs e)
  202. {
  203. OpenGL gl = openGLControl.OpenGL;
  204. setLight(gl);
  205. //gl.Enable(OpenGL.GL_NORMALIZE);
  206. gl.ClearColor(, , , );
  207. }
  208.  
  209. private void setLight(OpenGL gl)
  210. {
  211. //0号灯光,默认灯光
  212. gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_DIFFUSE, defDiffLight);
  213. gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_SPECULAR, defSpecLight);
  214. gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_POSITION, defLightPos);
  215.  
  216. //1号灯光
  217. gl.Light(OpenGL.GL_LIGHT1, OpenGL.GL_DIFFUSE, diffLightR);
  218. gl.Light(OpenGL.GL_LIGHT1, OpenGL.GL_SPECULAR, specLightR);
  219. gl.Light(OpenGL.GL_LIGHT1, OpenGL.GL_POSITION, lightPosR);
  220.  
  221. //2号灯光
  222. gl.Light(OpenGL.GL_LIGHT2, OpenGL.GL_DIFFUSE, diffLightG);
  223. gl.Light(OpenGL.GL_LIGHT2, OpenGL.GL_SPECULAR, specLightG);
  224. gl.Light(OpenGL.GL_LIGHT2, OpenGL.GL_POSITION, lightPosG);
  225.  
  226. //3号灯光
  227. gl.Light(OpenGL.GL_LIGHT3, OpenGL.GL_DIFFUSE, diffLightB);
  228. gl.Light(OpenGL.GL_LIGHT3, OpenGL.GL_SPECULAR, specLightB);
  229. gl.Light(OpenGL.GL_LIGHT3, OpenGL.GL_POSITION, lightPosB);
  230.  
  231. gl.Enable(OpenGL.GL_LIGHTING);
  232. gl.Enable(OpenGL.GL_LIGHT0); //启用默认光源
  233.  
  234. }
  235.  
  236. private void openGLControl_Resized(object sender, EventArgs e)
  237. {
  238. OpenGL gl = openGLControl.OpenGL;
  239. gl.MatrixMode(OpenGL.GL_PROJECTION);
  240. gl.LoadIdentity();
  241. gl.Perspective(70.0f, (double)Width / (double)Height, 0.01, 100.0);
  242. gl.LookAt(-, , -, , , , , , );
  243. gl.MatrixMode(OpenGL.GL_MODELVIEW);
  244. }
  245.  
  246. }
  247. }

截取了一帧的效果如下图:

有三个光球围绕球体旋转,三组光分别为红,绿,蓝,因此它们的组合可以在球面上生成所有可能的颜色效果.

函数drawSphere是二次曲面球体,函数drawSphere1是三角形构成的球体.

下面我们研究一下二次曲面的几个关键的需要注意的设置函数:

(1) QuadricDrawStyle(IntPtr quadObject, uint drawStyle);

第一个参数是二次方程对象状态的指针,第二个参数的枚举值如下表:

常量 描述
GLU_FILL 二次方程对象画成实体
GLU_LINE 二次方程对象画成线框
GLU_POINT 二次方程对象画成一组顶点的集合
GLU_SILHOUETTE 类似于线框,但相邻的多边形的边不被绘制。

(2) QuadricNormals(IntPtr quadricObject, uint normals);

这个函数指定二次方程对象如何生成法线。第二个参数可以是:GLU_NONE不生成法线,GLU_FLAT扁平法线,GLU_SMOOTH平滑法线。

(3) QuadricOrientation(IntPtr quadricObject, int orientation);

这个函数可以指定法线的朝向,指向外面还是只想里面。orientation可以是GLU_OUTSIDE或者是GLU_INSIDE这两个值。OpenGL默认是以GL_CCW逆时针为正方向的

(4) QuadricTexture(IntPtr quadricObject, int textureCoords);

这个函数可以指定二次方程表面的纹理坐标,textureCoords这个参数可以是GL_TRUE或者GL_FALSE.当为球体和圆柱体生成纹理坐标时,纹理是对称地环绕在球体和圆柱体的表面的。如果应用到圆盘上,那么纹理的中心就是圆盘的中心,然后以线性插值的方式扩展到圆盘的边界。

读者可以尝试改变这些函数的参数,会发现受光效果是不同的.

也可以尝试用drawSphere1()函数替换掉drawSphere()函数,它是不需要做任何设定,就有很好的效果.

本节源代码下载

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

SharpGL学习笔记(十三) 光源例子:环绕二次曲面球体的光源的更多相关文章

  1. SharpGL学习笔记(十一) 光源创建的综合例子:光源参数可调节的测试场景

    灯光的测试例子:光源参数可以调节的测试场景 先看一下测试场景和效果. 场景中可以切换视图, 以方便观察三维体和灯光的位置.环境光,漫射光,镜面反射光都可以在四种颜色间切换. 灯光位置和摄像机位置(Lo ...

  2. java之jvm学习笔记十三(jvm基本结构)

    java之jvm学习笔记十三(jvm基本结构) 这一节,主要来学习jvm的基本结构,也就是概述.说是概述,内容很多,而且概念量也很大,不过关于概念方面,你不用担心,我完全有信心,让概念在你的脑子里变成 ...

  3. SharpGL学习笔记(七) OpenGL的变换总结

    笔者接触OpenGL最大的困难是: 经常调试一份代码时, 屏幕漆黑一片, 也不知道结果对不对,不知道如何是好! 这其实就是关于OpenGL"变换"的基础概念没有掌握好, 以至于对& ...

  4. python3.4学习笔记(十三) 网络爬虫实例代码,使用pyspider抓取多牛投资吧里面的文章信息,抓取政府网新闻内容

    python3.4学习笔记(十三) 网络爬虫实例代码,使用pyspider抓取多牛投资吧里面的文章信息PySpider:一个国人编写的强大的网络爬虫系统并带有强大的WebUI,采用Python语言编写 ...

  5. Go语言学习笔记十三: Map集合

    Go语言学习笔记十三: Map集合 Map在每种语言中基本都有,Java中是属于集合类Map,其包括HashMap, TreeMap等.而Python语言直接就属于一种类型,写法上比Java还简单. ...

  6. SharpGL学习笔记(六) 裁剪变换

    在OpenGL中,除了视景体定义的6个裁剪平面(上下左右前后)外, 用户还可以定义一个或者多个附加的裁剪平面,以去掉场景中无关的目标. 附加平面裁剪函数原型如下: ClipPlane(OpenGL.G ...

  7. Vue学习笔记十三:Vue+Bootstrap+vue-resource从接口获取数据库数据

    目录 前言 SpringBoot提供后端接口 Entity类 JPA操作接口 配置文件 数据库表自动映射,添加数据 写提供数据的接口 跨域问题 前端修改 效果图 待续 前言 Vue学习笔记九的列表案例 ...

  8. SharpGL学习笔记(十二) 光源例子:解决光源场景中的常见问题

    笔者学到光源这一节,遇到的问题就比较多了,收集了一些如下所述: (1) 导入的3ds模型,如果没有材质光照效果很奇怪.如下图 (2) 导入的3ds模型,有材质,灯光效果发暗,材质偏色,效果也很奇怪. ...

  9. SharpGL学习笔记(八) 矩阵堆栈和变换的综合例子: 机器人

    我们先引入关于"矩阵堆栈"的官方说法: OpenGL的矩阵堆栈指的就是内存中专门用来存放矩阵数据的某块特殊区域.实际上,在创建.装入.相乘模型变换和投影变换矩阵时,都已用到堆栈操作 ...

随机推荐

  1. React Native ——实现一个简单的抓取github上的项目数据列表

    /** * Sample React Native App * https://github.com/facebook/react-native */ 'use strict'; var React ...

  2. Git使用总结

    一.Git的特性 Speed 速度(git是用c语言写的.一般都是提交到本地) Simple design Strong support for non-linear development (tho ...

  3. Traffic Lights

    Traffic Lights time limit per test 2 seconds memory limit per test 256 megabytes input standard inpu ...

  4. SQL Server 中关于 @@error 的一个小误区

    在SQL Server中,我常常会看到有些前辈这样写: ) ROLLBACK TRANSACTION T else COMMIT TRANSACTION T 一开始,我看见别人这么写,我就想当然的以为 ...

  5. CentOS linux系统搭建LAMP环境

    准备工作: 1.配置防火墙,开启80端口.3306端口vi /etc/sysconfig/iptables-A INPUT -m state –state NEW -m tcp -p tcp –dpo ...

  6. MongoDB的学习--文档的插入、删除和更新

    最近在看<MongoDB权威指南>,写博客记录一下相关内容~~ 关于安装之类的最基本的就不多说了,从基本操作增删改查开始. MongoDB官网地址:http://www.mongodb.o ...

  7. Hadoop入门进阶课程2--Hadoop2.X 64位编译

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,博主为石山园,博客地址为 http://www.cnblogs.com/shishanyuan  ...

  8. Java泛型数组

    文章来自http://blog.csdn.net/orzlzro/article/details/7017435 Java 不支持泛型数组.也就是说, List<String>[] ls ...

  9. EPANET中读取INPUT文件的函数文件——INPUT1.C/INPUT2.C/INPUT3.C

    首先介绍下这3个文件的关系:可以说INPUT1.C的函数粒度最大,它的函数getdata()就完成了整个INPUT文件数据的读入,该函数又调用了INPUT2.C中的部分函数,INPUT2.C文件中的函 ...

  10. MIME(Multipurpose Internet Mail Extensions)的简介

    多用途互联网邮件扩展类型(MIME) 作用:用于标识Web资源类型(Multipurpose Internet Mail Extensions,MIME) 效果:Web上MIME为每种类型的资源提供一 ...