text:
//
// Kino/Obscurance - SSAO (screen-space ambient obscurance) effect for Unity
//
// Copyright (C) 2016 Keijiro Takahashi
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
using UnityEngine;
using UnityEngine.Rendering;

namespace Kino
{
    [ExecuteInEditMode]
    [RequireComponent(typeof(Camera))]
    [AddComponentMenu("Kino Image Effects/Obscurance")]
    public partial class Obscurance : MonoBehaviour
    {
        #region Public Properties

        /// Degree of darkness produced by the effect.
        public float intensity {
            get { return _intensity; }
            set { _intensity = value; }
        }

        [SerializeField, Range(0, 4), Tooltip(
            "Degree of darkness produced by the effect.")]
        float _intensity = 1;

        /// Radius of sample points, which affects extent of darkened areas.
        public float radius {
            get { return Mathf.Max(_radius, 1e-4f); }
            set { _radius = value; }
        }

        [SerializeField, Tooltip(
            "Radius of sample points, which affects extent of darkened areas.")]
        float _radius = 0.3f;

        /// Number of sample points, which affects quality and performance.
        public SampleCount sampleCount {
            get { return _sampleCount; }
            set { _sampleCount = value; }
        }

        public enum SampleCount { Lowest, Low, Medium, High, Variable }

        [SerializeField, Tooltip(
            "Number of sample points, which affects quality and performance.")]
        SampleCount _sampleCount = SampleCount.Medium;

        /// Determines the sample count when SampleCount.Variable is used.
        /// In other cases, it returns the preset value of the current setting.
        public int sampleCountValue {
            get {
                switch (_sampleCount) {
                    case SampleCount.Lowest: return 3;
                    case SampleCount.Low:    return 6;
                    case SampleCount.Medium: return 12;
                    case SampleCount.High:   return 20;
                }
                return Mathf.Clamp(_sampleCountValue, 1, 256);
            }
            set { _sampleCountValue = value; }
        }

        [SerializeField]
        int _sampleCountValue = 24;

        /// Halves the resolution of the effect to increase performance.
        public bool downsampling {
            get { return _downsampling; }
            set { _downsampling = value; }
        }

        [SerializeField, Tooltip(
            "Halves the resolution of the effect to increase performance.")]
        bool _downsampling = false;

        /// Source buffer used for obscurance estimation.
        public OcclusionSource occlusionSource {
            get {
                var isGBuffer = _occlusionSource == OcclusionSource.GBuffer;
                if (isGBuffer && !IsGBufferAvailable)
                    // An unavailable source was chosen:
                    // fallback to DepthNormalsTexture.
                    return OcclusionSource.DepthNormalsTexture;
                else
                    return _occlusionSource;
            }
            set { _occlusionSource = value; }
        }

        public enum OcclusionSource {
            DepthTexture, DepthNormalsTexture, GBuffer
        }

        [SerializeField, Tooltip(
            "Source buffer used for obscurance estimation")]
        OcclusionSource _occlusionSource = OcclusionSource.GBuffer;

        /// Enables the ambient-only mode in that the effect only affects
        /// ambient lighting. This mode is only available with G-buffer source
        /// and HDR rendering.
        public bool ambientOnly {
            get {
                return _ambientOnly && targetCamera.hdr &&
                    occlusionSource == OcclusionSource.GBuffer;
            }
            set { _ambientOnly = value; }
        }

        [SerializeField, Tooltip(
            "If checked, the effect only affects ambient lighting.")]
        bool _ambientOnly = false;

        #endregion

        #region Private Properties

        // AO shader material
        Material aoMaterial {
            get {
                if (_aoMaterial == null) {
                    var shader = Shader.Find("Hidden/Kino/Obscurance");
                    _aoMaterial = new Material(shader);
                    _aoMaterial.hideFlags = HideFlags.DontSave;
                }
                return _aoMaterial;
            }
        }

        [SerializeField] Shader _aoShader;
        Material _aoMaterial;

        // Command buffer for the AO pass
        CommandBuffer aoCommands {
            get {
                if (_aoCommands == null) {
                    _aoCommands = new CommandBuffer();
                    _aoCommands.name = "Kino.Obscurance";
                }
                return _aoCommands;
            }
        }

        CommandBuffer _aoCommands;

        // Target camera
        Camera targetCamera {
            get { return GetComponent<Camera>(); }
        }

        // Property observer
        PropertyObserver propertyObserver { get; set; }

        // Check if the G-buffer is available
        bool IsGBufferAvailable {
            get {
                var path = targetCamera.actualRenderingPath;
                return path == RenderingPath.DeferredShading;
            }
        }

        // Reference to the quad mesh in the built-in assets
        // (used in MRT blitting)
        [SerializeField] Mesh _quadMesh;

        #endregion

        #region Effect Passes

        // Build commands for the AO pass (used in the ambient-only mode).
        void BuildAOCommands()
        {
            var cb = aoCommands;

            var tw = targetCamera.pixelWidth;
            var th = targetCamera.pixelHeight;
            var ts = downsampling ? 2 : 1;
            var format = RenderTextureFormat.R8;
            var rwMode = RenderTextureReadWrite.Linear;
            var filter = FilterMode.Bilinear;

            // AO buffer
            var m = aoMaterial;
            var rtMask = Shader.PropertyToID("_ObscuranceTexture");
            cb.GetTemporaryRT(
                rtMask, tw / ts, th / ts, 0, filter, format, rwMode
            );

            // AO estimation
            cb.Blit(null, rtMask, m, 2);

            // Blur buffer
            var rtBlur = Shader.PropertyToID("_ObscuranceBlurTexture");

            // 1st blur iteration (large kernel)
            cb.GetTemporaryRT(rtBlur, tw, th, 0, filter, format, rwMode);
            cb.SetGlobalVector("_BlurVector", Vector2.right * 2);
            cb.Blit(rtMask, rtBlur, m, 4);
            cb.ReleaseTemporaryRT(rtMask);

            cb.GetTemporaryRT(rtMask, tw, th, 0, filter, format, rwMode);
            cb.SetGlobalVector("_BlurVector", Vector2.up * 2 * ts);
            cb.Blit(rtBlur, rtMask, m, 4);
            cb.ReleaseTemporaryRT(rtBlur);

            // 2nd blur iteration (small kernel)
            cb.GetTemporaryRT(rtBlur, tw, th, 0, filter, format, rwMode);
            cb.SetGlobalVector("_BlurVector", Vector2.right * ts);
            cb.Blit(rtMask, rtBlur, m, 6);
            cb.ReleaseTemporaryRT(rtMask);

            cb.GetTemporaryRT(rtMask, tw, th, 0, filter, format, rwMode);
            cb.SetGlobalVector("_BlurVector", Vector2.up * ts);
            cb.Blit(rtBlur, rtMask, m, 6);
            cb.ReleaseTemporaryRT(rtBlur);

            // Combine AO to the G-buffer.
            var mrt = new RenderTargetIdentifier[] {
                BuiltinRenderTextureType.GBuffer0,      // Albedo, Occ
                BuiltinRenderTextureType.CameraTarget   // Ambient
            };
            cb.SetGlobalTexture(rtMask, rtMask);
            cb.SetRenderTarget(mrt, BuiltinRenderTextureType.CameraTarget);
            cb.DrawMesh(_quadMesh, Matrix4x4.identity, m, 0, 8);

            cb.ReleaseTemporaryRT(rtMask);
        }

        // Execute the AO pass immediately (used in the forward mode).
        void ExecuteAOPass(RenderTexture source, RenderTexture destination)
        {
            var tw = source.width;
            var th = source.height;
            var ts = downsampling ? 2 : 1;
            var format = RenderTextureFormat.R8;
            var rwMode = RenderTextureReadWrite.Linear;
            var useGBuffer = occlusionSource == OcclusionSource.GBuffer;

            // AO buffer
            var m = aoMaterial;
            var rtMask = RenderTexture.GetTemporary(
                tw / ts, th / ts, 0, format, rwMode
            );

            // AO estimation
            Graphics.Blit(null, rtMask, m, (int)occlusionSource);

            // 1st blur iteration (large kernel)
            var rtBlur = RenderTexture.GetTemporary(tw, th, 0, format, rwMode);
            m.SetVector("_BlurVector", Vector2.right * 2);
            Graphics.Blit(rtMask, rtBlur, m, useGBuffer ? 4 : 3);
            RenderTexture.ReleaseTemporary(rtMask);

            rtMask = RenderTexture.GetTemporary(tw, th, 0, format, rwMode);
            m.SetVector("_BlurVector", Vector2.up * 2 * ts);
            Graphics.Blit(rtBlur, rtMask, m, useGBuffer ? 4 : 3);
            RenderTexture.ReleaseTemporary(rtBlur);

            // 2nd blur iteration (small kernel)
            rtBlur = RenderTexture.GetTemporary(tw, th, 0, format, rwMode);
            m.SetVector("_BlurVector", Vector2.right * ts);
            Graphics.Blit(rtMask, rtBlur, m, useGBuffer ? 6 : 5);
            RenderTexture.ReleaseTemporary(rtMask);

            rtMask = RenderTexture.GetTemporary(tw, th, 0, format, rwMode);
            m.SetVector("_BlurVector", Vector2.up * ts);
            Graphics.Blit(rtBlur, rtMask, m, useGBuffer ? 6 : 5);
            RenderTexture.ReleaseTemporary(rtBlur);

            // Combine AO with the source.
            m.SetTexture("_ObscuranceTexture", rtMask);
            Graphics.Blit(source, destination, m, 7);

            RenderTexture.ReleaseTemporary(rtMask);
        }

