/* ____ _ _ __ __ _ * | _ \ _ __ ___ (_) ___ ___| |_ \ \ / /_ _ _ __ __| | ___ _ __ * | |_) | '__/ _ \| |/ _ \/ __| __| \ \ /\ / / _` | '_ \ / _` |/ _ \ '__| * | __/| | | (_) | | __/ (__| |_ \ V V / (_| | | | | (_| | __/ | * |_| |_| \___// |\___|\___|\__| \_/\_/ \__,_|_| |_|\__,_|\___|_| * |__/ * * * ENJMIN - Hits PlayTime 2013 * * This file is part of the Wander project, * created and developped by : * Louis Schnellbach * */ using UnityEngine; using System.Collections; using System.Collections.Generic; [ExecuteInEditMode] [RequireComponent(typeof(Camera))] public class CameraPostProcess : MonoBehaviour { RenderTexture m_finalTex; List m_list = new List (); public Shader shader; private Material m_materialPostProcess = null; private Material m_materialInitTexture = null; private int m_width; private int m_height; float CAMERA_NEAR; float CAMERA_FAR; float CAMERA_FOV; float CAMERA_ASPECT_RATIO; void Start () { camera.depthTextureMode = DepthTextureMode.DepthNormals; // Disable if we don't support image effects if (!SystemInfo.supportsImageEffects) { enabled = false; return; } // Disable the image effect if the shader can't // run on the users graphics card if (!shader || !shader.isSupported) enabled = false; } //Free texture void OnDisable () { m_list.Clear (); DestroyImmediate (m_finalTex); DestroyImmediate (m_materialPostProcess); DestroyImmediate (m_materialInitTexture); } void OnEnable () { if (m_materialPostProcess == null) { m_materialPostProcess = new Material (shader); m_materialPostProcess.hideFlags = HideFlags.HideAndDontSave; } if (m_materialInitTexture == null) { m_materialInitTexture = new Material (Shader.Find ("Xleek/BlackTexture")); m_materialInitTexture.hideFlags = HideFlags.HideAndDontSave; } m_list.Clear (); camera.depthTextureMode = DepthTextureMode.DepthNormals; m_finalTex = new RenderTexture ((int)camera.pixelWidth, (int)camera.pixelHeight, 0); } public void AddSource (Source obj) { m_list.Add (obj); //Debug.Log ("Added Source. (" + m_list.Count.ToString () + ")"); } public void RemoveSource (Source obj) { m_list.Remove (obj); //Debug.Log ("Removed Source. (" + m_list.Count.ToString () + ")"); } // Called by camera to apply image effect void OnRenderImage (RenderTexture source, RenderTexture destination) { //Clear FinalTexture before each display Graphics.Blit (null, m_finalTex, m_materialInitTexture); // Setup the texture and floating point values in the shader m_materialPostProcess.SetTexture ("_MainTex", source); //Send to shader the frustum corner m_materialPostProcess.SetMatrix ("_FrustumCornersWS", frustumCorner ()); //And the camera position (computed once) m_materialPostProcess.SetVector ("_CameraWS", camera.transform.position); //Start rendering each source m_list.ForEach (delegate(Source src) { if (src != null) { m_materialPostProcess.SetTexture ("_FinalTex", m_finalTex); m_materialPostProcess.SetVector ("_Position", src.Position); m_materialPostProcess.SetColor ("_SourceColor", src.SourceColor); m_materialPostProcess.SetFloat ("_Radius", src.Radius); m_materialPostProcess.SetFloat ("_MaxRadius", src.MaxRadius); m_materialPostProcess.SetFloat ("_VisibleWidth", src.VisibleWidth); m_materialPostProcess.SetFloat ("_HaloWidth", src.HaloWidth); CustomGraphicBlit (source, m_finalTex, m_materialPostProcess); } }); //Final (at least !) blit Graphics.Blit (m_finalTex, destination); } void CustomGraphicBlit (RenderTexture source, RenderTexture destination, Material material) { RenderTexture.active = destination; GL.PushMatrix (); GL.LoadOrtho (); material.SetPass (0); GL.Begin (GL.QUADS); GL.MultiTexCoord2 (0, 0.0f, 0.0f); GL.Vertex3 (0.0f, 0.0f, 3.0f); // BL GL.MultiTexCoord2 (0, 1.0f, 0.0f); GL.Vertex3 (1.0f, 0.0f, 2.0f); // BR GL.MultiTexCoord2 (0, 1.0f, 1.0f); GL.Vertex3 (1.0f, 1.0f, 1.0f); // TR GL.MultiTexCoord2 (0, 0.0f, 1.0f); GL.Vertex3 (0.0f, 1.0f, 0.0f); // TL GL.End (); GL.PopMatrix (); } //Avoid to write this in the render method Matrix4x4 frustumCorner () { Matrix4x4 frustumCorners = Matrix4x4.identity; CAMERA_NEAR = camera.nearClipPlane; CAMERA_FAR = camera.farClipPlane; CAMERA_FOV = camera.fieldOfView; CAMERA_ASPECT_RATIO = camera.aspect; float fovWHalf = CAMERA_FOV * 0.5f; Vector3 toRight = camera.transform.right * CAMERA_NEAR * Mathf.Tan (fovWHalf * Mathf.Deg2Rad) * CAMERA_ASPECT_RATIO; Vector3 toTop = camera.transform.up * CAMERA_NEAR * Mathf.Tan (fovWHalf * Mathf.Deg2Rad); Vector3 topLeft = (camera.transform.forward * CAMERA_NEAR - toRight + toTop); float CAMERA_SCALE = topLeft.magnitude * CAMERA_FAR / CAMERA_NEAR; topLeft.Normalize (); topLeft *= CAMERA_SCALE; Vector3 topRight = (camera.transform.forward * CAMERA_NEAR + toRight + toTop); topRight.Normalize (); topRight *= CAMERA_SCALE; Vector3 bottomRight = (camera.transform.forward * CAMERA_NEAR + toRight - toTop); bottomRight.Normalize (); bottomRight *= CAMERA_SCALE; Vector3 bottomLeft = (camera.transform.forward * CAMERA_NEAR - toRight - toTop); bottomLeft.Normalize (); bottomLeft *= CAMERA_SCALE; frustumCorners.SetRow (0, topLeft); frustumCorners.SetRow (1, topRight); frustumCorners.SetRow (2, bottomRight); frustumCorners.SetRow (3, bottomLeft); return frustumCorners; } }