今天学习的是镜面的反射光照,其实一般在场景中基本环境光和漫反射光照已经可以表现出一个不错的照明了,今天的镜面反射光照其实仅仅适合于需要在表面添加抛光或者闪耀的物体上,例如金属、玻璃等等,同时也是基于之前的环境光和漫反射光的基础之上的,先来看看镜面反射光照的公式吧。

镜面反射光照公式:I=AiAc+Di*Dc*N.L+Si*Sc*(R.V)^n

      公式说明:其中,AiAc+Di*Dc*N.L是前一节的公式,即环境光+漫反射光,Si和Sc分别为镜面反射光照的强度和颜色,R=2*(N.L)*N-L表示反射向量。

      V:为从相机的位置指向观察目标的向量,即V=cameraPosition-mul(position,world)也就是高光的部分始终面向相机可以被看到。

      相机的位置:通常在Game中定义视角矩阵ViewMatrix的第一个参数,即:ViewMatrix=Matrix.CreateLookAt(CameraPosition,CameraTarget,VectorUp)中的CameraPosition

      观察目标:即为POSITION0中存储的物体位置,当然这是模型空间的坐标,需要利用World转换为世界空间中的坐标。

      n:表示光泽属性,n越大,表明物体表面越光滑,反光越强。

     参照公式修改上一节中的部分代码即可完成效果,当然最好是新建一个项目,自己从头到尾按部就班的写代码,温故而知新......下面贴出变动的代码:

  1. #region 镜面反射光照
  2. effect.CurrentTechnique = effect.Techniques["SpecularLight"];
  3. foreach (EffectPass pass in effect.CurrentTechnique.Passes)
  4. {
  5. pass.Apply();
  6. foreach (ModelMesh mesh in model.Meshes)
  7. {
  8. foreach (ModelMeshPart part in mesh.MeshParts)
  9. {
  10. effect.Parameters["World"].SetValue(modelTransform[mesh.ParentBone.Index] * Matrix.CreateScale(30.0f) * Matrix.CreateRotationX(rotateAngle) * Matrix.CreateRotationY(rotateAngle));
  11. effect.Parameters["View"].SetValue(viewMatrix);
  12. effect.Parameters["Projection"].SetValue(projectMatrix);
  13.  
  14. //环境光参数
  15. effect.Parameters["AmbientColor"].SetValue(new Vector4(0.1f, 0.2f, 0f, 0.2f));
  16. effect.Parameters["AmbientIntensity"].SetValue(0.5f);
  17.  
  18. //漫反射光参数
  19. effect.Parameters["DiffuseIntensity"].SetValue(0.5f);
  20. effect.Parameters["DiffuseColor"].SetValue(new Vector4(1.0f, 0.0f, 0.5f, ));
  21. effect.Parameters["LightDirection"].SetValue(new Vector4(, , 1.0f, 1.0f));
  22.  
  23. //镜面高光参数
  24. effect.Parameters["VecEye"].SetValue(new Vector4(camPosition, ));
  25. effect.Parameters["SpecularIntensity"].SetValue(1f);
  26. effect.Parameters["SpecularColor"].SetValue(new Vector4(1.0f, 0.0f, 0.5f, 0.5f));
  27.  
  28. graphics.GraphicsDevice.SetVertexBuffer(part.VertexBuffer);
  29. graphics.GraphicsDevice.Indices = part.IndexBuffer;
  30.  
  31. graphics.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, part.VertexOffset, , part.NumVertices, part.StartIndex, part.PrimitiveCount);
  32. }
  33. }
  34. }
  35. #endregion