        // Update the common material properties.
        void UpdateMaterialProperties()
        {
            var m = aoMaterial;
            m.SetFloat("_Intensity", intensity);
            m.SetFloat("_Radius", radius);
            m.SetFloat("_TargetScale", downsampling ? 0.5f : 1);
            m.SetInt("_SampleCount", sampleCountValue);
        }

        #endregion

        #region MonoBehaviour Functions

        void OnEnable()
        {
            // Register the command buffer if in the ambient-only mode.
            if (ambientOnly) targetCamera.AddCommandBuffer(
                CameraEvent.BeforeReflections, aoCommands
            );

            // Enable depth textures which the occlusion source requires.
            if (occlusionSource == OcclusionSource.DepthTexture)
                targetCamera.depthTextureMode |= DepthTextureMode.Depth;

            if (occlusionSource != OcclusionSource.GBuffer)
                targetCamera.depthTextureMode |= DepthTextureMode.DepthNormals;
        }

        void OnDisable()
        {
            // Destroy all the temporary resources.
            if (_aoMaterial != null) DestroyImmediate(_aoMaterial);
            _aoMaterial = null;

            if (_aoCommands != null) targetCamera.RemoveCommandBuffer(
                CameraEvent.BeforeReflections, _aoCommands
            );
            _aoCommands = null;
        }

        void Update()
        {
            if (propertyObserver.CheckNeedsReset(this, targetCamera))
            {
                // Reinitialize all the resources by disabling/enabling itself.
                // This is not very efficient way but just works...
                OnDisable();
                OnEnable();

                // Build the command buffer if in the ambient-only mode.
                if (ambientOnly)
                {
                    aoCommands.Clear();
                    BuildAOCommands();
                }

                propertyObserver.Update(this, targetCamera);
            }

            // Update the material properties (later used in the AO commands).
            if (ambientOnly) UpdateMaterialProperties();
        }

        [ImageEffectOpaque]
        void OnRenderImage(RenderTexture source, RenderTexture destination)
        {
            if (ambientOnly)
            {
                // Do nothing in the ambient-only mode.
                Graphics.Blit(source, destination);
            }
            else
            {
                // Execute the AO pass.
                UpdateMaterialProperties();
                ExecuteAOPass(source, destination);
            }
        }

        #endregion
    }
}


text:
fileFormatVersion: 2
guid: d901ddf32d7c84ed4b0f84623ef3a7a0
timeCreated: 1456469754
licenseType: Pro
MonoImporter:
  serializedVersion: 2
  defaultReferences:
  - _aoShader: {fileID: 4800000, guid: 7541b5f18b1224a81927d8b1184b122b, type: 3}
  - _quadMesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:

repo_name: keijiro/KinoDatamosh

repo_language: C#

mime_type: text/plain


text:
fileFormatVersion: 2
guid: 8f6dbe2cc8ffe4604a9b907745b92da2
folderAsset: yes
timeCreated: 1455515619
licenseType: Pro
DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: 7dde330d3542e44209291a0fb4cf460e
folderAsset: yes
timeCreated: 1456726545
licenseType: Pro
DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: 5dce06de9574c40f782c3cdb4218f34e
folderAsset: yes
timeCreated: 1455515624
licenseType: Pro
DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: 150e73556e4cb49d7b7b6a41ada61e06
timeCreated: 1456723172
licenseType: Pro
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
//
// Kino/Obscurance - SSAO (screen-space ambient obscurance) effect for Unity
//
// Copyright (C) 2016 Keijiro Takahashi
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
using UnityEngine;

namespace Kino
{
    public partial class Obscurance : MonoBehaviour
    {
        // Observer class that detects changes on properties
        struct PropertyObserver
        {
            // Obscurance properties
            bool _downsampling;
            OcclusionSource _occlusionSource;
            bool _ambientOnly;

            // Camera properties
            int _pixelWidth;
            int _pixelHeight;

            // Check if it has to reset itself for property changes.
            public bool CheckNeedsReset(Obscurance target, Camera camera)
            {
                return
                    _downsampling != target.downsampling ||
                    _occlusionSource != target.occlusionSource ||
                    _ambientOnly != target.ambientOnly ||
                    _pixelWidth != camera.pixelWidth ||
                    _pixelHeight != camera.pixelHeight;
            }

            // Update the internal state.
            public void Update(Obscurance target, Camera camera)
            {
                _downsampling = target.downsampling;
                _occlusionSource = target.occlusionSource;
                _ambientOnly = target.ambientOnly;
                _pixelWidth = camera.pixelWidth;
                _pixelHeight = camera.pixelHeight;
            }
        }
    }
}


text:
//
// Kino/Obscurance - SSAO (screen-space ambient obscurance) effect for Unity
//
// Copyright (C) 2016 Keijiro Takahashi
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
using UnityEngine;
using UnityEditor;

namespace Kino
{
    [CanEditMultipleObjects]
    [CustomEditor(typeof(Obscurance))]
    public class ObscuranceEditor : Editor
    {
        SerializedProperty _intensity;
        SerializedProperty _radius;
        SerializedProperty _sampleCount;
        SerializedProperty _sampleCountValue;
        SerializedProperty _downsampling;
        SerializedProperty _occlusionSource;
        SerializedProperty _ambientOnly;

        static GUIContent _textValue = new GUIContent("Value");

        static string _textNoGBuffer =
            "G-buffer is currently unavailable. " +
            "Change Renderring Path in camera settings to Deferred.";

        static string _textNoAmbientOnly =
            "The ambient-only mode is currently disabled; " +
            "it requires G-buffer source and HDR rendering.";

        void OnEnable()
        {
            _intensity = serializedObject.FindProperty("_intensity");
            _radius = serializedObject.FindProperty("_radius");
            _sampleCount = serializedObject.FindProperty("_sampleCount");
            _sampleCountValue = serializedObject.FindProperty("_sampleCountValue");
            _downsampling = serializedObject.FindProperty("_downsampling");
            _occlusionSource = serializedObject.FindProperty("_occlusionSource");
            _ambientOnly = serializedObject.FindProperty("_ambientOnly");
        }

        public override void OnInspectorGUI()
        {
            var obscurance = (Obscurance)target;

            serializedObject.Update();

            EditorGUILayout.PropertyField(_intensity);
            EditorGUILayout.PropertyField(_radius);
            EditorGUILayout.PropertyField(_sampleCount);

            if (_sampleCount.hasMultipleDifferentValues ||
                _sampleCount.enumValueIndex == (int)Obscurance.SampleCount.Variable)
            {
                EditorGUI.indentLevel++;
                EditorGUILayout.PropertyField(_sampleCountValue, _textValue);
                EditorGUI.indentLevel--;
            }

            EditorGUILayout.PropertyField(_downsampling);
            EditorGUILayout.PropertyField(_occlusionSource);

            if (!_occlusionSource.hasMultipleDifferentValues)
                if (_occlusionSource.enumValueIndex != (int)obscurance.occlusionSource)
                    EditorGUILayout.HelpBox(_textNoGBuffer, MessageType.Warning);

            EditorGUILayout.PropertyField(_ambientOnly);

            if (!_ambientOnly.hasMultipleDifferentValues)
                if (_ambientOnly.boolValue != obscurance.ambientOnly)
                    EditorGUILayout.HelpBox(_textNoAmbientOnly, MessageType.Warning);

            serializedObject.ApplyModifiedProperties();
        }
    }
}


