我的前老板告诉我,shader要想做好,就要多看多记。

初学sahder,自然想看看大佬们的shader都是怎么写的。虽然程序员只需要ctrl+c ctrl+v就可以编程,但是我还是想细致理解其中的过程,在看这个雷达波的shader中感觉学到了很多东西,特此记录。接上一篇。依然是这个雷达波的shader。

首先,贴上大佬的链接:

http://www.manew.com/thread-105501-1-1.html

然后开始拾大佬的牙慧。

大佬的总体思路是,先实现一个球的边缘会发光,然后在考虑与别的物体相交边缘高亮,然后再加上一些扭曲。这个shader就完成了。

我直接把每一行代码都加上注释,详细的解释这些代码。

/*Created by chenjdhttp://www.cnblogs.com/murongxiaopifu/
*/
Shader "chenjd/ForceField"
{
Properties
{_Color("Color", Color) = (0,0,0,0)_NoiseTex("NoiseTexture", 2D) = "white" {}_DistortStrength("DistortStrength", Range(0,1)) = 0.2_DistortTimeFactor("DistortTimeFactor", Range(0,1)) = 0.2_RimStrength("RimStrength",Range(0, 10)) = 2_IntersectPower("IntersectPower", Range(0, 3)) = 2
}SubShader
{ZWrite OffCull OffBlend SrcAlpha OneMinusSrcAlphaTags{"RenderType" = "Transparent""Queue" = "Transparent"}/*通过GrabPass定义了一个抓取屏幕图像的Pass,在这个Pass中定义了一个字符串,该字符串决定了抓到的图像会存储到哪一张纹理中就是存到了sampler2D _GrabTempTex;这个里面*,这里在扭曲里会用到*/GrabPass{"_GrabTempTex"}Pass
{CGPROGRAM
#pragma target 3.0
#pragma vertex vert
#pragma fragment frag#include "UnityCG.cginc"struct appdata
{float4 vertex : POSITION;float2 uv : TEXCOORD0;float3 normal : NORMAL;
};struct v2f
{float4 vertex : SV_POSITION;float2 uv : TEXCOORD0;float4 screenPos : TEXCOORD1;float4 grabPos : TEXCOORD2;float3 normal : NORMAL;float3 viewDir : TEXCOORD3;
};sampler2D _GrabTempTex;
float4 _GrabTempTex_ST;
sampler2D _NoiseTex;
float4 _NoiseTex_ST;
float _DistortStrength;
float _DistortTimeFactor;
float _RimStrength;
float _IntersectPower;//通过声明_CameraDepthTexture变量来访问摄像机的深度纹理,摄像机也要有这么一个设置camera.depthTextureMode=DepthTextureMode.Depth
sampler2D _CameraDepthTexture;v2f vert(appdata v)
{v2f o;o.vertex = UnityObjectToClipPos(v.vertex);//计算顶点在抓取到的纹理中的位置o.grabPos = ComputeGrabScreenPos(o.vertex);o.uv = TRANSFORM_TEX(v.uv, _NoiseTex);//计算顶点在当前屏幕中的位置o.screenPos = ComputeScreenPos(o.vertex);//因为_CameraDepthTexture中不记录透明物体的深度,所以用COMPUTE_EYEDEPTH(o.screenPos.z)来计算屏幕位置对应的深度。//在UnityCG.cginc 里   #define COMPUTE_EYEDEPTH(o) o = -UnityObjectToViewPos( v.vertex ).zCOMPUTE_EYEDEPTH(o.screenPos.z);o.normal = UnityObjectToWorldNormal(v.normal);o.viewDir = normalize(UnityWorldSpaceViewDir(mul(unity_ObjectToWorld, v.vertex)));return o;
}fixed4 _Color;fixed4 frag(v2f i) : SV_Target
{//获取已有的深度信息,此时的深度图里没有力场的信息//判断相交//这段代码在文章里解释一下//SAMPLE_DEPTH_TEXTURE_PROJ是对深度纹理进行采样 第二个参数通常使用顶点着色器输出插值而得的屏幕坐标//UNITY_PROJ_COORD:given a 4-component vector, return a texture coordinate suitable for projected texture reads. On most platforms this returns the given value directly.//LinearEyeDepth让深度值线性化float sceneZ = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.screenPos)));float partZ = i.screenPos.z;float diff = sceneZ - partZ;float intersect = (1 - diff) * _IntersectPower;//圆环//这个画圆环就是一个菲涅尔折射了,让物体边缘发光float3 viewDir = normalize(UnityWorldSpaceViewDir(mul(unity_ObjectToWorld, i.vertex)));float rim = 1 - abs(dot(i.normal, normalize(i.viewDir))) * _RimStrength;float glow = max(intersect, rim);//扭曲//扭曲就是加一些噪声 然后让uv动起来就可以了float4 offset = tex2D(_NoiseTex, i.uv - _Time.xy * _DistortTimeFactor);i.grabPos.xy -= offset.xy * _DistortStrength;fixed4 color = tex2Dproj(_GrabTempTex, i.grabPos);fixed4 col = _Color * glow + color;return col;
}ENDCG
}
}
}