接下来看看fx里面的代码:

  1. float4x4 World;
  2. float4x4 View;
  3. float4x4 Projection;
  4.  
  5. //Ambient
  6. float4 AmbientColor;
  7. float AmbientIntensity;
  8.  
  9. //Diffuse
    float4 DiffuseColor;
  10. float DiffuseIntensity;
  11. float4 LightDirection;
  12.  
  13. //Specular
  14. float4 VecEye;
  15. float SpecularIntensity;
  16. float4 SpecularColor;
  17.  
  18. struct VertexShaderOutput
  19. {
  20. float4 Position : POSITION0;
  21. float3 Normal:TEXCOORD0;
  22. float4 VecEye:TEXCOORD1;
  23. float4 Light:TEXCOORD2;
  24. };
  25.  
  26. VertexShaderOutput VertexShaderFunction(float4 Position:POSITION0,float3 Normal:NORMAL)
  27. {
  28. VertexShaderOutput output;
  29.  
  30. float4 worldPosition = mul(Position, World);
  31. float4 viewPosition = mul(worldPosition, View);
  32. output.Position = mul(viewPosition, Projection);
  33.  
  34. output.Normal =normalize(mul(Normal,World));
  35.  
  36. output.VecEye = normalize(VecEye-mul(Position,World));
  37.  
  38. output.Light = normalize(LightDirection);
  39.  
  40. return output;
  41. }
  42.  
  43. float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
  44. {
  45. float4 vAmbient = AmbientIntensity*AmbientColor;//环境光
  46.  
  47. float4 vDiffuse = DiffuseIntensity*DiffuseColor*saturate(dot(input.Normal,input.Light));//漫反射光
  48.  
  49. float4 vSpecular = SpecularIntensity*SpecularColor*pow(saturate(dot(normalize(*saturate(dot(input.Normal,input.Light))*input.Normal-input.Light),input.VecEye)),);//镜面高光
  50.  
  51. return vAmbient+vDiffuse+vSpecular;
  52. }
  53.  
  54. technique SpecularLight
  55. {
  56. pass Pass0
  57. {
  58. VertexShader = compile vs_2_0 VertexShaderFunction();
  59. PixelShader = compile ps_2_0 PixelShaderFunction();
  60. }
  61. }

fx中的代码为了更好的展示各个光照的公式效果,代码上没有简化,其次需要注意光照方向Light,相机指向物体的位置VecEye,以及物体表面的法线这几个向量一定要记得单位化,利用fx里面自带的normalize方法,最后看看效果图:

感觉效果挺好的,也领略到了HLSL的魅力,继续学习.......

HLSL之镜面反射光照的更多相关文章

  1. HLSL之漫反射光

    整整忙了一个月了,总算清闲下来了,从上次写完环境光后又过了这么长时间,继续学习......加油!!今天整理下漫反射光并记录下来,那就直接进入主题吧,开始漫反射光的学习. 漫反射光是在环境光的基础上添加 ...

  2. [图形学] Chp17 OpenGL光照和表面绘制函数

    这章学了基本光照模型,物体的显示受到以下效果影响:全局环境光,点光源(环境光漫反射分量,点光源漫反射分量,点光源镜面反射分量),材质系数(漫反射系数,镜面反射系数),自身发光,雾气效果等.其中点光源有 ...

  3. [CG编程] 基本光照模型的实现与拓展以及常见光照模型解析

    0.前言 这篇文章写于去年的暑假.大二的假期时间多,小组便开发一个手机游戏的项目,开发过程中忙里偷闲地了解了Unity的shader编写,而CG又与shaderLab相似,所以又阅读了<CG教程 ...

  4. 西川善司【神秘海域(Uncharted)】的图形分析

          本文是为传播0月8日发售的[神秘海域 合集]魅力而短篇连载的第2回,这次主要集中在神秘海域系列的图形的技术方面.原文链接在 http://weekly.ascii.jp/elem/000/ ...

  5. RenderMonkey 练习 第二天 【opengl 光照模型】

    光照模型 3D渲染中, 物体表面的光照计算公式为: I = 环境光(Iambient) + 漫反射光(Idiffuse) + 镜面高光(Ispecular); 其中,环境光(ambient)计算公式为 ...

  6. Elays'Blog

    文章导航 阴影的重要意义 阴影是光线被阻挡的结果,它能够使场景看起来真实很多,可以让观察者获得物体之间的空间位置关系.如下图所示: 图1 可以看到,有阴影的时候能够更容易的看出立方体是悬浮在地板上的. ...

  7. CSharpGL(39)GLSL光照示例:鼠标拖动太阳(光源)观察平行光的漫反射和镜面反射效果

    CSharpGL(39)GLSL光照示例:鼠标拖动太阳(光源)观察平行光的漫反射和镜面反射效果 开始 一图抵千言.首先来看鼠标拖动太阳(光源)的情形. 然后是鼠标拖拽旋转模型的情形. 然后我们移动摄像 ...

  8. DirectX11 With Windows SDK--07 添加光照与常用几何模型

    前言 对于3D游戏来说,合理的光照可以让游戏显得更加真实.接下来会介绍光照的各种分量,以及常见的光照模型.除此之外,该项目还用到了多个常量缓冲区,因此还会提及HLSL的常量缓冲区打包规则以及如何设置多 ...

  9. Obj模型功能完善(物体材质,光照,法线贴图).Cg着色语言+OpenTK+F#实现.

    这篇文章给大家讲Obj模型里一些基本功能的完善,包含Cg着色语言,矩阵转换,光照,多重纹理,法线贴图的运用. 在上篇中,我们用GLSL实现了基本的phong光照,这里用Cg着色语言来实现另一钟Blin ...

