赞助广告

 

年份

最新评论

评论 RSS

在场景中添加光线——在Deferred Shading引擎中添加阴影能力

clock 二月 14, 2011 15:02 by author alex
问题 虽然你已经掌握了基本的计算机实时光照,但你应该注意到光源还没有投射出阴影。这是因为pixel shader是基于光线与法线的夹角计算光照的。直到现在,pixel shader还没有考虑到光线与像素间的物体。 阴影映射(shadow mapping)技术在我的网站(http://www. riemers. net)的第三个系列中加以介绍,这个技术可以对一个光源生成正确的阴影,但是你想用deferred渲染的方法实现。 解决方案 在场景中添加阴影的一个极好的方法是阴影映射技术,我已经在我的网站上详细介绍了 (http://www.riemers.net)。 简而言之,阴影映射技术将... [更多...]

在场景中添加光线——使用Deferred Shading在场景中添加多光源

clock 二月 14, 2011 15:00 by author alex
问题 你想在场景中同时使用多个光源。 一个方法是使用多个光源绘制场景并将每个光源的影响混合在一起。当添加一个新光源时场景需要整个被重新绘制,这个方法无法拓展,因为帧频率会随着光源的增加按比例下降。 解决方案 本教程中将使用一个完全不同的方法。你将3D场景绘制到一张2D纹理中。然后,为这张纹理中的所有像素计算所有光源的光照。这意味着你要在2D纹理上进行逐像素的处理,但只需绘制3D场景一次。 但在进行光线计算时需要每个像素的初始3D位置,对吗?对。继续看下去如何做,整个过程分为3步,如图6-12所示。 在第一步中,你将整个3D场景绘制到一张纹理中(见教程3-8)—不是一张纹理而是一次三... [更多...]

在场景中添加光线——添加HLSL镜面高光

clock 二月 14, 2011 14:52 by author alex
问题 你想使用自定义的HLSL effect在场景中添加镜面高光。镜面高光是位于反光位置的高亮度区域,如图6-11所示。 解决方案 下面的讨论将帮助你判断哪个像素具有高光分量。 图6-11的左图显示了一条光线L,从光源指向三角形中的一个像素。在左图中还显示了 eye向量,从相机指向像素。如果L的反射向量与E相同,那么这个像素就有一个高光分量。 图6-11 使用靠近eye向量的光线方向检测像素 你可以通过求L关于像素法线的镜像获取L的反射向量。如果镜像方向与eye向量夹角很小则这两个方向几乎是相同的。你可以通过点乘这两个向量检测两者的夹角(可参见教程 6-8)。 如果角度... [更多...]

在场景中添加光线——使用HLSL定义聚光灯

clock 二月 14, 2011 14:50 by author alex
问题 前面教程中定义的点光源从一个点发出四面八方的光。你想定义一个聚光灯,它与点光源很很像,但光线只照亮一个圆锥区域,如图6-10。 图6-10 定义一个聚光灯的变量 解决方案 在pixel shader中,判断当前像素是否在光照圆锥中,这可以通过将光线方向和圆锥方向进行点乘做到。 工作原理 开始的代码与前面的教程中的是一样的。因为聚光灯比点光源需要设置的东西更多,你需要将下列XNA-to-HLSL变量添加到. fx文件中: float xLightStrength; float3 xConeDirection; float xConeAngle; float ... [更多...]

在场景中添加光线——添加HLSL逐像素光照

clock 二月 14, 2011 14:48 by author alex
问题 如教程6-3所示,要获得最好的光照效果应该使用逐像素光照,特别是对那些由大三角形构成的曲线的情况中。你想使用自己的effect添加逐像素光照。 解决方案 前两个教程中,你在每个顶点中计算明暗值(shading value,也可以翻译成着色值)。三角形三个顶点的明暗值会进行线性以获取每个像素的明暗值。 在逐像素光照中,你想对三个顶点的法线进行插值以获取每个像素的法线,这样就可以基于每个像素的法线计算光照因子。但是,当从一个顶点到另一个顶点进行法线插值时结果是有缺陷的。如图6-9中的左图所示,图中的水平直线表示一个顶点包含法线的三角形。当你在像素上对这左右两个顶点的法线进行插值时,插... [更多...]

在场景中添加光线——使用HLSL定义点光源

clock 二月 14, 2011 14:46 by author alex
问题 直到现在,你都是用单向光照亮场景,这对在3D世界中添加阳光是很有用的。但很多情况中,你还需要一个从点发出的光线,例如一个探照灯或爆炸。这种光源叫做点光源。 解决方案 将点光源的3D位置从XNA项目传送到XNA effect中。对每个顶点,计算光源指向顶点的方向,并将这个方向作为光线方向。知道了光线方向就可以像以前一样继续了。 工作原理 在. fx文件中,使用下列代码替换xLightDirection参数,让你可以将光源的3D位置从XNA项目传递到HLSL effect中: float3 xLightPosition; 然后,对每个顶点,你要计算从光源指向顶点的方向。从... [更多...]

在场景中添加光线——添加HLSL Vertex Shading

clock 二月 14, 2011 14:39 by author alex
问题 使用你配置好的光照,BasicEffect可以很好地绘制场景。但是,如果你想定义一些更酷的效果,首先要实现的就是正确的光照。 本教程中,你将学习如何编写一个基本的HLSL effect实现逐顶点光照。 解决方案 传递每个顶点的3D位置和法线到effect中。显卡上的vertex shader需要对每个顶点做两件事。 首先,当绘制3D世界时,总是要使用世界矩阵,视矩阵和投影矩阵将3D位置转换为对应的2D屏幕坐标。 第二,通过叉乘光线方向和法线方向计算顶点的光照强度。 工作原理 首先需要在XNA项目中定义顶点。显然你需要将3D位置存储在每个顶点中。要在vertex shade... [更多...]

在场景中添加光线——在反光表面添加镜面高光

clock 二月 14, 2011 14:36 by author alex
问题 就算开启了逐像素明暗,有些金属或闪光表面仍显得有点暗淡。在现实生活中,当观察诸如金属、玻璃或一些塑料时,你会发现某些区域的反光非常强烈。这样的区域如图6-6的虚线圆圈所示。这些高亮的区域叫做镜面高光(specular highlights)。 图6-6 镜面高光 解决方案 和逐像素光照一样,你只需简单地告知BasicEffect创建镜面高光就可以开启它。 注意:镜面高光只应添加到发光材质上。不要将它们添加到诸如衣服或草地的柔软表面,或至少让反光效果非常微弱。 工作原理 使用BasicEffect开启镜面高光非常简单。对每个光源,你指定高光颜色。然后,设置高光强度。... [更多...]

在场景中添加光线——给光线添加更高的细节:逐像素光照

clock 二月 14, 2011 14:31 by author alex
问题 在前两个教程中,是在每个顶点中计算明暗程度,对三角形的每个像素需要对这个值进行插值。所以这叫做逐顶点光照(per-vertex lighting,又叫做高洛德着色,高洛德浓淡Gouraud shading)。 在某些情况中,逐顶点光照没不能产生最好的结果。特别是使用大三角形或有锐利的边缘或两者都有时,往往得不到想要的结果。 举例说明,如图左边是一个有三个面的立方体。图的右边表示共享的法线应该如何定义。本例中,光线方向用四根箭头表示。 图6-5 Vertex shader对per-pixel lighting 关注立方体的顶部,对应右图中顶点2和4之间的线段。使用逐顶点... [更多...]

在场景中添加光线——在顶点间共享法线

clock 二月 14, 2011 14:27 by author alex
问题 在前面的教程中,你学习了如何根据法线数据使三角形获取正确的光照。 但是,盲目地将这个方法施加到所有三角形中往往得不到最好的效果。 如果三角形的每个顶点具有相同的法线方向,那么光照是一样的,所有像素会获得同样的光照。如果两个相邻三角形(不在同一平面)也是如此施加光照,那么一个三角形的所有像素获得同样的光照,另一个三角形的所有像素获得另一个光照。这会导致很容易地可见看见两者的边界,因为两个三角形有不同的颜色。 如果三角形中的颜色是平滑过渡的,你想获取一个更好的效果。要做到这点,从一个三角形到另一个三角形的明暗应该平滑过渡。 解决方案 显卡是根据三角形的三个顶点计算明暗的。三角形中... [更多...]

在场景中添加光线——定义法线和使用BasicEffect

clock 二月 14, 2011 14:24 by author alex
问题 没有正确地光照,场景会缺乏真实感。在某些情况中,如果光照不正确3D效果会完全消失。 例如,一个有着不透明颜色的球,如果没有光照,球的所有像素将会是相同的颜色,在屏幕上看起来像一个平面的盘子。当光照正确时,球上面对光照的部分比其他部分的颜色更亮,使球看起来是一个真实的3D对象。 解决方案 在计算机图形学中,所有的3D对象都是由三角形组成的。你想使三角形对应入射光可以正确地被照亮。图6-1显示了一条从左向右的单向光,它影响到一个矩形的六个不同位置,每个矩形都是由两个三角形组成的。 图6-1 根据入射光的三角形光照情况 简单地定义光源的位置和对象的位置不足以让显卡在对象上... [更多...]

在场景中添加光线——概述

clock 二月 14, 2011 14:21 by author alex
给场景添加光照听起来很简单:设置3D世界中物体的位置,定义光源的位置就可以了。但是,虽然看起来让显卡实现光照很简单,其实不是。 对物体的每个表面,显卡需要计算表面接受光照的数量,这个光照数量是基于光线方向和表面法线方向的夹角的。幸运的是,XNA框架拥有BasicEffect,它可以为你进行所有的计算。本章第一部分解释如何使用BasicEffect给场景添加光照。 但是,如它的名称所示,BasicEffect只能用来计算基本的光照。如果你想在场景中添加点光源该怎么办呢,例如一个蜡烛?或许你还想在场景中添加多个光源,给物体添加阴影。 要解决这些问题,你需要在HLSL中编写自己的effect。... [更多...]

处理顶点——为赛道创建顶点

clock 二月 14, 2011 14:16 by author alex
问题 给定三维空间中的一个基点集合,你想创建一条通过所有点的赛道。你想创建顶点,计算法线,在赛道上贴上纹理。 解决方案 你可以经过几个步骤从3D点的集合创建一个赛道。首先使用教程5-16中讨论的3维Catmull-Rom插值生成位于你预定义的点之间的样条上的额外点。第一步可用图5-33中的从“a”指向“b的箭头表示”。 基于这些点无法定义三角形。对样条上的每个点,你要计算垂直于样条的方向,在样条两侧各添加一个点,如图5-33中的“b”所示。 图5-33 为赛道生成顶点 最后,通过将这些新计算的点转换为顶点创建一个TriangleList,如图5-36的“d”所示。 工作... [更多...]

处理顶点——在3D空间中使用Catmull-Rom插值生成额外的顶点

clock 二月 14, 2011 14:14 by author alex
问题 给定一个3D空间中的点序列,你想构建一个漂亮的,光滑曲线可以通过所有这些点。图5-32中的黑色曲线显示了这样条曲线,灰色线段表示使用简单的线性插值的情况,可参见教程5-9。 图5-32 通过5点的Catmul-Rom样条(spline) 这在许多情况中是很用的。例如,你可以用它产生一个赛道,可参见教程5-17。当相机非常靠近模型或地形时,你可以使用Catmull-Rom插值产生额外的顶点,使模型或地形看起来更加光滑。 解决方案 如果你想在两个基点之间生成Catmull-Rom样条,你还需要知道两个邻近基点。在图5-32中,当你想在点1和点2之间生成曲线时,你需要知道基... [更多...]

处理顶点——在3D世界添加水面

clock 二月 14, 2011 14:12 by author alex
问题 你可以在CPU上计算所有波的3D位置,但这样做会消耗大量的资源,每帧向显卡发送大量的数据是不可接受的。 解决方案 在XNA程序中,你只需创建一个三角形组成的平面网格。这和创建地形类似,在教程5-8中已经解释过了,只不过这次网格是平的,你将需一次性地把这些数据传递到显卡。当绘制网格时,vertex shader会在网格上添加水波,pixel shader添加反射,这一切都在GPU中完成,CPU只处理Draw指令,让CPU可以处理更重要的工作。 vertex shader接受网格的顶点数据并改变它们的高度,这样平的网格会形成一个波涛起伏的海面。你可以使用一个正弦波产生这个高度。只有... [更多...]

处理顶点——通过切线空间的凹凸映射添加逐像素细节

clock 二月 14, 2011 14:05 by author alex
问题 虽然前一个教程中具有不变法线的平面物体工作良好,但如果对一个曲面或有转角的表面进行凹凸映射仍会遇到麻烦。 主要问题是包含在凹凸映射中的偏离法线是在切线空间中的,这意味着它与默认法线有联系。 为了形象化的说明这个问题,设想绘制一个圆柱体,如图5-30所示。左图表示圆柱体顶点的默认法线。 图5-30 圆柱体的默认法线和凹凸映射法线 想象一下你想对这个圆柱体使用凹凸映射。例如,你想对圆柱体的所有像素使用包含 (–1,0,1)方向法线的凹凸映射。这个法线相对于默认法线向左偏转45度。 获取这个法线正确的方式是位于默认法线的起点沿着这个默认法线向左旋转45度。看一下顶点法线0... [更多...]

处理顶点——凹凸映射:固定法线

clock 二月 14, 2011 13:59 by author alex
问题 三角形的最主要问题是它是平的。如果你使用两个三角形绘制一堵巨大的墙并在墙上附上一个漂亮的纹理,结果是令人失望的平的。 你可以将三角形分割成更小的三角形以添加细节,这需要定义每个顶点的3D位置,但这样做会消耗太多的资源。 解决方案 你可以使用凹凸映射代替上述这个丑陋的方法。凹凸映射通过改变三角形每个像素的颜色给观察者留下三角形表面高低起伏的印象。 如果你看一张平整的红色的塑料板的图片,会发现所有像素几乎是一个颜色的。但是如果是一个粗糙表面的图片,比方说一块红砖,像素会有不同的红色,让观察者知道这块砖的表面是粗糙的。 这就是你想模拟的效果。在一个粗糙表面上,像素反光情况不同导致颜... [更多...]

处理顶点——创建自己的顶点格式

clock 二月 14, 2011 13:52 by author alex
问题 顶点用来存储从XNA项目发送到显卡的数据。一个顶点格式包含存储在顶点中的数据的描述。XNA框架自带有默认的顶点格式,从简单的VertexPositionColor到 VertexPostionNormalTexture格式。 但是,如果你需要顶点带有额外的数据,例如切线或时间数据,就需要定义自己的顶点格式。如果要在顶点shader中使用这个数据,这一步是必须的。所以,只有编写自定义的顶点和像素shader时,你才需要定义一个自定义顶点格式。 解决方案 顶点格式定义了在顶点中存储何种类型的数据,何种数据可以被vertex shader访问。例如,当使用VertexPositionC... [更多...]

处理顶点——从XML文件加载数据

clock 二月 14, 2011 13:48 by author alex
问题 你想从一个XML文件中加载数据到XNA项目。你可以使用默认的.NET文件IO功能在XNA项目启动时读取文件做到这点,但这在Xbox360平台上无法工作。 你想使用内容管道将一个XML文件串行化为一个二进制文件,这样就可以在XNA项目中读取包含在这些文件中的内容了。 解决方案 在XML文件中,只需简单地将你想要加载的对象插入到<XNAContent>和<Asset>标签之间,下面的XML示例文件是一个自定义的MapData类对象: <?xml version="1.0" encoding="utf-8"?>... [更多...]

处理顶点——计算光标与地形的碰撞点:表面拾取

clock 二月 9, 2011 09:12 by author alex
问题 你想获取地形上由光标指示的位置的精确3D坐标。 解决方案 如教程4-19的介绍中讨论的那样,通过光标指示的屏幕上的一个2D点对应3D场景中的一条射线。在本教程中,我们将沿着这条射线直到它与地形发生碰撞。 你可以使用一个二分法搜索(binary search algorithm)做到这点,这可以根据你选择的精度获取碰撞位置。 对高低起伏的地形来说,可能在射线和地形之间有多个碰撞点,如图5-20所示。所以,在二分法搜索之前需要进行线性搜索,以保证检测到的碰撞是最靠近相机的。 工作原理 下面的这个方法将光标的2D屏幕位置转换为一个3D射线,这已经在教程4-19的第一部分介绍过了。... [更多...]

友情链接赞助