SharpGL学习笔记(十二) 光源例子:解决光源场景中的常见问题

时间:2022-08-28 12:32:15

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

  • (1) 导入的3ds模型,如果没有材质光照效果很奇怪.
    如下图
  • SharpGL学习笔记(十二) 光源例子:解决光源场景中的常见问题
  • (2) 导入的3ds模型,有材质,灯光效果发暗,材质偏色,效果也很奇怪.

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

  • SharpGL学习笔记(十二) 光源例子:解决光源场景中的常见问题
  • (3) 场景引入灯光后,场景中的物体的颜色就全部消失了,即合引入颜色材质,效果也是怪怪的.

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

  • SharpGL学习笔记(十二) 光源例子:解决光源场景中的常见问题
  • (4) 场景中有物体引入材质后,整个场景的颜色就变得很奇怪

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

  • SharpGL学习笔记(十二) 光源例子:解决光源场景中的常见问题
  • (5) 导入的3ds模型,贴图颜色失真。

  • SharpGL学习笔记(十二) 光源例子:解决光源场景中的常见问题

    下图中的茶壶,柱体,地板的贴图分别对应上图材质图片,可以看到经过纹理映射后,贴图颜色失真。
    这种问题并不是光源的问题,但是我也在这里一并列出来。

  • SharpGL学习笔记(十二) 光源例子:解决光源场景中的常见问题

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

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

 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SharpGL; namespace SharpGLWinformsApplication1
{
/// <summary>
/// 原创文章,出自"博客园, 猪悟能'S博客" : http://www.cnblogs.com/hackpig/
/// </summary>
public partial class SharpGLForm : Form
{
private float rotation = 0.0f,rotation2=0f,rotation3=0f;
SharpGL.SceneGraph.Assets.Texture textureBox = new SharpGL.SceneGraph.Assets.Texture(); float[] fLightPosition = new float[] { 16f, 9f, -18f, 0f };// 光源位置
float[] fLightAmbient = new float[] { 1f, 1f, 1f, 0f };// 环境光参数
float[] fLightDiffuse = new float[] { 1f, 1f, 1f,0f };// 漫射光参数 float[] fLightPosition2 = new float[] { -7f, 5f, 2f, 0f };// 光源位置
float[] fLightAmbient2 = new float[] { 0f, 0f, 1f, 0f };// 环境光参数
float[] fLightDiffuse2 = new float[] { 0f, 0f, 1f, 0f };// 漫射光参数 bool f1 = false; public SharpGLForm()
{
InitializeComponent();
} private void openGLControl_OpenGLDraw(object sender, PaintEventArgs e)
{
OpenGL gl = openGLControl.OpenGL;
gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);
gl.LoadIdentity();
gl.Rotate(rotation3, , , );
drawGrid(gl);
drawLightPT(gl);
drawLightPT2(gl);
drawTextrueBox(gl, , , );
drawSphere(gl, , , , false); moveLightA(gl);
rotation3+=0.1f;
} private void moveLightA(OpenGL gl)
{
if (!f1)
--fLightPosition[];
else
++fLightPosition[];
if (fLightPosition[] > 15f)
{
f1 = !f1;
}
else if (fLightPosition[] < -25f)
{
f1 = !f1;
}
gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_POSITION, fLightPosition);//光源位置
} private void drawLightPT(OpenGL gl)
{
gl.PushMatrix();
{
gl.Disable(OpenGL.GL_TEXTURE_2D);
gl.Color(0f,1f, 1f);
gl.Scale(0.2, 0.2, 0.2);
gl.Translate(fLightPosition[]- , fLightPosition[]+, fLightPosition[]);
drawBox(gl, , , );
}
gl.PopMatrix();
} private void drawLightPT2(OpenGL gl)
{ rotation2+=4f;
gl.PushMatrix();
{
gl.LoadIdentity();
gl.Disable(OpenGL.GL_TEXTURE_2D);
gl.Color(0f, 1f, 1f);
gl.Scale(0.2, 0.2, 0.2);
gl.Rotate(rotation2, , , );
gl.Translate(- , , ); drawBox(gl, , , );
}
gl.PopMatrix();
} private void drawTextrueBox(OpenGL gl, float xPos, float yPos, float zPos)
{
rotation += 3.0f;
gl.PushMatrix();
{
textureBox.Bind(gl);
gl.Enable(OpenGL.GL_TEXTURE_2D);
gl.Rotate(rotation, , , );
gl.Translate(-, , -);
gl.Scale(, , );
drawBox(gl,xPos, yPos, zPos);
}
gl.PopMatrix();
} private void drawBox(OpenGL gl, float xPos, float yPos, float zPos)
{
gl.PushMatrix();
gl.Translate(xPos, yPos, zPos); gl.Begin(OpenGL.GL_QUADS); //前
gl.TexCoord(, ); gl.Vertex(, , );
gl.TexCoord(, ); gl.Vertex(-, , );
gl.TexCoord(, ); gl.Vertex(-, -, );
gl.TexCoord(, ); gl.Vertex(, -, ); //底
gl.TexCoord(, ); gl.Vertex(, , );
gl.TexCoord(, ); gl.Vertex(, , -);
gl.TexCoord(, ); gl.Vertex(-, , -);
gl.TexCoord(, ); gl.Vertex(-, , ); //左
gl.TexCoord(, ); gl.Vertex(-, , );
gl.TexCoord(, ); gl.Vertex(-, , -);
gl.TexCoord(, ); gl.Vertex(-, -, -);
gl.TexCoord(, ); gl.Vertex(-, -, ); //右
gl.TexCoord(, ); gl.Vertex(, , );
gl.TexCoord(, ); gl.Vertex(, , -);
gl.TexCoord(, ); gl.Vertex(, -, -);
gl.TexCoord(, ); gl.Vertex(, -, ); //后
gl.TexCoord(, ); gl.Vertex(, , -);
gl.TexCoord(, ); gl.Vertex(-, , -);
gl.TexCoord(, ); gl.Vertex(-, -, -);
gl.TexCoord(, ); gl.Vertex(, -, -); //顶
gl.TexCoord(, ); gl.Vertex(, -, );
gl.TexCoord(, ); gl.Vertex(, -, -);
gl.TexCoord(, ); gl.Vertex(-, -, -);
gl.TexCoord(, ); gl.Vertex(-, -, ); gl.End();
gl.PopMatrix(); } void drawSphere(OpenGL gl, double radius, int segx, int segy, bool isLines)
{ gl.PushMatrix();
gl.Disable(OpenGL.GL_TEXTURE_2D);
gl.Translate(-7f, -1f, 2f);
var sphere = gl.NewQuadric(); if (isLines)
gl.QuadricDrawStyle(sphere, OpenGL.GL_LINES);
else
gl.QuadricDrawStyle(sphere, OpenGL.GL_QUADS);
gl.QuadricNormals(sphere, OpenGL.GLU_SMOOTH);
gl.QuadricOrientation(sphere, (int)OpenGL.GLU_OUTSIDE);
gl.QuadricTexture(sphere, (int)OpenGL.GLU_FALSE);
gl.Sphere(sphere, radius, segx, segy);
gl.DeleteQuadric(sphere);
gl.PopMatrix(); } void drawGrid(OpenGL gl)
{
//关闭纹理和光照
gl.Disable(OpenGL.GL_TEXTURE_2D);
gl.Disable(OpenGL.GL_LIGHTING);

//绘制过程
gl.PushAttrib(OpenGL.GL_CURRENT_BIT); //保存当前属性
gl.PushMatrix(); //压入堆栈
gl.Translate(0f, -2f, 0f);
gl.Color(0f, 0f, 1f); //在X,Z平面上绘制网格
for (float i = -; i <= ; i += )
{
//绘制线
gl.Begin(OpenGL.GL_LINES);
{
if (i == )
gl.Color(0f, 1f, 0f);
else
gl.Color(0f, 0f, 1f); //X轴方向
gl.Vertex(-50f, 0f, i);
gl.Vertex(50f, 0f, i);
//Z轴方向
gl.Vertex(i, 0f, -50f);
gl.Vertex(i, 0f, 50f); }
gl.End();
}
gl.PopMatrix();
gl.PopAttrib();
gl.Enable(OpenGL.GL_LIGHTING);
} private void openGLControl_OpenGLInitialized(object sender, EventArgs e)
{
OpenGL gl = openGLControl.OpenGL;
textureBox.Create(gl, "image.bmp"); gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_AMBIENT, fLightAmbient);//环境光源
gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_DIFFUSE, fLightDiffuse);//漫射光源
gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_POSITION, fLightPosition);//光源位置 gl.Light(OpenGL.GL_LIGHT1, OpenGL.GL_AMBIENT, fLightAmbient2);//环境光源
gl.Light(OpenGL.GL_LIGHT1, OpenGL.GL_DIFFUSE, fLightDiffuse2);//漫射光源
gl.Light(OpenGL.GL_LIGHT1, OpenGL.GL_POSITION, fLightPosition2);//光源位置 gl.Enable(OpenGL.GL_LIGHTING);//开启光照
gl.Enable(OpenGL.GL_LIGHT0);
gl.Enable(OpenGL.GL_LIGHT1); gl.Enable(OpenGL.GL_NORMALIZE);
gl.ClearColor(, , , ); } private void openGLControl_Resized(object sender, EventArgs e)
{
OpenGL gl = openGLControl.OpenGL;
gl.MatrixMode(OpenGL.GL_PROJECTION);
gl.LoadIdentity();
gl.Perspective(60.0f, (double)Width / (double)Height, 0.01, 100.0);
gl.LookAt(-, , -, -, , , , , );
gl.MatrixMode(OpenGL.GL_MODELVIEW);
} }
}

