Files
2026-02-21 16:45:37 +08:00

160 lines
5.3 KiB
C#

using UnityEngine;
namespace UnityStandardAssets.ImageEffects
{
[ExecuteInEditMode]
[RequireComponent(typeof(Camera))]
[AddComponentMenu("Image Effects/Noise/Noise And Grain (Filmic)")]
public class NoiseAndGrain : PostEffectsBase
{
public float intensityMultiplier = 0.25f;
public float generalIntensity = 0.5f;
public float blackIntensity = 1f;
public float whiteIntensity = 1f;
public float midGrey = 0.2f;
public bool dx11Grain;
public float softness;
public bool monochrome;
public Vector3 intensities = new Vector3(1f, 1f, 1f);
public Vector3 tiling = new Vector3(64f, 64f, 64f);
public float monochromeTiling = 64f;
public FilterMode filterMode = FilterMode.Bilinear;
public Texture2D noiseTexture;
public Shader noiseShader;
private Material noiseMaterial;
public Shader dx11NoiseShader;
private Material dx11NoiseMaterial;
private static float TILE_AMOUNT = 64f;
public override bool CheckResources()
{
CheckSupport(false);
noiseMaterial = CheckShaderAndCreateMaterial(noiseShader, noiseMaterial);
if (dx11Grain && supportDX11)
{
dx11NoiseMaterial = CheckShaderAndCreateMaterial(dx11NoiseShader, dx11NoiseMaterial);
}
if (!isSupported)
{
ReportAutoDisable();
}
return isSupported;
}
private void OnRenderImage(RenderTexture source, RenderTexture destination)
{
if (!CheckResources() || null == noiseTexture)
{
Graphics.Blit(source, destination);
if (null == noiseTexture)
{
Debug.LogWarning("Noise & Grain effect failing as noise texture is not assigned. please assign.", base.transform);
}
return;
}
softness = Mathf.Clamp(softness, 0f, 0.99f);
if (dx11Grain && supportDX11)
{
dx11NoiseMaterial.SetFloat("_DX11NoiseTime", Time.frameCount);
dx11NoiseMaterial.SetTexture("_NoiseTex", noiseTexture);
dx11NoiseMaterial.SetVector("_NoisePerChannel", (!monochrome) ? intensities : Vector3.one);
dx11NoiseMaterial.SetVector("_MidGrey", new Vector3(midGrey, 1f / (1f - midGrey), -1f / midGrey));
dx11NoiseMaterial.SetVector("_NoiseAmount", new Vector3(generalIntensity, blackIntensity, whiteIntensity) * intensityMultiplier);
if (softness > Mathf.Epsilon)
{
RenderTexture temporary = RenderTexture.GetTemporary((int)((float)source.width * (1f - softness)), (int)((float)source.height * (1f - softness)));
DrawNoiseQuadGrid(source, temporary, dx11NoiseMaterial, noiseTexture, (!monochrome) ? 2 : 3);
dx11NoiseMaterial.SetTexture("_NoiseTex", temporary);
Graphics.Blit(source, destination, dx11NoiseMaterial, 4);
RenderTexture.ReleaseTemporary(temporary);
}
else
{
DrawNoiseQuadGrid(source, destination, dx11NoiseMaterial, noiseTexture, monochrome ? 1 : 0);
}
return;
}
if ((bool)noiseTexture)
{
noiseTexture.wrapMode = TextureWrapMode.Repeat;
noiseTexture.filterMode = filterMode;
}
noiseMaterial.SetTexture("_NoiseTex", noiseTexture);
noiseMaterial.SetVector("_NoisePerChannel", (!monochrome) ? intensities : Vector3.one);
noiseMaterial.SetVector("_NoiseTilingPerChannel", (!monochrome) ? tiling : (Vector3.one * monochromeTiling));
noiseMaterial.SetVector("_MidGrey", new Vector3(midGrey, 1f / (1f - midGrey), -1f / midGrey));
noiseMaterial.SetVector("_NoiseAmount", new Vector3(generalIntensity, blackIntensity, whiteIntensity) * intensityMultiplier);
if (softness > Mathf.Epsilon)
{
RenderTexture temporary2 = RenderTexture.GetTemporary((int)((float)source.width * (1f - softness)), (int)((float)source.height * (1f - softness)));
DrawNoiseQuadGrid(source, temporary2, noiseMaterial, noiseTexture, 2);
noiseMaterial.SetTexture("_NoiseTex", temporary2);
Graphics.Blit(source, destination, noiseMaterial, 1);
RenderTexture.ReleaseTemporary(temporary2);
}
else
{
DrawNoiseQuadGrid(source, destination, noiseMaterial, noiseTexture, 0);
}
}
private static void DrawNoiseQuadGrid(RenderTexture source, RenderTexture dest, Material fxMaterial, Texture2D noise, int passNr)
{
RenderTexture.active = dest;
float num = (float)noise.width * 1f;
float num2 = 1f * (float)source.width / TILE_AMOUNT;
fxMaterial.SetTexture("_MainTex", source);
GL.PushMatrix();
GL.LoadOrtho();
float num3 = 1f * (float)source.width / (1f * (float)source.height);
float num4 = 1f / num2;
float num5 = num4 * num3;
float num6 = num / ((float)noise.width * 1f);
fxMaterial.SetPass(passNr);
GL.Begin(7);
for (float num7 = 0f; num7 < 1f; num7 += num4)
{
for (float num8 = 0f; num8 < 1f; num8 += num5)
{
float num9 = Random.Range(0f, 1f);
float num10 = Random.Range(0f, 1f);
num9 = Mathf.Floor(num9 * num) / num;
num10 = Mathf.Floor(num10 * num) / num;
float num11 = 1f / num;
GL.MultiTexCoord2(0, num9, num10);
GL.MultiTexCoord2(1, 0f, 0f);
GL.Vertex3(num7, num8, 0.1f);
GL.MultiTexCoord2(0, num9 + num6 * num11, num10);
GL.MultiTexCoord2(1, 1f, 0f);
GL.Vertex3(num7 + num4, num8, 0.1f);
GL.MultiTexCoord2(0, num9 + num6 * num11, num10 + num6 * num11);
GL.MultiTexCoord2(1, 1f, 1f);
GL.Vertex3(num7 + num4, num8 + num5, 0.1f);
GL.MultiTexCoord2(0, num9, num10 + num6 * num11);
GL.MultiTexCoord2(1, 0f, 1f);
GL.Vertex3(num7, num8 + num5, 0.1f);
}
}
GL.End();
GL.PopMatrix();
}
}
}