You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
205 lines
7.1 KiB
205 lines
7.1 KiB
using System; |
|
using UnityEngine; |
|
|
|
namespace UnityStandardAssets.ImageEffects |
|
{ |
|
[ExecuteInEditMode] |
|
[RequireComponent (typeof(Camera))] |
|
[AddComponentMenu("Image Effects/Rendering/Screen Space Ambient Occlusion")] |
|
public class ScreenSpaceAmbientOcclusion : MonoBehaviour |
|
{ |
|
public enum SSAOSamples |
|
{ |
|
Low = 0, |
|
Medium = 1, |
|
High = 2, |
|
} |
|
|
|
[Range(0.05f, 1.0f)] |
|
public float m_Radius = 0.4f; |
|
public SSAOSamples m_SampleCount = SSAOSamples.Medium; |
|
[Range(0.5f, 4.0f)] |
|
public float m_OcclusionIntensity = 1.5f; |
|
[Range(0, 4)] |
|
public int m_Blur = 2; |
|
[Range(1,6)] |
|
public int m_Downsampling = 2; |
|
[Range(0.2f, 2.0f)] |
|
public float m_OcclusionAttenuation = 1.0f; |
|
[Range(0.00001f, 0.5f)] |
|
public float m_MinZ = 0.01f; |
|
|
|
public Shader m_SSAOShader; |
|
private Material m_SSAOMaterial; |
|
|
|
public Texture2D m_RandomTexture; |
|
|
|
private bool m_Supported; |
|
|
|
private static Material CreateMaterial (Shader shader) |
|
{ |
|
if (!shader) |
|
return null; |
|
Material m = new Material (shader); |
|
m.hideFlags = HideFlags.HideAndDontSave; |
|
return m; |
|
} |
|
private static void DestroyMaterial (Material mat) |
|
{ |
|
if (mat) |
|
{ |
|
DestroyImmediate (mat); |
|
mat = null; |
|
} |
|
} |
|
|
|
|
|
void OnDisable() |
|
{ |
|
DestroyMaterial (m_SSAOMaterial); |
|
} |
|
|
|
void Start() |
|
{ |
|
if (!SystemInfo.supportsImageEffects || !SystemInfo.SupportsRenderTextureFormat (RenderTextureFormat.Depth)) |
|
{ |
|
m_Supported = false; |
|
enabled = false; |
|
return; |
|
} |
|
|
|
CreateMaterials (); |
|
if (!m_SSAOMaterial || m_SSAOMaterial.passCount != 5) |
|
{ |
|
m_Supported = false; |
|
enabled = false; |
|
return; |
|
} |
|
|
|
//CreateRandomTable (26, 0.2f); |
|
|
|
m_Supported = true; |
|
} |
|
|
|
void OnEnable () { |
|
GetComponent<Camera>().depthTextureMode |= DepthTextureMode.DepthNormals; |
|
} |
|
|
|
private void CreateMaterials () |
|
{ |
|
if (!m_SSAOMaterial && m_SSAOShader.isSupported) |
|
{ |
|
m_SSAOMaterial = CreateMaterial (m_SSAOShader); |
|
m_SSAOMaterial.SetTexture ("_RandomTexture", m_RandomTexture); |
|
} |
|
} |
|
|
|
[ImageEffectOpaque] |
|
void OnRenderImage (RenderTexture source, RenderTexture destination) |
|
{ |
|
if (!m_Supported || !m_SSAOShader.isSupported) { |
|
enabled = false; |
|
return; |
|
} |
|
CreateMaterials (); |
|
|
|
m_Downsampling = Mathf.Clamp (m_Downsampling, 1, 6); |
|
m_Radius = Mathf.Clamp (m_Radius, 0.05f, 1.0f); |
|
m_MinZ = Mathf.Clamp (m_MinZ, 0.00001f, 0.5f); |
|
m_OcclusionIntensity = Mathf.Clamp (m_OcclusionIntensity, 0.5f, 4.0f); |
|
m_OcclusionAttenuation = Mathf.Clamp (m_OcclusionAttenuation, 0.2f, 2.0f); |
|
m_Blur = Mathf.Clamp (m_Blur, 0, 4); |
|
|
|
// Render SSAO term into a smaller texture |
|
RenderTexture rtAO = RenderTexture.GetTemporary (source.width / m_Downsampling, source.height / m_Downsampling, 0); |
|
float fovY = GetComponent<Camera>().fieldOfView; |
|
float far = GetComponent<Camera>().farClipPlane; |
|
float y = Mathf.Tan (fovY * Mathf.Deg2Rad * 0.5f) * far; |
|
float x = y * GetComponent<Camera>().aspect; |
|
m_SSAOMaterial.SetVector ("_FarCorner", new Vector3(x,y,far)); |
|
int noiseWidth, noiseHeight; |
|
if (m_RandomTexture) { |
|
noiseWidth = m_RandomTexture.width; |
|
noiseHeight = m_RandomTexture.height; |
|
} else { |
|
noiseWidth = 1; noiseHeight = 1; |
|
} |
|
m_SSAOMaterial.SetVector ("_NoiseScale", new Vector3 ((float)rtAO.width / noiseWidth, (float)rtAO.height / noiseHeight, 0.0f)); |
|
m_SSAOMaterial.SetVector ("_Params", new Vector4( |
|
m_Radius, |
|
m_MinZ, |
|
1.0f / m_OcclusionAttenuation, |
|
m_OcclusionIntensity)); |
|
|
|
bool doBlur = m_Blur > 0; |
|
Graphics.Blit (doBlur ? null : source, rtAO, m_SSAOMaterial, (int)m_SampleCount); |
|
|
|
if (doBlur) |
|
{ |
|
// Blur SSAO horizontally |
|
RenderTexture rtBlurX = RenderTexture.GetTemporary (source.width, source.height, 0); |
|
m_SSAOMaterial.SetVector ("_TexelOffsetScale", |
|
new Vector4 ((float)m_Blur / source.width, 0,0,0)); |
|
m_SSAOMaterial.SetTexture ("_SSAO", rtAO); |
|
Graphics.Blit (null, rtBlurX, m_SSAOMaterial, 3); |
|
RenderTexture.ReleaseTemporary (rtAO); // original rtAO not needed anymore |
|
|
|
// Blur SSAO vertically |
|
RenderTexture rtBlurY = RenderTexture.GetTemporary (source.width, source.height, 0); |
|
m_SSAOMaterial.SetVector ("_TexelOffsetScale", |
|
new Vector4 (0, (float)m_Blur/source.height, 0,0)); |
|
m_SSAOMaterial.SetTexture ("_SSAO", rtBlurX); |
|
Graphics.Blit (source, rtBlurY, m_SSAOMaterial, 3); |
|
RenderTexture.ReleaseTemporary (rtBlurX); // blurX RT not needed anymore |
|
|
|
rtAO = rtBlurY; // AO is the blurred one now |
|
} |
|
|
|
// Modulate scene rendering with SSAO |
|
m_SSAOMaterial.SetTexture ("_SSAO", rtAO); |
|
Graphics.Blit (source, destination, m_SSAOMaterial, 4); |
|
|
|
RenderTexture.ReleaseTemporary (rtAO); |
|
} |
|
|
|
/* |
|
private void CreateRandomTable (int count, float minLength) |
|
{ |
|
Random.seed = 1337; |
|
Vector3[] samples = new Vector3[count]; |
|
// initial samples |
|
for (int i = 0; i < count; ++i) |
|
samples[i] = Random.onUnitSphere; |
|
// energy minimization: push samples away from others |
|
int iterations = 100; |
|
while (iterations-- > 0) { |
|
for (int i = 0; i < count; ++i) { |
|
Vector3 vec = samples[i]; |
|
Vector3 res = Vector3.zero; |
|
// minimize with other samples |
|
for (int j = 0; j < count; ++j) { |
|
Vector3 force = vec - samples[j]; |
|
float fac = Vector3.Dot (force, force); |
|
if (fac > 0.00001f) |
|
res += force * (1.0f / fac); |
|
} |
|
samples[i] = (samples[i] + res * 0.5f).normalized; |
|
} |
|
} |
|
// now scale samples between minLength and 1.0 |
|
for (int i = 0; i < count; ++i) { |
|
samples[i] = samples[i] * Random.Range (minLength, 1.0f); |
|
} |
|
|
|
string table = string.Format ("#define SAMPLE_COUNT {0}\n", count); |
|
table += "const float3 RAND_SAMPLES[SAMPLE_COUNT] = {\n"; |
|
for (int i = 0; i < count; ++i) { |
|
Vector3 v = samples[i]; |
|
table += string.Format("\tfloat3({0},{1},{2}),\n", v.x, v.y, v.z); |
|
} |
|
table += "};\n"; |
|
Debug.Log (table); |
|
} |
|
*/ |
|
} |
|
}
|
|
|