text:
fileFormatVersion: 2
guid: d4c34df7fb8f94f15bbe24c63dbe9df0
timeCreated: 1455515930
licenseType: Pro
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
//
// Kino/Obscurance - SSAO (screen-space ambient obscurance) effect for Unity
//
// Copyright (C) 2016 Keijiro Takahashi
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
Shader "Hidden/Kino/Obscurance"
{
    Properties
    {
        _MainTex("", 2D) = ""{}
        _ObscuranceTexture("", 2D) = ""{}
    }
    SubShader
    {
        // 0: Occlusion estimation with CameraDepthTexture
        Pass
        {
            ZTest Always Cull Off ZWrite Off
            CGPROGRAM
            #define SOURCE_DEPTH 1
            #include "Obscurance.cginc"
            #pragma vertex vert_img
            #pragma fragment frag_ao
            #pragma target 3.0
            ENDCG
        }
        // 1: Occlusion estimation with CameraDepthNormalsTexture
        Pass
        {
            ZTest Always Cull Off ZWrite Off
            CGPROGRAM
            #define SOURCE_DEPTHNORMALS 1
            #include "Obscurance.cginc"
            #pragma vertex vert_img
            #pragma fragment frag_ao
            #pragma target 3.0
            ENDCG
        }
        // 2: Occlusion estimation with G-Buffer
        Pass
        {
            ZTest Always Cull Off ZWrite Off
            CGPROGRAM
            #define SOURCE_GBUFFER 1
            #include "Obscurance.cginc"
            #pragma vertex vert_img
            #pragma fragment frag_ao
            #pragma target 3.0
            ENDCG
        }
        // 3: Noise reduction (first pass) with CameraDepthNormalsTexture
        Pass
        {
            ZTest Always Cull Off ZWrite Off
            CGPROGRAM
            #define SOURCE_DEPTHNORMALS 1
            #include "Obscurance.cginc"
            #pragma vertex vert_img
            #pragma fragment frag_blur1
            #pragma target 3.0
            ENDCG
        }
        // 4: Noise reduction (first pass) with G Buffer
        Pass
        {
            ZTest Always Cull Off ZWrite Off
            CGPROGRAM
            #define SOURCE_GBUFFER 1
            #include "Obscurance.cginc"
            #pragma vertex vert_img
            #pragma fragment frag_blur1
            #pragma target 3.0
            ENDCG
        }
        // 5: Noise reduction (second pass) with CameraDepthNormalsTexture
        Pass
        {
            ZTest Always Cull Off ZWrite Off
            CGPROGRAM
            #define SOURCE_DEPTHNORMALS 1
            #include "Obscurance.cginc"
            #pragma vertex vert_img
            #pragma fragment frag_blur2
            #pragma target 3.0
            ENDCG
        }
        // 6: Noise reduction (second pass) with G Buffer
        Pass
        {
            ZTest Always Cull Off ZWrite Off
            CGPROGRAM
            #define SOURCE_GBUFFER 1
            #include "Obscurance.cginc"
            #pragma vertex vert_img
            #pragma fragment frag_blur2
            #pragma target 3.0
            ENDCG
        }
        // 7: Occlusion combiner
        Pass
        {
            ZTest Always Cull Off ZWrite Off
            CGPROGRAM
            #include "Obscurance.cginc"
            #pragma vertex vert_multitex
            #pragma fragment frag_combine
            #pragma target 3.0
            ENDCG
        }
        // 8: Occlusion combiner for the ambient-only mode
        Pass
        {
            Blend Zero OneMinusSrcColor, Zero OneMinusSrcAlpha
            ZTest Always Cull Off ZWrite Off
            CGPROGRAM
            #include "Obscurance.cginc"
            #pragma vertex vert_gbuffer
            #pragma fragment frag_gbuffer_combine
            #pragma target 3.0
            ENDCG
        }
    }
}


text:
fileFormatVersion: 2
guid: 53ad5775ae0684d458bfbf2674b495e0
timeCreated: 1463548334
licenseType: Pro
ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: 7541b5f18b1224a81927d8b1184b122b
timeCreated: 1455515931
licenseType: Pro
ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:


text:
// Upgrade NOTE: commented out 'float4x4 _WorldToCamera', a built-in variable
// Upgrade NOTE: replaced '_WorldToCamera' with 'unity_WorldToCamera'

// --------
// Additional options for further customization
// --------

// By default, a fixed sampling pattern is used in the AO estimator.
// Although this gives preferable results in most cases, a completely
// random sampling pattern could give aesthetically good results in some
// cases. Comment out the line below to use the random pattern instead of
// the fixed one.
#define FIX_SAMPLING_PATTERN 1

// The constant below determines the contrast of occlusion. Altough this
// allows intentional over/under occlusion, currently is not exposed to the
// editor, because it’s thought to be rarely useful.
static const float kContrast = 0.6;

// The constant below controls the geometry-awareness of the blur filter.
// The higher value, the more sensitive it is.
static const float kGeometry = 50;

// The constants below are used in the AO estimator. Beta is mainly used
// for suppressing self-shadowing noise, and Epsilon is used to prevent
// calculation underflow. See the paper (Morgan 2011 http://goo.gl/2iz3P)
// for further details of these constants.
static const float kBeta = 0.002;
static const float kEpsilon = 1e-4;

// --------

#include "UnityCG.cginc"

// Global shader properties
sampler2D _CameraGBufferTexture2;
sampler2D_float _CameraDepthTexture;
sampler2D _CameraDepthNormalsTexture;
// float4x4 _WorldToCamera;

// Source texture properties
sampler2D _MainTex;
float4 _MainTex_TexelSize;
sampler2D _ObscuranceTexture;

// Material shader properties
int _SampleCount;
half _Intensity;
float _Radius;
float _TargetScale;
float2 _BlurVector;

// Utility for sin/cos
float2 CosSin(float theta)
{
    float sn, cs;
    sincos(theta, sn, cs);
    return float2(cs, sn);
}

// Gamma encoding function for AO value
// (do nothing if in the linear mode)
half EncodeAO(half x)
{
    // Gamma encoding
    half x_g = 1 - pow(1 - x, 1 / 2.2);
    // ColorSpaceLuminance.w is 0 (gamma) or 1 (linear).
    return lerp(x_g, x, unity_ColorSpaceLuminance.w);
}

// Pseudo random number generator with 2D argument
float UVRandom(float u, float v)
{
    float f = dot(float2(12.9898, 78.233), float2(u, v));
    return frac(43758.5453 * sin(f));
}

// Interleaved gradient function from Jimenez 2014 http://goo.gl/eomGso
float GradientNoise(float2 uv)
{
    uv = floor(uv * _ScreenParams.xy);
    float f = dot(float2(0.06711056f, 0.00583715f), uv);
    return frac(52.9829189f * frac(f));
}

// Boundary check for depth sampler
// (returns a very large value if it lies out of bounds)
float CheckBounds(float2 uv, float d)
{
    float ob = any(uv < 0) + any(uv > 1);
#if defined(UNITY_REVERSED_Z)
    ob += (d <= 0.00001);
#else
    ob += (d >= 0.99999);
#endif
    return ob * 1e8;
}

// Depth/normal sampling functions
float SampleDepth(float2 uv)
{
#if SOURCE_GBUFFER || SOURCE_DEPTH
    float d = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, uv);
    return LinearEyeDepth(d) + CheckBounds(uv, d);
#else
    float4 cdn = tex2D(_CameraDepthNormalsTexture, uv);
    float d = DecodeFloatRG(cdn.zw);
    return d * _ProjectionParams.z + CheckBounds(uv, d);
#endif
}

float3 SampleNormal(float2 uv)
{
#if SOURCE_GBUFFER
    float3 norm = tex2D(_CameraGBufferTexture2, uv).xyz * 2 - 1;
    return mul((float3x3)unity_WorldToCamera, norm);
#else
    float4 cdn = tex2D(_CameraDepthNormalsTexture, uv);
    return DecodeViewNormalStereo(cdn) * float3(1, 1, -1);
#endif
}

float SampleDepthNormal(float2 uv, out float3 normal)
{
#if SOURCE_GBUFFER || SOURCE_DEPTH
    normal = SampleNormal(uv);
    return SampleDepth(uv);
#else
    float4 cdn = tex2D(_CameraDepthNormalsTexture, uv);
    normal = DecodeViewNormalStereo(cdn) * float3(1, 1, -1);
    float d = DecodeFloatRG(cdn.zw);
    return d * _ProjectionParams.z + CheckBounds(uv, d);
#endif
}

// Reconstruct view-space position from UV and depth.
// p11_22 = (unity_CameraProjection._11, unity_CameraProjection._22)
// p13_31 = (unity_CameraProjection._13, unity_CameraProjection._23)
float3 ReconstructViewPos(float2 uv, float depth, float2 p11_22, float2 p13_31)
{
    return float3((uv * 2 - 1 - p13_31) / p11_22, 1) * depth;
}

// Normal vector comparer (for geometry-aware weighting)
half CompareNormal(half3 d1, half3 d2)
{
    return pow((dot(d1, d2) + 1) * 0.5, kGeometry);
}

// Final combiner function
half3 CombineObscurance(half3 src, half3 ao)
{
    return lerp(src, 0, EncodeAO(ao));
}

// Sample point picker
float3 PickSamplePoint(float2 uv, float index)
{
    // Uniformaly distributed points on a unit sphere http://goo.gl/X2F1Ho
#if FIX_SAMPLING_PATTERN
    float gn = GradientNoise(uv * _TargetScale);
    float u = frac(UVRandom(0, index) + gn) * 2 - 1;
    float theta = (UVRandom(1, index) + gn) * UNITY_PI * 2;
#else
    float u = UVRandom(uv.x + _Time.x, uv.y + index) * 2 - 1;
    float theta = UVRandom(-uv.x - _Time.x, uv.y + index) * UNITY_PI * 2;
#endif
    float3 v = float3(CosSin(theta) * sqrt(1 - u * u), u);
    // Make them distributed between [0, _Radius]
    float l = sqrt((index + 1) / _SampleCount) * _Radius;
    return v * l;
}

