unity 全息和xRay shader
Posted xiaogeformax
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了unity 全息和xRay shader相关的知识,希望对你有一定的参考价值。
unity 全息和xRay shader
这个是网上的效果,科幻的感觉是不是很强烈。
下面是我们去实现的效果。
先看下效果图,左边的是Xray的效果,右边是全息的效果。都有着异曲同工的妙处。
全息的效果
全息特效只显示物体的轮廓,必然会有用到类似于边缘光照的效果。
void surf(Input IN, inout SurfaceOutput o)
float4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
float border = 1 - (abs(dot(IN.viewDir, IN.worldNormal)));
float alpha = (border * (1 - _DotProduct) + _DotProduct);
o.Alpha = c.a * alpha;
这个里面用了类似边缘光照的算法。
float rim = 1 - max(0, dot(worldViewDir, worldNormal));
这里把float border = 1 - (abs(dot(IN.viewDir, IN.worldNormal)));
在边缘光照里面,当worldViewDir和worldNormal大于90度的时候,就会将其置于1,就是说模型背面的部分全部置为1,所以不是透明的。但是在全息特效里面,用了abs函数,不管是正面还是背面都是给其减去了,所以,只会显示出边缘光照,中间就会呈现出镂空的效果。
同时,在后面的代码对其alpha值进行线性插值。
纹理中的初始alpha值与新的系数进行插值去完成的。
下面看下全部的shader代码:
Shader "CookbookShaders/Chapter02/Silhouette"
Properties
_Color("Color", Color) = (1,1,1,1)
_MainTex("Albedo (RGB)", 2D) = "white"
_DotProduct("Rim effect", Range(-1,1)) = 0.25
SubShader
Tags
"Queue" = "Transparent"
"IgnoreProjector" = "True"
"RenderType" = "Transparent"
LOD 200
Cull Off
CGPROGRAM
//#pragma surface surf Lambert alpha:fade nolighting
#pragma surface surf Lambert alpha
sampler2D _MainTex;
fixed4 _Color;
float _DotProduct;
struct Input
float2 uv_MainTex;
float3 worldNormal;
float3 viewDir;
;
//void surf(Input IN, inout SurfaceOutputStandard o)
void surf(Input IN, inout SurfaceOutput o)
float4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
float border = 1 - (abs(dot(IN.viewDir, IN.worldNormal)));
float alpha = (border * (1 - _DotProduct) + _DotProduct);
o.Alpha = c.a * alpha;
ENDCG
FallBack "Diffuse"
XRay特效
我们看下xRay的代码,其实效果和全息的有着很大的相似度。
v2f vert (appdata v)
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
float3 viewDir = normalize(ObjSpaceViewDir(v.vertex));//计算出顶点到相机的向量
float val = 1 - saturate(dot(v.normal, viewDir));//计算点乘值
o.color = _RimColor * val * (1 + _RimIntensity);//计算强度
return o;
fixed4 frag (v2f i) : COLOR
return i.color;
这里的最后的颜色用了_RimColor 和上面的val相乘,val和上面的全息特效相似,都是在边缘时较大,在模型的中间比较小。后面,又给乘了个强度。
下面给出全部代码:
Shader "Xray"
Properties
_RimColor("RimColor", Color) = (0, 0, 1, 1)
_RimIntensity("Intensity", Range(0, 2)) = 1
SubShader
Tags "Queue"="Transparent" "RenderType"="Opaque"
LOD 200
Pass
//Blend SrcAlpha One//打开混合模式
Blend SrcAlpha One
ZWrite off
Lighting off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
float4 vertex : POSITION;
float3 normal:Normal;
;
struct v2f
float4 pos : SV_POSITION;
fixed4 color:COLOR;
;
fixed4 _RimColor;
float _RimIntensity;
v2f vert (appdata v)
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
float3 viewDir = normalize(ObjSpaceViewDir(v.vertex));//计算出顶点到相机的向量
float val = 1 - saturate(dot(v.normal, viewDir));//计算点乘值
o.color = _RimColor * val * (1 + _RimIntensity);//计算强度
return o;
fixed4 frag (v2f i) : COLOR
return i.color;
ENDCG
另一种全息
同样是上面的模型,下面来展示另一种全息,是把模型的全身变为很多的点,然后绕成一圈圈的。然后调制颜色为淡蓝色,成为下面的样子。
在顶点函数里面,我们使用了o.worldPos = mul(unity_ObjectToWorld, v.vertex);获得物体本身的坐标,之后,在片元着色器里面进行处理。
col = _Color * max(0, cos(i.worldPos.y * _ScanningFrequency + _Time.x * _ScanningSpeed) + _Bias);
col = 1 - max(0, cos(i.worldPos.x _ScanningFrequency + _Time.x * _ScanningSpeed) +0.9);
col = 1 - max(0, cos(i.worldPos.z _ScanningFrequency + _Time.x * _ScanningSpeed) +0.9);
这个是片元里面的代码,分别对其 X,Y,Z坐标进行处理。首先对Y坐标进行处理,就是高度,使用cos函数,对其进行处理,将cos函数小于0的部分全部置为0,后面进行乘上颜色,使之为透明。
同样的道理,对X,Z进行切割,使用1-max(**) 省略公式了,就是把cos的数值为1的部分进行透明。在X,Z坐标上很少的一部分为透明。
下面看下全部的shader代码吧
代码来源World of Zero,shader的第一行就有的,在此引用了。
Shader "World of Zero/Hologram"
Properties
_MainTex ("Texture", 2D) = "white"
_Color ("Color", Color) = (1, 0, 0, 1)
_Bias("Bias", range(-2,2)) = 0
_ScanningFrequency ("Scanning Frequency", Float) = 100
_ScanningSpeed ("Scanning Speed", Float) = 100
SubShader
Tags "Queue" = "Transparent" "RenderType" = "Transparent"
LOD 100
ZWrite Off
Blend SrcAlpha One
Cull Off
Pass
CGPROGRAM
#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(2)
float4 vertex : SV_POSITION;
float4 worldPos : TEXCOORD1;
;
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
float _Bias;
float _ScanningFrequency;
float _ScanningSpeed;
v2f vert (appdata v)
v2f o;
o.worldPos = mul(unity_ObjectToWorld, v.vertex);
o.vertex= UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
fixed4 frag (v2f i) : SV_Target
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv);
// apply fog
UNITY_APPLY_FOG(i.fogCoord, col);
col = _Color * max(0, cos(i.worldPos.y * _ScanningFrequency + _Time.x * _ScanningSpeed) + _Bias);
col *= 1 - max(0, cos(i.worldPos.x * _ScanningFrequency + _Time.x * _ScanningSpeed) +0.9);
col *= 1 - max(0, cos(i.worldPos.z * _ScanningFrequency + _Time.x * _ScanningSpeed) +0.9);
return col;
ENDCG
以上是关于unity 全息和xRay shader的主要内容,如果未能解决你的问题,请参考以下文章
小功能⭐️Unity2018 Shader Graph——全息影像物体消融
小功能⭐️Unity2018 Shader Graph——全息影像物体消融
小功能⭐️Unity2018 Shader Graph——全息影像物体消融