ShadowGun Billboard Blinking God Rays
原理
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相关推荐
- UnityShader实例10:广告牌(Billboard)材质
原文链接: http://blog.csdn.net/u011047171/article/details/47255233 广告牌(Billboard)材质 Billboard概述 Billboar ...
- Unity Shader - Billboard 广告板/广告牌 - BB树,BB投影
文章目录 实现 CPU层 使用简单实现方式 模仿Shader层的复杂逻辑写法 向量叉乘的顺序 新的BB本地坐标系矩阵:newLocalMatrix可以不构建 2D的Billboard GPU层 带有可 ...
- 用无序列表做的网站公告牌(Billboard)
用无序列表做的网站公告牌(Billboard) 这是一个用无序列表加脚本制作的网站公告牌,可调用动态数据,你可设定轮显时间,在IE6+时有多种比较酷的过场效果,可访问性:IE6+.FF1+.OPera ...
- HDOJ2795 Billboard【线段树】
Problem : 2795 ( Billboard ) Judge Status : Accepted RunId : 5864258 Language : C Author : ...
- HDU 2795 Billboard (线段树+贪心)
HDU 2795 Billboard (线段树+贪心) 手动博客搬家:本文发表于20170822 21:30:17, 原地址https://blog.csdn.net/suncongbo/articl ...
- XNA Billboard(公告板技术)
公告板技术是3D游戏中用的非常多的一种技术,主要是用于控制场景中的Texture的方向,让他始终以一定的角度对着我们的镜头(一般是垂直于镜头). 如我们在3D游戏中看到的怪物的蓝.红和怪物名字.一些花 ...
- 线段树——思维(Codeforces 339D Xenia and Bit Operations/Billboard HDU - 2795)
Codeforces 339D Xenia and Bit Operations vj地址 题意:给出2的n次方个数,每次将现在这个序列中相邻的两个数运算后合并为一个数,得到一个新的序列,这个新序列的 ...
- cesium billboard 设置距离控制可见度
核心代码如下 viewer.entities.add({position: Cesium.Cartesian3.fromDegrees(longitude, latitude, height),bil ...
- osg布告板技术(Billboard)
公告牌技术,即billboard技术,在3D游戏中有着广泛的应用.它的本质就是用预先做好的几幅 位图来代替3D物体,极大地节省资源和提高速度.仔细观察<<魔法门>>系列游戏,它 ...
- HDOJ 2795 Billboard
线段树..... Billboard Time Limit: 20000/8000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
最新文章
- Myeclipse安装、配置、测试
- PlaceHolder 控件使用
- linux下清理信号量,Linux下kill的信号量列表
- 【拥抱大厂系列】面试官100%会严刑拷打的 CMS 垃圾回收器,下次面试就拿这篇文章怼回去!
- NYOJ128前缀式计算
- VTK:参数化超环形用法实战
- Android Studio 开发安卓软件时下载的工程项目 Sync with gradle 失败
- vue $ 符号(例如vm.$data vs vm.data):读取实例属性 vs 读取 data 数据
- 负载均衡集群介绍LVS介绍LVS调度算法LVS NAT模式搭建
- 万字干货!详解JavaScript执行过程
- BorderLayout布局管理器设置3个按钮
- Java中多态的一些简单理解
- 单片机c语言程序设计实训100例 代码,单片机C语言程序设计实训100例——基于8051+Proteus仿真[1]...
- 李宏毅机器学习Lesson2——Logistic Regression实现收入预测
- Gurobi软件求解线性规划问题(卜算学习记录)
- 测试开发工程师简历模版
- ROS学习笔记02、ROS使用C++、Python来实现HelloWorld
- DNA pull-down 要点
- 清华大学 zhongguo li 计算机,清华大学学者发表论文列表_郭美凤
- 去哪儿2017校园招聘笔试题——统计字符串中最先出现三次的字符