zoukankan      html  css  js  c++  java
  • SharpGL学习笔记(十二) 光源例子:解决光源场景中的常见问题

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

    • (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[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             else
    178                 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                     else
    212                         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.  对于问题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/

  • 相关阅读:
    88. Merge Sorted Array
    87. Scramble String
    86. Partition List
    85. Maximal Rectangle
    84. Largest Rectangle in Histogram
    83. Remove Duplicates from Sorted List
    82. Remove Duplicates from Sorted List II
    81. Search in Rotated Sorted Array II
    80. Remove Duplicates from Sorted Array II
    计算几何——点线关系(叉积)poj2318
  • 原文地址:https://www.cnblogs.com/hackpig/p/5824745.html
Copyright © 2011-2022 走看看