图片处理
unity 可以直接写shader对图片处理,调节图片的 亮度,饱和度,对比度
前言
有时需要对动态图片进行处理达到一些效果,就像照片美图处理
一、图片调节
图片需要变成灰色,颜色要更饱和等
二、Unity 中的shader 实现
1. 亮度,饱和度,对比度
代码如下(示例):
Shader “Unlit/ColorBlending”
{
Properties
{
_MainTex (“Texture”, 2D) = “white” {}
_Brightness(“亮度:”,Range(0.1,2))=1
_Saturation(“饱和度:”,Range(0,2))=1//±20
_Contrast(“对比度:”,Range(0.1,5))=1
}
SubShader
{
Tags { “RenderType”=“Opaque” }
LOD 100
Pass
{
ZTest Always Cull Off ZWrite Off
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;
};
sampler2D _MainTex;
float4 _MainTex_ST;
half _Brightness;
half _Saturation;
half _Contrast;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv);
fixed3 finalColor = col.rgb * _Brightness;
fixed lum = 0.2125 * col.r + 0.7154 * col.g + 0.0721 * col.b;
fixed3 lumColor = fixed3(lum, lum, lum);
finalColor = lerp(lumColor, finalColor, _Saturation);
fixed3 avgColor = fixed3(0.5, 0.5, 0.5);
finalColor = lerp(avgColor, finalColor, _Contrast);
return fixed4(finalColor,col.a);
}
ENDCG
}
}
}
2.效果对比
二、边缘检测
这是直接在处理UI里的图片,调整数值就可以达到边缘检测的效果图片;
Shader "Unlit/EdgeDetection"
{
Properties
{
_MainTex("Texture", 2D) = "white" {}
_EdgeOnly("边缘化:", Range(0,4)) = 1.0
_EdgeColor("边缘颜色:", Color) = (0,0,0,1)
_BackgroundColor("背景颜色:",Color) = (1,1,1,0)
_Thickness("权重:",Range(0,4)) = 1.0
_Speed("Speed",Range(-1,0)) = -0.5
}
SubShader
{
Tags { "RenderType"="Opaque" "Queue"="Transparent"}
LOD 100
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;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert(appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
/* UNITY_APPLY_FOG(i.fogCoord, col);*/
return col;
}
ENDCG
}
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 maskuv : TEXCOORD0;
float2 uv[9] : TEXCOORD1;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
sampler2D _MaskTex;
half4 _MainTex_TexelSize;
fixed _EdgeOnly;
fixed4 _EdgeColor;
fixed4 _BackgroundColor;
fixed _Thickness;
fixed _Speed;
fixed luminance(fixed4 color)
{
return 0.2125 * color.r + 0.7154 * color.g + 0.0721 * color.b;
}
half Sobel(v2f i)
{
const half Gx[9] = {-1,-2,-1,0,0,0,1,2,1};
const half Gy[9] = { -1,0,1,-2,0,2,-1,0,1 };
half texColor;
half edgeX = 0;
half edgeY = 0;
for (int it = 0; it < 9; it++)
{
texColor = luminance(tex2D(_MainTex, i.uv[it]));
edgeX += texColor * Gx[it];
edgeY += texColor * Gy[it];
}
half edge = 1 - abs(edgeX) - abs(edgeY);
return edge;
}
v2f vert(appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
half2 uv = v.uv;
o.maskuv = v.uv - frac(fixed2(0,_Speed * _Time.y));
//o.maskuv = v.uv + fixed2(0.7 * _Time.y,0);
o.uv[0] = uv + _MainTex_TexelSize.xy * half2(-1, -1) * _Thickness;
o.uv[1] = uv + _MainTex_TexelSize.xy * half2(0, -1) * _Thickness;
o.uv[2] = uv + _MainTex_TexelSize.xy * half2(1, -1) * _Thickness;
o.uv[3] = uv + _MainTex_TexelSize.xy * half2(-1, 0) * _Thickness;
o.uv[4] = uv + _MainTex_TexelSize.xy * half2(0, 0) * _Thickness;
o.uv[5] = uv + _MainTex_TexelSize.xy * half2(1, 0) * _Thickness;
o.uv[6] = uv + _MainTex_TexelSize.xy * half2(-1, 1) * _Thickness;
o.uv[7] = uv + _MainTex_TexelSize.xy * half2(0, 1) * _Thickness;
o.uv[8] = uv + _MainTex_TexelSize.xy * half2(1, 1) * _Thickness;
return o;
}
fixed4 frag(v2f i) : SV_Target
{
half edge = Sobel(i);
fixed4 maskColor = tex2D(_MaskTex, i.maskuv);
fixed4 withEdgeColor = lerp(_EdgeColor,tex2D(_MainTex, i.uv[4]),edge);
fixed4 onlyEdgeColor = lerp(_EdgeColor, _BackgroundColor, edge);
fixed4 col = lerp(withEdgeColor, onlyEdgeColor, _EdgeOnly);
return fixed4(col.rgb,col.a * (1 - maskColor.r));
}
ENDCG
}
}
Fallback off
}
2.效果对比
三、高斯模糊
1.目前效果一般,但是还能用
Shader "Custom/MaskedUIBlur" {
Properties{
_Size("Blur", Range(0, 60)) = 1
[HideInInspector]
_MainTex("Masking Texture", 2D) = "white" {}
[HideInInspector]
_AdditiveColor("Additive Tint color", Color) = (0, 0, 0, 0)
_MultiplyColor("Multiply Tint color", Color) = (1, 1, 1, 1)
}
Category{
// We must be transparent, so other objects are drawn before this one.
Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Opaque" }
SubShader
{
// Horizontal blur
GrabPass
{
"_HBlur"
}
Cull Off
Lighting Off
ZWrite Off
ZTest[unity_GUIZTestMode]
Blend SrcAlpha OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"
struct appdata_t {
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
};
struct v2f {
float4 vertex : POSITION;
float4 uvgrab : TEXCOORD0;
float2 uvmain : TEXCOORD1;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert(appdata_t v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
#if UNITY_UV_STARTS_AT_TOP
float scale = -1.0;
#else
float scale = 1.0;
#endif
o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y * scale) + o.vertex.w) * 0.5;
o.uvgrab.zw = o.vertex.zw;
o.uvmain = TRANSFORM_TEX(v.texcoord, _MainTex);
return o;
}
sampler2D _HBlur;
float4 _HBlur_TexelSize;
float _Size;
float4 _AdditiveColor;
float4 _MultiplyColor;
half4 frag(v2f i) : COLOR
{
half4 sum = half4(0,0,0,0);
#define GRABPIXEL(weight,kernelx) tex2Dproj( _HBlur, UNITY_PROJ_COORD(float4(i.uvgrab.x + _HBlur_TexelSize.x * kernelx * _Size, i.uvgrab.y, i.uvgrab.z, i.uvgrab.w))) * weight
sum += GRABPIXEL(0.05, -4.0);
sum += GRABPIXEL(0.09, -3.0);
sum += GRABPIXEL(0.12, -2.0);
sum += GRABPIXEL(0.15, -1.0);
sum += GRABPIXEL(0.18, 0.0);
sum += GRABPIXEL(0.15, +1.0);
sum += GRABPIXEL(0.12, +2.0);
sum += GRABPIXEL(0.09, +3.0);
sum += GRABPIXEL(0.05, +4.0);
half4 result = half4(sum.r * _MultiplyColor.r + _AdditiveColor.r,
sum.g * _MultiplyColor.g + _AdditiveColor.g,
sum.b * _MultiplyColor.b + _AdditiveColor.b,
tex2D(_MainTex, i.uvmain).a * _Size);
return result;
}
ENDCG
}
// Vertical blur
GrabPass
{
"_VBlur"
}
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"
struct appdata_t {
float4 vertex : POSITION;
float2 texcoord: TEXCOORD0;
};
struct v2f {
float4 vertex : POSITION;
float4 uvgrab : TEXCOORD0;
float2 uvmain : TEXCOORD1;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert(appdata_t v) {
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
#if UNITY_UV_STARTS_AT_TOP
float scale = -1.0;
#else
float scale = 1.0;
#endif
o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y * scale) + o.vertex.w) * 0.5;
o.uvgrab.zw = o.vertex.zw;
o.uvmain = TRANSFORM_TEX(v.texcoord, _MainTex);
return o;
}
sampler2D _VBlur;
float4 _VBlur_TexelSize;
float _Size;
float4 _AdditiveColor;
float4 _MultiplyColor;
half4 frag(v2f i) : COLOR
{
half4 sum = half4(0,0,0,0);
#define GRABPIXEL(weight,kernely) tex2Dproj( _VBlur, UNITY_PROJ_COORD(float4(i.uvgrab.x, i.uvgrab.y + _VBlur_TexelSize.y * kernely * _Size, i.uvgrab.z, i.uvgrab.w))) * weight
sum += GRABPIXEL(0.05, -4.0);
sum += GRABPIXEL(0.09, -3.0);
sum += GRABPIXEL(0.12, -2.0);
sum += GRABPIXEL(0.15, -1.0);
sum += GRABPIXEL(0.18, 0.0);
sum += GRABPIXEL(0.15, +1.0);
sum += GRABPIXEL(0.12, +2.0);
sum += GRABPIXEL(0.09, +3.0);
sum += GRABPIXEL(0.05, +4.0);
half4 result = half4(sum.r * _MultiplyColor.r + _AdditiveColor.r,
sum.g * _MultiplyColor.g + _AdditiveColor.g,
sum.b * _MultiplyColor.b + _AdditiveColor.b,
tex2D(_MainTex, i.uvmain).a * _Size);
return result;
}
ENDCG
}
//可重复
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"
struct appdata_t {
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
};
struct v2f {
float4 vertex : POSITION;
float4 uvgrab : TEXCOORD0;
float2 uvmain : TEXCOORD1;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert(appdata_t v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
#if UNITY_UV_STARTS_AT_TOP
float scale = -1.0;
#else
float scale = 1.0;
#endif
o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y * scale) + o.vertex.w) * 0.5;
o.uvgrab.zw = o.vertex.zw;
o.uvmain = TRANSFORM_TEX(v.texcoord, _MainTex);
return o;
}
sampler2D _HBlur;
float4 _HBlur_TexelSize;
float _Size;
float4 _AdditiveColor;
float4 _MultiplyColor;
half4 frag(v2f i) : COLOR
{
half4 sum = half4(0,0,0,0);
#define GRABPIXEL(weight,kernelx) tex2Dproj( _HBlur, UNITY_PROJ_COORD(float4(i.uvgrab.x + _HBlur_TexelSize.x * kernelx * (_Size*1.2), i.uvgrab.y, i.uvgrab.z, i.uvgrab.w))) * weight
sum += GRABPIXEL(0.05, -4.0);
sum += GRABPIXEL(0.09, -3.0);
sum += GRABPIXEL(0.12, -2.0);
sum += GRABPIXEL(0.15, -1.0);
sum += GRABPIXEL(0.18, 0.0);
sum += GRABPIXEL(0.15, +1.0);
sum += GRABPIXEL(0.12, +2.0);
sum += GRABPIXEL(0.09, +3.0);
sum += GRABPIXEL(0.05, +4.0);
half4 result = half4(sum.r * _MultiplyColor.r + _AdditiveColor.r,
sum.g * _MultiplyColor.g + _AdditiveColor.g,
sum.b * _MultiplyColor.b + _AdditiveColor.b,
tex2D(_MainTex, i.uvmain).a * (_Size * 1.2));
return result;
}
ENDCG
}
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"
struct appdata_t {
float4 vertex : POSITION;
float2 texcoord: TEXCOORD0;
};
struct v2f {
float4 vertex : POSITION;
float4 uvgrab : TEXCOORD0;
float2 uvmain : TEXCOORD1;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert(appdata_t v) {
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
#if UNITY_UV_STARTS_AT_TOP
float scale = -1.0;
#else
float scale = 1.0;
#endif
o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y * scale) + o.vertex.w) * 0.5;
o.uvgrab.zw = o.vertex.zw;
o.uvmain = TRANSFORM_TEX(v.texcoord, _MainTex);
return o;
}
sampler2D _VBlur;
float4 _VBlur_TexelSize;
float _Size;
float4 _AdditiveColor;
float4 _MultiplyColor;
half4 frag(v2f i) : COLOR
{
half4 sum = half4(0,0,0,0);
#define GRABPIXEL(weight,kernely) tex2Dproj( _VBlur, UNITY_PROJ_COORD(float4(i.uvgrab.x, i.uvgrab.y + _VBlur_TexelSize.y * kernely * (_Size*1.2), i.uvgrab.z, i.uvgrab.w))) * weight
sum += GRABPIXEL(0.05, -4.0);
sum += GRABPIXEL(0.09, -3.0);
sum += GRABPIXEL(0.12, -2.0);
sum += GRABPIXEL(0.15, -1.0);
sum += GRABPIXEL(0.18, 0.0);
sum += GRABPIXEL(0.15, +1.0);
sum += GRABPIXEL(0.12, +2.0);
sum += GRABPIXEL(0.09, +3.0);
sum += GRABPIXEL(0.05, +4.0);
half4 result = half4(sum.r * _MultiplyColor.r + _AdditiveColor.r,
sum.g * _MultiplyColor.g + _AdditiveColor.g,
sum.b * _MultiplyColor.b + _AdditiveColor.b,
tex2D(_MainTex, i.uvmain).a * (_Size * 1.2));
return result;
}
ENDCG
}
}
}
}
//重复结束
重复 Pass 修改_Size值,重复次数越多效果越佳,只是运行越大
2.效果对比
总结
参考部分忘了保存链接,对参考大神说声谢谢!