6-9.添加HLSL镜面高光

问题

你想要用你的自定义HLSL效果添加镜面高光到你的3D场景。镜面高光是光源反射产生的高亮区域,如6-11.

方案

下面的讨论将帮助你决定那个像素将有镜面光部分。

6-11左边显示一个光的传播,L是一条从光源命中三角形像素的向量。同样,眼的向量是从相机朝像素方向。如果L的反射线几乎和E一样,像素应该有镜面光部分。

你可以用镜像方法通过该像素的法线来找到L的反射线。如果它们间的夹角很小这个镜像了的方向几乎和眼的方向一样。你可以通过求它们的点积来检查这两个向量间的夹角。

如果夹角是0,意味着两个方向一样且你应该添加镜面部分到光照,点积就是1。如果两个方向不同,点积会比1小。

注意 两个向量A和B间的点积只不过是(A长度)×(B长度)×(cos(它们间的夹角))。如果A和B都单位化,点积就只是(cos(它们间的夹角))。如果AB间夹角是0,点积就是1.如果两个向量互相垂直,夹角是90度,点积就是0。就像6-11右上方显示的。如果两个向量相反,夹角180度,点积是-1.

当所有光向量和眼向量的夹角少于90度时这个点积将被转成正的,如6-11的右上。你不能马上把这个值用作镜面高光,因为这将添加一个镜面光部分到所有不超过眼向量90度的反射向量。你想要缩小反射向量在10度或以下。

你可以通过给点积的结果一个高次方来得出。求这个点积的12次方,例如,将只为偏移10度之内的向量产生一个大于0的值,如6-11右下部显示。

这将使每个像素结果在单精度值,表明在该像素的镜面部分的强度。

运作

一直以来,你将想要能够设置世界,视图和投影矩阵来变换你的3D位置到2D屏幕坐标。因为这节是为点光源而写,你需要能够修改它的位置。要计算眼向量,你需要知道相机的位置。你应该能设置镜面次方数来控制镜面高光的大小。因为光照的总量可能大于1,你应该能够缩小光强度来避免过度饱和。

注意 在许多情况,你将想要缩小光源的强度。要拥有多个光时要这么做,否则引起大多数像素融进光里,浪费了照明效果。

float4x4 xWorld;

float4x4 xView;

float4x4 xProjection;

float3 xLightPosition;

float3 xCameraPos;

float xAmbient;

float xSpecularPower;

float xLightStrength;

struct SLVertexToPixel

{

float4 Position          : POSITION;

float3 Normal           : TEXCOORD0;

float3 LightDirection : TEXCOORD1;

float3 EyeDirection       : TEXCOORD2;

};

struct SLPixelToFrame

{

float4 Color             : COLOR0;

};

这个顶点着色器也将计算EyeDirection并使它对所有像素用插值替换。像素着色器仍然只需要输出每个像素的颜色。

顶点着色器

顶点着色器和上一节没啥区别。唯一新增的是计算了眼向量。通过从目标减去原点得出从一个点到另一个点的向量。

SLVertexToPixel SLVertexShader(float4 inPos: POSITION0, float3 inNormal: NORMAL0)

{

SLVertexToPixel Output = (SLVertexToPixel)0;

float4x4 preViewProjection = mul(xView, xProjection);

float4x4 preWorldViewProjection = mul(xWorld, preViewProjection);

Output.Position = mul(inPos, preWorldViewProjection);

float3 final3DPos = mul(inPos, xWorld);

Output.LightDirection = final3DPos - xLightPosition;

Output.EyeDirection = final3DPos - xCameraPos;

float3x3 rotMatrix = (float3x3)xWorld;

float3 rotNormal = mul(inNormal, rotMatrix);

Output.Normal = rotNormal;

return Output;

}

像素着色器

像素着色器更有趣。基色固定是蓝色,因此你不必浪费心思在这。一个很好的做法是,你单位化每个你在像素着色器接收到的方向,因为它的长度可能不是1.

和以前一样,你计算通用光照。把它和xLightStrength相乘来缩小它一点。

SLPixelToFrame SLPixelShader(SLVertexToPixel PSIn) : COLOR0

{

SLPixelToFrame Output = (SLPixelToFrame)0;

float4 baseColor = float4(0,0,1,1);

float3 normal = normalize(PSIn.Normal);

float3 lightDirection = normalize(PSIn.LightDirection);

float shading = dot(normal, -lightDirection);

shading *= xLightStrength;

float3 reflection = -reflect(lightDirection, normal);

float3 eyeDirection = normalize(PSIn.EyeDirection);

float specular = dot(reflection, eyeDirection);

specular = pow(specular, xSpecularPower);

specular *= xLightStrength;

Output.Color = baseColor*(shading+xAmbient)+specular;

return Output;

}

接着,你用反射原理通过法线镜像化光方向。因为光方向照向像素,它的反射线将向着眼。这和眼向量相反,所以你反转它。

镜面值通过眼向量和反转的反射光方向间的点积得出。使这个值有高的次方确保只为当那些两个向量差异小于10度左右的像素该值才显著的大于0。再有,这个值是和xLightStrength值相乘。

最后,环境光,着色值,镜面高光部分组合得出最终像素颜色。

注意 镜面部分添加白色到最终色。如果你的光有不同颜色,你应该用你的光的颜色乘以镜面值。

转载于:https://www.cnblogs.com/XNAconglele/archive/2009/09/26/1574319.html

6-9.添加HLSL镜面高光相关推荐

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

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

  2. 使用高效像素聚类实时去除高品质镜面高光

    0.摘要 在双色反射模型的基础上,最近的镜面反射高光去除技术通常会估计和群集照明色度值,​​以从单个图像中分离出漫反射和镜面反射分量.尽管这些技术能够获得视觉上令人愉悦的结果,但它们的聚类算法存在初始 ...

  3. Cg Programming/Unity/Specular Highlights镜面高光

    本教程涵盖了使用Phone反射模型的逐顶点光照(也叫做高洛德着色).它在章节"漫反射"中通过两个额外的术语扩展了着色器代码:环境光和镜面反射.这三个术语一起构成了Phone反射模型 ...

  4. 【Unity3D Shader编程】之十三 单色透明Shader 标准镜面高光Shader

    本系列文章由@浅墨_毛星云 出品,转载请注明出处.   文章链接: http://blog.csdn.net/poem_qianmo/article/details/50878538 作者:毛星云(浅 ...

  5. 【Unity3D Shader编程】之十三 单色透明Shader 标准镜面高光Shader

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 本系列文 ...

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

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

  7. Unity可编程渲染管线系列(七)反射(镜面和环境)

    目录 1 高亮的高光 1.1 光滑度 1.2 表面数据 1.3 漫反射光 1.4 镜面选项 1.5 镜面高光 1.6 逐物体平滑度 2 反射环境 2.1 采样环境 2.2 调制反射 2.3 菲涅尔 2 ...

  8. 《Unity着色器和屏幕特效开发秘笈》—— 3.4 创建BlinnPhong高光类型

    本节书摘来自华章出版社<Unity着色器和屏幕特效开发秘笈>一 书中的第3章,第3.4节,作者:(美)Kenny Lammers,更多章节内容可以访问云栖社区"华章计算机&quo ...

  9. HLSL内置函数一览

    本文版权归 博客园 七星重剑 所有,如有转载,请按如下方式于显示位置标明原创作者及出处,以示尊重!! 作者:七星重剑 原文:每天30分钟看Shader--(1)HLSL固有函数 [Intrinsic ...

最新文章

  1. java面试浦发_记一次凉凉的浦发面试
  2. 计算机中数据的编码方式
  3. VC++开发简易输电线路管理信息系统
  4. Hadoop自学笔记(七)Hadoop环境配置和优化
  5. FM对采购业务的预算控制
  6. ng-content的一个实际例子
  7. json 文件打读取
  8. Linux系统编程24:基础IO之在Linux下深刻理解C语言中的动静态库以及头文件和库的关系
  9. Windows 10 IIS所有的html返回空白
  10. 华为p50 pro 鸿蒙,华为P50Pro真豪横!鸿蒙系统+真全屏5摄,网友:太香了!
  11. ntdll.dll 0xc0000005
  12. 文章刚刚开源就被培训机构“BP”了,过于不要脸
  13. 很好的--张量(Tensor)的技术以及它在不同场景中的应用--转载贪心科技
  14. CentOS 8 修改DNS地址
  15. window7安装过后有多大?6.18G
  16. 如何防止单元格在Google表格中进行编辑
  17. 新手零基础快速入门Docker
  18. 瑞星2005升级问题汇总
  19. 关于Petalinux自启问题
  20. Ear Clipping算法简介

热门文章

  1. android 配置aspect_Android全面屏适配
  2. Datatable转为ListT / DataRow转为实体类对象
  3. 大数据与人工智能催生智能时代
  4. An中的共轭类的个数
  5. 在线数据迁移,数字化时代的必修课——京东云数据迁移实践
  6. JAVA中 BufferedImage、ImageIO用法
  7. C语言(二十三)auto自动变量
  8. marker 头像 高德地图_高德地图头像怎么更换 高德地图更换头像图文教程
  9. 《C#程序设计》猜猜看游戏开发总结
  10. 物联网云平台DTU Modbus协议 上位机 下位机 源码 源代码 程序