接下来重点解释一下这几行:
    float sceneZ = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.screenPos)));

float partZ = i.screenPos.z;

float diff = sceneZ - partZ;
    float intersect = (1 - diff) * _IntersectPower;

sceneZ是获取到深度纹理中的深度,但是这个深度不包括透明物体的。partZ才是该透明物体(就是能量罩)上每一个点的深度。

为什么相交的地方会发光呢? 首先要判断相交的地方在哪里,怎么判断呢?就要用到深度值了,(以上边第二张图)如果能量罩上的某些点深度值和立方体上某些点的深度值一致,那么这些点就是交线上的点了。所以用sceneZ-partZ来表示这些点的距离差,差值越小说明越靠近。然后用1-diff来说明相交的程度。可以先这么理解,差值越小,1-diff越大,相交得越厉害。

之后再使用这句float glow = max(intersect, rim);就可以让交线处发光了,这句该怎么理解呢?

可以这么看,假设我们不考虑交线发光,那么这个图是这样子的。

的确,交线处无发光的迹象,然而球的边缘却是发光的。

当它使用float glow = max(intersect, rim)这句时,可以这么理解,当远离交线时,intersect值比较小,所以远离交线的地方就取rim值,当离交线很近时,显然intersect值比较大,这时候就要取intersect的值,所以交线处也会发亮。

至此,这个交线发亮就做完了,但是其中有一点为什么diff=sceneZ-partZ,而不是diff=partZ-sceneZ呢?下面是我自己的一些推理,不清楚对不对,大概是对的(我瞎猜的)

如图,黑色点是相机,红色的是不透明的物体,蓝色框是透明的物体。假设,sceneZ是红色物体的深度,partZ是透明物体的深度

显然红色离相机远,蓝色离相机近,所以sceneZ-partZ>0 当两者相差的过大时,sceneZ-partZ>1  那么intersect值会是一个负值,所以会用原始rim值。

考虑另一种情况

当蓝色在后面,红色在前面,此刻partZ>sceneZ   那么sceneZ-partZ<0,则intersect>1 此刻绿色框内应该疯狂发光才对

but,被红色不透明物体遮住了。。。你看不见。

所以只有下面这种情况才对

透明物体在不透明物体前面一点点,这样0<sceneZ-partZ<1。

也就是这么说当蓝色物体在红色物体后面时,虽然intersect值会很大,但是你看不见,被红色物体遮住了。当蓝色物体在红色物体前面一点点时,两者里的越近sceneZ-partZ越接近0 ,那么1-(sceneZ-partZ)会越大,即intersect值越大,所以交线发亮。所以使用diff=sceneZ-partZ没毛病。

告辞!

