原理

1. 广告牌

2. 闪烁

3. 体积光远近淡出入变化

效果

代码

Shader "Unlit/BlinkingBillboardedGodRay"
{Properties{_MainTex ("Base texture", 2D) = "white" {}_FadeOutDistNear ("Near fadeout dist", float) = 10    _FadeOutDistFar ("Far fadeout dist", float) = 10000  _Multiplier("Color multiplier", float) = 1_Bias("Bias",float) = 0_TimeOnDuration("ON duration",float) = 0.5_TimeOffDuration("OFF duration",float) = 0.5_BlinkingTimeOffsScale("Blinking time offset scale (seconds)",float) = 5_SizeGrowStartDist("Size grow start dist",float) = 5_SizeGrowEndDist("Size grow end dist",float) = 50_MaxGrowSize("Max grow size",float) = 2.5_NoiseAmount("Noise amount (when zero, pulse wave is used)", Range(0,0.5)) = 0_VerticalBillboarding("Vertical billboarding amount", Range(0,1)) = 1_ViewerOffset("Viewer offset", float) = 0_Color("Color", Color) = (1,1,1,1)}SubShader{Tags { "RenderType"="Transparent" "IgnoreProjector"="True" "Queue"="Transparent"}Blend One OneCull Off Lighting Off ZWrite Off Fog { Color (0,0,0,0) }LOD 100Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"sampler2D _MainTex;float _FadeOutDistNear;float _FadeOutDistFar;float _Multiplier;float   _Bias;float _TimeOnDuration;float   _TimeOffDuration;float _BlinkingTimeOffsScale;float _SizeGrowStartDist;float _SizeGrowEndDist;float _MaxGrowSize;float _NoiseAmount;float _VerticalBillboarding;float _ViewerOffset;float4 _Color;struct v2f{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;fixed4 color : TEXCOORD1;};// 通过方向确认右方和上方向量//void CalcOrthonormalBasis(float3 dir,out float3 right,out float3 up){up     = abs(dir.y) > 0.999f ? float3(0,0,1) : float3(0,1,0);      right = normalize(cross(up,dir));      up  = cross(dir,right);    }// 计算距离的缩放//float CalcDistScale(float dist){float      distScale   = min(max(dist - _SizeGrowStartDist,0) / _SizeGrowEndDist,1);return distScale * distScale * _MaxGrowSize;}// 封装通过距离算淡入淡出//float CalcFadeOutFactor(float dist){float        nfadeout    = saturate(dist / _FadeOutDistNear);float      ffadeout    = 1 - saturate(max(dist - _FadeOutDistFar,0) * 0.2);ffadeout *= ffadeout;nfadeout *= nfadeout;nfadeout *= nfadeout;nfadeout *= ffadeout;return nfadeout;}v2f vert(appdata_full v){v2f o;// 计算中心点位置// 计算物体到摄像机在模型坐标系中的方向//float3    centerOffs = float3(float(0.5).xx - v.color.rg,0) * v.texcoord1.xyy;float3 centerLocal = v.vertex.xyz + centerOffs.xyz;float3    viewerLocal = mul(unity_WorldToObject,float4(_WorldSpaceCameraPos,1));         float3  localDir = viewerLocal - centerLocal;// _VerticalBillboarding 表示是否忽略y向量转向//localDir[1] = lerp(0,localDir[1],_VerticalBillboarding);// 计算右边方向和顶方向//float localDirLength=length(localDir);float3 rightLocal;float3 upLocal;CalcOrthonormalBasis(localDir / localDirLength,rightLocal,upLocal);// 计算新的法向量和位置//float distScale   = CalcDistScale(localDirLength) * v.color.a;       float3 BBNormal = rightLocal * v.normal.x + upLocal * v.normal.y;float3 BBLocalPos = centerLocal - (rightLocal * centerOffs.x + upLocal * centerOffs.y) + BBNormal * distScale;BBLocalPos += _ViewerOffset * localDir;// 计算闪烁//float     time            = _Time.y + _BlinkingTimeOffsScale * v.color.b;               float       fracTime    = fmod(time,_TimeOnDuration + _TimeOffDuration);float     wave            = smoothstep(0,_TimeOnDuration * 0.25,fracTime)  * (1 - smoothstep(_TimeOnDuration * 0.75,_TimeOnDuration,fracTime));float     noiseTime   = time *  (6.2831853f / _TimeOnDuration);float     noise           = sin(noiseTime) * (0.5f * cos(noiseTime * 0.6366f + 56.7272f) + 0.5f);float     noiseWave   = _NoiseAmount * noise + (1 - _NoiseAmount);wave = _NoiseAmount < 0.01f ? wave : noiseWave;wave += _Bias;o.uv       = v.texcoord.xy;o.vertex   = UnityObjectToClipPos(float4(BBLocalPos,1));o.color   = CalcFadeOutFactor(localDirLength) * _Color * _Multiplier * wave;return o;}fixed4 frag(v2f i) : SV_Target{return tex2D(_MainTex, i.uv) * i.color;//return i.color;}ENDCG}}
}

说明

1. 首先,知道了Blinking GodRays Billboarded的shader之后,找相关的模型找了一会,原本的效果是这样的:

删除额外元素之后,发光的面片是这样的:

但是无论我怎么选都选不中,最后范围选择后才发现模型是两个面片分离的,点在中心点:

2. 这个shader的vert函数比较复杂,先看frag函数,就是一般的获取纹理,然后叠加上自定义的color。

fixed4 frag(v2f i) : SV_Target{return tex2D(_MainTex, i.uv) * i.color;//return i.color;}

3. vert函数中,为了实现广告牌效果(面片始终对着摄像机),首先计算了顶点到中心点的距离,这里是通过在做模型的时候,用顶点的RG通道,来表示顶点在模型坐标系中的距离中心点的偏移。看下原本模型的颜色:

// 计算中心点位置// 计算物体到摄像机在模型坐标系中的方向//float3  centerOffs = float3(float(0.5).xx - v.color.rg,0) * v.texcoord1.xyy;float3 centerLocal = v.vertex.xyz + centerOffs.xyz;float3    viewerLocal = mul(unity_WorldToObject,float4(_WorldSpaceCameraPos,1));         float3  localDir = viewerLocal - centerLocal;// _VerticalBillboarding 表示是否忽略y向量转向//localDir[1] = lerp(0,localDir[1],_VerticalBillboarding);

然后通过在模型坐标系中,顶点到摄像机的位置,确定出改变后新的法线BBNormal

最后把中心点加上新的法线,变成新的顶点位置BBLocalPos

// 计算右边方向和顶方向//float localDirLength=length(localDir);float3 rightLocal;float3 upLocal;CalcOrthonormalBasis(localDir / localDirLength,rightLocal,upLocal);// 计算新的法向量和位置//float distScale = CalcDistScale(localDirLength) * v.color.a;       float3 BBNormal = rightLocal * v.normal.x + upLocal * v.normal.y;float3 BBLocalPos = centerLocal - (rightLocal * centerOffs.x + upLocal * centerOffs.y) + BBNormal * distScale;BBLocalPos += _ViewerOffset * localDir; 

4. 最后计算闪烁和上一篇讲的淡入淡出

问题

如果有大神的话,麻烦指点一下:

1. 在计算顶点偏移的时候,为什么要乘上纹理坐标

float3   centerOffs = float3(float(0.5).xx - v.color.rg,0) * v.texcoord1.xyy;

2. 为什么在shader里实现广告牌,用脚本来实现的话,只要一个旋转就可以了。

ShadowGun Billboard Blinking God Rays相关推荐

  1. UnityShader实例10:广告牌(Billboard)材质

    原文链接: http://blog.csdn.net/u011047171/article/details/47255233 广告牌(Billboard)材质 Billboard概述 Billboar ...

  2. Unity Shader - Billboard 广告板/广告牌 - BB树,BB投影

    文章目录 实现 CPU层 使用简单实现方式 模仿Shader层的复杂逻辑写法 向量叉乘的顺序 新的BB本地坐标系矩阵:newLocalMatrix可以不构建 2D的Billboard GPU层 带有可 ...

  3. 用无序列表做的网站公告牌(Billboard)

    用无序列表做的网站公告牌(Billboard) 这是一个用无序列表加脚本制作的网站公告牌,可调用动态数据,你可设定轮显时间,在IE6+时有多种比较酷的过场效果,可访问性:IE6+.FF1+.OPera ...

  4. HDOJ2795 Billboard【线段树】

    Problem : 2795 ( Billboard )     Judge Status : Accepted RunId : 5864258    Language : C    Author : ...

  5. HDU 2795 Billboard (线段树+贪心)

    HDU 2795 Billboard (线段树+贪心) 手动博客搬家:本文发表于20170822 21:30:17, 原地址https://blog.csdn.net/suncongbo/articl ...

  6. XNA Billboard(公告板技术)

    公告板技术是3D游戏中用的非常多的一种技术,主要是用于控制场景中的Texture的方向,让他始终以一定的角度对着我们的镜头(一般是垂直于镜头). 如我们在3D游戏中看到的怪物的蓝.红和怪物名字.一些花 ...

  7. 线段树——思维(Codeforces 339D Xenia and Bit Operations/Billboard HDU - 2795)

    Codeforces 339D Xenia and Bit Operations vj地址 题意:给出2的n次方个数,每次将现在这个序列中相邻的两个数运算后合并为一个数,得到一个新的序列,这个新序列的 ...

  8. cesium billboard 设置距离控制可见度

    核心代码如下 viewer.entities.add({position: Cesium.Cartesian3.fromDegrees(longitude, latitude, height),bil ...

  9. osg布告板技术(Billboard)

    公告牌技术,即billboard技术,在3D游戏中有着广泛的应用.它的本质就是用预先做好的几幅 位图来代替3D物体,极大地节省资源和提高速度.仔细观察<<魔法门>>系列游戏,它 ...

  10. HDOJ 2795 Billboard

    线段树..... Billboard Time Limit: 20000/8000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

最新文章

  1. Myeclipse安装、配置、测试
  2. PlaceHolder 控件使用
  3. linux下清理信号量,Linux下kill的信号量列表
  4. 【拥抱大厂系列】面试官100%会严刑拷打的 CMS 垃圾回收器,下次面试就拿这篇文章怼回去!
  5. NYOJ128前缀式计算
  6. VTK:参数化超环形用法实战
  7. Android Studio 开发安卓软件时下载的工程项目 Sync with gradle 失败
  8. vue $ 符号(例如vm.$data vs vm.data):读取实例属性 vs 读取 data 数据
  9. 负载均衡集群介绍LVS介绍LVS调度算法LVS NAT模式搭建
  10. 万字干货!详解JavaScript执行过程
  11. BorderLayout布局管理器设置3个按钮
  12. Java中多态的一些简单理解
  13. 单片机c语言程序设计实训100例 代码,单片机C语言程序设计实训100例——基于8051+Proteus仿真[1]...
  14. 李宏毅机器学习Lesson2——Logistic Regression实现收入预测
  15. Gurobi软件求解线性规划问题(卜算学习记录)
  16. 测试开发工程师简历模版
  17. ROS学习笔记02、ROS使用C++、Python来实现HelloWorld
  18. DNA pull-down 要点
  19. 清华大学 zhongguo li 计算机,清华大学学者发表论文列表_郭美凤
  20. 去哪儿2017校园招聘笔试题——统计字符串中最先出现三次的字符

热门文章

  1. 最全讲解--电子电气架构演进
  2. 可作为工质状态参数的是_§2工质的热力状态及其基本状态参数
  3. 微信发ascii_微信翻译竟能识别神秘代码!这里有份超全的彩蛋总结 | 晓技巧
  4. AS4120原厂单节 2A 开关型锂离子电池充电芯片
  5. CATIA 版本代号的含义
  6. python图片中文字识别
  7. JAVA指定区域内截图_Java+Selenium根据元素创建指定区域截图——Element快照
  8. HBase 官方文档中文版
  9. 上海航芯 | 热敏打印机方案分享
  10. FL studio 20简易入门教程 -- 第八篇 -- 技巧合集