// Obscurance estimator function
float EstimateObscurance(float2 uv)
{
    // Parameters used in coordinate conversion
    float3x3 proj = (float3x3)unity_CameraProjection;
    float2 p11_22 = float2(unity_CameraProjection._11, unity_CameraProjection._22);
    float2 p13_31 = float2(unity_CameraProjection._13, unity_CameraProjection._23);

    // View space normal and depth
    float3 norm_o;
    float depth_o = SampleDepthNormal(uv, norm_o);

#if SOURCE_DEPTHNORMALS
    // Offset the depth value to avoid precision error.
    // (depth in the DepthNormals mode has only 16-bit precision)
    depth_o -= _ProjectionParams.z / 65536;
#endif

    // Reconstruct the view-space position.
    float3 vpos_o = ReconstructViewPos(uv, depth_o, p11_22, p13_31);

    // Distance-based AO estimator based on Morgan 2011 http://goo.gl/2iz3P
    float ao = 0.0;

    for (int s = 0; s < _SampleCount; s++)
    {
        // Sample point
#if SHADER_API_D3D11
        // This 'floor(1.0001 * s)' operation is needed to avoid a NVidia
        // shader issue. This issue is only observed on DX11.
        float3 v_s1 = PickSamplePoint(uv, floor(1.0001 * s));
#else
        float3 v_s1 = PickSamplePoint(uv, s);
#endif
        v_s1 = faceforward(v_s1, -norm_o, v_s1);
        float3 vpos_s1 = vpos_o + v_s1;

        // Reproject the sample point
        float3 spos_s1 = mul(proj, vpos_s1);
        float2 uv_s1 = (spos_s1.xy / vpos_s1.z + 1) * 0.5;

        // Depth at the sample point
        float depth_s1 = SampleDepth(uv_s1);

        // Relative position of the sample point
        float3 vpos_s2 = ReconstructViewPos(uv_s1, depth_s1, p11_22, p13_31);
        float3 v_s2 = vpos_s2 - vpos_o;

        // Estimate the obscurance value
        float a1 = max(dot(v_s2, norm_o) - kBeta * depth_o, 0);
        float a2 = dot(v_s2, v_s2) + kEpsilon;
        ao += a1 / a2;
    }

    ao *= _Radius; // intensity normalization

    // Apply other parameters.
    return pow(ao * _Intensity / _SampleCount, kContrast);
}

// Geometry-aware separable blur filter (large kernel)
half SeparableBlurLarge(sampler2D tex, float2 uv, float2 delta)
{
#if !SHADER_API_MOBILE
    // 9-tap Gaussian blur with adaptive sampling
    float2 uv1a = uv - delta;
    float2 uv1b = uv + delta;
    float2 uv2a = uv - delta * 2;
    float2 uv2b = uv + delta * 2;
    float2 uv3a = uv - delta * 3.2307692308;
    float2 uv3b = uv + delta * 3.2307692308;

    half3 n0 = SampleNormal(uv);

    half w0 = 0.37004405286;
    half w1a = CompareNormal(n0, SampleNormal(uv1a)) * 0.31718061674;
    half w1b = CompareNormal(n0, SampleNormal(uv1b)) * 0.31718061674;
    half w2a = CompareNormal(n0, SampleNormal(uv2a)) * 0.19823788546;
    half w2b = CompareNormal(n0, SampleNormal(uv2b)) * 0.19823788546;
    half w3a = CompareNormal(n0, SampleNormal(uv3a)) * 0.11453744493;
    half w3b = CompareNormal(n0, SampleNormal(uv3b)) * 0.11453744493;

    half s = tex2D(_MainTex, uv).r * w0;
    s += tex2D(_MainTex, uv1a).r * w1a;
    s += tex2D(_MainTex, uv1b).r * w1b;
    s += tex2D(_MainTex, uv2a).r * w2a;
    s += tex2D(_MainTex, uv2b).r * w2b;
    s += tex2D(_MainTex, uv3a).r * w3a;
    s += tex2D(_MainTex, uv3b).r * w3b;

    return s / (w0 + w1a + w1b + w2a + w2b + w3a + w3b);
#else
    // 9-tap Gaussian blur with linear sampling
    // (less quality but slightly fast)
    float2 uv1a = uv - delta * 1.3846153846;
    float2 uv1b = uv + delta * 1.3846153846;
    float2 uv2a = uv - delta * 3.2307692308;
    float2 uv2b = uv + delta * 3.2307692308;

    half3 n0 = SampleNormal(uv);

    half w0 = 0.2270270270;
    half w1a = CompareNormal(n0, SampleNormal(uv1a)) * 0.3162162162;
    half w1b = CompareNormal(n0, SampleNormal(uv1b)) * 0.3162162162;
    half w2a = CompareNormal(n0, SampleNormal(uv2a)) * 0.0702702703;
    half w2b = CompareNormal(n0, SampleNormal(uv2b)) * 0.0702702703;

    half s = tex2D(_MainTex, uv).r * w0;
    s += tex2D(_MainTex, uv1a).r * w1a;
    s += tex2D(_MainTex, uv1b).r * w1b;
    s += tex2D(_MainTex, uv2a).r * w2a;
    s += tex2D(_MainTex, uv2b).r * w2b;

    return s / (w0 + w1a + w1b + w2a + w2b);
#endif
}

// Geometry-aware separable blur filter (small kernel)
half SeparableBlurSmall(sampler2D tex, float2 uv, float2 delta)
{
    float2 uv1 = uv - delta;
    float2 uv2 = uv + delta;

    half3 n0 = SampleNormal(uv);

    half w0 = 2;
    half w1 = CompareNormal(n0, SampleNormal(uv1));
    half w2 = CompareNormal(n0, SampleNormal(uv2));

    half s = tex2D(_MainTex, uv).r * w0;
    s += tex2D(_MainTex, uv1).r * w1;
    s += tex2D(_MainTex, uv2).r * w2;

    return s / (w0 + w1 + w2);
}

// Pass 0: Obscurance estimation
half4 frag_ao(v2f_img i) : SV_Target
{
    return EstimateObscurance(i.uv);
}

// Pass 1: Geometry-aware separable blur (1st iteration)
half4 frag_blur1(v2f_img i) : SV_Target
{
    float2 delta = _MainTex_TexelSize.xy * _BlurVector;
    return SeparableBlurLarge(_MainTex, i.uv, delta);
}

// Pass 2: Geometry-aware separable blur (2nd iteration)
half4 frag_blur2(v2f_img i) : SV_Target
{
    float2 delta = _MainTex_TexelSize.xy * _BlurVector;
    return SeparableBlurSmall(_MainTex, i.uv, delta);
}

// Pass 3: Combiner for the forward mode
struct v2f_multitex
{
    float4 pos : SV_POSITION;
    float2 uv0 : TEXCOORD0;
    float2 uv1 : TEXCOORD1;
};

v2f_multitex vert_multitex(appdata_img v)
{
    // Handles vertically-flipped case.
    float vflip = sign(_MainTex_TexelSize.y);

    v2f_multitex o;
    o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    o.uv0 = v.texcoord.xy;
    o.uv1 = (v.texcoord.xy - 0.5) * float2(1, vflip) + 0.5;
    return o;
}

half4 frag_combine(v2f_multitex i) : SV_Target
{
    half4 src = tex2D(_MainTex, i.uv0);
    half ao = tex2D(_ObscuranceTexture, i.uv1).r;
    return half4(CombineObscurance(src.rgb, ao), src.a);
}

// Pass 4: Combiner for the ambient-only mode
v2f_img vert_gbuffer(appdata_img v)
{
    v2f_img o;
    o.pos = v.vertex * float4(2, 2, 0, 0) + float4(0, 0, 0, 1);
#if UNITY_UV_STARTS_AT_TOP
    o.uv = v.texcoord * float2(1, -1) + float2(0, 1);
#else
    o.uv = v.texcoord;
#endif
    return o;
}

#if !SHADER_API_GLES // excluding the MRT pass under GLES2

struct CombinerOutput
{
    half4 gbuffer0 : SV_Target0;
    half4 gbuffer3 : SV_Target1;
};

CombinerOutput frag_gbuffer_combine(v2f_img i)
{
    half ao = tex2D(_ObscuranceTexture, i.uv).r;
    CombinerOutput o;
    o.gbuffer0 = half4(0, 0, 0, ao);
    o.gbuffer3 = half4((half3)EncodeAO(ao), 0);
    return o;
}

#else

fixed4 frag_gbuffer_combine(v2f_img i) : SV_Target0
{
    return 0;
}

#endif


text:
fileFormatVersion: 2
guid: 33b7ee32b891649c9b34592a2f9518b9
folderAsset: yes
timeCreated: 1463486730
licenseType: Pro
DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:


text:
//
// Kino/Datamosh - Glitch effect simulating video compression artifacts
//
// Copyright (C) 2016 Keijiro Takahashi
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
using UnityEngine;

namespace Kino
{
    [RequireComponent(typeof(Camera))]
    public class Datamosh : MonoBehaviour
    {
        #region Public properties and methods

        /// Size of compression macroblock.
        public int blockSize {
            get { return Mathf.Max(4, _blockSize) ; }
            set { _blockSize = value; }
        }

        [SerializeField]
        [Tooltip("Size of compression macroblock.")]
        int _blockSize = 16;

        /// Entropy coefficient. The larger value makes the stronger noise.
        public float entropy {
            get { return _entropy; }
            set { _entropy = value; }
        }

        [SerializeField, Range(0, 1)]
        [Tooltip("Entropy coefficient. The larger value makes the stronger noise.")]
        float _entropy = 0.5f;

        /// Contrast of stripe-shaped noise.
        public float noiseContrast {
            get { return _noiseContrast; }
            set { _noiseContrast = value; }
        }

        [SerializeField, Range(0.5f, 4.0f)]
        [Tooltip("Contrast of stripe-shaped noise.")]
        float _noiseContrast = 1;

        /// Scale factor for velocity vectors.
        public float velocityScale {
            get { return _velocityScale; }
            set { _velocityScale = value; }
        }

        [SerializeField, Range(0, 2)]
        [Tooltip("Scale factor for velocity vectors.")]
        float _velocityScale = 0.8f;

        /// Amount of random displacement.
        public float diffusion {
            get { return _diffusion; }
            set { _diffusion = value; }
        }

        [SerializeField, Range(0, 2)]
        [Tooltip("Amount of random displacement.")]
        float _diffusion = 0.4f;

        /// Start glitching.
        public void Glitch()
        {
            _sequence = 1;
        }

        /// Stop glitching.
        public void Reset()
        {
            _sequence = 0;
        }

        #endregion

        #region Private properties

        [SerializeField]
        Shader _shader;

        Material _material;

        RenderTexture _workBuffer; // working buffer
        RenderTexture _dispBuffer; // displacement buffer

        int _sequence;
        int _lastFrame;

        RenderTexture NewWorkBuffer(RenderTexture source)
        {
            return RenderTexture.GetTemporary(source.width, source.height);
        }

        RenderTexture NewDispBuffer(RenderTexture source)
        {
            var rt = RenderTexture.GetTemporary(
                source.width / _blockSize,
                source.height / _blockSize,
                0, RenderTextureFormat.ARGBHalf
            );
            rt.filterMode = FilterMode.Point;
            return rt;
        }

        void ReleaseBuffer(RenderTexture buffer)
        {
            if (buffer != null) RenderTexture.ReleaseTemporary(buffer);
        }

        #endregion

        #region MonoBehaviour functions

        void OnEnable()
        {
            _material = new Material(Shader.Find("Hidden/Kino/Datamosh"));
            _material.hideFlags = HideFlags.DontSave;

            GetComponent<Camera>().depthTextureMode |=
                DepthTextureMode.Depth | DepthTextureMode.MotionVectors;

            _sequence = 0;
        }

        void OnDisable()
        {
            ReleaseBuffer(_workBuffer);
            _workBuffer = null;

            ReleaseBuffer(_dispBuffer);
            _dispBuffer = null;

            DestroyImmediate(_material);
            _material = null;
        }

        void OnRenderImage(RenderTexture source, RenderTexture destination)
        {
            _material.SetFloat("_BlockSize", _blockSize);
            _material.SetFloat("_Quality", 1 - _entropy);
            _material.SetFloat("_Contrast", _noiseContrast);
            _material.SetFloat("_Velocity", _velocityScale);
            _material.SetFloat("_Diffusion", _diffusion);

            if (_sequence == 0)
            {
                // Step 0: no effect, just keep the last frame.

                // Update the working buffer with the current frame.
                ReleaseBuffer(_workBuffer);
                _workBuffer = NewWorkBuffer(source);
                Graphics.Blit(source, _workBuffer);

                // Blit without effect.
                Graphics.Blit(source, destination);
            }
            else if (_sequence == 1)
            {
                // Step 1: start effect, no moshing.

                // Initialize the displacement buffer.
                ReleaseBuffer(_dispBuffer);
                _dispBuffer = NewDispBuffer(source);
                Graphics.Blit(null, _dispBuffer, _material, 0);

                // Simply blit the working buffer because motion vectors
                // might not be ready (because of camera switching).
                Graphics.Blit(_workBuffer, destination);

                _sequence++;
            }
            else
            {
                // Step 2: apply effect.

                if (Time.frameCount != _lastFrame)
                {
                    // Update the displaceent buffer.
                    var newDisp = NewDispBuffer(source);
                    Graphics.Blit(_dispBuffer, newDisp, _material, 1);
                    ReleaseBuffer(_dispBuffer);
                    _dispBuffer = newDisp;

                    // Moshing!
                    var newWork = NewWorkBuffer(source);
                    _material.SetTexture("_WorkTex", _workBuffer);
                    _material.SetTexture("_DispTex", _dispBuffer);
                    Graphics.Blit(source, newWork, _material, 2);
                    ReleaseBuffer(_workBuffer);
                    _workBuffer = newWork;

                    _lastFrame = Time.frameCount;
                }

                // Blit the result.
                Graphics.Blit(_workBuffer, destination);
            }
        }

        #endregion
    }
}


text:
fileFormatVersion: 2
guid: 9a84a8e36dc3847148680b51e5506967
folderAsset: yes
timeCreated: 1463486750
licenseType: Pro
DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: cdbbfa0d5bee14ea1bb3a8762969e899
timeCreated: 1463486917
licenseType: Pro
MonoImporter:
  serializedVersion: 2
  defaultReferences:
  - _shader: {fileID: 4800000, guid: 998cec7a45d274e3995fbccf2c4480bf, type: 3}
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: 697d6445d1d644b80a2a33f719a81a0c
folderAsset: yes
timeCreated: 1463843600
licenseType: Pro
DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: bb7881a14b4c94d52b2e5e77821e6c90
timeCreated: 1463843675
licenseType: Pro
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
//
// Kino/Datamosh - Glitch effect simulating video compression artifacts
//
// Copyright (C) 2016 Keijiro Takahashi
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
using UnityEngine;
using UnityEditor;

namespace Kino
{
    [CanEditMultipleObjects]
    [CustomEditor(typeof(Datamosh))]
    public class DatamoshEditor : Editor
    {
        SerializedProperty _blockSize;
        SerializedProperty _entropy;
        SerializedProperty _noiseContrast;
        SerializedProperty _velocityScale;
        SerializedProperty _diffusion;

        void OnEnable()
        {
            _blockSize = serializedObject.FindProperty("_blockSize");
            _entropy = serializedObject.FindProperty("_entropy");
            _noiseContrast = serializedObject.FindProperty("_noiseContrast");
            _velocityScale = serializedObject.FindProperty("_velocityScale");
            _diffusion = serializedObject.FindProperty("_diffusion");
        }

        public override void OnInspectorGUI()
        {
            serializedObject.Update();

            EditorGUILayout.PropertyField(_blockSize);
            EditorGUILayout.PropertyField(_entropy);
            EditorGUILayout.PropertyField(_noiseContrast);
            EditorGUILayout.PropertyField(_velocityScale);
            EditorGUILayout.PropertyField(_diffusion);

            serializedObject.ApplyModifiedProperties();

            EditorGUI.BeginDisabledGroup(!EditorApplication.isPlaying);

            if (GUILayout.Button("Glitch!"))
                foreach (Datamosh d in targets) d.Glitch();

            if (GUILayout.Button("Clear"))
                foreach (Datamosh d in targets) d.Reset();

            EditorGUI.EndDisabledGroup ();
        }
    }
}


text:
fileFormatVersion: 2
guid: 998cec7a45d274e3995fbccf2c4480bf
timeCreated: 1463486684
licenseType: Pro
ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:


text:
//
// Kino/Datamosh - Glitch effect simulating video compression artifacts
//
// Copyright (C) 2016 Keijiro Takahashi
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
Shader "Hidden/Kino/Datamosh"
{
    Properties
    {
        _MainTex("", 2D) = ""{}
        _WorkTex("", 2D) = ""{}
        _DispTex("", 2D) = ""{}
    }

    CGINCLUDE

    #include "UnityCG.cginc"

    sampler2D _MainTex;
    float4 _MainTex_TexelSize;

    sampler2D _WorkTex;
    float4 _WorkTex_TexelSize;

    sampler2D _DispTex;
    float4 _DispTex_TexelSize;

    sampler2D_half _CameraMotionVectorsTexture;
    float4 _CameraMotionVectorsTexture_TexelSize;

    float _BlockSize;
    float _Quality;
    float _Contrast;
    float _Velocity;
    float _Diffusion;

    // PRNG
    float UVRandom(float2 uv)
    {
        float f = dot(float2(12.9898, 78.233), uv);
        return frac(43758.5453 * sin(f));
    }

    // Vertex shader for multi texturing
    struct v2f_multitex
    {
        float4 pos : SV_POSITION;
        float2 uv0 : TEXCOORD0;
        float2 uv1 : TEXCOORD1;
    };

    v2f_multitex vert_multitex(appdata_full v)
    {
        v2f_multitex o;
        o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
        o.uv0 = v.texcoord.xy;
        o.uv1 = v.texcoord.xy;
    #if UNITY_UV_STARTS_AT_TOP
        if (_MainTex_TexelSize.y < 0.0)
            o.uv1.y = 1.0 - v.texcoord.y;
    #endif
        return o;
    }

    // Initialization shader
    half4 frag_init(v2f_img i) : SV_Target
    {
        return 0;
    }

    // Displacement buffer updating shader
    half4 frag_update(v2f_img i) : SV_Target
    {
        float2 uv = i.uv;
        float2 t0 = float2(_Time.y, 0);

        // Random numbers
        float3 rand = float3(
            UVRandom(uv + t0.xy),
            UVRandom(uv + t0.yx),
            UVRandom(uv.yx - t0.xx)
        );

        // Motion vector
        half2 mv = tex2D(_CameraMotionVectorsTexture, uv).rg;
        mv *= _Velocity;

        // Normalized screen space -> Pixel coordinates
        mv = mv * _ScreenParams.xy;

        // Small random displacement (diffusion)
        mv += (rand.xy - 0.5) * _Diffusion;

        // Pixel perfect snapping
        mv = round(mv);

        // Accumulates the amount of motion.
        half acc = tex2D(_MainTex, i.uv).a;
        half mv_len = length(mv);
        // - Simple update
        half acc_update = acc + min(mv_len, _BlockSize) * 0.005;
        acc_update += rand.z * lerp(-0.02, 0.02, _Quality);
        // - Reset to random level
        half acc_reset = rand.z * 0.5 + _Quality;
        // - Reset if the amount of motion is larger than the block size.
        acc = saturate(mv_len > _BlockSize ? acc_reset : acc_update);

        // Pixel coordinates -> Normalized screen space
        mv *= (_ScreenParams.zw - 1);

        // Random number (changing by motion)
        half mrand = UVRandom(uv + mv_len);

        return half4(mv, mrand, acc);
    }

    // Moshing shader
    half4 frag_mosh(v2f_multitex i) : SV_Target
    {
        // Color from the original image
        half4 src = tex2D(_MainTex, i.uv1);

        // Displacement vector (x, y, random, acc)
        half4 disp = tex2D(_DispTex, i.uv0);

        // Color from the working buffer (slightly scaled to make it blurred)
        half3 work = tex2D(_WorkTex, i.uv1 - disp.xy * 0.98).rgb;

        // Generate some pseudo random numbers.
        float4 rand = frac(float4(1, 17.37135, 841.4272, 3305.121) * disp.z);

        // Generate noise patterns that look like DCT bases.
        // - Frequency
        float2 uv = i.uv1 * _DispTex_TexelSize.zw * (rand.x * 80 / _Contrast);
        // - Basis wave (vertical or horizontal)
        float dct = cos(lerp(uv.x, uv.y, 0.5 < rand.y));
        // - Random amplitude (the high freq, the less amp)
        dct *= rand.z * (1 - rand.x) * _Contrast;

        // Conditional weighting
        // - DCT-ish noise: acc > 0.5
        float cw = (disp.w > 0.5) * dct;
        // - Original image: rand < (Q * 0.8 + 0.2) && acc == 1.0
        cw = lerp(cw, 1, rand.w < lerp(0.2, 1, _Quality) * (disp.w > 0.999));
        // - If the conditions above are not met, choose work.

        return half4(lerp(work, src.rgb, cw), src.a);
    }

    ENDCG

    SubShader
    {
        Cull Off ZWrite Off ZTest Always
        Pass
        {
            CGPROGRAM
            #pragma vertex vert_img
            #pragma fragment frag_init
            #pragma target 3.0
            ENDCG
        }
        Pass
        {
            CGPROGRAM
            #pragma vertex vert_img
            #pragma fragment frag_update
            #pragma target 3.0
            ENDCG
        }
        Pass
        {
            CGPROGRAM
            #pragma vertex vert_multitex
            #pragma fragment frag_mosh
            #pragma target 3.0
            ENDCG
        }
    }
}


text:
fileFormatVersion: 2
guid: b04e253fd90e09646b7032c3100d8444
folderAsset: yes
timeCreated: 1452843621
licenseType: Pro
DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: fb9dc05a19a2fad4caf8b1a87a2c484c
folderAsset: yes
timeCreated: 1452843589
licenseType: Pro
DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: 0965c0a5f97c14e31a16959dd1103305
folderAsset: yes
timeCreated: 1452484574
licenseType: Pro
DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: af303efbcda15c14abef72a3a904c771
folderAsset: yes
timeCreated: 1452843633
licenseType: Pro
DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: fb3fa56e3b2454553aef859ff356d123
timeCreated: 1452500661
licenseType: Pro
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: 419a4d015120b054b8e817a78d3e4712
timeCreated: 1452781280
licenseType: Pro
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
//
// Klak - Utilities for creative coding with Unity
//
// Copyright (C) 2016 Keijiro Takahashi
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
using UnityEngine;
using UnityEditor;
using System.IO;

namespace Klak
{
    public class ImageSequenceWindow : EditorWindow
    {
        #region Private Variables

        // recorder settings
        int _frameRate = 30;
        int _superSampling = 1;
        bool _autoRecord;

        // recorder state
        bool _isRecording;
        int _frameCount;
        int _previousFrame;

        #endregion

        #region Recorder Functions

        void InitializeRecorder()
        {
            _isRecording = false;
            if (_autoRecord) StartRecord();
        }

        void StartRecord()
        {
            _frameCount = -1;
            _isRecording = true;
        }

        void EndRecord()
        {
            Time.captureFramerate = 0;
            _isRecording = false;
        }

        void StepRecorder()
        {
            if (_frameCount == 0)
            {
                Directory.CreateDirectory("Capture");
                Time.captureFramerate = _frameRate;
            }
            else if (_frameCount > 0)
            {
                var name = "Capture/frame" + _frameCount.ToString("0000") + ".png";
                Application.CaptureScreenshot(name, _superSampling);
            }
            _frameCount++;
        }

        #endregion

        #region EditorWindow Functions

        [MenuItem ("Window/Image Sequence")]
        static void Init()
        {
            var instance = CreateInstance<ImageSequenceWindow>();
            instance.minSize = instance.maxSize =
                new Vector2(20, 6) * EditorGUIUtility.singleLineHeight;
            instance.titleContent = new GUIContent("Image Sequence");
            instance.ShowUtility();
        }

        void OnEnable()
        {
            EditorApplication.playmodeStateChanged += OnPlaymodeChanged;
        }

        void OnDisable()
        {
            EditorApplication.playmodeStateChanged -= OnPlaymodeChanged;
        }

        void OnPlaymodeChanged()
        {
            // detecting a start of the play mode
            if (!Application.isPlaying && EditorApplication.isPlayingOrWillChangePlaymode)
                InitializeRecorder();
            Repaint();
        }

        void OnGUI()
        {
            _frameRate = EditorGUILayout.IntSlider("Frame Rate", _frameRate, 1, 120);
            _superSampling = EditorGUILayout.IntSlider("Supersampling", _superSampling, 1, 4);
            _autoRecord = EditorGUILayout.Toggle("Auto Recording", _autoRecord);

            if (EditorApplication.isPlaying)
            {
                var fatButton = GUILayout.Height(30);

                if (!_isRecording)
                {
                    if (GUILayout.Button("REC", fatButton)) StartRecord();
                }
                else
                {
                    var time = (float)_frameCount / _frameRate;
                    var label = "STOP  (" + time.ToString("0.0") + "s)";
                    if (GUILayout.Button(label, fatButton)) EndRecord();
                }
            }
        }

        void Update()
        {
            var frame = Time.frameCount;
            if (_previousFrame != frame)
            {
                if (Application.isPlaying && _isRecording)
                {
                    StepRecorder();
                    Repaint();
                }
                _previousFrame = frame;
            }
        }

        #endregion
    }
}


text:
//
// Klak - Utilities for creative coding with Unity
//
// Copyright (C) 2016 Keijiro Takahashi
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
using UnityEngine;
using UnityEditor;

namespace Klak
{
    public static class GUIHelper
    {
        public static void ShowInputValueNote()
        {
            EditorGUILayout.HelpBox(
                "Receives float values from the inputValue property.",
                MessageType.None);
        }
    }
}


text:
//
// Klak - Utilities for creative coding with Unity
//
// Copyright (C) 2016 Keijiro Takahashi
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
using UnityEngine;