学习雷达波,防护罩shader的记录相关推荐

  1. 【HLSL学习笔记】WPF Shader Effect Library算法解读之[DirectionalBlur]

    原文:[HLSL学习笔记]WPF Shader Effect Library算法解读之[DirectionalBlur] 方位模糊是一个按照指定角度循环位移并叠加纹理,最后平均颜色值并输出的一种特效. ...

  2. Python批量运行Gprmax仿真并快速提取雷达波走时和振幅

    Python批量运行Gprmax仿真并快速提取雷达波走时和振幅 使用gprmax仿真模拟时,通常在cmd窗口写命令,运行结果保存的文件夹不能任意选择,这样很不方便.尤其是在做钻孔电磁波仿真时,需要大量 ...

  3. DSP学习(4)—— 看代码记录

    DSP学习(4)-- 看代码记录 文章目录 DSP学习(4)-- 看代码记录 前言 一.一些缩写 二.C语言忘记的知识 条件编译中使用的预编译指令 前言 本文用于记录看代码中间遇到的不认识的东西. 一 ...

  4. python|利用打飞机小游戏学习分支和循环|今天是记录自己学习的第四天呀!加油!

    ** python|利用打飞机小游戏学习分支和循环|今天是记录自己学习的第四天呀!加油! ** /*** Author:Jiang Zhiying Data:2017.11.11 Emial:1443 ...

  5. 利用JQ实现的,高仿 彩虹岛官网导航栏(学习HTML过程中的小记录)

    利用JQ实现的,高仿 彩虹岛官网导航栏(学习HTML过程中的小记录)   作者:王可利(Star·星星) 总结: 今天学习的jQ类库的使用,代码重复的比较多需要完善.严格区分大小写,在 $(" ...

  6. 【学习日记】初次使用golang记录

    [学习日记]初次使用golang记录 前言 初次使用后感 安装 工作目录设置 go换源 附上这个压缩图片的小demo 前言 有个需求是图片上传的功能,上传后想压缩一下,无奈php图片处理效率太低.于是 ...

  7. 学习笔记之车道线相关记录

    一. 车道线相关的知识 &&1.标线的分类 以下分类来自于百科: 按照道路交通标线的功能划分为:指示标线.警告标线和禁止标线. 按标划方法可分为:白色虚线.白色实线.黄色虚线.黄色实线 ...

  8. 【深度学习】图像匹配Siamese网络实验记录

    图像匹配Siamese网络实验记录 Ⅰ. Siamese 网络介绍 Ⅱ. 数据集 AT&T 分拣行李匹配图像 Ⅲ. 实验记录 A. 模型1 1. 实验1 2. 实验2 3. 实验3 B. 模型 ...

  9. deeplearning.14深度学习猫咪识别阶段性检测记录

    猫咪识别阶段性检测记录 numpy基础 猫咪图像识别 一.加载数据以及数据预处理 二.使用神经网络的思维方式建立logistic回归 总结完整代码及注释 numpy基础 打开jupyter Noteb ...

  10. 前端学习从入门到高级全程记录之1 (HTML基础知识)

    本次学习目标 掌握HTML的基本知识,能够写出简单的页面. 1. 开发工具 1.浏览器(chrome(谷歌浏览器),IE浏览器,火狐浏览器,QQ浏览器等等). 2.代码编辑器(sublime,HBui ...

最新文章

  1. spring IOC和DI
  2. javaweb家居用品线上销售系统_智能家居订单管理系统方案设计路线
  3. 计算机网络之网络层:9、BGP协议
  4. mysql启动错误处理
  5. MSSQL-Server On Docker
  6. 原 IntelliJ IDEA 中 右键新建时,选项没有Java class的解决方法和具体解释
  7. 负载电流对电感值和电感尺寸的影响 // 《精通开关电源设计》P50:负载电流对电感值和电感尺寸的影响
  8. java解析marc乱码_国际C语言乱码大赛(IOCCC)的一个经典作品
  9. Excel怎么做均值-极差控制图
  10. 要想Essay写得好,切记要警惕这六大禁区
  11. PHP 5.6,7.0,7.1,7.2 和 HHVM 运行效率比较
  12. linux字体文件路径,Linux下安装字体
  13. KLayout教程(一)画不同的形状
  14. 计算机网络考研、招聘面试问题总结
  15. 踩坑sunbeam rbt 去除host reads
  16. Franka Emika 机械臂在ROS下控制
  17. 嵌入式Linux基础教程-读书笔记
  18. UDP实战模拟——聊天模拟器
  19. JAVA编程实现猜数游戏
  20. 三 Laya3D 加载资源 (场景/预设/模型网格/材质/动画文件/贴图/粒子)

热门文章

  1. Linux网络----DNS域名解析主从与分离实验
  2. redis 配置文件设置密码不生效的问题
  3. 第2关- 条件判断与条件嵌套
  4. 大象装企营销:家装公司要做大必学的60种渠道拓展方法
  5. mysql静态视图_在Django中创建第一个静态视图
  6. 日本手机界面设计浅谈
  7. mc储存服务器地址的文件,如何创建mc服务器地址
  8. 使用高德地图vue组件库vue-amap是,用content渲染点标记问题解决
  9. Linux驱动开发基础__mmap
  10. 计算机网络中man是,在计算机网络中,MAN是城域网的简称