Search Unity

[FREE] Stochastic Screen Space Reflection

Discussion in 'Assets and Asset Store' started by Charkes, Nov 6, 2016.

  1. Charkes

    Charkes

    Joined:
    Apr 17, 2013
    Posts:
    228
    Last edited: Nov 26, 2016
    Rowlan, TooManySugar, Mauri and 17 others like this.
  2. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Awesome! more reading here (and why isn't it baseline in Unity?!)
     
    hopeful and Charkes like this.
  3. Charkes

    Charkes

    Joined:
    Apr 17, 2013
    Posts:
    228
    Thanks @hippocoder !

    I've made small update and also change the git structure.

    Now it's a project with a sample scene.

    There's also a package containing the effect only.
     
  4. Luckymouse

    Luckymouse

    Joined:
    Jan 31, 2010
    Posts:
    484
    Hey Charkes, seems you like the SSR effect a lot ;), glad to see you have new SSR for unity.
    However I tested on my mac in unity editor 5.4.2 and it doesn't work as expected. In editor mode, there have no SSR effect, in play mode it rendered completely black. I got neither script or shader error in the editor, so i don't have a clue why it is not working.
    Here is the screenshot.
    SSR_EditorMode.png SSR_PlayMode.png
     
    Last edited: Nov 14, 2016
  5. kenshin

    kenshin

    Joined:
    Apr 21, 2010
    Posts:
    940
    very interesting, thanks for sharing!!!
     
    Charkes likes this.
  6. Charkes

    Charkes

    Joined:
    Apr 17, 2013
    Posts:
    228
    Yeah I like SSR :).

    About mac support, it's expected.

    I've made an update just a minute ago, let me know if it works.

    EDIT : Editor mode will be added later.
     
  7. StaffanEk

    StaffanEk

    Joined:
    Jul 13, 2012
    Posts:
    380
    Thank you very much for your work Charkes.

    This should be included in the new unity effect stack.
     
    Charkes likes this.
  8. Luckymouse

    Luckymouse

    Joined:
    Jan 31, 2010
    Posts:
    484
    I see you added #pragma glsl in the shader, unlike unity 4.x, it is no longer used in unity 5. So I got same result.
     
  9. Charkes

    Charkes

    Joined:
    Apr 17, 2013
    Posts:
    228
    I wasn't aware of that. I don't have a mac around for testing, it's going to be tricky. What happend if you disable these options : Ray reuse, mipmap and temporal ?
     
  10. Luckymouse

    Luckymouse

    Joined:
    Jan 31, 2010
    Posts:
    484
    It seems disabled the mipmap that made more obvious different than other option in combine debug pass, which less black area. However disabled mipmap did not make too much different in other debug pass. in general that disabled Ray reuse and temporal mades only small different. The artifact is still there.
    Here is the animated gif to show the debug passes:
    Stochastic_SSR_Mac.gif

    My old macbook can only do openGL3.3, I don't know it is because of my graphic card that is too old. Not sure if it happens in other newer macs.
     
    Last edited: Nov 14, 2016
  11. Charkes

    Charkes

    Joined:
    Apr 17, 2013
    Posts:
    228
    From what I see, it looks like the previous frame reprojection don't work well here (Not used in debug pass). I'll figured out why.

    Can you try this :

    Code (CSharp):
    1. //The MIT License(MIT)
    2.  
    3. //Copyright(c) 2016 Charles Greivelding Thomas
    4.  
    5. //Permission is hereby granted, free of charge, to any person obtaining a copy
    6. //of this software and associated documentation files (the "Software"), to deal
    7. //in the Software without restriction, including without limitation the rights
    8. //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    9. //copies of the Software, and to permit persons to whom the Software is
    10. //furnished to do so, subject to the following conditions:
    11.  
    12. //The above copyright notice and this permission notice shall be included in all
    13. //copies or substantial portions of the Software.
    14.  
    15. //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    16. //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    17. //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    18. //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    19. //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    20. //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    21. //SOFTWARE.
    22.  
    23. using System.Collections;
    24. using System.Collections.Generic;
    25. using UnityEngine;
    26. using UnityEngine.Rendering;
    27.  
    28. namespace cCharkes
    29. {
    30.     [System.Serializable]
    31.     public enum ResolutionMode
    32.     {
    33.         halfRes = 2,
    34.         fullRes = 1,
    35.     };
    36.  
    37.     [System.Serializable]
    38.     public enum SSRDebugPass
    39.     {
    40.         Combine,
    41.         Reflection,
    42.         Cubemap,
    43.         ReflectionAndCubemap,
    44.         SSRMask,
    45.         CombineNoCubemap,
    46.         RayCast,
    47.         Jitter,
    48.     };
    49.  
    50.     [RequireComponent(typeof(Camera))]
    51.     [AddComponentMenu("cCharkes/Image Effects/Rendering/Stochastic Screen Space Reflection")]
    52.     public class StochasticSSR : MonoBehaviour
    53.     {
    54.         Vector4 debug;
    55.  
    56.         [Header("RayCast")]
    57.         [SerializeField]
    58.         ResolutionMode depthMode = ResolutionMode.halfRes;
    59.  
    60.         [SerializeField]
    61.         ResolutionMode rayMode = ResolutionMode.halfRes;
    62.  
    63.         //[SerializeField]
    64.         FilterMode rayFilterMode = FilterMode.Bilinear;
    65.  
    66.         [Range(1, 100)]
    67.         [SerializeField]
    68.         int rayDistance = 70;
    69.  
    70.         [Range(0.0f, 1.0f)]
    71.         [SerializeField]
    72.         float BRDFBias = 0.7f;
    73.  
    74.         //[SerializeField]
    75.         Texture noise;
    76.  
    77.         [Header("Resolve")]
    78.         [SerializeField]
    79.         ResolutionMode resolveMode = ResolutionMode.fullRes;
    80.  
    81.         [SerializeField]
    82.         bool rayReuse = true;
    83.  
    84.         [SerializeField]
    85.         bool normalization = true;
    86.  
    87.         [SerializeField]
    88.         bool reduceFireflies = true;
    89.  
    90.         [SerializeField]
    91.         bool useMipMap = true;
    92.  
    93.         //[SerializeField]
    94.         int maxMipMap = 5;
    95.  
    96.         [Header("Temporal")]
    97.         [SerializeField]
    98.         bool useTemporal = true;
    99.  
    100.         [SerializeField]
    101.         float scale = 2.0f;
    102.  
    103.         [Range(0.0f, 1.0f)]
    104.         [SerializeField]
    105.         float minResponse = 0.85f;
    106.  
    107.         [Range(0.0f, 1.0f)]
    108.         [SerializeField]
    109.         float maxResponse = 0.95f;
    110.  
    111.         [Header("General")]
    112.         [SerializeField]
    113.         bool useFresnel = true;
    114.  
    115.         [Range(0.0f, 1.0f)]
    116.         [SerializeField]
    117.         float screenFadeSize = 0.25f;
    118.  
    119.         [Header("Debug")]
    120.  
    121.         [Range(0.0f, 1.0f)]
    122.         [SerializeField]
    123.         float smoothnessRange = 1.0f;
    124.  
    125.         public SSRDebugPass debugPass = SSRDebugPass.Combine;
    126.  
    127.         Camera m_camera;
    128.  
    129.         private Matrix4x4 projectionMatrix;
    130.         private Matrix4x4 viewProjectionMatrix;
    131.         private Matrix4x4 inverseViewProjectionMatrix;
    132.         private Matrix4x4 worldToCameraMatrix;
    133.         private Matrix4x4 cameraToWorldMatrix;
    134.  
    135.         private Matrix4x4 prevViewProjectionMatrix;
    136.  
    137.         RenderTexture temporalBuffer;
    138.  
    139.         RenderTexture mainBuffer0, mainBuffer1;
    140.         RenderTexture mipMapBuffer0, mipMapBuffer1, mipMapBuffer2;
    141.  
    142.         RenderBuffer[] renderBuffer = new RenderBuffer[2];
    143.  
    144.         float[] dist = new float[5] { 1.0f / 1024.0f, 1.0f / 256.0f, 1.0f / 128.0f, 1.0f / 64.0f, 1.0f / 32.0f };
    145.  
    146.         int[] mipLevel = new int[5] { 0, 2, 3, 4, 5 };
    147.  
    148.         void Awake()
    149.         {
    150.  
    151.             noise = Resources.Load("tex_BlueNoise_256x256_UNI") as Texture2D;
    152.             m_camera = GetComponent<Camera>();
    153.             m_camera.depthTextureMode |= DepthTextureMode.Depth | DepthTextureMode.MotionVectors;
    154.         }
    155.  
    156.         static Material m_rendererMaterial = null;
    157.         protected Material rendererMaterial
    158.         {
    159.             get
    160.             {
    161.                 if (m_rendererMaterial == null)
    162.                 {
    163.                     m_rendererMaterial = new Material(Shader.Find("Hidden/Stochastic SSR"));
    164.                     m_rendererMaterial.hideFlags = HideFlags.DontSave;
    165.                 }
    166.                 return m_rendererMaterial;
    167.             }
    168.         }
    169.  
    170.         public static RenderTexture CreateRenderTexture(int w, int h, int d, RenderTextureFormat f, bool useMipMap, bool generateMipMap, FilterMode filterMode)
    171.         {
    172.             RenderTexture r = new RenderTexture(w, h, d, f);
    173.             r.filterMode = filterMode;
    174.             r.useMipMap = useMipMap;
    175.             r.generateMips = generateMipMap;
    176.             r.Create();
    177.             return r;
    178.         }
    179.  
    180.         void OnDestroy()
    181.         {
    182.             Object.DestroyImmediate(rendererMaterial);
    183.         }
    184.  
    185.         void OnDisable()
    186.         {
    187.             ReleaseRenderTargets();
    188.         }
    189.  
    190.         void ReleaseRenderTargets()
    191.         {
    192.  
    193.             if (temporalBuffer != null)
    194.             {
    195.                 temporalBuffer.Release();
    196.                 temporalBuffer = null;
    197.             }
    198.  
    199.             if (mainBuffer0 != null || mainBuffer1 != null)
    200.             {
    201.                 mainBuffer0.Release();
    202.                 mainBuffer0 = null;
    203.                 mainBuffer1.Release();
    204.                 mainBuffer1 = null;
    205.             }
    206.  
    207.             if (mipMapBuffer0 != null)
    208.             {
    209.                 mipMapBuffer0.Release();
    210.                 mipMapBuffer0 = null;
    211.             }
    212.         }
    213.  
    214.         void UpdateRenderTargets(int width, int height)
    215.         {
    216.             if (temporalBuffer != null && temporalBuffer.width != width)
    217.             {
    218.                 ReleaseRenderTargets();
    219.             }
    220.  
    221.             if (temporalBuffer == null || !temporalBuffer.IsCreated())
    222.             {
    223.                 temporalBuffer = CreateRenderTexture(width, height, 0, RenderTextureFormat.ARGBHalf, false, false, FilterMode.Bilinear);
    224.  
    225.             }
    226.  
    227.             if (mainBuffer0 == null || !mainBuffer0.IsCreated())
    228.             {
    229.                 mainBuffer0 = CreateRenderTexture(width, height, 0, RenderTextureFormat.DefaultHDR, false, false, FilterMode.Bilinear);
    230.                 mainBuffer1 = CreateRenderTexture(width, height, 0, RenderTextureFormat.DefaultHDR, false, false, FilterMode.Bilinear);
    231.             }
    232.  
    233.             if (mipMapBuffer0 == null || !mipMapBuffer0.IsCreated())
    234.             {
    235.                 mipMapBuffer0 = CreateRenderTexture(1024, 1024, 0, RenderTextureFormat.DefaultHDR, true, true, FilterMode.Bilinear); // Need to be power of two
    236.                 mipMapBuffer1 = CreateRenderTexture(1024, 1024, 0, RenderTextureFormat.DefaultHDR, true, true, FilterMode.Bilinear); // Need to be power of two
    237.                 mipMapBuffer2 = CreateRenderTexture(1024, 1024, 0, RenderTextureFormat.DefaultHDR, true, false, FilterMode.Bilinear); // Need to be power of two
    238.             }
    239.         }
    240.  
    241.         void UpdateVariable()
    242.         {
    243.             rendererMaterial.SetTexture("_Noise", noise);
    244.             rendererMaterial.SetVector("_NoiseSize", new Vector2(noise.width, noise.height));
    245.             rendererMaterial.SetFloat("_BRDFBias", BRDFBias);
    246.             rendererMaterial.SetFloat("_SmoothnessRange", smoothnessRange);
    247.             rendererMaterial.SetFloat("_EdgeFactor", screenFadeSize);
    248.             rendererMaterial.SetInt("_NumSteps", rayDistance);
    249.  
    250.             if (!rayReuse)
    251.                 rendererMaterial.SetInt("_RayReuse", 0);
    252.             else
    253.                 rendererMaterial.SetInt("_RayReuse", 1);
    254.  
    255.             if (!normalization)
    256.                 rendererMaterial.SetInt("_UseNormalization", 0);
    257.             else
    258.                 rendererMaterial.SetInt("_UseNormalization", 1);
    259.  
    260.             if (!useFresnel)
    261.                 rendererMaterial.SetInt("_UseFresnel", 0);
    262.             else
    263.                 rendererMaterial.SetInt("_UseFresnel", 1);
    264.  
    265.             if (!useTemporal)
    266.                 rendererMaterial.SetInt("_UseTemporal", 0);
    267.             else
    268.                 rendererMaterial.SetInt("_UseTemporal", 1);
    269.  
    270.             if (!reduceFireflies)
    271.                 rendererMaterial.SetInt("_Fireflies", 0);
    272.             else
    273.                 rendererMaterial.SetInt("_Fireflies", 1);
    274.  
    275.             switch (debugPass)
    276.             {
    277.                 case SSRDebugPass.Combine:
    278.                     rendererMaterial.SetInt("_DebugPass", 0);
    279.                     break;
    280.                 case SSRDebugPass.Reflection:
    281.                     rendererMaterial.SetInt("_DebugPass", 1);
    282.                     break;
    283.                 case SSRDebugPass.Cubemap:
    284.                     rendererMaterial.SetInt("_DebugPass", 2);
    285.                     break;
    286.                 case SSRDebugPass.ReflectionAndCubemap:
    287.                     rendererMaterial.SetInt("_DebugPass", 3);
    288.                     break;
    289.                 case SSRDebugPass.SSRMask:
    290.                     rendererMaterial.SetInt("_DebugPass", 4);
    291.                     break;
    292.                 case SSRDebugPass.CombineNoCubemap:
    293.                     rendererMaterial.SetInt("_DebugPass", 5);
    294.                     break;
    295.                 case SSRDebugPass.RayCast:
    296.                     rendererMaterial.SetInt("_DebugPass", 6);
    297.                     break;
    298.                 case SSRDebugPass.Jitter:
    299.                     rendererMaterial.SetInt("_DebugPass", 7);
    300.                     break;
    301.             }
    302.         }
    303.  
    304.         void UpdatePrevMatrices(RenderTexture source, RenderTexture destination)
    305.         {
    306.             worldToCameraMatrix = m_camera.worldToCameraMatrix;
    307.             cameraToWorldMatrix = worldToCameraMatrix.inverse;
    308.  
    309.             projectionMatrix = GL.GetGPUProjectionMatrix(m_camera.projectionMatrix, false);
    310.             viewProjectionMatrix = projectionMatrix * worldToCameraMatrix;
    311.             inverseViewProjectionMatrix = viewProjectionMatrix.inverse;
    312.  
    313.             rendererMaterial.SetMatrix("_ProjectionMatrix", projectionMatrix);
    314.             rendererMaterial.SetMatrix("_ViewProjectionMatrix", viewProjectionMatrix);
    315.             rendererMaterial.SetMatrix("_InverseProjectionMatrix", projectionMatrix.inverse);
    316.             rendererMaterial.SetMatrix("_InverseViewProjectionMatrix", inverseViewProjectionMatrix);
    317.             rendererMaterial.SetMatrix("_WorldToCameraMatrix", worldToCameraMatrix);
    318.             rendererMaterial.SetMatrix("_CameraToWorldMatrix", cameraToWorldMatrix);
    319.  
    320.             rendererMaterial.SetMatrix("_PrevViewProjectionMatrix", prevViewProjectionMatrix);
    321.             rendererMaterial.SetMatrix("_PrevInverseViewProjectionMatrix", prevViewProjectionMatrix * Matrix4x4.Inverse(viewProjectionMatrix));
    322.         }
    323.  
    324.         RenderTexture CreateTempBuffer(int x, int y, int depth, RenderTextureFormat format)
    325.         {
    326.             return RenderTexture.GetTemporary(x, y, depth, format);
    327.         }
    328.  
    329.         void ReleaseTempBuffer(RenderTexture rt)
    330.         {
    331.             RenderTexture.ReleaseTemporary(rt);
    332.         }
    333.  
    334.         [ImageEffectOpaque]
    335.         void OnRenderImage(RenderTexture source, RenderTexture destination)
    336.         {
    337.             int width = m_camera.pixelWidth;
    338.             int height = m_camera.pixelHeight;
    339.  
    340.             UpdatePrevMatrices(source, destination);
    341.             UpdateRenderTargets(width, height);
    342.             UpdateVariable();
    343.  
    344.             int rayWidth = width / (int)rayMode;
    345.             int rayHeight = height / (int)rayMode;
    346.             debug = new Vector4(width, height, m_camera.nearClipPlane / (m_camera.nearClipPlane - m_camera.farClipPlane), 0.0f);
    347.             rendererMaterial.SetVector("_Project", debug);
    348.             rendererMaterial.SetVector("_RayCastSize", new Vector2((float)rayWidth, (float)rayHeight));
    349.  
    350.             RenderTexture rayCast = CreateTempBuffer(rayWidth, rayHeight, 0, RenderTextureFormat.ARGBHalf);
    351.             RenderTexture rayCastMask = CreateTempBuffer(rayWidth, rayHeight, 0, RenderTextureFormat.RHalf);
    352.             RenderTexture depthBuffer = CreateTempBuffer(width / (int)depthMode, height / (int)depthMode, 0, RenderTextureFormat.RFloat);
    353.             rayCast.filterMode = rayFilterMode;
    354.             depthBuffer.filterMode = FilterMode.Point;
    355.  
    356.             rendererMaterial.SetTexture("_RayCast", rayCast);
    357.             rendererMaterial.SetTexture("_RayCastMask", rayCastMask);
    358.             rendererMaterial.SetTexture("_CameraDepthBuffer", depthBuffer);
    359.  
    360.             // Depth Buffer
    361.             Graphics.SetRenderTarget(depthBuffer);
    362.             rendererMaterial.SetPass(4);
    363.             DrawFullScreenQuad();
    364.             ReleaseTempBuffer(depthBuffer);
    365.             //
    366.  
    367.             switch (debugPass)
    368.             {
    369.                 case SSRDebugPass.Reflection:
    370.                 case SSRDebugPass.Cubemap:
    371.                 case SSRDebugPass.CombineNoCubemap:
    372.                 case SSRDebugPass.RayCast:
    373.                 case SSRDebugPass.ReflectionAndCubemap:
    374.                 case SSRDebugPass.SSRMask:
    375.                 case SSRDebugPass.Jitter:
    376.                 case SSRDebugPass.Combine:
    377.                     Graphics.Blit(source, mainBuffer0, rendererMaterial, 1);
    378.                     break;
    379.                 /*case SSRDebugPass.Combine:
    380.                     Graphics.Blit(mainBuffer1, mainBuffer0, rendererMaterial, 8);
    381.                     break;*/
    382.             }
    383.  
    384.             // Raycast pass
    385.             renderBuffer[0] = rayCast.colorBuffer;
    386.             renderBuffer[1] = rayCastMask.colorBuffer;
    387.             Graphics.SetRenderTarget(renderBuffer, rayCast.depthBuffer);
    388.             rendererMaterial.SetPass(3);
    389.             DrawFullScreenQuad();
    390.             //
    391.  
    392.             int resolveWidth = width / (int)resolveMode;
    393.             int resolveHeight = height / (int)resolveMode;
    394.  
    395.             RenderTexture resolvePass = CreateTempBuffer(resolveWidth, resolveHeight, 0, RenderTextureFormat.ARGBHalf);
    396.  
    397.             rendererMaterial.SetVector("_BufferSize", new Vector2((float)rayWidth, (float)rayHeight));
    398.             rendererMaterial.SetInt("_MaxMipMap", maxMipMap);
    399.  
    400.             if (useMipMap)
    401.             {
    402.                 Graphics.Blit(mainBuffer0, mipMapBuffer0); // Copy the source frame buffer to the mip map buffer
    403.  
    404.                 for (int i = 0; i < maxMipMap; i++)
    405.                 {
    406.                     rendererMaterial.SetVector("_GaussianDir", dist[i] * new Vector2(1.0f, 0.0f));
    407.                     rendererMaterial.SetInt("_MipMapCount", mipLevel[i]);
    408.                     Graphics.Blit(mipMapBuffer0, mipMapBuffer1, rendererMaterial, 6);
    409.  
    410.                     rendererMaterial.SetVector("_GaussianDir", dist[i] * new Vector2(0.0f, 1.0f));
    411.                     rendererMaterial.SetInt("_MipMapCount", mipLevel[i]);
    412.                     Graphics.Blit(mipMapBuffer1, mipMapBuffer0, rendererMaterial, 6);
    413.  
    414.                     Graphics.SetRenderTarget(mipMapBuffer2, i);
    415.                     DrawFullScreenQuad();
    416.                 }
    417.  
    418.                 Graphics.Blit(mipMapBuffer2, resolvePass, rendererMaterial, 0); // Resolve pass using mip map buffer
    419.             }
    420.             else
    421.             {
    422.                 Graphics.Blit(mainBuffer0, resolvePass, rendererMaterial, 0); // Resolve pass without mip map buffer
    423.             }
    424.  
    425.             rendererMaterial.SetTexture("_ReflectionBuffer", resolvePass);
    426.  
    427.             ReleaseTempBuffer(rayCast);
    428.             ReleaseTempBuffer(rayCastMask);
    429.  
    430.             if (useTemporal)
    431.             {
    432.                 rendererMaterial.SetFloat("_TScale", scale);
    433.                 rendererMaterial.SetFloat("_TMinResponse", minResponse);
    434.                 rendererMaterial.SetFloat("_TMaxResponse", maxResponse);
    435.  
    436.                 RenderTexture temporalBuffer0 = CreateTempBuffer(width, height, 0, RenderTextureFormat.ARGBHalf);
    437.  
    438.                 rendererMaterial.SetTexture("_PreviousBuffer", temporalBuffer);
    439.  
    440.                 Graphics.Blit(resolvePass, temporalBuffer0, rendererMaterial, 5); // Temporal pass
    441.  
    442.                 rendererMaterial.SetTexture("_ReflectionBuffer", temporalBuffer0);
    443.  
    444.                 Graphics.Blit(temporalBuffer0, temporalBuffer);
    445.  
    446.                 ReleaseTempBuffer(temporalBuffer0);
    447.             }
    448.  
    449.             switch(debugPass)
    450.             {
    451.                 case SSRDebugPass.Reflection:
    452.                 case SSRDebugPass.Cubemap:
    453.                 case SSRDebugPass.CombineNoCubemap:
    454.                 case SSRDebugPass.RayCast:
    455.                 case SSRDebugPass.ReflectionAndCubemap:
    456.                 case SSRDebugPass.SSRMask:
    457.                 case SSRDebugPass.Jitter:
    458.                 case SSRDebugPass.Combine:
    459.                     Graphics.Blit(source, destination, rendererMaterial, 2);
    460.                     break;
    461.                 /*case SSRDebugPass.Combine:
    462.                     Graphics.Blit(source, mainBuffer1, rendererMaterial, 2);
    463.                     Graphics.Blit(mainBuffer1, destination);
    464.                     break;*/
    465.             }
    466.  
    467.             ReleaseTempBuffer(resolvePass);
    468.  
    469.             prevViewProjectionMatrix = viewProjectionMatrix;
    470.         }
    471.  
    472.         public void DrawFullScreenQuad()
    473.         {
    474.             GL.PushMatrix();
    475.             GL.LoadOrtho();
    476.  
    477.             GL.Begin(GL.QUADS);
    478.             GL.MultiTexCoord2(0, 0.0f, 0.0f);
    479.             GL.Vertex3(0.0f, 0.0f, 0.0f); // BL
    480.  
    481.             GL.MultiTexCoord2(0, 1.0f, 0.0f);
    482.             GL.Vertex3(1.0f, 0.0f, 0.0f); // BR
    483.  
    484.             GL.MultiTexCoord2(0, 1.0f, 1.0f);
    485.             GL.Vertex3(1.0f, 1.0f, 0.0f); // TR
    486.  
    487.             GL.MultiTexCoord2(0, 0.0f, 1.0f);
    488.             GL.Vertex3(0.0f, 1.0f, 0.0f); // TL
    489.  
    490.             GL.End();
    491.             GL.PopMatrix();
    492.         }
    493.     }
    494. }
    495.  
    Copy past this in StochasticSSR.cs (replace everything), it will disable the first free bounce.

    Let me know if it's working.
     
  12. Luckymouse

    Luckymouse

    Joined:
    Jan 31, 2010
    Posts:
    484
    After replaced the codes, It seems working much better, right now it just got some little black dots/noise when temporal is on, turn off the temporal seems removed all that little black dots. Good job!
    Stochastic_SSR_Mac_fix1.png
     
  13. Charkes

    Charkes

    Joined:
    Apr 17, 2013
    Posts:
    228
    Ok great. For black dots, it must be a nan I left somewhere. Thanks !
     
  14. Reanimate_L

    Reanimate_L

    Joined:
    Oct 10, 2009
    Posts:
    2,788
    i agree with @hippocoder, this is actually better and more performant than the current built in ssr imo.
    ping @Chman :D

    On second thought, performance are the same, but still looks better especially for reflection in rough surfaces
     
    Last edited: Nov 22, 2016
    arcturgray and Charkes like this.
  15. Charkes

    Charkes

    Joined:
    Apr 17, 2013
    Posts:
    228
    @rea glad you liked it. I've made some updates on GitHub and BitBucket.

    Linear for bluenoise
    Fixed cone for mip map selection
    Added scene view support (has issues)


    Known issues :

    No MAC support.
    Not working in scene view if DepthTextureMode.MotionVectors is used by any script attached to the camera.
    Half res depth shows artefact with a low clipping plane.
    Blue noise animation pattern too visible.
     
    arcturgray and Reanimate_L like this.
  16. Reanimate_L

    Reanimate_L

    Joined:
    Oct 10, 2009
    Posts:
    2,788
    Nice, btw it seems your SSR doesn't work quite well with post process stack.
    Sometimes i'm getting black screen randomly
     
  17. Charkes

    Charkes

    Joined:
    Apr 17, 2013
    Posts:
    228
    Damn I thought I fixed that, I'm not sure exactly what is causing this.

    Was it with my test scene or yours ?
     
  18. Reanimate_L

    Reanimate_L

    Joined:
    Oct 10, 2009
    Posts:
    2,788
    Both, seems happen more often if the eye adaptation effect from PPstack are active.
     
  19. Charkes

    Charkes

    Joined:
    Apr 17, 2013
    Posts:
    228
    I may have found the problem, something related to some temp RT I'm using, they got lost rendomly. Will update in a few minutes.

    EDIT : I've updated the repo, hope it's fixed, it is on my side.
     
    Last edited: Nov 26, 2016
    Syberam and Reanimate_L like this.
  20. Charkes

    Charkes

    Joined:
    Apr 17, 2013
    Posts:
    228
    See some lovely reflection shots :





     
    Luckymouse, hopeful, Martin_H and 2 others like this.
  21. Charkes

    Charkes

    Joined:
    Apr 17, 2013
    Posts:
    228
    I can't figured out how to make it work properly in scene view. Getting previous frame (both for temporal and bounce) is problematic. I must be doing something really wrong there.

    So I've let scene view working but, temporal and bounce reflection is not enabled unless you hit play.

    The view is noisy of course but at least you have some feedbacks.

    If someone has as an idea please let me know. ( @Chman and @Aras :) ? )
     
    Crossway and Martin_H like this.
  22. Reanimate_L

    Reanimate_L

    Joined:
    Oct 10, 2009
    Posts:
    2,788
    I think that how it is at the moment, afaik motion blur and TAA are not working in scene view
     
  23. Charkes

    Charkes

    Joined:
    Apr 17, 2013
    Posts:
    228
    Ok, do you know any fix or others who has same issue ?
     
  24. Martin_H

    Martin_H

    Joined:
    Jul 11, 2015
    Posts:
    4,436
    This looks pretty promising! I have a question: will this work at long viewdistances? E.g. in an RTS where the cam might be 600 meters away from the geometry, or flight sims or stuff like that. The SSR solution in the official post effects stack currently doesn't work well for me because of some (hard coded?) distance limitations.
     
  25. Charkes

    Charkes

    Joined:
    Apr 17, 2013
    Posts:
    228
    I think it will happend too on mine, pixels at far distance get so tiny that they become hard to sample and it get worse when mip map are enabled in the options.

    If you do full res raytrace it will be better but slower.

    But I didn't tested much on long viewdistance. Let me know if you do.
     
    Martin_H likes this.
  26. Martin_H

    Martin_H

    Joined:
    Jul 11, 2015
    Posts:
    4,436
    I gave it a quick try and it does seem to work fine with the long viewdistance. Very nice! However I have so few shiny surfaces in my scene, that it probably isn't worth the performance cost to have any kind of SSR, compared to other effects I could be using, like a second layer of SSAO or more particle effects.

    Thanks a lot for sharing your work!
     
  27. Charkes

    Charkes

    Joined:
    Apr 17, 2013
    Posts:
    228
    Good to know :) !

    I think this ssr is usefull when you have lot of surfaces variations, it plays really nice in scene, but if you have mainly just rough surfaces then I agree it's probably not worth it.

    My pleasure !
     
    Martin_H likes this.
  28. Kolyasisan

    Kolyasisan

    Joined:
    Feb 2, 2015
    Posts:
    397
    Hi, really liked your SSR solution. But I have a question. Unity's SSR can reflect backfaces to approximately fill the gaps (Pic 1), yet this one doesn't (Pic 2). Are we going to get this feature? Or am I doing something wrong?
     

    Attached Files:

    • 1.PNG
      1.PNG
      File size:
      1.2 MB
      Views:
      1,418
    • 2.PNG
      2.PNG
      File size:
      1.2 MB
      Views:
      1,261
    Last edited: Dec 6, 2016
  29. Charkes

    Charkes

    Joined:
    Apr 17, 2013
    Posts:
    228
    Hi,

    It's totally expected actually (you don't do anything wrong :)). I'm rewriting my raymarch code which will hopefully support this but can't say when.

    Thanks !
     
    punk likes this.
  30. Reanimate_L

    Reanimate_L

    Joined:
    Oct 10, 2009
    Posts:
    2,788
    your ssr surprisingly works nicely for water :D
    upload_2017-1-11_1-47-24.png
     
  31. Charkes

    Charkes

    Joined:
    Apr 17, 2013
    Posts:
    228
    I guess you made you water as deferred to make it work with it ?

    Really nice !
     
  32. Reanimate_L

    Reanimate_L

    Joined:
    Oct 10, 2009
    Posts:
    2,788
    Thanks, Yep it totally deferred water.
     
  33. Charkes

    Charkes

    Joined:
    Apr 17, 2013
    Posts:
    228
    Cool, I've made similar shader some time ago, but I missed too much my edge fade and refraction so I revert back to forward :).

    Would love to see a vidéo of your water with ssr btw.
     
  34. Reanimate_L

    Reanimate_L

    Joined:
    Oct 10, 2009
    Posts:
    2,788
    i can relate to that, still struggling with depth buffer at the moment
     
    Charkes likes this.
  35. Reanimate_L

    Reanimate_L

    Joined:
    Oct 10, 2009
    Posts:
    2,788
    indirectly related, and i swear i'll stop spamming your thread :D
    i find a way on how to handle multiple depth buffer from multiple camera, and the clue are exactly in your ssr code, it's basically how you handle depth buffer :D
    upload_2017-1-14_21-18-28.png
     
  36. Charkes

    Charkes

    Joined:
    Apr 17, 2013
    Posts:
    228
    That's ok it has the benefit of keeping the thread alive :).

    Well done !
     
    Martin_H likes this.
  37. Reanimate_L

    Reanimate_L

    Joined:
    Oct 10, 2009
    Posts:
    2,788
    well then if you don't mind :)
    thanks to you i'm now have a good start to create full deferred water with multiple depth support :)
    which mean deferred effect and soft particle can interact with it :)
    screenshot below are without the displacement
    upload_2017-1-14_23-45-33.png
    ohh. . . and it receive shadow :D
     
  38. Reanimate_L

    Reanimate_L

    Joined:
    Oct 10, 2009
    Posts:
    2,788
    @Charkes
    i found a weird problem
    Far
    upload_2017-1-16_1-21-42.png
    Close to object
    upload_2017-1-16_1-22-19.png
    problem gone without your ssr
     
    SirTwistedStorm likes this.
  39. Charkes

    Charkes

    Joined:
    Apr 17, 2013
    Posts:
    228
    Hey @rea can you give me more details ?

    Maybe a screen of the ssr in the inspector, also is there any other image effects in use ?

    Also what is your hardware specs ?
     
  40. Reanimate_L

    Reanimate_L

    Joined:
    Oct 10, 2009
    Posts:
    2,788
    i use PostProcessing stack on top of the SSR, but even toggling it on and off doesn't affect it.
    my specs are 16gb ram, i5, gtx660tioc
    oh i have to disable atm it due that exact problem
    upload_2017-1-16_22-57-0.png
     
    Last edited: Jan 16, 2017
  41. Charkes

    Charkes

    Joined:
    Apr 17, 2013
    Posts:
    228
    Did you try to use half res for Ray and Depth Mode ? Full Res is maybe a bit gpu intense considering your GPU.

    Edit : And my raytrace is also slow.
     
  42. Reanimate_L

    Reanimate_L

    Joined:
    Oct 10, 2009
    Posts:
    2,788
    Yeah i'm moving to half res for those, also disable the mipmap usage increase the performance.
     
  43. Kolyasisan

    Kolyasisan

    Joined:
    Feb 2, 2015
    Posts:
    397
    I also have this problem. It gets very slow if being moved close to the objects.
     
  44. Charkes

    Charkes

    Joined:
    Apr 17, 2013
    Posts:
    228
    Syberam likes this.
  45. Flurgle

    Flurgle

    Joined:
    May 16, 2016
    Posts:
    389
    @rea oh my, that might be the coolest screenshot I've seen in Unity in a while. Can you share how you got that overall look (is that stock Stand Asset water)? Also incredible lighting on the rock.


    Some observations (in Unity 5.6.08b):
    Simply looks amazing:


    1) cCharke Stochastic SSR is much more accurate when reflecting off normal maps (see the floor)

    cCharke Stochastic SSR - note the green ripple reflections on the ground:


    Unity SSR - heavily blurred green splotches - doesn't form into proper ripples:

    2) Unity SSR looks much smoother in fast animated / moving scenes (due to how Stoch SSR is drawn), though Stochastic SSR picks up MUCH more detail .

    Stochastic SSR while in animated sequence (camera moving) - Please look at the cube's face on the left, also note on the right, the much greater reflection under the green sphere:


    Unity SSR while camera is moving:

    No SSR while camera is moving

    3) For curved surfaces, Stochastic SSR picks up far more detail from the surroundings, though Unity ssr picks up a larger amount (not sure what this is called)

    Stoch SSR - Notice the rainbow colors on the edge of the wooden material. Notice some subtle reflections at the base of the sphere:


    Unity SSR - Notice the sphere on the right has picked up much more ground texture, however it lacks the stronger reflections seen in Stoch, and the rich colors on the side:


    No SSR as control:




     
    Last edited: Feb 14, 2017
    SirTwistedStorm and hopeful like this.
  46. elmax

    elmax

    Joined:
    Oct 6, 2013
    Posts:
    19
    Looks totally awesome... any chance to get this working in single pass stereo?
     
  47. srmojuze

    srmojuze

    Joined:
    Mar 18, 2013
    Posts:
    127
    Wow. Literally the Frostbite engine SSR.
     
    Charkes likes this.
  48. cerlet

    cerlet

    Joined:
    Jun 24, 2015
    Posts:
    1
    Hi everyone, can anyone explain this code snippet in StochasticSSR.cs between lines 440 - 452 :
    Code (CSharp):
    1.             RenderTexture depthBuffer = CreateTempBuffer(width / (int)depthMode, height / (int)depthMode, 0, RenderTextureFormat.RFloat);
    2.             rayCast.filterMode = rayFilterMode;
    3.             depthBuffer.filterMode = FilterMode.Point;
    4.  
    5.             rendererMaterial.SetTexture("_RayCast", rayCast);
    6.             rendererMaterial.SetTexture("_RayCastMask", rayCastMask);
    7.             rendererMaterial.SetTexture("_CameraDepthBuffer", depthBuffer);
    8.  
    9.             // Depth Buffer
    10.             Graphics.SetRenderTarget(depthBuffer);
    11.             rendererMaterial.SetPass(4);
    12.             DrawFullScreenQuad();
    and this is the fragment shader part of the pass "4" :

    Code (CSharp):
    1.     float4 depth(VertexOutput i ) : SV_Target
    2.     {
    3.         float2 uv = i.uv;
    4.         return tex2D(_CameraDepthTexture, uv);
    5.     }
    I really don't know anything about Unity internals and clearly I am missing something obvious but as I understand we are both reading from and writing to the same texture (depthBuffer) here.
     
  49. jazznazz

    jazznazz

    Joined:
    Apr 27, 2012
    Posts:
    5
    Hello Charkes,
    These reflections look SO much better than the Unity standard! Thank you for the hard work !
    There's slight issue with transparent Standard shader objects though - Unity 2017.1:
     
  50. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,546
    Really great solution, though I'm finding one kind of harsh issue with it that the Unity SSR doesn't seem to have, which is objects behind others picking up lighting from them that they shouldn't be given the distance.

    You can see in these two comparison images, there is a 4ft tall Kiosk floating in the area near the camera, it is nowhere near the second level floor at the top left, yet in your SSR implementation, it is picking up A LOT of the gold trim lighting, but with Unity's it's cleanly ignoring it as it should, since its depth buffer value is much closer than that area.



    If I don't have "reduce fireflies" on in your settings, that gold splotchyness in the background is much more extreme too.
    Everything else about the implementation seems great though and performs similar to Unity's, so that's definitely awesome!
     
    NeatWolf and Flurgle like this.