313 lines
7.8 KiB
Markdown
313 lines
7.8 KiB
Markdown
|
## BrightnessSaturationAndContrast
|
|||
|
### 给摄像机添加脚本
|
|||
|
添加2个Meta,让其可以在编辑器模式下运行,并且只能绑定Camera组件。
|
|||
|
```
|
|||
|
[ExecuteInEditMode]
|
|||
|
[RequireComponent(typeof(Camera))]
|
|||
|
```
|
|||
|
实现基础类
|
|||
|
```
|
|||
|
using UnityEngine;
|
|||
|
|
|||
|
[ExecuteInEditMode]
|
|||
|
[RequireComponent(typeof(Camera))]
|
|||
|
public class PostEffectsBase : MonoBehaviour
|
|||
|
{
|
|||
|
protected void CheckResources()
|
|||
|
{
|
|||
|
bool isSupported = CheckSupport();
|
|||
|
|
|||
|
if (isSupported == false)
|
|||
|
{
|
|||
|
NotSupported();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
protected bool CheckSupport()
|
|||
|
{
|
|||
|
if (SystemInfo.supportsImageEffects == false || SystemInfo.supportsRenderTextures == false)
|
|||
|
{
|
|||
|
Debug.LogWarning("Not Supported!");
|
|||
|
return false;
|
|||
|
}
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
protected void NotSupported()
|
|||
|
{
|
|||
|
enabled = false;
|
|||
|
}
|
|||
|
|
|||
|
protected Material CheckShaderAndCreateMaterial(Shader shader, Material material)
|
|||
|
{
|
|||
|
if (shader == null)
|
|||
|
return null;
|
|||
|
if (shader.isSupported && material && material.shader == shader)
|
|||
|
return material;
|
|||
|
if (!shader.isSupported)
|
|||
|
return null;
|
|||
|
else
|
|||
|
{
|
|||
|
material = new Material(shader);
|
|||
|
material.hideFlags = HideFlags.DontSave;
|
|||
|
if (material)
|
|||
|
return material;
|
|||
|
else
|
|||
|
return null;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
protected void Start()
|
|||
|
{
|
|||
|
CheckResources();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
```
|
|||
|
之后根据需求在子类中添加变量:
|
|||
|
```
|
|||
|
using UnityEngine;
|
|||
|
|
|||
|
public class BrightnessSaturationAndContrast : PostEffectsBase
|
|||
|
{
|
|||
|
[Range(0.0f, 3.0f)]
|
|||
|
public float brightness = 1.0f;
|
|||
|
|
|||
|
[Range(0.0f, 3.0f)]
|
|||
|
public float saturation = 1.0f;
|
|||
|
|
|||
|
[Range(0.0f, 3.0f)]
|
|||
|
public float contrast = 1.0f;
|
|||
|
|
|||
|
public Shader briSatConShader;
|
|||
|
private Material briSatConMaterial;
|
|||
|
|
|||
|
public Material material
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
briSatConMaterial = CheckShaderAndCreateMaterial(briSatConShader, briSatConMaterial);
|
|||
|
return briSatConMaterial;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void OnRenderImage(RenderTexture src, RenderTexture dest)
|
|||
|
{
|
|||
|
if (material != null)
|
|||
|
{
|
|||
|
material.SetFloat("_Brightness", brightness);
|
|||
|
material.SetFloat("_Saturation", saturation);
|
|||
|
material.SetFloat("_Contrast", contrast);
|
|||
|
|
|||
|
Graphics.Blit(src, dest, material);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Graphics.Blit(src, dest);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
最后在OnRenderImage中调用Graphics.Blit()进行渲染。
|
|||
|
|
|||
|
### 添加后处理Shader
|
|||
|
```
|
|||
|
Shader "PostProcess/BrightnessSaturationAndContrast" {
|
|||
|
|
|||
|
Properties {
|
|||
|
_MainTex ("Base", 2D) = "white" {}
|
|||
|
_Brightness("Brightness",Float)=1
|
|||
|
_Saturation("Saturation",Float)=1
|
|||
|
_Contrast("Constrast",Float)=1
|
|||
|
}
|
|||
|
|
|||
|
SubShader {
|
|||
|
Pass{
|
|||
|
ZTest Always Cull Off ZWrite Off
|
|||
|
|
|||
|
CGPROGRAM
|
|||
|
#pragma vertex vert
|
|||
|
#pragma fragment frag
|
|||
|
|
|||
|
#include "UnityCG.cginc"
|
|||
|
|
|||
|
sampler2D _MainTex;
|
|||
|
half _Brightness;
|
|||
|
half _Saturation;
|
|||
|
half _Contrast;
|
|||
|
|
|||
|
struct v2f{
|
|||
|
float4 pos : SV_POSITION;
|
|||
|
half2 uv : TEXCOORD0;
|
|||
|
};
|
|||
|
|
|||
|
v2f vert(appdata_img v)
|
|||
|
{
|
|||
|
v2f o;
|
|||
|
o.pos = UnityObjectToClipPos(v.vertex);
|
|||
|
o.uv=v.texcoord;
|
|||
|
return o;
|
|||
|
}
|
|||
|
|
|||
|
fixed4 frag(v2f i) : SV_Target{
|
|||
|
fixed4 renderTex=tex2D(_MainTex,i.uv);
|
|||
|
|
|||
|
fixed3 finalColor=renderTex.rgb * _Brightness;
|
|||
|
fixed luminance=0.2125*renderTex.r+0.7154*renderTex.g+0.0721*renderTex.b;
|
|||
|
fixed3 luminanceColor=fixed3(luminance,luminance,luminance);
|
|||
|
finalColor =lerp(luminanceColor,finalColor,_Saturation);
|
|||
|
|
|||
|
fixed3 avgColor=fixed3(0.5,0.5,0.5);
|
|||
|
finalColor=lerp(avgColor,finalColor,_Contrast);
|
|||
|
return fixed4(finalColor,renderTex.a);
|
|||
|
}
|
|||
|
|
|||
|
ENDCG
|
|||
|
}
|
|||
|
}
|
|||
|
Fallback Off
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
## 高斯模糊
|
|||
|
|
|||
|
与之前不同,这里利用RenderTexture.GetTemporary函数分配了一块与屏幕图像大小相同的缓冲区。这是因为,高斯模糊需要调用两个Pass,我们需要使用一块中间缓存来存储第一个Pass执行完毕后得到的模糊结果。`RenderTexture buffer = RenderTexture.GetTemporary(rtW, rtH, 0);`我们首先调用`Graphics.Blit(src, buffer, material, 0),`使用Shader中的第一个pass对src进行处理,并将结果存储在了buffer中。然后在调用`Graphics.Blit(src, buffer, material, 1)`,使用Shader中的第二个Pass对buffer进行处理,返回最终的屏幕图像。最后,我们还需要调用`RenderTexture.ReleaseTemporary`来释放之前分配的缓存。
|
|||
|
|
|||
|
```
|
|||
|
private void OnRenderImage(RenderTexture src, RenderTexture dest)
|
|||
|
{
|
|||
|
if (material != null)
|
|||
|
{
|
|||
|
int rtW = src.width;
|
|||
|
int rtH = src.height;
|
|||
|
RenderTexture buffer = RenderTexture.GetTemporary(rtW, rtH, 0);
|
|||
|
|
|||
|
Graphics.Blit(src, buffer, material, 0);
|
|||
|
Graphics.Blit(buffer, dest, material, 1);
|
|||
|
|
|||
|
RenderTexture.Release(buffer);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Graphics.Blit(src, dest);
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
实现降采样:
|
|||
|
```
|
|||
|
private void OnRenderImage(RenderTexture src, RenderTexture dest)
|
|||
|
{
|
|||
|
if (material != null)
|
|||
|
{
|
|||
|
int rtW = src.width / downSample;
|
|||
|
int rtH = src.height / downSample;
|
|||
|
RenderTexture buffer = RenderTexture.GetTemporary(rtW, rtH, 0);
|
|||
|
buffer.filterMode=FilterMode.Bilinear;
|
|||
|
|
|||
|
Graphics.Blit(src, buffer, material, 0);
|
|||
|
Graphics.Blit(buffer, dest, material, 1);
|
|||
|
|
|||
|
RenderTexture.Release(buffer);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Graphics.Blit(src, dest);
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
### CGINCLUDE
|
|||
|
使用CGINCLUDE与ENDCG关键字将通用部分引用给其他Pass
|
|||
|
```
|
|||
|
Shader "Unity Shaders Book/Chapter 12/Gaussian Blur" {
|
|||
|
Properties {
|
|||
|
_MainTex ("Base (RGB)", 2D) = "white" {}
|
|||
|
_BlurSize ("Blur Size", Float) = 1.0
|
|||
|
}
|
|||
|
SubShader {
|
|||
|
CGINCLUDE
|
|||
|
|
|||
|
#include "UnityCG.cginc"
|
|||
|
|
|||
|
sampler2D _MainTex;
|
|||
|
half4 _MainTex_TexelSize;
|
|||
|
float _BlurSize;
|
|||
|
|
|||
|
struct v2f {
|
|||
|
float4 pos : SV_POSITION;
|
|||
|
half2 uv[5]: TEXCOORD0;
|
|||
|
};
|
|||
|
|
|||
|
v2f vertBlurVertical(appdata_img v) {
|
|||
|
v2f o;
|
|||
|
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
|
|||
|
|
|||
|
half2 uv = v.texcoord;
|
|||
|
|
|||
|
o.uv[0] = uv;
|
|||
|
o.uv[1] = uv + float2(0.0, _MainTex_TexelSize.y * 1.0) * _BlurSize;
|
|||
|
o.uv[2] = uv - float2(0.0, _MainTex_TexelSize.y * 1.0) * _BlurSize;
|
|||
|
o.uv[3] = uv + float2(0.0, _MainTex_TexelSize.y * 2.0) * _BlurSize;
|
|||
|
o.uv[4] = uv - float2(0.0, _MainTex_TexelSize.y * 2.0) * _BlurSize;
|
|||
|
|
|||
|
return o;
|
|||
|
}
|
|||
|
|
|||
|
v2f vertBlurHorizontal(appdata_img v) {
|
|||
|
v2f o;
|
|||
|
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
|
|||
|
|
|||
|
half2 uv = v.texcoord;
|
|||
|
|
|||
|
o.uv[0] = uv;
|
|||
|
o.uv[1] = uv + float2(_MainTex_TexelSize.x * 1.0, 0.0) * _BlurSize;
|
|||
|
o.uv[2] = uv - float2(_MainTex_TexelSize.x * 1.0, 0.0) * _BlurSize;
|
|||
|
o.uv[3] = uv + float2(_MainTex_TexelSize.x * 2.0, 0.0) * _BlurSize;
|
|||
|
o.uv[4] = uv - float2(_MainTex_TexelSize.x * 2.0, 0.0) * _BlurSize;
|
|||
|
|
|||
|
return o;
|
|||
|
}
|
|||
|
|
|||
|
fixed4 fragBlur(v2f i) : SV_Target {
|
|||
|
float weight[3] = {0.4026, 0.2442, 0.0545};
|
|||
|
|
|||
|
fixed3 sum = tex2D(_MainTex, i.uv[0]).rgb * weight[0];
|
|||
|
|
|||
|
for (int it = 1; it < 3; it++) {
|
|||
|
sum += tex2D(_MainTex, i.uv[it*2-1]).rgb * weight[it];
|
|||
|
sum += tex2D(_MainTex, i.uv[it*2]).rgb * weight[it];
|
|||
|
}
|
|||
|
|
|||
|
return fixed4(sum, 1.0);
|
|||
|
}
|
|||
|
|
|||
|
ENDCG
|
|||
|
|
|||
|
ZTest Always Cull Off ZWrite Off
|
|||
|
|
|||
|
Pass {
|
|||
|
NAME "GAUSSIAN_BLUR_VERTICAL"
|
|||
|
|
|||
|
CGPROGRAM
|
|||
|
|
|||
|
#pragma vertex vertBlurVertical
|
|||
|
#pragma fragment fragBlur
|
|||
|
|
|||
|
ENDCG
|
|||
|
}
|
|||
|
|
|||
|
Pass {
|
|||
|
NAME "GAUSSIAN_BLUR_HORIZONTAL"
|
|||
|
|
|||
|
CGPROGRAM
|
|||
|
|
|||
|
#pragma vertex vertBlurHorizontal
|
|||
|
#pragma fragment fragBlur
|
|||
|
|
|||
|
ENDCG
|
|||
|
}
|
|||
|
}
|
|||
|
FallBack "Diffuse"
|
|||
|
}
|
|||
|
|
|||
|
```
|