Example #1
0
        public override double GetValue(double x, double y)
        {
            // Get random samples:
            Vector3[] samples = RandomSamples[MaterialID_];

            // read random normal from noise texture:
            // From 0-1 range to 0-RandomVectorImageSize, clamp, then (y*xSize)+x
            int pixelIndex = (
                ((int)(y * RandomVectorImageSize) % RandomVectorImageSize) * RandomVectorImageSize +
                ((int)(x * RandomVectorImageSize) % RandomVectorImageSize)
                );

            // Get the colour:
            Color randNC = RandomVectorsColours[pixelIndex];

            Vector3 randN = new Vector3(randNC.r, randNC.g, randNC.b);

            // read scene depth/normal
            Color   viewNormC = Normals.GetColour(x, y);
            Vector3 viewNorm  = new Vector3(viewNormC.r, viewNormC.g, viewNormC.b);

            float depth = (float)Depth.GetValue(x, y);
            float scale = SSAOPower / depth;

            // accumulated occlusion factor
            float occ         = 0f;
            int   sampleCount = samples.Length;

            for (int s = 0; s < sampleCount; s++)
            {
                // Reflect sample direction around a random vector
                Vector3 randomDir = Vector3.Reflect(samples[s], randN);

                // Make it point to the upper hemisphere
                float flip = (Vector3.Dot(viewNorm, randomDir) >= 0f) ? 1f : -1f;

                randomDir *= flip;

                // Add a bit of normal to reduce self shadowing
                randomDir.x += viewNorm.x * 0.3f;
                randomDir.y += viewNorm.y * 0.3f;
                randomDir.z += viewNorm.z * 0.3f;

                float sD = depth - (randomDir.z * Radius);

                // Sample depth at offset location:
                float sampleD = (float)Depth.GetValue(x + (randomDir.x * scale), y + (randomDir.y * scale));

                float zd = (sD - sampleD);

                if (zd > MinZ)
                {
                    // Clamp zd such that it's no higher than 1.
                    if (zd > 1f)
                    {
                        zd = 1f;
                    }

                    // This sample occludes, contribute to occlusion
                    occ += (float)System.Math.Pow(1f - zd, AttenuationPower);                  // + 1.0-saturate(pow(1.0 - zd, 11.0) + zd) + 1.0/(1.0+zd*zd*10); // iq
                }
            }

            return(1f - (occ / (float)sampleCount));
        }