• 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/

  • 相关阅读:
    SpringBoot配置Druid数据源
    springboot自定义异常处理
    SpringBoot配置详解
    设计模式 | 模板方法模式(template method)
    设计模式 | 原型模式(prototype)
    设计模式 | 工厂方法模式(factory method)
    设计模式 | 代理模式(proxy)
    设计模式 | 装饰模式(decorator)
    设计模式 | 策略模式(strategy)
    设计模式 | 简单工厂模式(static factory method)
  • 原文地址:https://www.cnblogs.com/hackpig/p/5824745.html
Copyright © 2020-2023  润新知