首页 > 代码库 > SharpGL学习笔记(十一) 光源创建的综合例子:光源参数可调节的测试场景

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

 

灯光的测试例子:光源参数可以调节的测试场景

 

先看一下测试场景和效果。

场景中可以切换视图, 以方便观察三维体和灯光的位置。环境光,漫射光,镜面反射光都可以在四种颜色间切换。

灯光位置和摄像机位置(LookAt)可以输入数值或者点动调节,也可以按键盘的QEWASD六个键进行调节。

你还会注意到:球体对光的效果要敏感柔和些,而那个六面体BOX看来效果不好。这是因为灯光对顶点发生作用。在程序里面,球休的顶点数量有20*10,而BOX只有4*6个,而且还重合了一些顶点。

这一点,在3dsmax的全局光照里面表现很明显,做为墙壁的box顶点数量越大,计算出来光照效果越好

还有,界面上灯光位置是 -1,5,1,1  前三个是x,y,z, 后面的一个1不是坐标,它取值0或者1,表示灯光是定向光源(directonal),还是定位光源(positional)。

技术分享

 

代码如下:

  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  14     public partial class SharpGLForm : Form 15     { 16         private float rotation = 0.0f; 17         private bool isRotate = false; 18         private bool isLines = false; 19         private bool isFrontView = false; 20         private bool isLeftView = false; 21         private bool isTopView = false; 22         private bool isPerspective = true; 23         private float[] lightPos = new float[] { -1, -3, 1, 1 }; 24         private float[] lightSphereColor = new float[] { 1f, 1f, 1f }; 25         private IList<float[]> lightColor = new List<float[]>(); 26         private double[] lookatValue = http://www.mamicode.com/{ 1, 1, 2, 0, 0, 0, 0, 1, 0 }; 27         private IList<double[]> viewDefaultPos = new List<double[]>(); 28         public SharpGLForm() 29         { 30             InitializeComponent(); 31         } 32  33         private void openGLControl_OpenGLDraw(object sender, PaintEventArgs e) 34         { 35             OpenGL gl = openGLControl.OpenGL; 36             gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT); 37             gl.LoadIdentity(); 38             gl.Rotate(rotation, 0.0f, 1.0f, 0.0f); 39  40             drawGrid(gl); 41             DrawCube(ref gl, 1.5f,-1f, -2f, isLines); 42             drawOneSphere(ref gl,-3,-2,-4,isLines); 43             if (isRotate) 44                 rotation += 3.0f; 45         } 46  47         private void setLightColor(OpenGL gl) 48         { 49             gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_AMBIENT, lightColor[0]); 50             gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_DIFFUSE, lightColor[1]); 51             gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_SPECULAR, lightColor[2]); 52         } 53  54         private void openGLControl_OpenGLInitialized(object sender, EventArgs e) 55         { 56             OpenGL gl = openGLControl.OpenGL; 57  58             //四个视图的缺省位置 59             viewDefaultPos.Add(new double[] { 1, 1, 2, 0, 0, 0, 0, 1, 0 });     //透视 60             viewDefaultPos.Add(new double[] { 0, 0, 2, 0, 0, 0, 0, 1, 0 });     //前视  61             viewDefaultPos.Add(new double[] { 5, 0, 0, 0, 0, 0, 0, 1, 0 });     //左视 62             viewDefaultPos.Add(new double[] { 0, 13, 0, -1, 0, 0, 0, 1, 0 });   //顶视 63             lookatValue =http://www.mamicode.com/(double[])viewDefaultPos[0].Clone(); 64  65             lightColor.Add(new float[] { 1f, 1f, 1f, 1f });  //环境光(ambient light) 66             lightColor.Add(new float[] { 1f, 1f, 1f, 1f });  //漫射光(diffuse light) 67             lightColor.Add(new float[] { 1f, 1f, 1f, 1f });  //镜面反射光(specular light) 68  69             setLightColor(gl); 70             gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_POSITION, lightPos); 71              72             gl.Enable(OpenGL.GL_LIGHTING); 73             gl.Enable(OpenGL.GL_LIGHT0); 74  75             gl.ClearColor(0, 0, 0, 0); 76         } 77  78         private void drawOneSphere(ref OpenGL gl, float xPos, float yPos, float zPos, bool isLine) 79         { 80             gl.PushMatrix(); 81             { 82                 gl.Translate(xPos, yPos, zPos); 83                 gl.Color(lightSphereColor); 84                 drawSphere(gl,1,20,10,isLine); 85             } 86             gl.PopMatrix(); 87         } 88  89         private void openGLControl_Resized(object sender, EventArgs e) 90         { 91  92             OpenGL gl = openGLControl.OpenGL; 93             gl.MatrixMode(OpenGL.GL_PROJECTION); 94             gl.LoadIdentity(); 95             gl.Perspective(40.0f, (double)Width / (double)Height, 0.01, 100.0); 96  97  98             gl.LookAt(lookatValue[0], lookatValue[1], lookatValue[2], 99                 lookatValue[3], lookatValue[4], lookatValue[5],100                 lookatValue[6], lookatValue[7], lookatValue[8]);101             102             gl.MatrixMode(OpenGL.GL_MODELVIEW);103             updateLabInfo();104         }105 106         internal void DrawCube(ref OpenGL Gl, float xPos, float yPos, float zPos, bool isLine)107         {108             Gl.PushMatrix();109             Gl.Translate(xPos, yPos, zPos);110             if (isLine)111                 Gl.Begin(OpenGL.GL_LINE_STRIP);112             else113                 Gl.Begin(OpenGL.GL_POLYGON);114 115             /** 顶面 */116             Gl.Vertex(0.0f, 0.0f, 0.0f);117             Gl.Vertex(0.0f, 0.0f, -1.0f);118             Gl.Vertex(-1.0f, 0.0f, -1.0f);119             Gl.Vertex(-1.0f, 0.0f, 0.0f);120 121             /** 前面 */122             Gl.Vertex(0.0f, 0.0f, 0.0f);123             Gl.Vertex(-1.0f, 0.0f, 0.0f);124             Gl.Vertex(-1.0f, -1.0f, 0.0f);125             Gl.Vertex(0.0f, -1.0f, 0.0f);126 127             /** 右面 */128             Gl.Vertex(0.0f, 0.0f, 0.0f);129             Gl.Vertex(0.0f, -1.0f, 0.0f);130             Gl.Vertex(0.0f, -1.0f, -1.0f);131             Gl.Vertex(0.0f, 0.0f, -1.0f);132 133             /** 左面*/134             Gl.Vertex(-1.0f, 0.0f, 0.0f);135             Gl.Vertex(-1.0f, 0.0f, -1.0f);136             Gl.Vertex(-1.0f, -1.0f, -1.0f);137             Gl.Vertex(-1.0f, -1.0f, 0.0f);138 139             /** 底面 */140             Gl.Vertex(0.0f, 0.0f, 0.0f);141             Gl.Vertex(0.0f, -1.0f, -1.0f);142             Gl.Vertex(-1.0f, -1.0f, -1.0f);143             Gl.Vertex(-1.0f, -1.0f, 0.0f);144 145 146             /** 后面 */147             Gl.Vertex(0.0f, 0.0f, 0.0f);148             Gl.Vertex(-1.0f, 0.0f, -1.0f);149             Gl.Vertex(-1.0f, -1.0f, -1.0f);150             Gl.Vertex(0.0f, -1.0f, -1.0f);151             Gl.End();152             Gl.PopMatrix();153         }154 155         void drawGrid(OpenGL gl)156         {157             //绘制过程158             gl.PushAttrib(OpenGL.GL_CURRENT_BIT);  //保存当前属性159             gl.PushMatrix();                        //压入堆栈160             gl.Translate(0f, -2f, 0f);161             gl.Color(0f, 0f, 1f);162 163             //在X,Z平面上绘制网格164             for (float i = -50; i <= 50; i += 1)165             {166                 //绘制线167                 gl.Begin(OpenGL.GL_LINES);168                 {169                     if (i == 0)170                         gl.Color(0f, 1f, 0f);171                     else172                         gl.Color(0f, 0f, 1f);173 174                     //X轴方向175                     gl.Vertex(-50f, 0f, i);176                     gl.Vertex(50f, 0f, i);177                     //Z轴方向 178                     gl.Vertex(i, 0f, -50f);179                     gl.Vertex(i, 0f, 50f);180 181                 }182                 gl.End();183             }184             gl.PopMatrix();185             gl.PopAttrib();186         }187 188       189         void drawSphere(OpenGL gl,double radius,int segx,int segy,bool isLines)190         {191             gl.PushMatrix();192             gl.Translate(2f, 1f, 2f);193             var sphere = gl.NewQuadric();194             if (isLines)195                 gl.QuadricDrawStyle(sphere, OpenGL.GL_LINES);196             else197                 gl.QuadricDrawStyle(sphere, OpenGL.GL_QUADS);198             gl.QuadricNormals(sphere, OpenGL.GLU_SMOOTH);199             gl.QuadricOrientation(sphere, (int)OpenGL.GLU_OUTSIDE);200             gl.QuadricTexture(sphere, (int)OpenGL.GLU_FALSE);201             gl.Sphere(sphere, radius, segx, segy);202             gl.DeleteQuadric(sphere);203             gl.PopMatrix();204         }205 206         private void moveObject(int obj,string keyName)207         {208             //obj==0移动视图209             switch (keyName)210             {211                 case "btnQ":212                     if (obj == 0) ++lookatValue[1];   //y213                     else214                         ++lightPos[1];215                     break;216                 case "btnE":217                     if (obj == 0) --lookatValue[1];218                     else219                         --lightPos[1];220                     break;221                 case "btnW":222                     if (obj == 0) --lookatValue[2];   //z223                     else224                        --lightPos[2];225                     break;226                 case "btnS":227                     if (obj == 0)  ++lookatValue[2];228                     else229                         ++lightPos[2];230                     break;231                 case "btnA":232                     if (obj == 0) --lookatValue[0];  //X233                     else234                        --lightPos[0];235                     break;236                 case "btnD":237                     if (obj == 0)  ++lookatValue[0];238                     else239                         ++lightPos[0];240                     break;241             }242         }243 244         private void rbPerspective_CheckedChanged(object sender, EventArgs e)245         {246             switch (((RadioButton)sender).Name)247             {248                 case "rbPerspective":249                     isPerspective = !isPerspective;250                     isFrontView = false;251                     isTopView = false;252                     isLeftView = false;253                     break;254                 case "rbLeft":255                      isLeftView = !isLeftView;256                     isFrontView = false;257                     isPerspective = false;258                     isTopView = false;259                     break;260                 case "rbFront":261                      isFrontView = !isFrontView;262                     isTopView = false;263                     isPerspective = false;264                     isLeftView = false;265                     break;266                 case "rbTop":267                      isTopView = !isTopView;268                     isPerspective = false;269                     isLeftView = false;270                     isFrontView = false;271                     break;272                 default:273                     return;274             }275             setViewDefaultValue();276             openGLControl_Resized(null, null);277         }278 279         private void cbxRotate_CheckedChanged(object sender, EventArgs e)280         {281             var cbx=((CheckBox)sender);282             switch (cbx.Name)283             {284                 case "cbxRotate":285                     isRotate = cbx.Checked;286                     break;287                 case "cbxLines":288                     isLines = cbx.Checked;289                     break;290                 case "cbxLightOff":291                     if (!cbx.Checked)292                         this.openGLControl.OpenGL.Enable(OpenGL.GL_LIGHT0);293                     else294                         this.openGLControl.OpenGL.Disable(OpenGL.GL_LIGHT0);295                     break;296             }297         }298 299         private void SharpGLForm_Load(object sender, EventArgs e)300         {301             this.cbxLightType.SelectedIndex = 0;302             updateLabInfo();303         }304 305         private void updateLabInfo()306         {307             tbLightPos.Text = string.Format("{0},{1},{2},{3}", lightPos[0], lightPos[1], lightPos[2], lightPos[3]);308             tbLookAt.Text = string.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8}", lookatValue[0], lookatValue[1], lookatValue[2],309                 lookatValue[3], lookatValue[4], lookatValue[5], lookatValue[6], lookatValue[7], lookatValue[8]);310         }311 312         private void rbWhite_CheckedChanged(object sender, EventArgs e)313         {314             var rad = ((RadioButton)sender);315             var lightType = this.cbxLightType.SelectedIndex;316             if (rad.Checked)317             {318                 switch (rad.Name)319                 {320                     case "rbWhite":321                         lightColor[lightType][0] = 1f;322                         lightColor[lightType][1] = 1f;323                         lightColor[lightType][2] = 1f;324                         lightColor[lightType][3] = 1f;325                         break;326                     case "rbRed":327                         lightColor[lightType][0] = 1f;328                         lightColor[lightType][1] = 0f;329                         lightColor[lightType][2] = 0f;330                         lightColor[lightType][3] = 1f;331                         break;332                     case "rbGreen":333                         lightColor[lightType][0] = 0f;334                         lightColor[lightType][1] = 1f;335                         lightColor[lightType][2] = 0f;336                         lightColor[lightType][3] = 1f;337                         break;338                     case "rbBlue":339                         lightColor[lightType][0] = 0f;340                         lightColor[lightType][1] = 0f;341                         lightColor[lightType][2] = 1f;342                         lightColor[lightType][3] = 1f;343                         break;344                 }345                 setLightColor(openGLControl.OpenGL);346             }347         }348 349         private void cbxLightType_SelectedIndexChanged(object sender, EventArgs e)350         {351             var lightType = this.cbxLightType.SelectedIndex;352             if (lightType >= 0)353                 judgeColor(lightColor[lightType]);354         }355 356         private void judgeColor(float[] color)357         {358             if (color[0] == 1f && color[1] == 1f && color[2] == 1f && color[3] == 1f)359                 rbWhite.Checked = true;360             else if (color[0] == 1f && color[1] == 0f && color[2] == 0f && color[3] == 1f)361                 rbRed.Checked = true;362             else if (color[0] == 0f && color[1] == 1f && color[2] == 0f && color[3] == 1f)363                 rbGreen.Checked = true;364             else if (color[0] == 0f && color[1] == 0f && color[2] == 1f && color[3] == 1f)365                 rbBlue.Checked = true;   366         }367 368         private void btnQ_Click(object sender, EventArgs e)369         {370             moveObject(radioButton1.Checked ? 0 : 1,((Button)sender).Name);371             openGLControl_Resized(null, null);372             openGLControl.OpenGL.Light(OpenGL.GL_LIGHT0, OpenGL.GL_POSITION, lightPos);373         }374 375         private void setViewDefaultValue()376         {377             if (isPerspective)378             {379                 lookatValue = http://www.mamicode.com/(double[])viewDefaultPos[0].Clone();380             }381             else if (isFrontView)382             {383                 lookatValue = http://www.mamicode.com/(double[])viewDefaultPos[1].Clone();384             }385             else if (isLeftView)386             {387                 lookatValue = http://www.mamicode.com/(double[])viewDefaultPos[2].Clone();388             }389             else if (isTopView)390             {391                 lookatValue = http://www.mamicode.com/(double[])viewDefaultPos[3].Clone();392             }393         }394 395         private void btnDefaultPOS_Click(object sender, EventArgs e)396         {397             if (radioButton1.Checked)398             {399                 setViewDefaultValue();400             }401             else402             {403                 lightPos = new float[] { -1, -3, 1, 1 };404                 openGLControl.OpenGL.Light(OpenGL.GL_LIGHT0, OpenGL.GL_POSITION, lightPos);405             }406             openGLControl_Resized(null, null); 407         }408 409         private void openGLControl_KeyDown(object sender, KeyEventArgs e)410         {411             string name = string.Empty;412             switch (e.KeyCode)413             {414                 case Keys.W:415                     name = "btnW";416                     break;417                 case Keys.A:418                     name = "btnA";419                     break;420                 case Keys.S:421                     name = "btnS";422                     break;423                 case Keys.D:424                     name = "btnD";425                     break;426                 case Keys.Q:427                     name = "btnQ";428                     break;429                 case Keys.E:430                     name = "btnE";431                     break;432             }433             moveObject(radioButton1.Checked ? 0 : 1, name);434             openGLControl_Resized(null, null);435         }436 437         private void btnSetPos_Click(object sender, EventArgs e)438         {439             if (radioButton1.Checked)440             {441                 double[] ary = tbLookAt.Text.Split(,).Select(s => Convert.ToDouble(s)).ToArray();442                 lookatValue =http://www.mamicode.com/ ary;443                 openGLControl_Resized(null, null); 444             }445             else446             {447                 float[] ary = tbLightPos.Text.Split(,).Select(s => Convert.ToSingle(s)).ToArray();448                 lightPos = ary;449                 openGLControl.OpenGL.Light(OpenGL.GL_LIGHT0, OpenGL.GL_POSITION, ary);450             }451            452         }453 454        455     }456 }

 

有关灯光的代码如下粗体显示部分:

 1   private void setLightColor(OpenGL gl) 2         { 3             gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_AMBIENT, lightColor[0]); 4             gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_DIFFUSE, lightColor[1]); 5             gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_SPECULAR, lightColor[2]); 6         } 7  8         private void openGLControl_OpenGLInitialized(object sender, EventArgs e) 9         {10             OpenGL gl = openGLControl.OpenGL;11 12             //四个视图的缺省位置13             viewDefaultPos.Add(new double[] { 1, 1, 2, 0, 0, 0, 0, 1, 0 });     //透视14             viewDefaultPos.Add(new double[] { 0, 0, 2, 0, 0, 0, 0, 1, 0 });     //前视 15             viewDefaultPos.Add(new double[] { 5, 0, 0, 0, 0, 0, 0, 1, 0 });     //左视16             viewDefaultPos.Add(new double[] { 0, 13, 0, -1, 0, 0, 0, 1, 0 });   //顶视17             lookatValue =http://www.mamicode.com/(double[])viewDefaultPos[0].Clone();18 19             lightColor.Add(new float[] { 1f, 1f, 1f, 1f });  //环境光(ambient light)20             lightColor.Add(new float[] { 1f, 1f, 1f, 1f });  //漫射光(diffuse light)21             lightColor.Add(new float[] { 1f, 1f, 1f, 1f });  //镜面反射光(specular light)22 23             setLightColor(gl);24             gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_POSITION, lightPos);25             26             gl.Enable(OpenGL.GL_LIGHTING);27             gl.Enable(OpenGL.GL_LIGHT0);28 29             gl.ClearColor(0, 0, 0, 0);30         }

 

第3,4,5行是创建灯光三个部分 环境光,漫射光,镜面反射光。

第24行是设定灯光的位置。

第26,27是让灯光开,有效。

 

灯光代码确实比较简单,这段代码其它部分没什么好说的,笔者按界面功能直述其意,朋友们应该很容易懂。

唯一要关注下的是:视图和灯光的参数修改是如何实时生效的。

 

 

本节源代码下载

 

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

 

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