UnityMol  0.9.6-875
UnityMol viewer / In developement
ScreenSpaceAmbientOcclusion.cs
Go to the documentation of this file.
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 }
void OnRenderImage(RenderTexture source, RenderTexture destination)