博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SharpGL学习笔记(十二) 光源例子:解决光源场景中的常见问题
阅读量:6229 次
发布时间:2019-06-21

本文共 10380 字,大约阅读时间需要 34 分钟。

 

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

  • (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     ///  14     /// 原创文章,出自"博客园, 猪悟能'S博客" : http://www.cnblogs.com/hackpig/ 15     ///  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.  对于问题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博客" : 

 

你可能感兴趣的文章
ORA-39901 EXPDP分区报错/分区表删除不完全
查看>>
HDU 4946 共线凸包
查看>>
图片轮播插件 Slides-SlidesJS-3
查看>>
让python 3支持mysqldb的解决方法
查看>>
JAVA与.NET的相互调用——TCP/IP相互调“.NET研究”用基本架构
查看>>
一起谈.NET技术,打包Asp.Net 网站成为一个exe方便快捷的进行客户演示
查看>>
[转]Android中设置TextView的颜色setTextColor
查看>>
随手记一 2018/04/23 Ajax基础了解
查看>>
C++ C# python 中输入输出函数对比
查看>>
Java 入门
查看>>
test4 结对项目
查看>>
idea老版本下载
查看>>
SQL SERVER 2008 多边形问题的解决
查看>>
RTEMS进程同步机制
查看>>
关于访问MSMQ远端私有队列的一点经验
查看>>
前端表单校验插件 jquery.validate.min.js自定义校验规则
查看>>
MySQL系列:高可用架构之MHA
查看>>
python堡垒机开发
查看>>
共享内存
查看>>
关于this
查看>>