随机推荐

  1. Bugtags 与其它产品的区别

    如果您刚刚接触 Bugtags,可能心里会有这样的疑问,下面将介绍 Bugtags 与其它的一些产品的区别. Bugtags 不是做统计的 SDK 大家都会在 App 里集成用户数据统计的 SDK,但 ...

  2. vc6开发ActiveX并发布全攻略(三)(转)

    一.环境: windows xp sp3 Microsoft VC++ 6.0 二.制作文件 打开iexpress.exe(windows提供的一个向导式cab制作工具,位置:C:\WINDOWS\s ...

  3. 面向对于javascript编程

    以构造函数的方式定义对象 function Person(name, age) { this.name = name; this.age = age; this.sayName = function ...

  4. Home not found. Define system property "openfireHome" or create and add the openfire_init.xml file to the classpath

    启动openfire后出现这个错误,貌似什么配置没对吧.网上搜索了下,找到解决办法, $ vi /etc/profile在里面加入:export openfireHome=/opt/openfire ...

  5. EXCL poi导入

    public static void importExcel2(File file) throws Exception { InputStream is = new FileInputStream(f ...

  6. Linux网络状态工具ss命令使用详解

    ss命令用于显示socket状态. 他可以显示PACKET sockets, TCP sockets, UDP sockets, DCCP sockets, RAW sockets, Unix dom ...

  7. delphi TEdit设为下横线,类似填表格

    delphi TEdit设为下横线,类似填表格效果,无需第三方控件就可以实现. 无须编写代码,只要设置一下控件属性 需要修改这些属性: BorderStyle改为bsNone BevelKind改为b ...

  8. centos 6 initctl

    在centos6中有initctl 可以启动tty等.此命令在 upstart-0.6.5-10.el6.x86_64 rpm包中 或者 mingetty 命令启动 tty #initctl star ...

  9. php json_encode中文unicode问题

    php调用json_encode将中文字符串存入mysql后读取出来有问题,发现存进去的时候把'\'给去掉了.解决方法是调用json_encode时候后面加JSON_UNESCAPED_UNICODE ...

  10. Nginx服务测试时的一些配置:wireshark、常用搜索URL格式、关闭防火墙、siege

    wrieshark sudo yum install wireshark-gnome sudo wireshar (以root启动,否则看不到网卡) 网站URL格式 以查询lumia为例 google ...