问题

在前两个教程中,是在每个顶点中计算明暗程度,对三角形的每个像素需要对这个值进行插值。所以这叫做逐顶点光照(per-vertex lighting,又叫做高洛德着色,高洛德浓淡Gouraud shading)。

在某些情况中,逐顶点光照没不能产生最好的结果。特别是使用大三角形或有锐利的边缘或两者都有时,往往得不到想要的结果。

举例说明,如图左边是一个有三个面的立方体。图的右边表示共享的法线应该如何定义。本例中,光线方向用四根箭头表示。

图6-5 Vertex shader对per-pixel lighting

关注立方体的顶部,对应右图中顶点2和4之间的线段。使用逐顶点光照,会计算顶点2和4的明暗。在顶点4光照不多,因为顶点4的法线几乎是垂直于光线方向的,这里我们认为是20%的光照。顶点2光照得多,因为它的法线方向几乎和光线方向一致,我们设为80%光照。在逐顶点光照中,三角形中的像素的明暗要进行插值,所有介于这两个顶点之间的像素接受的光照是20%至80%之间的插值。这样,没有一个像素可以获得100%的光照。

但是,顶点2和4之间的某一个像素的顶点方向与光线方向完全一致!这个法线显示在图6-5的右图中。很明显,这个像素应该获得100%的光照,但是使用逐顶点光照,这个像素只能获得介于20%和80%之间的某个光照值。

解决方案

逐顶点光照只计算顶点的精确明暗,而在顶点间的像素的明暗是通过插值获取的。

使用逐像素光照,你对所有像素的法线进行插值,让你可以计算每个像素的精确明暗。

工作原理

使用BasicEffect,很容易使用逐像素光照。在设置BasicEffect参数时,只需添加以下代码行:

basicEffect.PreferPerPixelLighting = true; 

注意:要使逐像素shader可以工作,你必须要拥有支持Shader 2.0以上的显卡。你可以使用以下代码检查显卡的支持:

GraphicsDevice. GraphicsDeviceCapabilities.MaxPixelShaderProfile>=ShaderProfile.PS_2_0 
代码

下面的代码创建如图6-5左图所示的顶点。因为某些法线可能不再是单位长度,所有确保在最后要对它们进行归一化:

private void InitVertices()
{vertices = new VertexPositionNormalTexture[8]; vertices[0] = new VertexPositionNormalTexture(new Vector3(0, -1, 0), new Vector3(-1, 0, 0), new Vector2(0, 1)); vertices[1] = new VertexPositionNormalTexture(new Vector3(0, -1,- 1), new Vector3(-1, 0, 0), new Vector2(0, 0)); vertices[2] = new VertexPositionNormalTexture(new Vector3(0, 0, 0), new Vector3(-1, 1, 0), new Vector2(0.33f, 1));vertices[3] = new VertexPositionNormalTexture(new Vector3(0, 0,- 1), new Vector3(-1, 1, 0), new Vector2(0.33f, 0)); vertices[4] = new VertexPositionNormalTexture(new Vector3(1, 0, 0), new Vector3(1, 1, 0), new Vector2(0.66f, 1)); vertices[5] = new VertexPositionNormalTexture(new Vector3(1, 0,- 1), new Vector3(1, 1, 0), new Vector2(0.66f, 0)); vertices[6] = new VertexPositionNormalTexture(new Vector3(1, -1, 0), new Vector3(1, 0, 0), new Vector2(1, 1)); vertices[7] = new VertexPositionNormalTexture(new Vector3(1, -1,- 1), new Vector3(1, 0, 0), new Vector2(1, 0)); for (int i = 0; i < vertices.Length; i++)vertices[i].Normal.Normalize();myVertexDeclaration = new VertexDeclaration(device, VertexPositionNormalTexture.VertexElements);
} 

阅读教程6-1中的“归一化法线”理解为何需要最后的for循环。

注意:因为XNA没有提供一个包含3D位置、颜色、法线的顶点结构,这个教程使用一个蓝色的纹理让每个像素的颜色都是一样的。通过这种方式,你看到的颜色中的所有变化都会被光照影响。

然后就可以使用逐像素光照绘制三角形了:

basicEffect.World = Matrix.Identity;
basicEffect.View = fpsCam.ViewMatrix;
basicEffect.Projection = fpsCam.ProjectionMatrix;
basicEffect.Texture = blueTexture;
basicEffect.TextureEnabled = true;
basicEffect.LightingEnabled = true;
Vector3 lightDirection = new Vector3(3, -10, 0);
lightDirection.Normalize();
basicEffect.DirectionalLight0.Direction = lightDirection;
basicEffect.DirectionalLight0.DiffuseColor = Color.White.ToVector3();
basicEffect.DirectionalLight0.Enabled = true;
basicEffect.PreferPerPixelLighting = true; basicEffect.Begin();
foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes)
{pass.Begin(); device.VertexDeclaration = myVertexDeclaration; device.DrawUserPrimitives<VertexPositionNormalTexture>(PrimitiveType.TriangleStrip, vertices, 0, 6); pass.End();
}
basicEffect.End();

