来源:《UNITY SHADER入门精要》

文章目录

  • 1、镜面反射ShaderLab的方式
  • 2、逐顶点的镜面反射
  • 3、逐像素光照计算

1、镜面反射ShaderLab的方式

  我们回忆之前的公式:
cspcular=(clight⋅mspecular)max⁡(0,v^⋅r)mgloss\boldsymbol{c}_{spcular}=\left( \boldsymbol{c}_{light}\cdot \boldsymbol{m}_{specular} \right) \max \left( 0, \hat{v}\,\,\cdot \,\,\boldsymbol{r} \right) ^{m_{gloss}} cspcular​=(clight​⋅mspecular​)max(0,v^⋅r)mgloss​
  我们计算镜面反射需要四个参数:入射光线clight\boldsymbol{c}_{light}clight​ 、材质的高光反射系数mspecular\boldsymbol{m}_{specular}mspecular​ 、视角方向 v^\hat{v}v^ 、反射方向 r\boldsymbol{r}r 。而其中,反射方向 r\boldsymbol{r}r 又需要由表面法线 n^\hat{n}n^ 和 光源方向 I\boldsymbol{I}I 计算而得。

  公式不难写出,不过,CG提供了计算反射方向的函数:reflect(i, n)。其中参数:i 为入射方向;n 为法线方向。

2、逐顶点的镜面反射