效果如下图:

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

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

SharpGL学习笔记(十二) 光源例子:解决光源场景中的常见问题

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

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

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

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

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

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

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

   SharpGL学习笔记(十二) 光源例子:解决光源场景中的常见问题

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);

可以看到,效果正常了。

SharpGL学习笔记(十二) 光源例子:解决光源场景中的常见问题

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

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

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

本节源代码下载

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

SharpGL学习笔记(十二) 光源例子:解决光源场景中的常见问题的更多相关文章

  1. ROS学习笔记十二:使用gazebo在ROS中仿真

    想要在ROS系统中对我们的机器人进行仿真,需要使用gazebo. gazebo是一种适用于复杂室内多机器人和室外环境的仿真环境.它能够在三维环境中对多个机器人.传感器及物体进行仿真,产生实际传感器反馈 ...

  2. python3&period;4学习笔记&lpar;十二&rpar; python正则表达式的使用,使用pyspider匹配输出带&period;html结尾的URL

    python3.4学习笔记(十二) python正则表达式的使用,使用pyspider匹配输出带.html结尾的URL实战例子:使用pyspider匹配输出带.html结尾的URL:@config(a ...

  3. Go语言学习笔记十二: 范围&lpar;Range&rpar;

    Go语言学习笔记十二: 范围(Range) rang这个关键字主要用来遍历数组,切片,通道或Map.在数组和切片中返回索引值,在Map中返回key. 这个特别像python的方式.不过写法上比较怪异使 ...

  4. SharpGL学习笔记&lpar;十四&rpar; 材质:十二个材质球

    材质颜色 OpenGL用材料对光的红.绿.蓝三原色的反射率来近似定义材料的颜色.象光源一样,材料颜色也分成环境.漫反射和镜面反射成分,它们决定了材料对环境光.漫反射光和镜面反射光的反射程度.在进行光照 ...

  5. SharpGL学习笔记&lpar;十&rpar; 常见的光源类型,创建光源

    在OpenGL中,使用光源的特性组合,如颜色,位置,方向等等,可以创建多种不同类型的灯光. 常见的几种灯光类型有: 定向光源(directonal) 定位光源(positional) 衰减光源 聚光灯 ...

  6. java jvm学习笔记十二(访问控制器的栈校验机制)

    欢迎装载请说明出处:http://blog.csdn.net/yfqnihao 本节源码:http://download.csdn.net/detail/yfqnihao/4863854 这一节,我们 ...

  7. SharpGL学习笔记&lpar;十九&rpar; 摄像机漫游

    所谓的摄像机漫游,就是可以在场景中来回走动. 现实中,我们通过眼睛观察东西,身体移动带动眼睛移动观察身边的事物,这也是在漫游. 在OpenGL中我们使用函数LookAt()来操作摄像机在三维场景中进行 ...

  8. &lpar;C&sol;C&plus;&plus;学习笔记&rpar; 十二&period; 指针

    十二. 指针 ● 基本概念 位系统下为4字节(8位十六进制数),在64位系统下为8字节(16位十六进制数) 进制表示的, 内存地址不占用内存空间 指针本身是一种数据类型, 它可以指向int, char ...

  9. SharpGL学习笔记&lpar;十五&rpar; 纹理映射

    纹理映射非常实用,在游戏场景中已经无所不在了. 一个较少的多边形构成的模形,配合好的纹理贴图进行映射,可以得到逼真的效果.游戏中的天空,地面,墙面,和植物都是纹理贴图进行映射的. 例如最终幻想8的男女 ...

随机推荐

  1. Python之路【第十八篇】Django小项目webQQ实现

    WEBQQ的实现的几种方式 1.HTTP协议特点 首先这里要知道HTTP协议的特点:短链接.无状态! 在不考虑本地缓存的情况举例来说:咱们在连接博客园的时候,当tcp连接后,我会把我自己的http头发 ...

  2. C&num;语法功能结构

    1.File打开指定文件夹或者文件,"\"为转义字符System.Diagnostics.Process.Start(Application.StartupPath + &quot ...

  3. c&num; 使用hook来监控鼠标键盘事件的示例代码

    如果这个程序在10几年前,QQ刚刚兴起的时候,有了这个代码,就可实现盗号了. 当然使用钩子我们更多的是实现"全局快捷键"的需求. 比如 程序最小化隐藏后要"某快捷键&qu ...

  4. 11&period;hibernate的连接查询

    1.创建如下javaweb项目结构 2.在项目的src下创建hibernate.cfg.xml主配置文件 <?xml version="1.0" encoding=&quot ...

  5. C&plus;&plus;中运行外部程序

    关于三个SDK函数: WinExec, ShellExecute,CreateProcess 的其他注意事项: [1]定义头文件 必须定义以下两个头文件: #include <shlobj.h& ...

  6. Calendar使用方法

    Calendar类的静态方法getInstance()可以初始化一个日历对象: Calendar now = Calendar.getInstance(); 可以使用下面三个方法把日历定到任何一个时间 ...

  7. J2EE进阶&lpar;七&rpar;利用SSH框架根据数据表建立model类

    J2EE进阶(七)利用SSH框架根据数据表建立model类 前言 在利用SSH框架进行项目开发时,若将数据库已经建好,并且数据表之间的依赖关系已经确定,可以利用Hibernate的反转功能进行mode ...

  8. codeforces 38G - Queue splay伸展树

    题目 https://codeforces.com/problemset/problem/38/G 题意: 一些人按顺序进入队列,每个人有两个属性,地位$A$和能力$C$ 每个人进入时都在队尾,并最多 ...

  9. HDU 2095 find your present &lpar;2&rpar; 动态链表

    解题报告:输入一个n,后面紧跟着输入n个数,输入的这n个数中,除了有一个数的个数为奇数外,其它的数的个数都是偶数个,现在要你找出这个个数为奇数的这个数. 看起来好像很简单的样子,不过,这题的重点不在这 ...

  10. 什么是DHTML?

    DHTML是近年来网络发展进程中最振奋人心也最具实用性的创新之一.它是一种通过各种技术的综合发展而得以实现的概念(当然,不同的浏览器,实现的程度也不同),这些技术包括Javascript, VBScr ...