namespace Klak.Math
{
    static class BasicMath
    {
        public static float Lerp(float a, float b, float mix)
        {
            return a * (1 - mix) + b * mix;
        }
        public static Vector3 Lerp(Vector3 a, Vector3 b, float mix)
        {
            return a * (1 - mix) + b * mix;
        }
    }
}


text:
//
// Klak - Utilities for creative coding with Unity
//
// Copyright (C) 2016 Keijiro Takahashi
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
using UnityEngine;
using Klak.VectorMathExtension;

namespace Klak.Math
{
    /// Exponential interpolation
    static class ETween
    {
        #region Static Functions

        public static float Step(
            float current, float target, float omega)
        {
            var exp = Mathf.Exp(-omega * Time.deltaTime);
            return Mathf.Lerp(target, current, exp);
        }

        public static float StepAngle(
            float current, float target, float omega)
        {
            var exp = Mathf.Exp(-omega * Time.deltaTime);
            var delta = Mathf.DeltaAngle(current, target);
            return target - delta * exp;
        }

        public static Vector3 Step(
            Vector3 current, Vector3 target, float omega)
        {
            var exp = Mathf.Exp(-omega * Time.deltaTime);
            return Vector3.Lerp(target, current, exp);
        }

        public static Quaternion Step(
            Quaternion current, Quaternion target, float omega)
        {
            if (current == target) return target;
            var exp = Mathf.Exp(-omega * Time.deltaTime);
            return Quaternion.Lerp(target, current, exp);

        }

        #endregion
    }

    /// Interpolation with critically damped spring model
    struct DTween
    {
        #region Static Functions

        public static float Step(
            float current, float target, ref float velocity, float omega)
        {
            var dt = Time.deltaTime;
            var n1 = velocity - (current - target) * (omega * omega * dt);
            var n2 = 1 + omega * dt;
            velocity = n1 / (n2 * n2);
            return current + velocity * dt;
        }

        public static Vector2 Step(
            Vector2 current, Vector2 target, ref Vector2 velocity, float omega)
        {
            var dt = Time.deltaTime;
            var n1 = velocity - (current - target) * (omega * omega * dt);
            var n2 = 1 + omega * dt;
            velocity = n1 / (n2 * n2);
            return current + velocity * dt;
        }

        public static Vector3 Step(
            Vector3 current, Vector3 target, ref Vector3 velocity, float omega)
        {
            var dt = Time.deltaTime;
            var n1 = velocity - (current - target) * (omega * omega * dt);
            var n2 = 1 + omega * dt;
            velocity = n1 / (n2 * n2);
            return current + velocity * dt;
        }

        public static Vector4 Step(
            Vector4 current, Vector4 target, ref Vector4 velocity, float omega)
        {
            var dt = Time.deltaTime;
            var n1 = velocity - (current - target) * (omega * omega * dt);
            var n2 = 1 + omega * dt;
            velocity = n1 / (n2 * n2);
            return current + velocity * dt;
        }

        public static Quaternion Step(
            Quaternion current, Quaternion target,
            ref Vector4 velocity, float omega)
        {
            var vcurrent = current.ToVector4();
            var vtarget = target.ToVector4();
            // We can use either of vtarget/-vtarget. Use closer one.
            if (Vector4.Dot(vcurrent, vtarget) < 0) vtarget = -vtarget;
            var dt = Time.deltaTime;
            var n1 = velocity - (vcurrent - vtarget) * (omega * omega * dt);
            var n2 = 1 + omega * dt;
            velocity = n1 / (n2 * n2);
            return (vcurrent + velocity * dt).ToNormalizedQuaternion();
        }

        #endregion

        #region Struct Implementation

        public float position;
        public float velocity;
        public float omega;

        public DTween(float position, float omega)
        {
            this.position = position;
            this.velocity = 0;
            this.omega = omega;
        }

        public void Step(float target)
        {
            position = Step(position, target, ref velocity, omega);
        }

        public static implicit operator float(DTween m)
        {
            return m.position;
        }

        #endregion
    }

    /// Interpolation with critically damped spring model
    struct DTweenVector2
    {
        public Vector2 position;
        public Vector2 velocity;
        public float omega;

        public DTweenVector2(Vector2 position, float omega)
        {
            this.position = position;
            this.velocity = Vector2.zero;
            this.omega = omega;
        }

        public void Step(Vector2 target)
        {
            position = DTween.Step(position, target, ref velocity, omega);
        }

        public static implicit operator Vector2(DTweenVector2 m)
        {
            return m.position;
        }
    }

    /// Interpolation with critically damped spring model
    struct DTweenVector3
    {
        public Vector3 position;
        public Vector3 velocity;
        public float omega;

        public DTweenVector3(Vector3 position, float omega)
        {
            this.position = position;
            this.velocity = Vector3.zero;
            this.omega = omega;
        }

        public void Step(Vector3 target)
        {
            position = DTween.Step(position, target, ref velocity, omega);
        }

        public static implicit operator Vector3(DTweenVector3 m)
        {
            return m.position;
        }
    }

    /// Interpolation with critically damped spring model
    struct DTweenQuaternion
    {
        public Quaternion rotation;
        public Vector4 velocity;
        public float omega;

        public DTweenQuaternion(Quaternion rotation, float omega)
        {
            this.rotation = rotation;
            this.velocity = Vector4.zero;
            this.omega = omega;
        }

        public void Step(Quaternion target)
        {
            rotation = DTween.Step(rotation, target, ref velocity, omega);
        }

        public static implicit operator Quaternion(DTweenQuaternion m)
        {
            return m.rotation;
        }
    }
}


text:
//
// Klak - Utilities for creative coding with Unity
//
// Copyright (C) 2016 Keijiro Takahashi
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
using UnityEngine;
using System;

namespace Klak.Math
{
    public struct FloatInterpolator
    {
        #region Nested Public Classes

        [Serializable]
        public class Config
        {
            public enum InterpolationType {
                Direct, Exponential, DampedSpring
            }

            [SerializeField]
            InterpolationType _interpolationType
                = InterpolationType.DampedSpring;

            public InterpolationType interpolationType {
                get { return _interpolationType; }
                set { _interpolationType = value; }
            }

            public bool enabled {
                get { return interpolationType != InterpolationType.Direct; }
            }

            [SerializeField, Range(0.1f, 50)]
            float _interpolationSpeed = 5;

            public float interpolationSpeed {
                get { return _interpolationSpeed; }
                set { _interpolationSpeed = value; }
            }
        }

        #endregion

        #region Private Members

        float _velocity;

        #endregion

        #region Public Properties And Methods

        public Config config { get; set; }
        public float currentValue { get; set; }
        public float targetValue { get; set; }

        public FloatInterpolator(float initialValue, Config config)
        {
            this.config = config;
            currentValue = targetValue =initialValue;
            _velocity = 0;
        }

        public float Step(float targetValue)
        {
            this.targetValue = targetValue;
            return Step();
        }

        public float Step()
        {
            if (config.interpolationType == Config.InterpolationType.Exponential)
            {
                currentValue = ETween.Step(
                    currentValue, targetValue, config.interpolationSpeed);
            }
            else if (config.interpolationType == Config.InterpolationType.DampedSpring)
            {
                currentValue = DTween.Step(
                    currentValue, targetValue, ref _velocity, config.interpolationSpeed);
            }
            else
            {
                currentValue = targetValue;
            }
            return currentValue;
        }

        #endregion
    }
}


text:
fileFormatVersion: 2
guid: a93c590d9dab4415eadb92e108635e30
timeCreated: 1453562143
licenseType: Pro
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: a20dd3f543e39e84583729e6e93c2911
timeCreated: 1452744639
licenseType: Pro
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: f8d594ef0c2194bfcbb842c19f8df85d
timeCreated: 1452474839
licenseType: Pro
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: fd47a5ebc73153e49b3e170cb40b85e3
folderAsset: yes
timeCreated: 1452853831
licenseType: Pro
DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: eb737738c6d26ed4891ed48e364e1041
timeCreated: 1452747941
licenseType: Pro
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
//
// Klak - Utilities for creative coding with Unity
//
// Copyright (C) 2016 Keijiro Takahashi
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
using UnityEngine;
using UnityEditor;

namespace Klak.Math
{
    using Config = FloatInterpolator.Config;

    [CustomPropertyDrawer(typeof(Config))]
    class FloatInterpolatorConfigDrawer : PropertyDrawer
    {
        static GUIContent _textSpeed = new GUIContent("Speed");

        bool CheckShouldExpand(SerializedProperty property)
        {
            var type = property.FindPropertyRelative("_interpolationType");
            return type.hasMultipleDifferentValues ||
                type.enumValueIndex != (int)Config.InterpolationType.Direct;
        }

        public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
        {
            var lineHeight = EditorGUIUtility.singleLineHeight;
            var lineSpace = EditorGUIUtility.standardVerticalSpacing;
            return CheckShouldExpand(property) ?
                lineHeight * 2 + lineSpace : lineHeight;
        }

        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            EditorGUI.BeginProperty(position, label, property);

