千家信息网

Unity喷墨效果Shader实现是怎样的

发表于:2024-09-21 作者:千家信息网编辑
千家信息网最后更新 2024年09月21日,Unity喷墨效果Shader实现是怎样的,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。对于游戏中使用的类似喷墨效果,在射击类游戏中
千家信息网最后更新 2024年09月21日Unity喷墨效果Shader实现是怎样的

Unity喷墨效果Shader实现是怎样的,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

对于游戏中使用的类似喷墨效果,在射击类游戏中经常使用比如玩家射击的子弹会在墙上出现类似喷墨效果,效果如下所示:

在默认情况下,屏幕的整个Alpha通道都是黑色的,直到玩家开始喷射油墨,才会使被油墨溅到区域的Alpha通道变为白色。然后图像效果就是其原有颜色与灰度进行混合。

实现方式如下所示:

从上图可以看出,使用Projector将喷漆绘制到物体表面并创建颜色遮罩。每个Projector都使用程序化动态生成,在子弹(空中飞行的白点)接触到某个表面时进行初始化。Projector带有一个盒式碰撞体,当子弹落在Projector上时,不会初始化新的Projector,而是让原先的Projector变大。这样漆量会变多,而场景中的Projector数量却保持不变。

默认情况下,Unity标准着色器会为所有不透明对象的Alpha通道写入1。所以下面使用自定义着色器来替换Unity标准着色器。新建一个标准表面着色器,将其表面函数替换为如下:

void surf(Input IN, inout SurfaceOutputStandard o)  {       //Albedo 来自带颜色的纹理       fixed4 c=tex2D(_MainTex, IN.uv_MainTex) * _Color;       o.Albedo = c.rgb;       o.Metallic = _Metallic;       o.Smoothness = _Glossiness;       o.Alpha = 0;  //只添加此行  }

下面这行很重要,用于避免Unity更改自定义的Alpha值。将#pragma那行代码改为如下:

CGPROGRAM  #pragma surface surf Standard fullforwardshadows keepalphs

注意,该技巧不可用于Unity中的延迟渲染管线,因为它重写了G-Buffer中的Alpha通道来存储遮罩数据。

当子弹撞击某个表面时就会在撞击处动态生成Unity Projector。这些Projector带有自定义材质与自定义着色器。材质纹理是一张带有Alpha通道喷溅形状图,本文示例使用的纹理如下图:


注意,纹理导入设置中要将Wrap Mode设为"Clamp"而非"Repeat"。用于Projector材质的着色器从Unity提供的ProjectorLight修改而来,代码如下:

Shader "Projector/ProjectAlpha"  {      Properties      {          _ShadowTex("Cookie", 2D) = "gray"{}      }      Subshader{          Tags{"Queue" = "Transparent"}          Pass          {              ZWrite Off              Blend Zero One,One One              Offset -1, -1              CGPROGRAM              #pragma vertex vert              #pragma fragment frag              #pragma multi_compile_fog              #include "UnityCG.cginc"                struct Input              {                  float4 vertex : LagPosition;                  float3 normal : NORMAL;              };                struct v2f              {                  float4 uvShadow : TEXCOORD0;                  UNITY_FOG_COORDS(2)                  float4 pos : SV_POSITION;                  fixed nv : COLOR0;              };                float4x4 unity_Projector;              float4x4 unity_ProjectorClip;                v2f vert(Input v)              {                  v2f o;                  o.pos = mul(UNITY_MATRIX_MVP, v.vertex);                  o.uvShadow = mul(unity_Projector, v.vertex);                  UNITY_TRANSFER_FOG(o, o.pos);                  float3 normView = normalize(float3(unity_Projector[2][0], unity_Projector[2][1], unity_Projector[2][2]));                  float nv = dot(v.normal, normView);                  o.nv = nv < 0 ? 1: 0;                  return o;              }                sampler2D _ShadowTex;              sampler2D _FalloffTex;                fixed4 frag(v2f i) : COLOR              {                  fixed4 texS = tex2DProj(_ShadowTex, UNITY_PROJ_COORD(i.uvShadow));                  fixed4 res = fixed4(1,1,1,texS.a);                    res.a = i.nv;                  UNITY_APPLY_FOG_COLOR(i.fogCoord, res, fixed4(1,1,1,1));                  return res;              }              EDNCG          }      }  }

再介绍一下,关于混合的部分:

当着色器计算某个像素的颜色时,该颜色必须作用于屏幕上该点已经存在的像素颜色之上。默认情况下,新的像素会完全覆盖原有像素,但新像素也可以与原有像素进行混合。混合通常用于让对象呈透明或半透明效果,当然也可以实现很多其它的炫酷特效。

关键字Blend可以包含在Subshader或Pass标签中,甚至对同一个着色器的不同Pass进行混合。添加Blend关键字后,必须写入混合因子。混合因子如下:

Src指向着色器用于计算的颜色。Dst指向屏幕上已有的像素颜色。着色器用于计算的颜色会与第一个因子相乘,而屏幕上已有颜色会与第二个因子相乘。将两个结果相加,就是最终写到屏幕的颜色。

所以"Blend SrcAlpha One"会将自身Alpha值与当前着色器计算的颜色相乘,此时屏幕上的颜色暂未改动。然后再将屏幕颜色计算后的结果与前者相加。还可以使用逗号分隔两组因子,逗号前的混合选项用于计算颜色,逗号后的混合选项仅计算Alpha通道。可以查阅Unity文档了解更多关于混合的内容。

用于Projector的着色器就是"Blend Zero One, One One","Zero One"移除了飞溅纹理的颜色,使用子弹所飞溅到的表面颜色。"One One"将飞溅物的Alpha值与表面Alpha值相加。

现在使用上面的着色器与材质来生成Projector,应该将场景视图的Alpha通道设为白色。

现在可以随意修改Alpha通道,但还未达到最终效果。下面利用Alpha遮罩来创建游戏所需的图像特效。

首先,创建要使用图像特效的着色器。在Unity中新建默认的Image Effect Shader,然后将片段代码替换为如下:

fixed4 frag(v2f i) : SV_Target  {     fixed4 col = tex2D(_MainTex, i.uv);     fixed3 bnw = dot(col.rgb, float3(0.3,0.59,0.11));     col.rgb = lerp(bnw, col.rgb, col.a);          return col;  }

可以随意更改bnw(Black&White)变量以达到理想的混合效果。最后还需要新建脚本来运行该图像特效。脚本非常简单,代码如下:

using System.Collections;  using System.Collections.Generic;  using UnityStandardAssets.ImageEffectBase;    [ExecuteInEditMode]  [ImageEffectAllowedInSceneView]  public class ALphaColorSwitch : ImageEffectBase{      void OnRenderImage(RenderTexture source, RenderTexture destination)      {          Graphics.Blit (source, destination, material);      }  }

注意,这里用到了ImageEffectBase,该资源在Unity标准资源库中(Unity 5.5及以上版本推荐使用Post Processing Stack资源库代替ImageEffects)。导入标准资源库后,将脚本绑定到相机(确保将相机的渲染模式设为Forward)上,并将公共的着色器变量设为前面提到的着色器。

到此就可以向场景中喷射油墨啦!

关于Unity喷墨效果Shader实现是怎样的问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注行业资讯频道了解更多相关知识。

颜色 混合 效果 通道 像素 屏幕 表面 因子 子弹 标准 纹理 代码 图像 材质 特效 资源 场景 就是 情况 更多 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 常州施工项目管控软件开发平台 数据库用户表空间迁移 兰州家庭教育与网络安全视频 2020秋网络安全知识竞赛 曙光服务器系统安装不进指定磁盘 ge国内服务器在哪 江苏义迅网络技术 网络安全检查总结范文 数据库包含的数据文件有哪些 铁路无缝线路设备数据库管理系统 天津图像识别软件开发公司 vfm数据库 电力组态软件开发编程语言 杭州和苏州软件开发公司哪里多 数据库字段长度截断 dellamd服务器推荐 苏州办公系统软件开发价格表 公安部网络安全管理局公告 吕梁网络技术是什么 上海建行软件开发有什么部门 武义做软件开发 mac连接服务器每次都要连接 java连接数据库的方法 哈尔滨天象网络技术有限公司 小程序前端数据写入数据库 电力组态软件开发编程语言 国军标软件开发计划书模板 兴乐网络技术有限公司电话 三级网络技术通过率 软件开发 出路
0