Shader "Unity Shaders Book/Chapter 6/Specular Vertex-Level" {Properties {_Diffuse ("Diffuse", Color) = (1, 1, 1, 1)_Specular ("Specular", Color) = (1, 1, 1, 1)_Gloss ("Gloss", Range(8.0, 256)) = 20}SubShader {Pass { Tags { "LightMode"="ForwardBase" }

  这里定义了三个 Properties ,其中,_Diffuse 用来控制漫反射的颜色系数, _Specular 用来控制高光反射的颜色, _Gloss 用来控制高光区域的大小。
  这里的 LightMode 设置为 ForwardBase 定义了该 Pass 在 Unity 的光照流水线中的角色。

         CGPROGRAM#pragma vertex vert#pragma fragment frag#include "Lighting.cginc"fixed4 _Diffuse;fixed4 _Specular;float _Gloss;

  同样,在CGPROGRAM之后,我们包含头文件"Lighting.cginc",用 #pragma 指定顶点/片元着色器的函数。
  声明 Properties 语义块中的属性:由于颜色属性的范围在0到1之间,因此对于Diffuse和Specular属性我们可以使用fixed精度的变量来存储它。而Gloss的范围很大,因此我们使用flot精度来存储。

         struct a2v {float4 vertex : POSITION;float3 normal : NORMAL;};struct v2f {float4 pos : SV_POSITION;fixed3 color : COLOR;};

  定义输入和输出要使用的结构体

         v2f vert(a2v v) {v2f o;// Transform the vertex from object space to projection spaceo.pos = UnityObjectToClipPos(v.vertex);// Get ambient termfixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;// Transform the normal from object space to world spacefixed3 worldNormal = normalize(mul((float3x3)unity_ObjectToWorld, v.normal));// Get the light direction in world spacefixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);// Compute diffuse termfixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLightDir));

  前面的计算是关于漫反射的,跟之前是一致的。

             // Get the reflect direction in world spacefixed3 reflectDir = normalize(reflect(-worldLightDir, worldNormal));// Get the view direction in world space,计算的是每一个顶点在世界空间的位置。fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, v.vertex).xyz);// Compute specular termfixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(reflectDir, viewDir)), _Gloss);o.color = ambient + diffuse + specular;return o;}fixed4 frag(v2f i) : SV_Target {return fixed4(i.color, 1.0);}ENDCG}} FallBack "Specular"
}

  这里采用的 CG 的 reflect() 函数计算了反射光线。由于参数要求传入的方向是从光源到交点处的,所以,采用的是它的反向量。
  然后,我们用计算得到的反射向量,计算得到高光值,然后都相加起来,返回就好了。
  最后,第21行,我们磨人的FallBack设置为 内置的 Specular。

  最后,我们注意到,逐顶点光照,由于线性插值的缘故,会有明细的线性效果,不够真实。所以,我们需要逐像素来出来计算。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oIf2liTz-1659590622745)(assets/image-20220620162252379.png)]

3、逐像素光照计算

  

Shader "Unity Shaders Book/Chapter 6/Specular Pixel-Level" {Properties {_Diffuse ("Diffuse", Color) = (1, 1, 1, 1)_Specular ("Specular", Color) = (1, 1, 1, 1)_Gloss ("Gloss", Range(8.0, 256)) = 20}SubShader {Pass { Tags { "LightMode"="ForwardBase" }CGPROGRAM#pragma vertex vert#pragma fragment frag#include "Lighting.cginc"fixed4 _Diffuse;fixed4 _Specular;float _Gloss;

  前面的代码和之前没有区别

         struct a2v {float4 vertex : POSITION;float3 normal : NORMAL;};struct v2f {float4 pos : SV_POSITION;float3 worldNormal : TEXCOORD0;float3 worldPos : TEXCOORD1;};

  因为是逐像素进行计算。这里的输出皆使用纹理坐标的语义来接收。

         v2f vert(a2v v) {v2f o;// Transform the vertex from object space to projection spaceo.pos = mul(UNITY_MATRIX_MVP, v.vertex);// Transform the normal from object space to world spaceo.worldNormal = mul(v.normal, (float3x3)_World2Object);// Transform the vertex from object spacet to world spaceo.worldPos = mul(_Object2World, v.vertex).xyz;return o;}

  顶点着色器所做的事情就是计算 世界空间下的法线方向和顶点坐标,并把它们传递给片元着色器。

         fixed4 frag(v2f i) : SV_Target {// Get ambient termfixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;fixed3 worldNormal = normalize(i.worldNormal);fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);// Compute diffuse termfixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLightDir));// Get the reflect direction in world spacefixed3 reflectDir = normalize(reflect(-worldLightDir, worldNormal));// Get the view direction in world spacefixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);// Compute specular termfixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(reflectDir, viewDir)), _Gloss);return fixed4(ambient + diffuse + specular, 1.0);}ENDCG}} FallBack "Specular"
}

【图形学】18 光照模型(三、镜面反射的Shader实现)相关推荐

  1. OpenGL南邮计算机图形学实验报告三——实现类似地月系统的两物体环绕移动

    OpenGL南邮计算机图形学实验报告三--实现类似地月系统的两物体环绕移动 计算机图形学的新题目要求 OpenGL配置参考: 南邮老前辈wonz哥的OpenGL配置(Shader.h始终不用改).SO ...

  2. 计算机图形学阴影的的分类,计算机图形学8_光照模型与阴影处理_.pdf

    您所在位置:网站首页 > 海量文档 &nbsp>&nbsp计算机&nbsp>&nbsp图形图像 计算机图形学8_光照模型与阴影处理_.pdf5页 本文 ...

  3. 简单 局部 整体光照模型计算机图形学,计算机图形学北大光照模型.ppt

    计算机图形学北大光照模型 * 当来自光源和周围环境的入射光照射在景物表面上时,将有部分光被反射或透射: 在视线方向的反射或透射光,被观察者眼睛中的视觉细胞接收 人眼中的杆状及锥状细胞接收光线,产生视觉 ...

  4. 计算机图形学实验报告 裁剪,计算机图形学-实验报告三-图形裁剪算法

    <计算机图形学-实验报告三-图形裁剪算法>由会员分享,可在线阅读,更多相关<计算机图形学-实验报告三-图形裁剪算法(9页珍藏版)>请在人人文库网上搜索. 1.图形裁剪算法1. ...

  5. 【XJTUSE计算机图形学】第三章 几何造型技术(1)——参数曲线和曲面

    文章目录 [XJTUSE计算机图形学]第三章 几何造型技术(1)--参数曲线和曲面 参数曲线和曲面 曲线曲面参数表示 非参数表示 参数表示 曲线的基本概念 插值.拟合和光顺(掌握概念) 参数化 概念 ...

  6. 图形学笔记(三)—— Harris角点检测器

    图形学笔记(三)-- Harris角点检测器 前言 CSDN不支持我的公式,大家可以到我的博客:wang-sy.github.io去看 从现在开始学习的是书中的第二章:局部图像描述子.这里主要是寻找图 ...

  7. 【XJTUSE计算机图形学】第三章 几何造型技术(2)——Bezier 曲线与曲面

    文章目录 [XJTUSE计算机图形学]第三章 几何造型技术(2)--Bezier 曲线与曲面 Bezier 曲线与曲面 Bezier 曲线的定义与性质 定义 习题 Bernstein基函数性质 Bez ...

  8. 真实图形学(光照模型)

    一 .颜色模型     真实感图形学,简单地说,就是希望用计算机生成像照相机拍的照片一样逼真的图形图像 .要实现这个目标,需要三部曲: 第一步:建立三维场景(建模): 第二步:消隐解决物体深度的显示及 ...

  9. 【图形学】光照模型-从最简单开始到BRDF实现

    不积跬步无以至千里,想要了解复杂的光照模型,就要从最简单的入手,看看他们是如何一步步"进化"成完善的样子.每天300字,看看能否在一个月能完结这个主题吧~ 首先从基本光照模型开始: ...

最新文章

  1. PostgreSQL11.3 创建用户和创建数据库
  2. 有关gitlab的神秘操作.....versiondomain设置...
  3. NestedScrollView平滑滑动嵌套 Fling
  4. 【每周CV论文推荐】 初学深度学习图像分割必须要读的文章
  5. “云网管” -云上构建网络自动化体系
  6. 关于项目管理的一些想法
  7. Elasticsearch SkyWalking 分布式链路追踪
  8. MySQL数据库应用形考_2020国开中优教育《MySQL数据库应用》形考任务题库
  9. RIPv1和RIPv2的区别和相同点
  10. 年总结(二):历经一年的蜕变
  11. 一招教你查看Mac本机WiFi密码
  12. 傅里叶变换对应的matlab函数,用MATLAB如何实现傅里叶变换
  13. 2020计算机软考初级都考什么,软考都考什么内容
  14. 【javascript】解析psd文件踩坑
  15. (学习笔记)JAVA开发需要掌握哪些技术?
  16. Java如何解析个人或他人微信二维码内的信息
  17. C++ 学习(四)程序流程结构 - 顺序结构、选择结构、循环结构、跳转语句
  18. html设置顶部背景颜色,css怎么设置背景颜色?
  19. Docker/Podman使用入门---从容器构建镜像 提交镜像到服务器UCloud dockerhub
  20. java 获得jtextarea_java JTextArea中获得光标所在行数

热门文章

  1. · 电动汽车(EV)充电标准及其差异
  2. 如何把两个PDF合成一个PDF文件
  3. Mac Mojave10.14安装vmvare Fusion 11.0.0 win8 镜像
  4. 面向医疗数据的差分隐私保护
  5. 视频太大怎么压缩变小?
  6. openwrt mysql改密码_openwrt的路由器重置root密码
  7. Frida Internal - Part 1: 架构、Gum 与 V8
  8. The right to contest automated decisions under the General Data Protection Regulation: Beyond the so
  9. php读书笔记,读书笔记:《Modern PHP》
  10. 《期权、期货及其他衍生产品》读书笔记(第九章:价值调节量)