1 using System;
2 using
UnityEngine;
3
4 namespace
UnityStandardAssets.ImageEffects
5 {
6     
[ExecuteInEditMode]
7     
[RequireComponent (typeof(Camera))]
8     
[AddComponentMenu("Image Effects/Rendering/Screen Space Ambient Occlusion")]
9     
public class ScreenSpaceAmbientOcclusion : MonoBehaviour
10     {
11         
public enum SSAOSamples
12         {
13             Low =
0,
14             Medium =
1,
15             High =
2,
16         }
17
18         
[Range(0.05f, 1.0f)]
19         
public float m_Radius = 0.4f;
20         
public SSAOSamples m_SampleCount = SSAOSamples.Medium;
21         
[Range(0.5f, 4.0f)]
22         
public float m_OcclusionIntensity = 1.5f;
23         
[Range(0, 4)]
24         
public int m_Blur = 2;
25         
[Range(1,6)]
26         
public int m_Downsampling = 2;
27         
[Range(0.2f, 2.0f)]
28         
public float m_OcclusionAttenuation = 1.0f;
29         
[Range(0.00001f, 0.5f)]
30         
public float m_MinZ = 0.01f;
31
32         
public Shader m_SSAOShader;
33         
private Material m_SSAOMaterial;
34
35         
public Texture2D m_RandomTexture;
36
37         
private bool m_Supported;
38
39         
private static Material CreateMaterial (Shader shader)
40         {
41             
if (!shader)
42                 
return null;
43             Material m =
new Material (shader);
44             m.hideFlags = HideFlags.HideAndDontSave;
45             
return m;
46         }
47         
private static void DestroyMaterial (Material mat)
48         {
49             
if (mat)
50             {
51                 DestroyImmediate (mat);
52                 mat =
null;
53             }
54         }
55
56
57         
void OnDisable()
58         {
59             DestroyMaterial (m_SSAOMaterial);
60         }
61
62         
void Start()
63         {
64             
if (!SystemInfo.supportsImageEffects || !SystemInfo.SupportsRenderTextureFormat (RenderTextureFormat.Depth))
65             {
66                 m_Supported =
false;
67                 enabled =
false;
68                 
return;
69             }
70
71             CreateMaterials ();
72             
if (!m_SSAOMaterial || m_SSAOMaterial.passCount != 5)
73             {
74                 m_Supported =
false;
75                 enabled =
false;
76                 
return;
77             }
78
79             
//CreateRandomTable (26, 0.2f);
80
81             m_Supported =
true;
82         }
83
84         
void OnEnable () {
85             GetComponent<Camera>().depthTextureMode |= DepthTextureMode.DepthNormals;
86         }
87
88         
private void CreateMaterials ()
89         {
90             
if (!m_SSAOMaterial && m_SSAOShader.isSupported)
91             {
92                 m_SSAOMaterial = CreateMaterial (m_SSAOShader);
93                 m_SSAOMaterial.SetTexture (
"_RandomTexture", m_RandomTexture);
94             }
95         }
96
97         
[ImageEffectOpaque]
98         
void OnRenderImage (RenderTexture source, RenderTexture destination)
99         {
100             
if (!m_Supported || !m_SSAOShader.isSupported) {
101                 enabled =
false;
102                 
return;
103             }
104             CreateMaterials ();
105
106             m_Downsampling = Mathf.Clamp (m_Downsampling,
1, 6);
107             m_Radius = Mathf.Clamp (m_Radius,
0.05f, 1.0f);
108             m_MinZ = Mathf.Clamp (m_MinZ,
0.00001f, 0.5f);
109             m_OcclusionIntensity = Mathf.Clamp (m_OcclusionIntensity,
0.5f, 4.0f);
110             m_OcclusionAttenuation = Mathf.Clamp (m_OcclusionAttenuation,
0.2f, 2.0f);
111             m_Blur = Mathf.Clamp (m_Blur,
0, 4);
112
113             
// Render SSAO term into a smaller texture
114             RenderTexture rtAO = RenderTexture.GetTemporary (source.width / m_Downsampling, source.height / m_Downsampling,
0);
115             
float fovY = GetComponent<Camera>().fieldOfView;
116             
float far = GetComponent<Camera>().farClipPlane;
117             
float y = Mathf.Tan (fovY * Mathf.Deg2Rad * 0.5f) * far;
118             
float x = y * GetComponent<Camera>().aspect;
119             m_SSAOMaterial.SetVector (
"_FarCorner", new Vector3(x,y,far));
120             
int noiseWidth, noiseHeight;
121             
if (m_RandomTexture) {
122                 noiseWidth = m_RandomTexture.width;
123                 noiseHeight = m_RandomTexture.height;
124             }
else {
125                 noiseWidth =
1; noiseHeight = 1;
126             }
127             m_SSAOMaterial.SetVector (
"_NoiseScale", new Vector3 ((float)rtAO.width / noiseWidth, (float)rtAO.height / noiseHeight, 0.0f));
128             m_SSAOMaterial.SetVector (
"_Params", new Vector4(
129                                                      m_Radius,
130                                                      m_MinZ,
131                                                      
1.0f / m_OcclusionAttenuation,
132                                                      m_OcclusionIntensity));
133
134             
bool doBlur = m_Blur > 0;
135             Graphics.Blit (doBlur ?
null : source, rtAO, m_SSAOMaterial, (int)m_SampleCount);
136
137             
if (doBlur)
138             {
139                 
// Blur SSAO horizontally
140                 RenderTexture rtBlurX = RenderTexture.GetTemporary (source.width, source.height,
0);
141                 m_SSAOMaterial.SetVector (
"_TexelOffsetScale",
142                                           
new Vector4 ((float)m_Blur / source.width, 0,0,0));
143                 m_SSAOMaterial.SetTexture (
"_SSAO", rtAO);
144                 Graphics.Blit (
null, rtBlurX, m_SSAOMaterial, 3);
145                 RenderTexture.ReleaseTemporary (rtAO);
// original rtAO not needed anymore
146
147                 
// Blur SSAO vertically
148                 RenderTexture rtBlurY = RenderTexture.GetTemporary (source.width, source.height,
0);
149                 m_SSAOMaterial.SetVector (
"_TexelOffsetScale",
150                                           
new Vector4 (0, (float)m_Blur/source.height, 0,0));
151                 m_SSAOMaterial.SetTexture (
"_SSAO", rtBlurX);
152                 Graphics.Blit (source, rtBlurY, m_SSAOMaterial,
3);
153                 RenderTexture.ReleaseTemporary (rtBlurX);
// blurX RT not needed anymore
154
155                 rtAO = rtBlurY;
// AO is the blurred one now
156             }
157
158             
// Modulate scene rendering with SSAO
159             m_SSAOMaterial.SetTexture (
"_SSAO", rtAO);
160             Graphics.Blit (source, destination, m_SSAOMaterial,
4);
161
162             RenderTexture.ReleaseTemporary (rtAO);
163         }
164
165         
/*
166         
private void CreateRandomTable (int count, float minLength)
167         {
168             Random.seed =
1337;
169             Vector3[] samples =
new Vector3[count];
170             // initial samples
171             
for (int i = 0; i < count; ++i)
172                 samples[i] = Random.onUnitSphere;
173             // energy minimization: push samples away
from others
174             
int iterations = 100;
175             
while (iterations-- > 0) {
176                 
for (int i = 0; i < count; ++i) {
177                     Vector3 vec = samples[i];
178                     Vector3 res = Vector3.zero;
179                     // minimize with other samples
180                     
for (int j = 0; j < count; ++j) {
181                         Vector3 force = vec - samples[j];
182                         
float fac = Vector3.Dot (force, force);
183                         
if (fac > 0.00001f)
184                             res += force * (
1.0f / fac);
185                     }
186                     samples[i] = (samples[i] + res *
0.5f).normalized;
187                 }
188             }
189             // now scale samples between minLength and
1.0
190             
for (int i = 0; i < count; ++i) {
191                 samples[i] = samples[i] * Random.Range (minLength,
1.0f);
192             }
193
194             
string table = string.Format ("#define SAMPLE_COUNT {0}\n", count);
195             table +=
"const float3 RAND_SAMPLES[SAMPLE_COUNT] = {\n";
196             
for (int i = 0; i < count; ++i) {
197                 Vector3 v = samples[i];
198                 table +=
string.Format("\tfloat3({0},{1},{2}),\n", v.x, v.y, v.z);
199             }
200             table +=
"};\n";
201             Debug.Log (table);
202         }
203         */

204     }
205 }


Tìm kết quả nhanh