6-9.添加HLSL镜面高光
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镜面高光相关推荐
- 在场景中添加光线——在反光表面添加镜面高光
问题 就算开启了逐像素明暗,有些金属或闪光表面仍显得有点暗淡.在现实生活中,当观察诸如金属.玻璃或一些塑料时,你会发现某些区域的反光非常强烈.这样的区域如图6-6的虚线圆圈所示.这些高亮的区域叫做镜面 ...
- 使用高效像素聚类实时去除高品质镜面高光
0.摘要 在双色反射模型的基础上,最近的镜面反射高光去除技术通常会估计和群集照明色度值,以从单个图像中分离出漫反射和镜面反射分量.尽管这些技术能够获得视觉上令人愉悦的结果,但它们的聚类算法存在初始 ...
- Cg Programming/Unity/Specular Highlights镜面高光
本教程涵盖了使用Phone反射模型的逐顶点光照(也叫做高洛德着色).它在章节"漫反射"中通过两个额外的术语扩展了着色器代码:环境光和镜面反射.这三个术语一起构成了Phone反射模型 ...
- 【Unity3D Shader编程】之十三 单色透明Shader 标准镜面高光Shader
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/50878538 作者:毛星云(浅 ...
- 【Unity3D Shader编程】之十三 单色透明Shader 标准镜面高光Shader
分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 本系列文 ...
- 在场景中添加光线——添加HLSL Vertex Shading
问题 使用你配置好的光照,BasicEffect可以很好地绘制场景.但是,如果你想定义一些更酷的效果,首先要实现的就是正确的光照. 本教程中,你将学习如何编写一个基本的HLSL effect实现逐顶点 ...
- Unity可编程渲染管线系列(七)反射(镜面和环境)
目录 1 高亮的高光 1.1 光滑度 1.2 表面数据 1.3 漫反射光 1.4 镜面选项 1.5 镜面高光 1.6 逐物体平滑度 2 反射环境 2.1 采样环境 2.2 调制反射 2.3 菲涅尔 2 ...
- 《Unity着色器和屏幕特效开发秘笈》—— 3.4 创建BlinnPhong高光类型
本节书摘来自华章出版社<Unity着色器和屏幕特效开发秘笈>一 书中的第3章,第3.4节,作者:(美)Kenny Lammers,更多章节内容可以访问云栖社区"华章计算机&quo ...
- HLSL内置函数一览
本文版权归 博客园 七星重剑 所有,如有转载,请按如下方式于显示位置标明原创作者及出处,以示尊重!! 作者:七星重剑 原文:每天30分钟看Shader--(1)HLSL固有函数 [Intrinsic ...
最新文章
- java面试浦发_记一次凉凉的浦发面试
- 计算机中数据的编码方式
- VC++开发简易输电线路管理信息系统
- Hadoop自学笔记(七)Hadoop环境配置和优化
- FM对采购业务的预算控制
- ng-content的一个实际例子
- json 文件打读取
- Linux系统编程24:基础IO之在Linux下深刻理解C语言中的动静态库以及头文件和库的关系
- Windows 10 IIS所有的html返回空白
- 华为p50 pro 鸿蒙,华为P50Pro真豪横!鸿蒙系统+真全屏5摄,网友:太香了!
- ntdll.dll 0xc0000005
- 文章刚刚开源就被培训机构“BP”了,过于不要脸
- 很好的--张量(Tensor)的技术以及它在不同场景中的应用--转载贪心科技
- CentOS 8 修改DNS地址
- window7安装过后有多大?6.18G
- 如何防止单元格在Google表格中进行编辑
- 新手零基础快速入门Docker
- 瑞星2005升级问题汇总
- 关于Petalinux自启问题
- Ear Clipping算法简介