Ejemplo n.º 1
0
        public Normal3 Sample(Random random)
        {
            /// Compute Height
            double theta = Math.Pow((random.NextDouble() - 0.5d) * Math.PI, Exponent);
            double r     = Math.Cos(theta);
            double w     = Math.Sin(theta);
            /// Compute u and v
            double angle = random.NextDouble() * 2 * Math.PI;
            double u     = r * Math.Cos(angle);
            double v     = r * Math.Sin(angle);
            /// Transform to Orientation
            Normal3 uDirection = Normal3.AnyPerpendicular(Orientation);
            Normal3 vDirection = Normal3.Perpendicular(Orientation, uDirection);

            return(new Normal3(uDirection * (float)u + vDirection * (float)v + Orientation * (float)w));
        }
Ejemplo n.º 2
0
        public Normal3 Sample(Random random)
        {
            /// Get Point uniformly on Disc
            double angle = random.NextDouble() * 2 * Math.PI;
            double r     = random.NextDouble() + random.NextDouble();

            r = r < 1 ? r : 2 - r;
            double u = r * Math.Cos(angle);
            double v = r * Math.Sin(angle);
            /// Raise Disc point to Hemisphere
            double  w          = Math.Sqrt(1 - u * u - v * v);
            Normal3 uDirection = Normal3.AnyPerpendicular(Orientation);
            Normal3 vDirection = Normal3.Perpendicular(Orientation, uDirection);

            return(new Normal3(uDirection * (float)u + vDirection * (float)v + Orientation * (float)w));
        }
Ejemplo n.º 3
0
        Vector3 SampleVNDF(float r1, float r2)
        {
            // Rotate so UnitZ is up, and flip incoming to outgoing direction
            Normal3 up = Normal3.UnitZ;

            OpenTK.Mathematics.Quaternion rotation;
            if (Orientation == -up)
            {
                rotation = new OpenTK.Mathematics.Quaternion(Normal3.AnyPerpendicular(up).Vector, 0f);
            }
            else
            {
                rotation = new OpenTK.Mathematics.Quaternion(Vector3.Cross(Orientation.Vector, up.Vector), Vector3.Dot(Orientation.Vector, up.Vector) + 1f).Normalized();
            }
            Vector3 Ve = rotation * -IncomingDirection.Vector;

            // Section 3.2: transforming the view direction to the hemisphere configuration
            Vector3 Vh = new Vector3(Roughness * Ve.X, Roughness * Ve.Y, Ve.Z).Normalized();

            // Section 4.1: orthonormal basis (with special case if cross product is zero)
            float   lensq = Vh.X * Vh.X + Vh.Y * Vh.Y;
            Vector3 T1    = lensq > 0 ? new Vector3(-Vh.Y, Vh.X, 0) / (float)Math.Sqrt(lensq) : new Vector3(1f, 0f, 0f);
            Vector3 T2    = Vector3.Cross(Vh, T1);

            // Section 4.2: parameterization of the projected area
            float r   = (float)Math.Sqrt(r1);
            float phi = 2.0f * (float)Math.PI * r2;
            float t1  = r * (float)Math.Cos(phi);
            float t2  = r * (float)Math.Sin(phi);
            float s   = 0.5f * (1f + Vh.Z);

            t2 = (1f - s) * (float)Math.Sqrt(1f - t1 * t1) + s * t2;

            // Section 4.3: reprojection onto hemisphere
            Vector3 Nh = t1 * T1 + t2 * T2 + (float)Math.Sqrt(Math.Max(0f, 1f - t1 * t1 - t2 * t2)) * Vh;

            // Section 3.4: transforming the normal back to the ellipsoid configuration
            Vector3 Ne = new(Roughness * Nh.X, Roughness *Nh.Y, (float)Math.Max(0.0, Nh.Z));

            return(rotation.Inverted() * Ne);
        }