projector

用到的组件

Projector组件

可以实现

0 角色选择光圈
1 普通圆点阴影
2 伪动态阴影 http://qiankanglai.me/2016/11/14/unity-projector/index.html
3 光的投影
4 投影仪(根据material的贴图,可以是图片、视频,另一个相机看到的景象)
5 3d或者2d手电筒的效果
参考:http://blog.sina.com.cn/s/blog_471132920101hhsd.html

注意事项:
1.确保Cookie Texture一定要设置为Clamp
2.为了避免projector bleeding, Cookie Texture 开启Border Mipmaps选项, 或者直接禁用Mipmap


3.FallOff
不管是orthographic还是不是。
如果不用FallOff, 投影下来的都是最亮即alpha为1的cookie,并且会向frustrum的正反2个方向投影,造成我们并不想看到的“双重投影”的效果(这个情况有的会出现有的不会)。不用fallOff,加到其他通道里也可以。用系统包带的Falloff贴图的话。投影会随着距离变淡。

projector之角色脚下的光圈shader编写

shader脚本如下,可以加其他的控制变量

// Upgrade NOTE: replaced '_Projector' with 'unity_Projector'Shader "Projector/Circle"
{Properties{_MainTex ("Cookie", 2D) = "white" {}}SubShader{Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane" }Pass{ColorMask RGBZWrite off Cull Off Lighting Off //Blend DstColor One//Blend SrcAlpha One            // particle addBlend SrcAlpha OneMinusSrcAlpha    // particle blendCGPROGRAM#pragma vertex vert#pragma fragment frag// make fog work#pragma multi_compile_fog#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;};struct v2f{float2 uv : TEXCOORD0;UNITY_FOG_COORDS(1)float4 vertex : SV_POSITION;float4 texc:TEXCOORD1;};sampler2D _MainTex;float4 _MainTex_ST;float4x4 unity_Projector;v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = TRANSFORM_TEX(v.uv, _MainTex);o.texc = mul(unity_Projector, v.vertex);UNITY_TRANSFER_FOG(o,o.vertex);return o;}fixed4 frag (v2f i) : SV_Target{// sample the texture//fixed4 col = tex2D(_MainTex, i.uv);float4 c = tex2Dproj(_MainTex, i.texc);// apply fogUNITY_APPLY_FOG(i.fogCoord, col);return c;}ENDCG}}
}

注意:贴图的采样uv是由unity_Projector 乘 v.vertex实现的,采样的时候用tex2Dproj(_MainTex, i.texc);采样,后者等价于tex2D(_MainTex, i.texc.xy/i.texc.z)。

可以再加上旋转脚本

参考:http://blog.csdn.net/ronintao/article/details/52236210
http://blog.csdn.net/candycat1992/article/details/41254799

projector之普通圆片阴影(blob shadow)

加在角色下面,记得把角色的layer加进projector设置下的“Ignore layer”即可。

伪动态阴影

就是用3d Max或者 Maya或者Unity,先把动画对应的阴影烘焙好, 做成序列帧。然后用projector的材质做对应的帧动画即可。

Dynamic Shadow Projector

参考:http://qiankanglai.me/2016/11/14/unity-projector/index.html
守护的影子是基于Asset Store上的Dynamic Shadow Projector插件修改制作的。

  1. 原理其实非常简单:使用Command Buffer控制相机里绘制Cast Shadow部分的模型到一个Render Texture;对这个Render Texture做一定处理之后(譬如是否打开MipMap,是否模糊等),利用Projector将其投影到Receive Shadow的部分。本质上就是生成一个贴图放影子,然后用tex2DProj画上去。

  2. 与ShadowMap优劣比较
    劣势
    无法实现自阴影,或者说实现代价比较大
    绘制影子物体的时候无法Batch
    优势
    可以很方便的实现模糊、软阴影;@赵忠健在ScreenSpaceShadowMask Blur里也对ShadowMap实现了模糊,但是为了完美嵌入Unity自己的RenderLoop需要折腾下
    可以控制增量更新,譬如产生影子的物体没有变化的时候,影子就完全不需要重绘
    可以很方便的控制投影的范围,这是我觉得最重要的一点
    当然它们也有一些共通的地方,可以很方便的控制Cast Shadow/Receive Shadow的部分。

  3. 需要注意的坑
    主要是使用的时候需要注意(对ShadowMap的使用来说也是类似的):

务必控制Cast Shadow/Receive Shadow的物体个数,保证不需要的物体不会参与绘制!以守护为例,只有几个模型参与了绘制,而且当模型超出范围之后立刻挪出渲染队列;接受影子的只有一个大平面,周围复杂的场景部分压根不参与Receive。

某些机器的显卡对于tex2DProj支持的有问题,不过目前只看到一个红米有…在这个设备上ShadowMap也是有问题的,所以目前还是处于没辙的状态。

  1. Fast Shadow Receiver
    当然,还有进一步优化的方法。我在另一个项目里直接使用了低模作为Geometry Proxy,降低Cast Shadow的消耗;另外有个插件Fast Shadow Receiver可以显著降低Receive Shadow消耗:
    原理也非常简单粗暴:直接生成一个Mesh来接受影子,对肯定接受不到的部分就不参与绘制。这个插件牛的地方在于它同时实现了Plane级别的接受和Mesh级别的,因为它直接实现了一个树形结构来保存Mesh信息,按需生成(目瞪口呆脸…)。譬如原来是一个复杂的场景接收影子的话就需要重绘整个模型,现在只需要绘制一小部分的网格就可以了~

光的投影

基本是就把黑的blob cookie换成 中间是白色的cookie即可。

投影仪(根据Meterial的贴图,可以是图片,视频,另一个相机看到的景象)

另一个相机绘制到RenderTexture,然后projector的材质使用RenderTexture即可

3D或者2D手电筒的效果

就是projector的方向和范围设置和手电一致。把电筒的光颜色投出去即可。

projector的消融shader

使用方法

  1. 新建场景,在场景中创建一个plane,layer设为AA,再创建一个sphere,layer设为BBB;
  2. 再在场景中场景一个空物体GameObject,为它添加Projector组件。
  3. Projector的Ignore Layer属性可以设置哪些layer不接受投影:假如不想让plane接收阴影,则选择AA;同样的,如果想要sphere不接受投影,可以把BBB也选上。
  4. 在material中填入material,将相应的材质进行投影。
  5. 可以设置projector的属性或旋转GameObject以将物体投射到不同的地方。

消融特效配套的shader及脚本及其参数

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'// Upgrade NOTE: replaced '_Projector' with 'unity_Projector'
// Upgrade NOTE: replaced '_ProjectorClip' with 'unity_ProjectorClip'Shader "TGame/Projector/Projector_AlphaBlended"
{Properties {_BurnAmount ("Burn Amount", Range(0.0, 1.0)) = 0.0_MainAlpha ("Main Alpha", Range(0.0, 1.0)) = 1.0_LineWidth("Burn Line Width", Range(0.0, 0.7)) = 0.1_TransparentWidth("Transparent Width", Range(0.0, 1.0)) = 0.1_MainColor ("Main Color", Color) = (1,1,1,1)_ShadowTex ("Cookie", 2D) = "" {}_FalloffTex ("FallOff", 2D) = "" {}_BurnTex ("Burn Noise, the r value which is smaller is first disappeared, the a value decides where disappeared", 2D) = "" {}_BurnFirstColor("Burn First Color", Color) = (1, 0, 0, 1)_BurnSecondColor("Burn Second Color", Color) = (1, 0, 0, 1)_Multipiler ("Multipiler",Range(0, 10)) = 1_XOffset("Horizontal Offset", float) = 0.01_YOffset("Vertical Offset", float) = 0.01}Subshader {Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane" }Pass {Cull Off Lighting Off ZWrite OffColorMask RGBOffset -1, -1Blend SrcAlpha OneMinusSrcAlphaCGPROGRAM#pragma vertex vert#pragma fragment frag#pragma multi_compile_fog#include "UnityCG.cginc"struct a2v {float4 vertex : POSITION;float4 texcoord : TEXCOORD0;fixed4 color : COLOR;};struct v2f {float4 uvShadow : TEXCOORD0;float4 uvFalloff : TEXCOORD1;float4 uvBurn : TEXCOORD2;fixed4 color : COLOR;UNITY_FOG_COORDS(3)float4 pos : SV_POSITION;};float4x4 unity_Projector;float4x4 unity_ProjectorClip;fixed _MainAlpha;fixed _BurnAmount;fixed _LineWidth;fixed _TransparentWidth;fixed _XOffset;fixed _YOffset;fixed4 _BurnFirstColor;fixed4 _BurnSecondColor;fixed _Multipiler;fixed4 _MainColor;sampler2D _ShadowTex;sampler2D _FalloffTex;sampler2D _BurnTex;float4 _BurnTex_ST;v2f vert (a2v v){v2f o;o.pos = UnityObjectToClipPos (v.vertex);o.uvShadow = mul (unity_Projector, v.vertex);o.uvFalloff = mul (unity_ProjectorClip, v.vertex);o.uvBurn = mul (unity_Projector, v.vertex);o.color = v.color;UNITY_TRANSFER_FOG(o,o.pos);return o;}fixed4 frag (v2f i) : SV_Target{fixed2 offset = fixed2(_XOffset, _YOffset);fixed4 burnColor = tex2Dproj (_BurnTex, UNITY_PROJ_COORD(i.uvBurn));clip(burnColor.r - _BurnAmount);fixed4 uvShadow = UNITY_PROJ_COORD(i.uvShadow);fixed2 uv = uvShadow.xy / uvShadow.w;uv += offset;fixed4 texS = tex2D(_ShadowTex, uv);texS.rgb *= _MainColor.rgb;fixed t = 1 - smoothstep(0.0, _LineWidth, burnColor.r - _BurnAmount);fixed3 color = lerp(_BurnFirstColor, _BurnSecondColor, t);color = pow(color, 5);color *= burnColor.a * burnColor.a;fixed4 texF = tex2Dproj (_FalloffTex, UNITY_PROJ_COORD(i.uvFalloff));fixed4 res = 2.0 * i.color * texS  * texF.a * _Multipiler;//return fixed4(texF.a, texF.a, texF.a, 1.0);//fixed4 res = 2.0 * i.color * texS  * _Multipiler;UNITY_APPLY_FOG_COLOR(i.fogCoord, res, fixed4(0,0,0,0));fixed3 finalColor = lerp(res.rgb, color, t * step(0.0001, _BurnAmount));fixed t1 = smoothstep(0.0, _TransparentWidth, burnColor.r - _BurnAmount);fixed t2 = lerp(0, 1, t1);fixed finalAlpha = lerp(1, t2, t2 * step(0.0001, _BurnAmount));return fixed4(finalColor.rgb, burnColor.a * texS.a * finalAlpha * _MainAlpha);}ENDCG}}
}

shader

  1. BurnAmount: 噪声贴图中小于该值的区域先消失,通过脚本控制逐渐变化;
  2. BurnLineWidth:控制消融时边缘的宽度,边缘处有两种颜色,下面BurnFirst Color为消融处里面的颜色,Burn Second Color为消融处外边缘的颜色;如果不需要边缘颜色,将该值设为0即可;
  3. MainColor:设置投影颜色的主颜色(需要a通道,不显示的地方a通道和颜色都设置为黑色,与噪声贴图比例一致,否则会出错);
  4. Cookie:投影区域主贴图,控制颜色,和MainColor相乘决定最终颜色;
  5. FallOff:不设置,具体也不知道什么作用;
  6. Burn Noise:噪声贴图,越黑的地方越先被消融;
  7. Burn First Color:燃烧区域内边缘的颜色;
  8. Burn Second Color:燃烧区域外边缘的颜色;
  9. Multiplier: 加强颜色,和前面的颜色相乘,使颜色更明显;

脚本

  1. Material:将要投影的material拖进来即可;
  2. Burn Speed:控制消融的速度,从而控制shader中的_BurnAmount属性,使其从0变到1,实现消融的效果。
    浮点数曲线
using UnityEngine;
using System.Collections;public enum ProjectorShaderProperties
{_MainAlpha,_BurnAmount,_XOffset,_YOffset
};public class ProjectorShaderFloatCurve : MonoBehaviour {public ProjectorShaderProperties m_projectorFloatProperty = ProjectorShaderProperties._BurnAmount;public AnimationCurve m_floatCurve = AnimationCurve.EaseInOut(0, -1, 1, 1);public float m_graphTimeMultiplier = 6;public float m_graphIntensityMultiplier = 1;public bool m_isLoop = false;public bool m_useSharedMaterial = true;private bool m_canUpdate;private float m_startTime;private Material m_mat;private float m_startFloat;private int m_propertyID;private string m_shaderProperty;private bool m_isInitialized;private void Awake(){var rend = GetComponent<Renderer>();if (rend == null){var projector = GetComponent<Projector>();if (projector != null){if (!m_useSharedMaterial){if (!projector.material.name.EndsWith("(Instance)"))projector.material = new Material(projector.material) { name = projector.material.name + " (Instance)" };m_mat = projector.material;}else{m_mat = projector.material;}}}else{if (!m_useSharedMaterial) m_mat = rend.material;else m_mat = rend.sharedMaterial;}m_shaderProperty = m_projectorFloatProperty.ToString();if (m_mat.HasProperty(m_shaderProperty)) m_propertyID = Shader.PropertyToID(m_shaderProperty);m_startFloat = m_mat.GetFloat(m_propertyID);var eval = m_floatCurve.Evaluate(0) * m_graphIntensityMultiplier;m_mat.SetFloat(m_propertyID, eval);m_isInitialized = true;}private void OnEnable(){m_startTime = Time.time;m_canUpdate = true;if (!m_isInitialized){var eval = m_floatCurve.Evaluate(0)* m_graphIntensityMultiplier;m_mat.SetFloat(m_propertyID, eval);}}private void Update(){var time = Time.time - m_startTime;if (m_canUpdate){var eval = m_floatCurve.Evaluate(time / m_graphTimeMultiplier) * m_graphIntensityMultiplier;m_mat.SetFloat(m_propertyID, eval);}if (time >= m_graphTimeMultiplier){if (m_isLoop) m_startTime = Time.time;else m_canUpdate = false;}}void OnDisable(){if (m_mat == null)return;if(m_useSharedMaterial) m_mat.SetFloat(m_propertyID, m_startFloat);}void OnDestroy(){if (!m_useSharedMaterial){if (m_mat != null)DestroyImmediate(m_mat);m_mat = null;}}
}
  1. _mainColor等颜色渐变
using UnityEngine;
using System.Collections;public enum ProjectorShaderColorProperties
{_MainColor
};public class ProjectorShaderColor : MonoBehaviour {public ProjectorShaderColorProperties m_colorProperty = ProjectorShaderColorProperties._MainColor;public Gradient m_mainColorGradient = new Gradient(){colorKeys = new GradientColorKey[]{new GradientColorKey(new Color(1f, .639f, .482f, 1f), 0f),new GradientColorKey(new Color(1f, .725f, .482f, 1f), .10f),new GradientColorKey(new Color(1f, .851f, .722f, 1f), .50f),new GradientColorKey(new Color(1f, .725f, .482f, 1f), .90f),new GradientColorKey(new Color(1f, .639f, .482f, 1f), 1f)}};public float m_graphTimeMultiplier = 6;public bool m_isLoop = false;public bool m_useSharedMaterial = false;private bool m_canUpdate;private float m_startTime;private Material m_mat;private string m_shaderProperty;private int m_propertyID;private bool m_isInitialized;private Color m_startColor;private void Awake(){var rend = GetComponent<Renderer>();if (rend == null){var projector = GetComponent<Projector>();if (projector != null){if (!m_useSharedMaterial){if (!projector.material.name.EndsWith("(Instance)"))projector.material = new Material(projector.material) { name = projector.material.name + " (Instance)" };m_mat = projector.material;}else{m_mat = projector.material;}}}else{if (!m_useSharedMaterial) m_mat = rend.material;else m_mat = rend.sharedMaterial;}m_shaderProperty = m_colorProperty.ToString();if (m_mat.HasProperty(m_shaderProperty)) m_propertyID = Shader.PropertyToID(m_shaderProperty);m_startColor = m_mat.GetColor(m_propertyID);var eval = m_mainColorGradient.Evaluate(0);m_mat.SetColor(m_propertyID, eval);m_isInitialized = true;}private void OnEnable(){m_startTime = Time.time;m_canUpdate = true;if (!m_isInitialized){var eval = m_mainColorGradient.Evaluate(0);m_mat.SetColor(m_propertyID, eval);}}// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {var time = Time.time - m_startTime;if (m_canUpdate){var eval = m_mainColorGradient.Evaluate(time / m_graphTimeMultiplier);m_mat.SetColor(m_propertyID, eval);}if (time >= m_graphTimeMultiplier){if (m_isLoop) m_startTime = Time.time;else m_canUpdate = false;}}void OnDisable(){if(m_mat == null){return;}m_mat.SetColor(m_propertyID, m_startColor);}
}

unity projector相关探讨和使用相关推荐

  1. Unity 面试题汇总(三)Unity 基础相关

    Unity 面试题汇总(三)Unity 基础相关 目录 Unity 面试题汇总(三)Unity 基础相关 0.FSM(状态机).HFSM(分层状态机).BT(行为树)的区别 1.什么是协同程序? 2. ...

  2. android+汽车零部件企业的供应商质量管理体系有待完善,汽车零部件采购质量管理的相关探讨论文...

    汽车零部件采购质量管理的相关探讨论文 摘要:汽车企业中,零部件的采购是十分重要的内容,也是企业生产资源的重要来源,做好汽车零部件采购的质量管理能够保证汽车生产的质量,为人们提供更加优质.安全的服务.因 ...

  3. 二维计算机动画基础,二维计算机动画制作新技术相关探讨

    胡巧红 吴忆蓉 摘要:二维计算机动画制作新技术的应用是确保二维动画质量能得到有效提升,同时减少人力消耗.缩短制作时间的主要途径.本文将首先对二维计算机动画的发展进行介绍,然后论述了现有二维计算机动画制 ...

  4. unity fixedupdate_unity相关

    会频繁更新 主要给自己看 性能优化总结:成本和分析 工具:Memory Profiler/Unity Editor Profiler/Frame Debugger/RenderDoc/ VS / AD ...

  5. (投影:Projector)Unity Projector 投影器原理以及优化

    很久很久以前,做过一个离线Mesh切割方式的Decay效果Unity3D中的贴花效果 适合场景景观布置,批次合并等,但运行时性能较差,这次我们来玩玩运行时投影器. 先上成平图 测试效果图, 图中的裤子 ...

  6. YDLIDAR G4雷达的unity使用相关+北阳雷达

    业务需求用到了G4激光雷达,需要对接雷达的sdk,最方便的是直接找unitypackage包来用,网上要么收费要么没用.所以还是自己对接吧 准备 先找相关文档,官网,sdk样例等.官网里各种文档和sd ...

  7. unity android输入法,Unity输入法相关(IME)

    在UI上的InputField中, 中文输入法的备选框不会跟随在光标旁边, 造成输入不方便. 看到有一个相似的, 可是是WebGL的 : https://blog.csdn.net/Rowley123 ...

  8. 游戏思考24:游戏寻路算法思考和Unity场景相关代码开发原则及导入地图数据(10/09)

    文章目录 一.游戏寻路算法 1)总体划分为 2)取几种算法详细介绍 (1)JPS介绍及其优化 二.场景相关开发原则 1)Unity开发商业项目场景开发基本原则 2)商业项目的大体流程和组织思路 一.游 ...

  9. unity test相关

    http://www.throwtheswitch.org/unity

