bạn có thể tạo hiệu ứng này bằng cách làm theo các bước dưới đây:
Hạt
Kết xuất đồ họa
bạn có thể lưu trữ kết quả bằng cách sử dụng RenderTexture. đây là ví dụ về bội số trong shadertoy:
https://www.shadertoy.com/view/ltccRl
iñigo quilez: Shadertoy sử dụng nhiều đường chuyền, mỗi lần cho một "Bộ đệm". Như tên cho thấy, điều này vượt qua lưu trữ kết quả trong một bộ đệm. Một bộ đệm chỉ là một kết cấu. Unity sẽ cho phép bạn kết xuất với kết cấu quá.
Tôi đã tạo một máy ảnh để kết xuất các hạt thành RenderTexture:
GrabPassing
bạn có thể lấy pass để áp dụng Biến dạng
Tôi đã giải thích nó trong bài viết này:
Làm thế nào tôi có thể tái tạo hiệu ứng hạt biến dạng của Quantum Break?
Mơ hồ
bằng cách sử dụng màu alpha trong suốt cuộc đời, chúng ta có hiệu ứng làm mờ đơn giản
để có kết quả tốt hơn, tốt hơn là sử dụng hiệu ứng làm mờ đơn giản, nhưng làm thế nào để chúng ta đạt được hiệu ứng nhòe?
Ma trận kết hợp
Trong xử lý ảnh, hạt nhân, ma trận chập hoặc mặt nạ là một ma trận nhỏ. Nó được sử dụng để làm mờ, làm sắc nét, dập nổi, phát hiện cạnh, và nhiều hơn nữa. Điều này được thực hiện bằng cách thực hiện tích chập giữa kernel và hình ảnh.
để biết thêm chi tiết, xin vui lòng theo liên kết này
Shader "Smkgames/Convolution"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
[Enum(kerEdgeDetectionA,1,kerEdgeDetectionB,2,kerEdgeDetectionC,3,kerSharpen,4,kerBoxBlur,5)]
_Kernel("Kernel", Float) = 1
}
SubShader
{
// No culling or depth
Cull Off ZWrite Off ZTest Always
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
sampler2D _MainTex;
float4 _MainTex_TexelSize;
float3x3 GetData(int channel, sampler2D tex, float2 uv, float4 size)
{
float3x3 mat;
for (int y=-1; y<2; y++)
{
for(int x=-1; x<2; x++)
{
mat[x+1][y+1]=tex2D(tex, uv + float2(x*size.x, y*size.y))[channel];
}
}
return mat;
}
float3x3 GetMean(float3x3 matr, float3x3 matg, float3x3 matb)
{
float3x3 mat;
for (int y=0; y<3; y++)
{
for(int x=0; x<3; x++)
{
mat[x][y] = (matr[x][y] + matg[x][y] + matb[x][y]) / 3.0;
}
}
return mat;
}
float Convolve(float3x3 kernel, float3x3 pixels, float denom, float offset)
{
float res = 0.0;
for (int y=0; y<3; y++)
{
for(int x=0; x<3; x++)
{
res += kernel[2-x][2-y]*pixels[x][y];
}
}
return res;
}
float _Kernel;
fixed4 frag (v2f i) : SV_Target
{
float3x3 kerEdgeDetectionA = float3x3 ( 0.0, 0, -1.0,
1.0, 0, -1.0,
0.0, 1.0, 0.0);
float3x3 kerEdgeDetectionB = float3x3 (0.0, 1.0, 0.0,
1.0, -4.0, 1.0,
0.0, 1.0, 0.0);
float3x3 kerEdgeDetectionC = float3x3 (-1.0, -1.0, -1.0,
-1.0, 8.0, -1.0,
-1.0, -1.0, -1.0);
float3x3 kerSharpen = float3x3 (0.0, -1.0, 0.0,
-1.0, 5.0, -1.0,
0.0, -1.0, 0.0);
float3x3 kerBoxBlur = (1.0/9.0)*float3x3 ( 1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
1.0, 1.0, 1.0);
float3x3 kernelSelection;
if(_Kernel == 1){
kernelSelection = kerEdgeDetectionA;
}else if(_Kernel == 2){
kernelSelection = kerEdgeDetectionB;
}else if(_Kernel == 3){
kernelSelection = kerEdgeDetectionC;
}else if(_Kernel == 4){
kernelSelection = kerSharpen;
}else if(_Kernel == 5){
kernelSelection = kerBoxBlur;
}
float3x3 matr = GetData(0, _MainTex, i.uv, _MainTex_TexelSize);
float3x3 matg = GetData(1, _MainTex, i.uv, _MainTex_TexelSize);
float3x3 matb = GetData(2, _MainTex, i.uv, _MainTex_TexelSize);
float3x3 mata = GetMean(matr, matg, matb);
// kernel
float4 gl_FragColor = float4(Convolve(kernelSelection,matr,1.0,0.0),
Convolve(kernelSelection,matg,1.0,0.0),
Convolve(kernelSelection,matb,1.0,0.0),
1.0);
return gl_FragColor;
}
ENDCG
}
}
}
Hộp mờ
Làm mờ hộp (còn được gọi là bộ lọc tuyến tính hộp) là bộ lọc tuyến tính miền không gian trong đó mỗi pixel trong ảnh kết quả có giá trị bằng giá trị trung bình của các pixel lân cận trong ảnh đầu vào. Nó là một dạng của bộ lọc thông thấp ("làm mờ"). Một ô mờ 3 x 3 có thể được viết dưới dạng ma trận
https://en.wikipedia.org/wiki/Box_blur
Shader "Smkgames/Simple Box Blur"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Blend SrcAlpha OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
sampler2D _MainTex;
float4 _MainTex_TexelSize;
float4 box(sampler2D tex, float2 uv, float4 size)
{
float4 c = tex2D(tex, uv + float2(-size.x, size.y)) + tex2D(tex, uv + float2(0, size.y)) + tex2D(tex, uv + float2(size.x, size.y)) +
tex2D(tex, uv + float2(-size.x, 0)) + tex2D(tex, uv + float2(0, 0)) + tex2D(tex, uv + float2(size.x, 0)) +
tex2D(tex, uv + float2(-size.x, -size.y)) + tex2D(tex, uv + float2(0, -size.y)) + tex2D(tex, uv + float2(size.x, -size.y));
return c / 9;
}
float4 frag (v2f i) : SV_Target
{
float4 col = box(_MainTex, i.uv, _MainTex_TexelSize);
return col;
}
ENDCG
}
}
}
Sự lặp lại
bạn có thể sử dụng Rendertexture để lưu trữ khung hình trước đó. Vì vậy, bạn có thể lấy khung hình trước đó sau đó làm mờ. bằng cách lặp lại điều này bạn đạt được mờ.
Bình thường
float4 distortion = tex2D(_MainTex,i.uv);
float3 distortionNormal = UnpackNormal(distortion);
Phần kết luận
Shader cuối cùng:
Shader "Smkgames/BrokenGlass3D"
{
Properties{
_MainTex("MainTex",2D) = "white"{}
_NormalIntensity("NormalIntensity",Float) = 1
_Alpha("Alpha",Float) = 1
}
SubShader
{
Tags {"Queue"="Transparent" "RenderType"="Transparent"}
Blend SrcAlpha OneMinusSrcAlpha
GrabPass
{
"_GrabTexture"
}
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float2 grabPos : TEXCOORD1;
float3 normal :NORMAL;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 grabPos : TEXCOORD1;
half3 worldNormal :TEXCOORD2;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float _Intensity,_Alpha;
v2f vert (appdata v)
{
v2f o;
o.uv = v.uv;
o.vertex = UnityObjectToClipPos(v.vertex);
o.grabPos = ComputeGrabScreenPos(o.vertex);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
return o;
}
sampler2D _GrabTexture;
float _NormalIntensity;
fixed4 frag (v2f i) : SV_Target
{
float4 distortion = tex2D(_MainTex,i.uv);
float3 distortionNormal = UnpackNormal(distortion);
distortionNormal.xy *= _NormalIntensity;
normalize(distortionNormal);
fixed4 col = tex2Dproj(_GrabTexture, i.grabPos+float4(distortionNormal.rgb,0));
return col;
}
ENDCG
}
}
}
không sử dụng màu alpha trong suốt cuộc đời:
bằng cách sử dụng màu alpha trong suốt cuộc đời:
Nguồn có sẵn:
https://github.com/smkplus/RainDrop
Còn nữa!
bạn cũng có thể tạo ra Ripples
Liên kết hữu ích
https://80.lv/articles/breakdown-animated-raindrop-m vật liệu-in-kiện4 /
https://seblagarde.wordpress.com/2013/01/03/water-drop-2b-dynamic-rain-and-its-effects/