转载于:https://www.cnblogs.com/AlexCheng/archive/2011/02/14/2120100.html

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

  1. 昇思MindSpore全场景AI框架 1.6版本,更高的开发效率,更好地服务开发者

    本文分享自华为云社区<昇思MindSpore全场景AI框架 1.6版本,更高的开发效率,更好地服务开发者>,作者: 技术火炬手. 全新的昇思MindSpore全场景AI框架1.6版本已发布 ...

  2. 四大车系中,哪个车系性价比更高?比较良心?配置更高?质量更好

    一,日系车是大家最熟悉的车型了. 日系车在以前,给大家的印象就是比较耐用,油耗比较低,但是最近几年,随着汽车工业的技术越来越先进,在某些方面,特别是油耗方面,日系车确实已经不占优势了,日系车可能现在最 ...

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

    问题 就算开启了逐像素明暗,有些金属或闪光表面仍显得有点暗淡.在现实生活中,当观察诸如金属.玻璃或一些塑料时,你会发现某些区域的反光非常强烈.这样的区域如图6-6的虚线圆圈所示.这些高亮的区域叫做镜面 ...

  4. 20 虚幻4【UE4】场景中模型高亮轮廓

    20.UE中如何使得模型再场景中高亮 1.场景的世界大纲搜索Post Process Volume(后期处理体积) 如果没有则需要在[放置Actor]中搜索,然后放到场景中 2.选中[Post Pro ...

  5. 如何在unity的前向渲染路径ForwardBase中同时使用逐顶点和逐像素光源

    前言:问题来自于<Unity Shader入门精要>中,第195页.书中给出了如何在forwardbase和forwardadd中计算逐像素光照,并没有给出如何同时进行逐顶点的光照,因此当 ...

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

    问题 虽然你已经掌握了基本的计算机实时光照,但你应该注意到光源还没有投射出阴影.这是因为pixel shader是基于光线与法线的夹角计算光照的.直到现在,pixel shader还没有考虑到光线与像 ...

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

    问题 使用你配置好的光照,BasicEffect可以很好地绘制场景.但是,如果你想定义一些更酷的效果,首先要实现的就是正确的光照. 本教程中,你将学习如何编写一个基本的HLSL effect实现逐顶点 ...

  8. js添加网页水印和three.js场景中加水印

    我们在日常网页开发的时候,可能想给自己的网页或者canvas里面添加水印,增添个人标记,我这里分为普通静态html页面和threejs中3d场景里面添加水印功能. 一 静态html页面添加水印 你只需 ...

  9. [unreal4入门系列之十] UE4添加角色到场景中

    现在我们已经有了一个场景并且运行了,我们需要添加一个角色到场景中.要这样做,我们必须从UE4的GameFramework类继承它. 一. 打开上次创建的关卡 如果你已经关闭了项目,并且保存了上次创建的 ...

最新文章

  1. 【Flutter】Dart 技巧 ( 独立主函数入口 | 可空类型判定 | 默认值设定 )
  2. sprintf,sscanf,snprintf
  3. JavaScript字符串的单引号和双引号问题
  4. java基础知识-对象和类
  5. python创建sqlite3数据库_Python之Sqlite3数据库基本操作
  6. 微软中文网,越办越好了!
  7. 开博第二篇-win7下的小凡模拟器-DynamipsGUI
  8. AngularJS内置指令 ng-xxx
  9. mysql load data infile 上传数据 不显示_第22问:我有带外键的表,你有数据么?
  10. hello linux
  11. 微信小程序 首页弹出用户协议
  12. swfobject.js
  13. mysql 明文密码_后台能看到明文密码的处理
  14. 显示随机森林多元回归结果
  15. 叉乘与空间曲线的切向量
  16. 英特尔神经计算棒_如何设置英特尔Movidius神经计算棒
  17. html网页有内容不能向下拉,为什么百度页面不能往下拉
  18. python金融基础知识_python金融实务从入门到精通(23节课)
  19. 苹果6更换电池注意事项
  20. 97. Interleaving String

热门文章

  1. 堆和栈的概念和区别 python_堆的意思
  2. 微信小程序wx.showToast
  3. 小米蓝牙左右互联_小米真无线蓝牙耳机Air2评测:支持弹窗动画,半入耳设计全面升级...
  4. springboot怎么杀进程_头疼,springboot进程总是自己退出
  5. 为什么大公司都不用mfc和qt_百度竞价推广效果下降,为什么有的老板还是只愿意做百度推广?...
  6. 管状合金电阻和片状合金电阻的区别_合金采样电阻的特点及作用
  7. mongodb 可是化_Mongodb GUI可视化管理工具推荐
  8. 将python算法转为scala_将Python转换为scalaasp
  9. flutter 禁止冒泡_【Flutter】Switch开关组件
  10. android错误怎么关机,Android系统小技巧:系统崩溃了只重启部分子系统,而不是全部重启...