你的位置:首页 > ASP.net教程

[ASP.net教程]SharpGL学习笔记(十二) 光源例子:解决光源场景中的常见问题


 

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

  • (1) 导入的3ds模型,如果没有材质光照效果很奇怪.
    如下图
  •  

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

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

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

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

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

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

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

 

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

 

 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[4] { 16f, 9f, -18f, 0f };// 光源位置  22     float[] fLightAmbient = new float[4] { 1f, 1f, 1f, 0f };// 环境光参数  23     float[] fLightDiffuse = new float[4] { 1f, 1f, 1f,0f };// 漫射光参数 24  25     float[] fLightPosition2 = new float[4] { -7f, 5f, 2f, 0f };// 光源位置  26     float[] fLightAmbient2 = new float[4] { 0f, 0f, 1f, 0f };// 环境光参数  27     float[] fLightDiffuse2 = new float[4] { 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, 0, 1, 0); 42       drawGrid(gl); 43       drawLightPT(gl); 44       drawLightPT2(gl); 45       drawTextrueBox(gl, 1, 0, 2); 46       drawSphere(gl, 2, 20, 20, false); 47  48       moveLightA(gl); 49       rotation3+=0.1f; 50     } 51  52     53     private void moveLightA(OpenGL gl) 54     { 55       if (!f1) 56         --fLightPosition[0]; 57       else 58         ++fLightPosition[0]; 59       if (fLightPosition[0] > 15f) 60       { 61         f1 = !f1; 62       } 63       else if (fLightPosition[0] < -25f) 64       { 65         f1 = !f1; 66       } 67       gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_POSITION, fLightPosition);//光源位置  68     } 69  70     71  72     private void drawLightPT(OpenGL gl) 73     { 74       gl.PushMatrix(); 75       { 76         gl.Disable(OpenGL.GL_TEXTURE_2D); 77         gl.Color(0f,1f, 1f); 78         gl.Scale(0.2, 0.2, 0.2); 79         gl.Translate(fLightPosition[0]-5 , fLightPosition[1]+5, fLightPosition[2]);  80         drawBox(gl, 0, 0, 0); 81       } 82       gl.PopMatrix(); 83     } 84  85     private void drawLightPT2(OpenGL gl) 86     { 87        88       rotation2+=4f; 89       gl.PushMatrix(); 90       { 91         gl.LoadIdentity(); 92         gl.Disable(OpenGL.GL_TEXTURE_2D); 93         gl.Color(0f, 1f, 1f); 94         gl.Scale(0.2, 0.2, 0.2); 95         gl.Rotate(rotation2, 0, 1, 0); 96         gl.Translate(-28 , 8 , 5); 97         98         drawBox(gl, 0, 0, 0); 99       }100       gl.PopMatrix();101     }102 103     private void drawTextrueBox(OpenGL gl, float xPos, float yPos, float zPos)104     {105       rotation += 3.0f;106       gl.PushMatrix();107       {108         textureBox.Bind(gl);109         gl.Enable(OpenGL.GL_TEXTURE_2D);110         gl.Rotate(rotation, 0, 1, 0);111         gl.Translate(-1, 2, -5);112         gl.Scale(3, 3, 3);113         drawBox(gl,xPos, yPos, zPos);114       }115       gl.PopMatrix();116     }117 118     private void drawBox(OpenGL gl, float xPos, float yPos, float zPos)119     {     120       gl.PushMatrix();121       gl.Translate(xPos, yPos, zPos);122      123       gl.Begin(OpenGL.GL_QUADS);124 125       //前126       gl.TexCoord(0, 0); gl.Vertex(0, 0, 0);127       gl.TexCoord(1, 0); gl.Vertex(-1, 0, 0);128       gl.TexCoord(1, 1); gl.Vertex(-1, -1, 0);129       gl.TexCoord(0, 1); gl.Vertex(0, -1, 0);130 131       //底132       gl.TexCoord(0, 0); gl.Vertex(0, 0, 0);133       gl.TexCoord(1, 0); gl.Vertex(0, 0, -1);134       gl.TexCoord(1, 1); gl.Vertex(-1, 0, -1);135       gl.TexCoord(0, 1); gl.Vertex(-1, 0, 0);136 137       //左138       gl.TexCoord(0, 0); gl.Vertex(-1, 0, 0);139       gl.TexCoord(1, 0); gl.Vertex(-1, 0, -1);140       gl.TexCoord(1, 1); gl.Vertex(-1, -1, -1);141       gl.TexCoord(0, 1); gl.Vertex(-1, -1, 0);142 143       //右144       gl.TexCoord(0, 0); gl.Vertex(0, 0, 0);145       gl.TexCoord(1, 0); gl.Vertex(0, 0, -1);146       gl.TexCoord(1, 1); gl.Vertex(0, -1, -1);147       gl.TexCoord(0, 1); gl.Vertex(0, -1, 0);148 149       //后150       gl.TexCoord(0, 0); gl.Vertex(0, 0, -1);151       gl.TexCoord(1, 0); gl.Vertex(-1, 0, -1);152       gl.TexCoord(1, 1); gl.Vertex(-1, -1, -1);153       gl.TexCoord(0, 1); gl.Vertex(0, -1, -1);154 155       //顶156       gl.TexCoord(0, 0); gl.Vertex(0, -1, 0);157       gl.TexCoord(1, 0); gl.Vertex(0, -1, -1);158       gl.TexCoord(1, 1); gl.Vertex(-1, -1, -1);159       gl.TexCoord(0, 1); gl.Vertex(-1, -1, 0);160 161 162       gl.End();163       gl.PopMatrix();164 165     }166 167     void drawSphere(OpenGL gl, double radius, int segx, int segy, bool isLines)168     {169      170       gl.PushMatrix();171       gl.Disable(OpenGL.GL_TEXTURE_2D);172       gl.Translate(-7f, -1f, 2f);173       var sphere = gl.NewQuadric();174     175       if (isLines)176         gl.QuadricDrawStyle(sphere, OpenGL.GL_LINES);177       else178         gl.QuadricDrawStyle(sphere, OpenGL.GL_QUADS);179       gl.QuadricNormals(sphere, OpenGL.GLU_SMOOTH);180       gl.QuadricOrientation(sphere, (int)OpenGL.GLU_OUTSIDE);181       gl.QuadricTexture(sphere, (int)OpenGL.GLU_FALSE);182       gl.Sphere(sphere, radius, segx, segy);183       gl.DeleteQuadric(sphere);184       gl.PopMatrix();185       186     }187 188 189   190 191     void drawGrid(OpenGL gl)192     {193       //关闭纹理和光照194       gl.Disable(OpenGL.GL_TEXTURE_2D);195       gl.Disable(OpenGL.GL_LIGHTING);196 197       //绘制过程198       gl.PushAttrib(OpenGL.GL_CURRENT_BIT); //保存当前属性199       gl.PushMatrix();            //压入堆栈200       gl.Translate(0f, -2f, 0f);201       gl.Color(0f, 0f, 1f);202 203       //在X,Z平面上绘制网格204       for (float i = -50; i <= 50; i += 1)205       {206         //绘制线207         gl.Begin(OpenGL.GL_LINES);208         {209           if (i == 0)210             gl.Color(0f, 1f, 0f);211           else212             gl.Color(0f, 0f, 1f);213 214           //X轴方向215           gl.Vertex(-50f, 0f, i);216           gl.Vertex(50f, 0f, i);217           //Z轴方向 218           gl.Vertex(i, 0f, -50f);219           gl.Vertex(i, 0f, 50f);220 221         }222         gl.End();223       }224       gl.PopMatrix();225       gl.PopAttrib();226       gl.Enable(OpenGL.GL_LIGHTING);227     }228 229     private void openGLControl_OpenGLInitialized(object sender, EventArgs e)230     {231       OpenGL gl = openGLControl.OpenGL;232       textureBox.Create(gl, "image.bmp");233 234       gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_AMBIENT, fLightAmbient);//环境光源 235       gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_DIFFUSE, fLightDiffuse);//漫射光源 236       gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_POSITION, fLightPosition);//光源位置 237 238       gl.Light(OpenGL.GL_LIGHT1, OpenGL.GL_AMBIENT, fLightAmbient2);//环境光源 239       gl.Light(OpenGL.GL_LIGHT1, OpenGL.GL_DIFFUSE, fLightDiffuse2);//漫射光源 240       gl.Light(OpenGL.GL_LIGHT1, OpenGL.GL_POSITION, fLightPosition2);//光源位置 241 242       gl.Enable(OpenGL.GL_LIGHTING);//开启光照 243       gl.Enable(OpenGL.GL_LIGHT0);244       gl.Enable(OpenGL.GL_LIGHT1);245 246       gl.Enable(OpenGL.GL_NORMALIZE);247       gl.ClearColor(0, 0, 0, 0);248       249     }250 251     private void openGLControl_Resized(object sender, EventArgs e)252     {253       OpenGL gl = openGLControl.OpenGL;254       gl.MatrixMode(OpenGL.GL_PROJECTION);255       gl.LoadIdentity();256       gl.Perspective(60.0f, (double)Width / (double)Height, 0.01, 100.0);257       gl.LookAt(-2, 3, -7, -2, 0, 0, 0, 1, 0);258       gl.MatrixMode(OpenGL.GL_MODELVIEW);259     }260 261 262    263   }264 }

 

效果如下图:

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

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

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

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

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

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

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

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

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

   

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

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

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

 

本节源代码下载

 

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