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

198     }
199 }


CreateRandomTable (26, 0.2f);

Render SSAO term into a smaller texture

Blur SSAO horizontally

RenderTexture.ReleaseTemporary (rtAO); original rtAO not needed anymore

Blur SSAO vertically

RenderTexture.ReleaseTemporary (rtBlurX); blurX RT not needed anymore

rtAO = rtBlurY; AO is the blurred one now

Modulate scene rendering with SSAO

initial samples

energy minimization: push samples away from others

minimize with other samples

now scale samples between minLength and 1.0



Gõ tìm kiếm nhanh...