最新文章

  1. android UI自动化测试工具Robotium VS NativeDriver VS Calabash
  2. ssl1615-Frogger【图论,最小生成树,并查集】
  3. pyspider爬虫框架
  4. JS获取当前时间戳的方法
  5. 分段显示 linux_ArchAudit:一款在 Arch Linux 上检查易受攻击的软件包的工具 | Linux 中国...
  6. layer——极简的jquery弹出层插件
  7. 学习逆向知识之用于游戏外挂的实现.第二讲,快速寻找植物大战僵尸阳光基址.以及动态基址跟静态基址的区别...
  8. python爬取方式_Python3 实现爬取网站下所有URL方式
  9. 修改注册表——让Excel同时显示两个窗口/多个文件
  10. el-select和el-tree组成树下拉框以及数据回显
  11. 中文论文网站、英文论文网站、专业领域论文网站(学术狗必备的21个论文网站)
  12. 记一次配置路由器无线桥接的过程——让古董路由器发挥余热
  13. 量化思维与常见的量化标
  14. 【MCU】基于STM32CubeMX定时器中断实现LED闪烁
  15. 【已解决】笔记本电脑连接wifi异常(无法连接到这个网络)
  16. SOLR7实践(二)--DIH配置及使用
  17. JavaScript script标签同步异步加载过程
  18. 概率统计Python计算:自定义离散型分布
  19. 如何在Excel中使用数据透视表计算百分比变化
  20. Grafana 介绍和使用

热门文章

  1. [机缘参悟-33]:眼见不一定为实,大多数时候“眼见为虚”
  2. 用python实现识别框选图片字体部分,并分割成单独图片
  3. java 获取回车字符_java回车键的字符
  4. 「历时6个月招聘数据收集」一份Python招聘分析报告
  5. 解析:为什么设计师选择mac电脑居多?
  6. 固态硬盘能不能提高计算机速度,固态硬盘—提升电脑速度最有效的利器!
  7. 电子书搜索引擎,快速寻找和下载电子书,搞定99.9%的电子书资源!
  8. 206计算机毕业设计
  9. 大学生计算机基础大难,大学生计算机基础实训六样文
  10. 论文翻译:2020_TinyLSTMs: Efficient Neural Speech Enhancement for Hearing Aids