            const int indentWidth = 16;
            var lineHeight = EditorGUIUtility.singleLineHeight;
            var lineSpace = EditorGUIUtility.standardVerticalSpacing;

            // these controls have single line height
            position.height = lineHeight;

            // interpolation type
            var type = property.FindPropertyRelative("_interpolationType");
            EditorGUI.PropertyField(position, type, label);

            if (CheckShouldExpand(property))
            {
                // indent the line
                position.width -= indentWidth;
                position.x += indentWidth;
                EditorGUIUtility.labelWidth -= indentWidth;

                // go to the next line
                position.y += lineHeight + lineSpace;

                // interpolation speed
                var speed = property.FindPropertyRelative("_interpolationSpeed");
                EditorGUI.PropertyField(position, speed, _textSpeed);
            }

            EditorGUI.EndProperty();
        }
    }
}


text:
//
// Klak - Utilities for creative coding with Unity
//
// Copyright (C) 2016 Keijiro Takahashi
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
using UnityEngine;

namespace Klak.VectorMathExtension
{
    /// Extension methods for Vector4
    static class Vector4Extension
    {
        public static Quaternion ToQuaternion(this Vector4 v)
        {
            return new Quaternion(v.x, v.y, v.z, v.w);
        }

        public static Quaternion ToNormalizedQuaternion(this Vector4 v)
        {
            v = Vector4.Normalize(v);
            return new Quaternion(v.x, v.y, v.z, v.w);
        }
    }

    /// Extension methods for Quaternion
    static class QuaternionExtension
    {
        public static Vector4 ToVector4(this Quaternion q)
        {
            return new Vector4(q.x, q.y, q.z, q.w);
        }
    }
}


text:
fileFormatVersion: 2
guid: b10930df277854f43b411412e91f9bf3
timeCreated: 1452477818
licenseType: Pro
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: e04f5e50cd25d4df6ad5fe43d1f88cca
timeCreated: 1452473647
licenseType: Pro
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
fileFormatVersion: 2
guid: 5f2b8436fbb9bd045ab8bdccf8490ae1
folderAsset: yes
timeCreated: 1452853741
licenseType: Pro
DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:


text:
//
// Klak - Utilities for creative coding with Unity
//
// Copyright (C) 2016 Keijiro Takahashi
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
using UnityEngine;
using Klak.Math;
using Klak.VectorMathExtension;

namespace Klak.Motion
{
    /// Follows a given transform smoothly
    [AddComponentMenu("Klak/Motion/Smooth Follow")]
    public class SmoothFollow : MonoBehaviour
    {
        #region Nested Classes

        public enum Interpolator {
            Exponential, Spring, DampedSpring
        }

        #endregion

        #region Editable Properties

        [SerializeField]
        Interpolator _interpolator = Interpolator.DampedSpring;

        [SerializeField]
        Transform _target;

        [SerializeField, Range(0, 10)]
        float _positionSpeed = 2;

        [SerializeField, Range(0, 10)]
        float _rotationSpeed = 2;

        [SerializeField]
        float _jumpDistance = 1;

        [SerializeField, Range(0, 360)]
        float _jumpAngle = 60;

        #endregion

        #region Public Properties And Methods

        public Interpolator interpolationType {
            get { return _interpolator; }
            set { _interpolator = value; }
        }

        public Transform target {
            get { return _target; }
            set { _target = value; }
        }

        public float positionSpeed {
            get { return _positionSpeed; }
            set { _positionSpeed = value; }
        }

        public float rotationSpeed {
            get { return _rotationSpeed; }
            set { _rotationSpeed = value; }
        }

        public float jumpDistance {
            get { return _jumpDistance; }
            set { _jumpDistance = value; }
        }

        public float jumpAngle {
            get { return _jumpAngle; }
            set { _jumpAngle = value; }
        }

        public void Snap()
        {
            if (_positionSpeed > 0) transform.position = target.position;
            if (_rotationSpeed > 0) transform.rotation = target.rotation;
        }

        public void JumpRandomly()
        {
            var r1 = Random.Range(0.5f, 1.0f);
            var r2 = Random.Range(0.5f, 1.0f);

            var dp = Random.onUnitSphere * _jumpDistance * r1;
            var dr = Quaternion.AngleAxis(_jumpAngle * r2, Random.onUnitSphere);

            transform.position = dp + target.position;
            transform.rotation = dr * target.rotation;
        }

        #endregion

        #region Private Properties And Functions

        Vector3 _vposition;
        Vector4 _vrotation;

        Vector3 SpringPosition(Vector3 current, Vector3 target)
        {
            _vposition = ETween.Step(_vposition, Vector3.zero, 1 + _positionSpeed * 0.5f);
            _vposition += (target - current) * (_positionSpeed * 0.1f);
            return current + _vposition * Time.deltaTime;
        }

        Quaternion SpringRotation(Quaternion current, Quaternion target)
        {
            var v_current = current.ToVector4();
            var v_target = target.ToVector4();
            _vrotation = ETween.Step(_vrotation, Vector4.zero, 1 + _rotationSpeed * 0.5f);
            _vrotation += (v_target - v_current) * (_rotationSpeed * 0.1f);
            return (v_current + _vrotation * Time.deltaTime).ToNormalizedQuaternion();
        }

        #endregion

        #region MonoBehaviour Functions

        void Update()
        {
            if (_interpolator == Interpolator.Exponential)
            {
                if (_positionSpeed > 0)
                    transform.position = ETween.Step(transform.position, target.position, _positionSpeed);
                if (_rotationSpeed > 0)
                    transform.rotation = ETween.Step(transform.rotation, target.rotation, _rotationSpeed);
            }
            else if (_interpolator == Interpolator.DampedSpring)
            {
                if (_positionSpeed > 0)
                    transform.position = DTween.Step(transform.position, target.position, ref _vposition, _positionSpeed);
                if (_rotationSpeed > 0)
                    transform.rotation = DTween.Step(transform.rotation, target.rotation, ref _vrotation, _rotationSpeed);
            }
            else
            {
                if (_positionSpeed > 0)
                    transform.position = SpringPosition(transform.position, target.position);
                if (_rotationSpeed > 0)
                    transform.rotation = SpringRotation(transform.rotation, target.rotation);
            }
        }

        #endregion
    }
}


text:
fileFormatVersion: 2
guid: 3975fff25a95a4a7cb28c27879976139
timeCreated: 1452484574
licenseType: Pro
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:


text:
//
// Klak - Utilities for creative coding with Unity
//
// Copyright (C) 2016 Keijiro Takahashi
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
using UnityEngine;
using UnityEditor;

namespace Klak.Motion
{
    [CanEditMultipleObjects]
    [CustomEditor(typeof(SmoothFollow))]
    public class SmoothFollowEditor : Editor
    {
        SerializedProperty _interpolator;
        SerializedProperty _target;
        SerializedProperty _positionSpeed;
        SerializedProperty _rotationSpeed;
        SerializedProperty _jumpDistance;
        SerializedProperty _jumpAngle;

        static GUIContent _textAngle = new GUIContent("Angle");
        static GUIContent _textDistance = new GUIContent("Distance");
        static GUIContent _textPosition = new GUIContent("Position");
        static GUIContent _textRotation = new GUIContent("Rotation");

        void OnEnable()
        {
            _interpolator = serializedObject.FindProperty("_interpolator");
            _target = serializedObject.FindProperty("_target");
            _positionSpeed = serializedObject.FindProperty("_positionSpeed");
            _rotationSpeed = serializedObject.FindProperty("_rotationSpeed");
            _jumpDistance = serializedObject.FindProperty("_jumpDistance");
            _jumpAngle = serializedObject.FindProperty("_jumpAngle");
        }

        public override void OnInspectorGUI()
        {
            serializedObject.Update();

            EditorGUILayout.PropertyField(_interpolator);
            EditorGUILayout.PropertyField(_target);

            EditorGUILayout.Space();

            EditorGUILayout.LabelField("Interpolation Speed", EditorStyles.boldLabel);
            EditorGUILayout.PropertyField(_positionSpeed, _textPosition);
            EditorGUILayout.PropertyField(_rotationSpeed, _textRotation);

            EditorGUILayout.Space();

            EditorGUILayout.LabelField("Random Jump", EditorStyles.boldLabel);
            EditorGUILayout.PropertyField(_jumpDistance, _textDistance);
            EditorGUILayout.PropertyField(_jumpAngle, _textAngle);

            if (EditorApplication.isPlaying && GUILayout.Button("Jump!"))
                foreach (SmoothFollow sf in targets)
                    sf.JumpRandomly();

            serializedObject.ApplyModifiedProperties();
        }
    }
}


text:
fileFormatVersion: 2
guid: 256db47c217b946e7bc54577f52b732e
timeCreated: 1463907917
licenseType: Pro
TextScriptImporter:
  userData:
  assetBundleName:
  assetBundleVariant: