Unity urp2d ShaderGraph 实现一个黑白转彩色的场景渐变效果 设计思路
设计背景:
2022网易minigame比赛,策划案里关卡背景是一个信中被损坏的场景,主角要去修复这个场景的故事。然后原本的场景呈现黑白色的效果,但主角旁边画面是彩色的,关卡结局还要有镜头拉远,然后整个画面以主角为中心扩散恢复颜色的视觉效果。
效果展示:
项目是URP管线,场景为2D SpriteRenderer,使用了shaderGraph,摄像机纹理实现了效果
原场景: 只有一块区域是彩色效果其他黑白:
游戏实机展示:
设计思路:
一开始刚拿到这个设计的时候,首先研究如何将画面变灰,很简单啊直接将unity自带的后处理加上color Adjustments,然后saturation拉到最低
很好效果完美实现,此贴完结(撒花)
-----------------------------------------------------------------
咳咳,开个玩笑。后处理只能对整个画面进行处理,而我们的需求是对场景内的一块区域动态处理它的显示效果,所以只能自己去写shader了。
先想想这个shader是写在屏幕空间呢还是世界空间呢?写在屏幕空间,做一层UI Mask,根据Image贴图和这个像素点的采样决定是否对其做灰色也是一个可行的方法,性能方面也比较优解。但这次我们需要以玩家为中心显示彩色区域,中间也有很多摄像机拉远的游戏逻辑,这时候去做世界空间到屏幕空间的转换也不太方便。因此这里就采用了给场景内的sprite上shader了。
先实现的变灰色图逻辑吧,本人去网上一顿查找,成功找到了一个shader(这里省去了一些代码,关键看fragment shader的实现)
Tags{ "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane""CanUseSpriteAtlas"="True"}Cull OffLighting OffZWrite OffBlend One OneMinusSrcAlphaPass{//这里省去了一些代码,关键看fragment shader的实现sampler2D _MainTex;float _GrayScale;fixed4 frag(v2f IN) : SV_Target{if(_Open > 0){fixed4 c = tex2D(_MainTex, IN.texcoord) * IN.color;//乘以一个灰度系数float cc = (c.r * 0.299 + c.g * 0.518 + c.b * 0.184); cc *= _GrayScale;c.r = c.g = c.b = cc;c.rgb *= c.a;return c;}else{return tex2D(_MainTex, IN.texcoord) * IN.color;}}ENDCG}
取灰度系数为一,其实里面最核心的一行代码就是:
//c为frag中该点color
c.r = c.g = c.b = (c.r * 0.299 + c.g * 0.518 + c.b * 0.184) * 灰度系数;
可以看到,变灰度图实际上是在片元着色器中,通过采样后对该点的RGB,对一个系数相乘再相加,做一些转换,最后在统一赋值给rbg实现的效果。
我们新建一个urp2DLit的ShaderGraph,在里面实现里面同样的逻辑效果,记得主采样贴图的参数的reference要正确设置成_MainTex才可以获取到sprite中的贴图
接着我们设置如何让画面变彩色。思路很简单先传入一个Vector3参数(世界空间坐标点),判断这个点的距离(float)是否小于一个值,如果是则输出sample Texture原本的color值,如果不是输出灰色转换后的color就好了。
新建两个参数 ,分别为Vector3和float
使用Position节点可以在Graph中获取该点位置,在使用Distance节点计算距离后Comparison距离值就好了!
最后用Branch节点分支 选择该店像素值(当然shader中最好不要用Branch,在GPU中做If的运算开销很大,后面会讲优化)
写一个脚本再同步一下参数,这里没有用unity的材质属性块MaterialPropertyBlock,因此修改时是直接修改所有材质的参数,如果需要也可以加上。
using UnityEngine;public class Gray2DController : MonoBehaviour
{public Material material;//pos就是场景中需要的彩色点public Transform pos;// public float distance;// Update is called once per framevoid Update(){if(material != null){material.SetVector("_Diastance", distance);if(pos != null)material.SetVector("_Pos", pos.position);}}
}
去场景里拿一张图测试一下效果
很好,看起来shader成功运行了起来。很高兴,又写完了一个需求,当天做完后忙其他事情了。
后几天,美术终于花完了场景最终稿,给我发了场景图层拆分,当我兴奋的搭完场景然后安装上我的材质后,然而:
我: ???????
好吧即然出现了问题,就只能继续研究了,随便看看能不能优化下原来的想法。
即然一张图是没有任何问题的,那就只能是多图情况下的混合模式的问题了。观察最开始CG代码的shader,里面的混合模式是:
Blend One OneMinusSrcAlpha
ShaderGraph中也可以设置混合模式,然而一顿研究和查找资料后发现:
(这张图的介绍来源Intro to Shader Graph | Cyanilux)
shaderGraph默认的四种混合居然不支持Blend One OneMinusSrcAlpha。那只能走走别的方向了,仔细想想,原来的shader也确实不太完美,因为我们要的是整个画面的黑白,而上面的shader则需要给每个场景物品都安装这个shader跑计算的话,无疑是降低了性能和扩展性的。(因为对于每个物品都要计算一遍距离Distance是很低效的)
这时候突然想到,如果这个shader混合模式达不到我们想要的效果,而且最好只做一张图片的处理的话,那我们完全可以在场景空间中在贴一张贴图,然后在场景里再放一个摄像机专门渲染这张帖图就行啦,然后玩家的主摄像机只需要渲染这张贴图的图层就好了!(其实这种方法应该早点想到的我是笨比)这样子也解决了性能的问题。
开始行动!首先我们新建一个Layer
在项目资源中右键,选择创建一个渲染器纹理
在场景中新建一个相机,这个相机是用来渲染场景物品的并输出到贴图上的,因此在剔除中取消勾选刚刚新建的RendererTexture层,然后将刚刚创建好的Texture加载输出上。
调整摄像机在场景的位置,选择创建的RenderTexture资源,调整大小,就可以在预览窗口中看到场景样子了(这里我用了场景大小,实际上直接用屏幕分辨率1920*1080,然后将刚刚的摄像机放到主摄像机子物品下做位置同步也是可以的)
然后我们修改shader参数,实际上就是把采样的SampleTexture从MainTex改成刚刚的摄像机贴图就好了
然后我们在场景中新建一个sprite,设置它的layer和大小,然后拖入这个shader材质,我们这个摄像机贴图就做好了。
我们回到场景中的主摄像机,可以让它只渲染这个贴图,当然将这个贴图放在场景最前面挡住后面的正常物品也是可以,但是这样运行时渲染管线还要额外做深度剔除的计算所以就可以直接在设置中直接剔除其他的物品。
这样我们这个效果就成功实现了。最后在来一个优化,还记得我们前面用了if节点,通过距离大小判断选择,这样一是if性能开销大,二是两个色域过渡时也比较尖锐(因为if是简单的二值判断然后选择)
我们可以放弃if节点,改用lerp在两个色域中做插值,就可以优化渐变效果,插值需要一个0-1的参数,我们选择使用“Saturate”节点,这个节点可以将一个浮点值映射到[0,1]的范围内,即输入大于1时=1,输入小于0时等于0,然后将结果连接到Lerp节点就可以了。
这样交界就有了一个柔和的过渡了。
最终ShaderGraph连接图:
Unity urp2d ShaderGraph 实现一个黑白转彩色的场景渐变效果 设计思路相关推荐
- 【游戏开发实战】Unity使用ShaderGraph制作一个Loading水球(能量球 | UI | 2D | 特效 | URP)
文章目录 一.前言 二.ShaderGraph入门 三.ShaderGraph制作2D Loading水球 1.创建Unlit Shader Graph 2.创建一个圆 3.从下到上填充的效果 4.填 ...
- [Other]来做一个微信打印机吧 -- 微信打印的设计思路參考
项目源代码地址:https://github.com/callmewhy/why-wechat-printer 近期微信打印机小火了一把.比方印美团,747微信打印机.都是利用微信公共平台实现照片的打 ...
- [Other]来做一个微信打印机吧 -- 微信打印的设计思路参考
项目源码地址:https://github.com/callmewhy/why-wechat-printer 最近微信打印机小火了一把,比如印美团,747微信打印机,都是利用微信公共平台实现照片的打印 ...
- 如何设计一个好的仪表盘:Dundas Dashboard设计思路
Dashboard的概念已经存在了很多年了,但这个概念的内涵在这些年发生了很大的变化.从最早的厂家追求靓丽仪表盘的玩具式界面,到今年以研究领域提倡的清楚务实的观点逐占上风,Dashboard已经进入主 ...
- Unity初学Shadergraph创建着色器学习教程
MP4 |视频:h264,1280×720 |音频:AAC,44.1 KHz,2 Ch 语言:英语+中英文字幕(根据原英文字幕机译更准确) |时长:51节课(4h 44m) |大小解压后:2.55 G ...
- 在unity用shaderGraph做出类似动物之森的柱面场景,甚至球面场景。
在unity用shaderGraph做出类似动物之森的柱状场景,甚至球状场景. 这个是模仿油管上NotSlot的视频https://www.youtube.com/watch?v=SOK3Ias5Nk ...
- Unity 之 ShaderGraph Input节点解析汇总
Unity 之 ShaderGraph Input节点解析汇总 一,Input Basic 基础输入节点 1.1 Vector 1, 2, 3, 4 1.2 Boolean 1.3 Color 1.4 ...
- Unity 之 ShaderGraph Channel节点解析汇总
Unity 之 ShaderGraph Channel节点解析汇总 一,Split 拆分节点 1.1 属性说明 1.2 示例演示 二,Combine 结合节点 2.1 属性说明 2.2 示例演示 三, ...
- Unity 之 ShaderGraph Procedural节点解析汇总
Unity 之 ShaderGraph Procedural节点解析汇总 一,Noise 噪音节点 1.1 Gradient Noise, Simple Noise, Voronoi 1.2 使用示例 ...
最新文章
- 网站建设需遵循用户访问习惯
- 使用异步任务加载网络上的图片
- 统计思维如何帮助大数据应用从人工走向智能?(上)
- power designer 连接数据库以及 Could not Initialize JavaVM! 错误的解决
- ip地址切换批处理脚本
- 软件安全备考--PE文件
- Torch中的benchmarkdeterministic是什么含义?
- 微信公众号:我们可以用它来干什么?
- 2020第二周美赛感想
- chatgpt国内能用吗?详细解读gpt的使用方法
- Oracle序列的创建和使用
- 2020-08-22
- ssl证书购买后如何认证签发
- 基于MT6261行车记录仪
- 2022年登高架设考试题模拟考试题库及模拟考试
- 容器(docker)
- 浅谈前端工程师的职业生涯の(上篇)
- 物联网“遇上”云原生,会擦出怎样的火花?
- 插入top.php,CmsTop手动区块(就是phpcms的碎片)的内容支持三种添加方式
- 移动互联网Pinterest战役打响 鲜淘铺推摇一摇功能
热门文章
- 甲板智慧-北京林业大学“林之心”项目
- 用链表,栈,队列实现简单的停车场项目
- 计算机不能上网 检查路线,电脑上不了网怎么解决?
- 【U8】固定资产卡片修改已计提月份
- max file descriptors [4096] for elasticsearch process is too low 问题定位
- 区块链+AI+广告:不仅数据更透明真实,他们让内容的权益回归作者
- python缩写月份单词_将python缩写的月份名称转换为全名
- 计算机控制课程设计论文,计算机控制课程设计论文.doc
- php后期维护麻烦,太吾绘卷维护费太高怎么办 后期建筑太耗资源解决方法介绍...
- angular指令心得(ng-model)