首页 > 代码库 > 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学习笔记(十一) 光源创建的综合例子:光源参数可调节的测试场景
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。