Скриншот по просьбам трудящихся:
Есть три параметра, которые задают вид постэффекта + он сильно зависит от текстуры шумка, из которой берутся семплы.
В оригинальном примере от нвидиа шум делается так:
- Код: Выделить всё
// function used to fill the volume noise texture
float4 noise_2d(float2 Pos : POSITION) : COLOR
{
float4 Noise = (float4)0;
for (int i = 1; i < NOISE2D_LIMIT; i += i) {
Noise.r += (noise(Pos * NOISE2D_SCALE * i)) / i;
Noise.g += (noise((Pos + 1)* NOISE2D_SCALE * i)) / i;
Noise.b += (noise((Pos + 2) * NOISE2D_SCALE * i)) / i;
Noise.a += (noise((Pos + 3) * NOISE2D_SCALE * i)) / i;
}
return (Noise + 0.5);
}
А я поленился и взял шумок из NoiseEffect ).
На фоне красный шарик с вертексным шейдером MrTwister из соседней темы.
Шейдер:
Синтаксис:
Используется glsl
Shader "Hidden/Frost Effect" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_DeltaX ("Delta X", Float) = 0.0073
_DeltaY ("Delta Y", Float) = 0.0108
_Freq ("Frequency", Float) = 0.115
//_DeltaX ("Delta X", Range(0.001,0.03)) = 0.0073
//_DeltaY ("Delta Y", Range(0.001,0.03)) = 0.0108
//_Freq ("Frequency", Range(0.0, 0.2)) = 0.115
//dummy slots
_GrainTex ("Base (RGB)", 2D) = "gray" {} //сюда кладем шум
}
SubShader {
Pass {
ZTest Always Cull Off ZWrite Off Fog { Mode off }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"
#pragma target 3.0
//здесь можно написать #define?)
struct v2f {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};
uniform sampler2D _MainTex;
uniform sampler2D _GrainTex;
uniform float _DeltaX;
uniform float _DeltaY;
uniform float _Freq;
v2f vert (appdata_img v)
{
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
o.uv = MultiplyUV (UNITY_MATRIX_TEXTURE0, v.texcoord);
return o;
}
float4 spline(float x, float4 c1, float4 c2, float4 c3, float4 c4, float4 c5, float4 c6, float4 c7, float4 c8, float4 c9)
{
float w1, w2, w3, w4, w5, w6, w7, w8, w9;
w1 = 0;
w2 = 0;
w3 = 0;
w4 = 0;
w5 = 0;
w6 = 0;
w7 = 0;
w8 = 0;
w9 = 0;
float tmp = x * 8.0;
if (tmp<=1.0) {
w1 = 1.0 - tmp;
w2 = tmp;
}
else if (tmp<=2.0) {
tmp = tmp - 1.0;
w2 = 1.0 - tmp;
w3 = tmp;
}
else if (tmp<=3.0) {
tmp = tmp - 2.0;
w3 = 1.0-tmp;
w4 = tmp;
}
else if (tmp<=4.0) {
tmp = tmp - 3.0;
w4 = 1.0-tmp;
w5 = tmp;
}
else if (tmp<=5.0) {
tmp = tmp - 4.0;
w5 = 1.0-tmp;
w6 = tmp;
}
else if (tmp<=6.0) {
tmp = tmp - 5.0;
w6 = 1.0-tmp;
w7 = tmp;
}
else if (tmp<=7.0) {
tmp = tmp - 6.0;
w7 = 1.0 - tmp;
w8 = tmp;
}
else {
tmp = saturate(tmp - 7.0);
w8 = 1.0-tmp;
w9 = tmp;
}
return w1*c1 + w2*c2 + w3*c3 + w4*c4 + w5*c5 + w6*c6 + w7*c7 + w8*c8 + w9*c9;
}
half4 frag (v2f i) : COLOR
{
//half4 col = tex2D(_MainTex, i.uv);
//return col;
float2 ox = float2(_DeltaX,0.0);
float2 oy = float2(0.0,_DeltaY);
float2 PP = i.uv - oy;
float4 C00 = tex2D(_MainTex,PP - ox);
float4 C01 = tex2D(_MainTex,PP);
float4 C02 = tex2D(_MainTex,PP + ox);
PP = i.uv;
float4 C10 = tex2D(_MainTex,PP - ox);
float4 C11 = tex2D(_MainTex,PP);
float4 C12 = tex2D(_MainTex,PP + ox);
PP = i.uv + oy;
float4 C20 = tex2D(_MainTex,PP - ox);
float4 C21 = tex2D(_MainTex,PP);
float4 C22 = tex2D(_MainTex,PP + ox);
float n = tex2D(_GrainTex, _Freq*i.uv).x;
n = fmod(n, 0.111111)/0.111111;
float4 result = spline(n,C00,C01,C02,C10,C11,C12,C20,C21,C22);
// this also looks pretty cool....
// float4 result = float4(n,n,n,1.0);
// float4 result = lerp(C00,C22,n);
return result;
}
ENDCG
}
}
Fallback off
}
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_DeltaX ("Delta X", Float) = 0.0073
_DeltaY ("Delta Y", Float) = 0.0108
_Freq ("Frequency", Float) = 0.115
//_DeltaX ("Delta X", Range(0.001,0.03)) = 0.0073
//_DeltaY ("Delta Y", Range(0.001,0.03)) = 0.0108
//_Freq ("Frequency", Range(0.0, 0.2)) = 0.115
//dummy slots
_GrainTex ("Base (RGB)", 2D) = "gray" {} //сюда кладем шум
}
SubShader {
Pass {
ZTest Always Cull Off ZWrite Off Fog { Mode off }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"
#pragma target 3.0
//здесь можно написать #define?)
struct v2f {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};
uniform sampler2D _MainTex;
uniform sampler2D _GrainTex;
uniform float _DeltaX;
uniform float _DeltaY;
uniform float _Freq;
v2f vert (appdata_img v)
{
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
o.uv = MultiplyUV (UNITY_MATRIX_TEXTURE0, v.texcoord);
return o;
}
float4 spline(float x, float4 c1, float4 c2, float4 c3, float4 c4, float4 c5, float4 c6, float4 c7, float4 c8, float4 c9)
{
float w1, w2, w3, w4, w5, w6, w7, w8, w9;
w1 = 0;
w2 = 0;
w3 = 0;
w4 = 0;
w5 = 0;
w6 = 0;
w7 = 0;
w8 = 0;
w9 = 0;
float tmp = x * 8.0;
if (tmp<=1.0) {
w1 = 1.0 - tmp;
w2 = tmp;
}
else if (tmp<=2.0) {
tmp = tmp - 1.0;
w2 = 1.0 - tmp;
w3 = tmp;
}
else if (tmp<=3.0) {
tmp = tmp - 2.0;
w3 = 1.0-tmp;
w4 = tmp;
}
else if (tmp<=4.0) {
tmp = tmp - 3.0;
w4 = 1.0-tmp;
w5 = tmp;
}
else if (tmp<=5.0) {
tmp = tmp - 4.0;
w5 = 1.0-tmp;
w6 = tmp;
}
else if (tmp<=6.0) {
tmp = tmp - 5.0;
w6 = 1.0-tmp;
w7 = tmp;
}
else if (tmp<=7.0) {
tmp = tmp - 6.0;
w7 = 1.0 - tmp;
w8 = tmp;
}
else {
tmp = saturate(tmp - 7.0);
w8 = 1.0-tmp;
w9 = tmp;
}
return w1*c1 + w2*c2 + w3*c3 + w4*c4 + w5*c5 + w6*c6 + w7*c7 + w8*c8 + w9*c9;
}
half4 frag (v2f i) : COLOR
{
//half4 col = tex2D(_MainTex, i.uv);
//return col;
float2 ox = float2(_DeltaX,0.0);
float2 oy = float2(0.0,_DeltaY);
float2 PP = i.uv - oy;
float4 C00 = tex2D(_MainTex,PP - ox);
float4 C01 = tex2D(_MainTex,PP);
float4 C02 = tex2D(_MainTex,PP + ox);
PP = i.uv;
float4 C10 = tex2D(_MainTex,PP - ox);
float4 C11 = tex2D(_MainTex,PP);
float4 C12 = tex2D(_MainTex,PP + ox);
PP = i.uv + oy;
float4 C20 = tex2D(_MainTex,PP - ox);
float4 C21 = tex2D(_MainTex,PP);
float4 C22 = tex2D(_MainTex,PP + ox);
float n = tex2D(_GrainTex, _Freq*i.uv).x;
n = fmod(n, 0.111111)/0.111111;
float4 result = spline(n,C00,C01,C02,C10,C11,C12,C20,C21,C22);
// this also looks pretty cool....
// float4 result = float4(n,n,n,1.0);
// float4 result = lerp(C00,C22,n);
return result;
}
ENDCG
}
}
Fallback off
}
Скрипт для камеры (переделанный ноиз):
Синтаксис:
Используется csharp
using UnityEngine;
[ExecuteInEditMode]
[RequireComponent (typeof(Camera))]
[AddComponentMenu("Image Effects/FrostEffect")]
public class FrostEffect : MonoBehaviour
{
/// Monochrome noise just adds grain. Non-monochrome noise
/// more resembles VCR as it adds noise in YUV color space,
/// thus introducing magenta/green colors.
//public bool monochrome = true;
//private bool rgbFallback = !false;
// Noise grain takes random intensity from Min to Max.
//public float grainIntensityMin = 0.1f;
//public float grainIntensityMax = 0.2f;
/// The size of the noise grains (1 = one pixel).
//public float grainSize = 2.0f;
// Scratches take random intensity from Min to Max.
//public float scratchIntensityMin = 0.05f;
//public float scratchIntensityMax = 0.25f;
/// Scratches jump to another locations at this times per second.
//public float scratchFPS = 10.0f;
/// While scratches are in the same location, they jitter a bit.
//public float scratchJitter = 0.01f;
public float frostDeltaX = 0.0073f;
//, Range(0.001,0.03))
public float frostDeltaY = 0.0108f;
//, Range(0.001,0.03))
public float frostFrequency = 0.115f;
//, Range(0.0, 0.2)) = 0.115
public Texture grainTexture;
//public Texture scratchTexture;
public Shader shaderRGB;
//public Shader shaderYUV;
private Material m_MaterialRGB;
//private Material m_MaterialYUV;
//private float scratchTimeLeft = 0.0f;
//private float scratchX, scratchY;
protected void Start ()
{
// Disable if we don't support image effects
if (!SystemInfo.supportsImageEffects) {
enabled = false;
return;
}
if( shaderRGB == null)
{
Debug.Log( "Noise shaders are not set up! Disabling noise effect." );
enabled = false;
}
else
{
if( !shaderRGB.isSupported ) // disable effect if RGB shader is not supported
enabled = false;
//else if( !shaderYUV.isSupported ) // fallback to RGB if YUV is not supported
// rgbFallback = true;
}
}
protected Material material {
get {
if( m_MaterialRGB == null ) {
m_MaterialRGB = new Material( shaderRGB );
m_MaterialRGB.hideFlags = HideFlags.HideAndDontSave;
}
return m_MaterialRGB;
}
}
protected void OnDisable() {
if( m_MaterialRGB )
DestroyImmediate( m_MaterialRGB );
}
//прикольно)
private void SanitizeParameters()
{
//странно клемпится
////frostDeltaX = Mathf.Clamp(frostDeltaX, 0.001f, 0.03f);
////frostDeltaY = Mathf.Clamp(frostDeltaY, 0.001f, 0.03f);
////frostFrequency = Mathf.Clamp(frostFrequency, 0.0f, 0.2f);
//grainIntensityMin = Mathf.Clamp(grainIntensityMin, 0.0f, 5.0f);
//grainIntensityMax = Mathf.Clamp(grainIntensityMax, 0.0f, 5.0f);
//scratchIntensityMin = Mathf.Clamp(scratchIntensityMin, 0.0f, 5.0f);
//scratchIntensityMax = Mathf.Clamp(scratchIntensityMax, 0.0f, 5.0f);
//scratchFPS = Mathf.Clamp(scratchFPS, 1, 30);
//scratchJitter = Mathf.Clamp(scratchJitter, 0.0f, 1.0f);
//grainSize = Mathf.Clamp(grainSize, 0.1f, 50.0f);
}
// Called by the camera to apply the image effect
void OnRenderImage (RenderTexture source, RenderTexture destination)
{
SanitizeParameters();
//if( scratchTimeLeft <= 0.0f )
//{
// scratchTimeLeft = Random.value * 2 / scratchFPS; // we have sanitized it earlier, won't be zero
// scratchX = Random.value;
// scratchY = Random.value;
//}
//scratchTimeLeft -= Time.deltaTime;
Material mat = material;
mat.SetTexture("_GrainTex", grainTexture);
//Debug.Log(""+Time.time);
mat.SetFloat("_DeltaX", frostDeltaX);
mat.SetFloat("_DeltaY", frostDeltaY);
mat.SetFloat("_Freq", frostFrequency);
//mat.SetTexture("_ScratchTex", scratchTexture);
//float grainScale = 1.0f / grainSize; // we have sanitized it earlier, won't be zero
//mat.SetVector("_GrainOffsetScale", new Vector4(
// Random.value,
// Random.value,
// (float)Screen.width / (float)grainTexture.width * grainScale,
// (float)Screen.height / (float)grainTexture.height * grainScale
//));
//mat.SetVector("_ScratchOffsetScale", new Vector4(
// scratchX + Random.value*scratchJitter,
// scratchY + Random.value*scratchJitter,
// (float)Screen.width / (float) scratchTexture.width,
// (float)Screen.height / (float) scratchTexture.height
//));
//mat.SetVector("_Intensity", new Vector4(
// Random.Range(grainIntensityMin, grainIntensityMax),
// Random.Range(scratchIntensityMin, scratchIntensityMax),
// 0, 0 ));
Graphics.Blit (source, destination, mat);
}
}
[ExecuteInEditMode]
[RequireComponent (typeof(Camera))]
[AddComponentMenu("Image Effects/FrostEffect")]
public class FrostEffect : MonoBehaviour
{
/// Monochrome noise just adds grain. Non-monochrome noise
/// more resembles VCR as it adds noise in YUV color space,
/// thus introducing magenta/green colors.
//public bool monochrome = true;
//private bool rgbFallback = !false;
// Noise grain takes random intensity from Min to Max.
//public float grainIntensityMin = 0.1f;
//public float grainIntensityMax = 0.2f;
/// The size of the noise grains (1 = one pixel).
//public float grainSize = 2.0f;
// Scratches take random intensity from Min to Max.
//public float scratchIntensityMin = 0.05f;
//public float scratchIntensityMax = 0.25f;
/// Scratches jump to another locations at this times per second.
//public float scratchFPS = 10.0f;
/// While scratches are in the same location, they jitter a bit.
//public float scratchJitter = 0.01f;
public float frostDeltaX = 0.0073f;
//, Range(0.001,0.03))
public float frostDeltaY = 0.0108f;
//, Range(0.001,0.03))
public float frostFrequency = 0.115f;
//, Range(0.0, 0.2)) = 0.115
public Texture grainTexture;
//public Texture scratchTexture;
public Shader shaderRGB;
//public Shader shaderYUV;
private Material m_MaterialRGB;
//private Material m_MaterialYUV;
//private float scratchTimeLeft = 0.0f;
//private float scratchX, scratchY;
protected void Start ()
{
// Disable if we don't support image effects
if (!SystemInfo.supportsImageEffects) {
enabled = false;
return;
}
if( shaderRGB == null)
{
Debug.Log( "Noise shaders are not set up! Disabling noise effect." );
enabled = false;
}
else
{
if( !shaderRGB.isSupported ) // disable effect if RGB shader is not supported
enabled = false;
//else if( !shaderYUV.isSupported ) // fallback to RGB if YUV is not supported
// rgbFallback = true;
}
}
protected Material material {
get {
if( m_MaterialRGB == null ) {
m_MaterialRGB = new Material( shaderRGB );
m_MaterialRGB.hideFlags = HideFlags.HideAndDontSave;
}
return m_MaterialRGB;
}
}
protected void OnDisable() {
if( m_MaterialRGB )
DestroyImmediate( m_MaterialRGB );
}
//прикольно)
private void SanitizeParameters()
{
//странно клемпится
////frostDeltaX = Mathf.Clamp(frostDeltaX, 0.001f, 0.03f);
////frostDeltaY = Mathf.Clamp(frostDeltaY, 0.001f, 0.03f);
////frostFrequency = Mathf.Clamp(frostFrequency, 0.0f, 0.2f);
//grainIntensityMin = Mathf.Clamp(grainIntensityMin, 0.0f, 5.0f);
//grainIntensityMax = Mathf.Clamp(grainIntensityMax, 0.0f, 5.0f);
//scratchIntensityMin = Mathf.Clamp(scratchIntensityMin, 0.0f, 5.0f);
//scratchIntensityMax = Mathf.Clamp(scratchIntensityMax, 0.0f, 5.0f);
//scratchFPS = Mathf.Clamp(scratchFPS, 1, 30);
//scratchJitter = Mathf.Clamp(scratchJitter, 0.0f, 1.0f);
//grainSize = Mathf.Clamp(grainSize, 0.1f, 50.0f);
}
// Called by the camera to apply the image effect
void OnRenderImage (RenderTexture source, RenderTexture destination)
{
SanitizeParameters();
//if( scratchTimeLeft <= 0.0f )
//{
// scratchTimeLeft = Random.value * 2 / scratchFPS; // we have sanitized it earlier, won't be zero
// scratchX = Random.value;
// scratchY = Random.value;
//}
//scratchTimeLeft -= Time.deltaTime;
Material mat = material;
mat.SetTexture("_GrainTex", grainTexture);
//Debug.Log(""+Time.time);
mat.SetFloat("_DeltaX", frostDeltaX);
mat.SetFloat("_DeltaY", frostDeltaY);
mat.SetFloat("_Freq", frostFrequency);
//mat.SetTexture("_ScratchTex", scratchTexture);
//float grainScale = 1.0f / grainSize; // we have sanitized it earlier, won't be zero
//mat.SetVector("_GrainOffsetScale", new Vector4(
// Random.value,
// Random.value,
// (float)Screen.width / (float)grainTexture.width * grainScale,
// (float)Screen.height / (float)grainTexture.height * grainScale
//));
//mat.SetVector("_ScratchOffsetScale", new Vector4(
// scratchX + Random.value*scratchJitter,
// scratchY + Random.value*scratchJitter,
// (float)Screen.width / (float) scratchTexture.width,
// (float)Screen.height / (float) scratchTexture.height
//));
//mat.SetVector("_Intensity", new Vector4(
// Random.Range(grainIntensityMin, grainIntensityMax),
// Random.Range(scratchIntensityMin, scratchIntensityMax),
// 0, 0 ));
Graphics.Blit (source, destination, mat);
}
}
Ну и текстура шумка: