6-1. 定义法线和使用BasicEffect

6章 添加光照到场景

照亮场景听起来很简单:设置对象的位置到3D世界,定义光照的位置,你预料你的3D场景被正确照亮。

对于对象的每个面,显卡要计算表面接收到的光的数量。这个数量基于光照方向和三角形平面之间的角度。幸运的是,XNA框架有BasicEffect能为你执行所有这些计算。

但和名字一样,这个类只能用作一些基础照明效果。但如果你想用点光源,例如蜡烛?或者想要多个光?给你的对象加阴影?

要回答这些问题,你将要在HLSL中编码自己的效果。但本章没有放弃BasicEffect。你将学到如何添加额外功能,例如支持点光源和聚光灯。最后还会指引你到延缓渲染的世界,允许你用大量光源同时照亮场景。更令人称道的,你将学到阴影映射技术。

 

6-1. 定义法线和使用BasicEffect

问题

没有正确的光照,你的场景将看起来少了很多真实感。有些情况下,对象不被正确照亮时3D效果也将消失殆尽。例如,考虑一个球有一个整体的颜色。没有光照,所有球的像素将有同样的颜色,结果平面上看着像一个小片。当正确光照,球面向光源的部分就比其它部分亮,球看着就更有3D感。

 

解决方案

在计算机图形中,所有3D对象由三角形构成。你要每个三角形被依照送入的光源正确照亮。6-1是一个从左到右的单向光并影响6个不同位置,每个面2个三角形。

 

 

简单定义光源的位置和对象的位置对于显卡添加正确光照到对象是不够的。对3D对象的每个三角形,你将要添加一些信息,允许显卡计算命中表面的光照量。

可以通过给每个对象的每个顶点指定法线向量做到,这是三角形角落的峰值。一旦你在每个顶点指定正确法线,BasicEffect可以用正确光照渲染你的对象。

 

如何运作

6-1中许多正方形被绘制,它们的颜色代表光照的量。越垂直于光照方向的,接收的光照越多。最后一个正方形完全垂直与光照方向所以被完全照亮。第一个正方形虽然离光源最近但没被照亮。

 

定义法线

显卡如何知道三角形接收到多少光?每个三角形的每个角落(顶点),你将定义垂直于三角形的方向。这个方向叫法线方向。这个法线方向已经在6-1用箭头指出。因为这里只有一个方向垂直于表面,同一个正方形的所有顶点有一样的法线方向。

这个法线方向允许你的显卡计算多少光命中三角形。光的方向显示为图像底部从左至右的长黑色箭头。旋转的黑板代表6-1中的正方形。在光的方向的每个正方形的法线的投影显示为光方向上的厚厚的黑块。黑块越大,三角形越亮。

 

 

左边的三角形的法线垂直于光方向,所以投影是0,三角形不被照亮。右边的三角形的法线和光方向平行,所以投影值最大,面被完全照亮。给出顶点中的光方向和法线,你的显卡可以很容易计算出投影长度(板的厚度)。这就是显卡如何计算正确光照。

 

应用Shading到场景

如前所述,对每个像素,显卡将计算应用到像素的光照量。接下来,显卡作用这个光照值于像素的原色上。

 

添加法线数据到顶点

      除了3D位置和颜色,每个顶点还存储法线方向。

   XNA有一个预订顶点格式允许你保存法线到每个顶点:VertexPositionNormalTexture结构。这个格式允许你保存每个顶点的3D位置,法线方向,和纹理坐标。

   下面的方法创建一个数组持有6个这种顶点, 2个三角形创建一个矩形。这个矩形躺在地上,因为所有Y坐标都是0.为此,法线都是(010)的向上向量,因为这是垂直于正方形的方向。顶点格式也预料你添加纹理坐标所以显卡知道从图像的什么位置采样颜色。

  

   InitVerticesP523

 

最后一行确保VertexDeclaration只创建一次,因为不用被改变。

 

正负法线

一个三角形实际上有2个垂直方向。如果三角形躺在地上,你可以定义指向上或下的法线。但是,你用哪一个?这很重要,因为选错将导致错误的光照或根本没有光照。作为一个规则,你将选择指向对象向外方向的法线。通常,三角形的一个面可以看作3D对象的里面,另一个面就是外面了。

 

设置BasicEffect参数

由于定义了顶点,你就准备渲染三角形。BasicEffect是基于光照效果渲染物体的预订效果。确保你有一个BasicEffect变量在每帧重用,因为每帧创建BasicEffect对象是很耗资源的。添加下面代码到类的顶部:

 

BasicEffect basicEffect;

 

LoadContent方法实例化:

 

basicEffect = new BasicEffect(device,null);

 

下面的代码将设置渲染3D场景的从一个方向照来的光,就像太阳:

 

 

上部设置世界,视图和投影矩阵,负责变换3D场景到2D屏幕。因为你已经存储纹理坐标到每个顶点里,你可以传递一个纹理到显卡并启用纹理使三角形从图像获得颜色。

接下来,你配置全局光照启动光照并定义环境光色。这是你的对象一直使用的光照量,不用在意环境光的光源。你可以指定灰色,微弱的看见对象。

最后,你定义光源。用BasicEffect一次可用3个光源。这样做要设置光的方向,光的颜色。最后但并非最不重要,你要启用你要使用的光。代码如下,只使用一个光。

basicEffect.Begin();

foreach(EffectPass pass in basicEffect.CurrentTechnique.Passes)

{

    Pass.Begin();

    Device.VertexDeclaration = myVertexDeclaration;

    DrawUserPrimitives<VertexPositionNormalTexture>

(PrimitiveType.TriangleList,vertices,0,2);

Pass.End();

      }

      basicEffect.End();

     

用世界矩阵

渲染三角形之前,你可以在效果里设置世界矩阵。这允许你移动你的三角形到3D世界另一个位置或旋转缩放它。这也应用到每个顶点的法线数据。如果正方形旋转,则法线也自动旋转。

 

规范化法线

一个顶点接收到的光的数量由光和法线之间的夹角。但是,这个值也依据法线长度和光方向的长度。为此,你要使这两个值规范化为1

转载于:https://www.cnblogs.com/XNAconglele/archive/2009/09/05/1560931.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值