Exemplo n.º 1
0
        private static Vec3 RandomUnitVector(XorShift64Star rng)
        {
            float a = 2f * XMath.PI * rng.NextFloat();
            float z = (rng.NextFloat() * 2f) - 1f;
            float r = XMath.Sqrt(1f - z * z);

            return(new Vec3(r * XMath.Cos(a), r * XMath.Sin(a), z));
        }
Exemplo n.º 2
0
        static void GetLatLon(float line, float sample, out float latitude, out float longitude)
        {
            var x = (sample - S0) * Scale;
            var y = (L0 - line) * Scale;
            var P = XMath.Sqrt(x * x + y * y);
            var C = 2f * GPUHorizons.Atan2(P, 2f * MoonRadius);

            latitude  = GPUHorizons.Asin(XMath.Cos(C) * XMath.Sin(LatP) + (y == 0 ? 0 : y * XMath.Sin(C) * XMath.Cos(LatP) / P));
            longitude = LonP + GPUHorizons.Atan2(x, y * LonFactor);
        }
Exemplo n.º 3
0
        // Returns the position in km
        static void GetVector3d(float line, float sample, float height_meters, out float x, out float y, out float z)
        {
            var radius = MoonRadius + height_meters / 1000f;

            GetLatLon(line, sample, out float lat, out float lon);
            z = radius * XMath.Sin(lat);
            var c = radius * XMath.Cos(lat);

            x = c * XMath.Cos(lon);  // TODO: Not sure about these
            y = c * XMath.Sin(lon);
        }
Exemplo n.º 4
0
        public static Vector3 PointOnHemisphere(this XorShift64Star random, Vector3 n)
        {
            float   azimuthal = random.NextFloat() * XMath.PI * 2f;
            float   z         = random.NextFloat();
            float   xyproj    = XMath.Sqrt(1 - z * z);
            Vector3 v         = new Vector3(xyproj * XMath.Cos(azimuthal), xyproj * XMath.Sin(azimuthal), z);

            if (Vector3.Dot(v, n) < 0)
            {
                return(v * -1);
            }
            else
            {
                return(v);
            }
        }
Exemplo n.º 5
0
        public static Vector3 GetGGXMicrofacet(XorShift64Star random, float roughness, Vector3 normal)
        {
            float rand1 = random.NextFloat();
            float rand2 = random.NextFloat();

            Vector3 B = GetPerpendicularVector(normal);
            Vector3 T = Vector3.Cross(B, normal);

            float a2        = roughness * roughness;
            float cosThetaH = XMath.Sqrt(XMath.Max(0f, (1f - rand1) / ((a2 - 1f) * rand1 + 1f)));
            float sinThetaH = XMath.Sqrt(XMath.Max(0f, 1f - cosThetaH * cosThetaH));
            float phiH      = rand2 * XMath.PI * 2f;

            return(T * (sinThetaH * XMath.Cos(phiH)) +
                   B * (sinThetaH * XMath.Sin(phiH)) +
                   normal * cosThetaH);
        }
Exemplo n.º 6
0
        public Ray GetRaySimple(float x, float y)
        {
            x = (x / (ScreenWidth - 1f) - 0.5f) * (ScreenWidth / ScreenHeight);
            y = (1f - y / (ScreenHeight - 1f)) - 0.5f;

            Vector3 direction = Vector3.Normalize(new Vector3(x * 36f, y * 36f, FocalLength));

            float angle = -sphericalPosition.Y + XMath.PIHalf;
            float newY  = direction.Y * XMath.Cos(angle) - direction.Z * XMath.Sin(angle);
            float newZ  = direction.Z * XMath.Cos(angle) - direction.Y * XMath.Sin(angle);

            direction.Y = newY;
            direction.Z = newZ;

            angle = sphericalPosition.Z + XMath.PIHalf;
            float newX = direction.X * XMath.Cos(angle) - direction.Z * XMath.Sin(angle);

            newZ        = direction.Z * XMath.Cos(angle) + direction.X * XMath.Sin(angle);
            direction.X = newX;
            direction.Z = newZ;

            return(new Ray(Position, direction));
        }
Exemplo n.º 7
0
        public Vector3 GetIndirectDiffuse2(XorShift64Star random, Scene scene, Vector3 position, Vector3 normal)
        {
            Vector3 lightAccumulator = new Vector3();
            int     samples          = 4;

            for (int i = 0; i < samples; i++)
            {
                float   azimuthal = random.NextFloat() * XMath.PI * 2f;
                float   z         = random.NextFloat();
                float   xyproj    = XMath.Sqrt(1 - z * z);
                Vector3 dir       = new Vector3(xyproj * XMath.Cos(azimuthal), xyproj * XMath.Sin(azimuthal), z);
                if (Vector3.Dot(dir, normal) < 0)
                {
                    dir *= -1;
                }
                Ray          ray          = new Ray(position + dir * 0.002f, dir);
                Intersection intersection = scene.TraceScene(ray);
                if (!intersection.Hit && !intersection.HitLight)
                {
                    lightAccumulator += Vector3.Multiply(scene.SkylightColor * scene.SkylightBrightness * Vector3.Dot(dir, normal), DiffuseColor) * Diffuse;
                    continue;
                }
                else if (!intersection.Hit || intersection.HitLight)
                {
                    continue;
                }
                Material hitMaterial = intersection.HitObject.Material;
                Vector3  lightC      = hitMaterial.GetShaded3(random, scene, intersection.HitPosition, dir, intersection.HitNormal);
                lightC           *= Vector3.Dot(dir, normal);
                lightAccumulator += Vector3.Multiply(lightC, DiffuseColor) * Diffuse;
            }

            lightAccumulator /= (float)samples;

            return(lightAccumulator);
        }
Exemplo n.º 8
0
        static void NearFieldKernel1(
            Index2 index,      // Contains (sample, line)  First dimension changes fastest
            int target_line,   // row within the 128 x 128 target patch
            int target_sample, // column
            int slope_idx_start,
            int slope_idx_stop,

            ArrayView <short> gpu_terrain,
            ArrayView <float> gpu_range,
            ArrayView <float> gpu_slope,
            ArrayView <float> gpu_rise,
            ArrayView <int> gpu_range_limit)
        {
            var flip = -LonFactor;

            // From ILGPU source code: public int ComputeLinearIndex(Index2 dimension) => Y * dimension.X + X;
            var rise_idx = index.ComputeLinearIndex(Dimension);
            var rise     = gpu_rise[rise_idx];

            var center_line   = target_line + index.Y;
            var center_sample = target_sample + index.X;
            var center_idx    = center_line * TerrainSize + center_sample;
            var center_height = 0.5f * gpu_terrain[center_idx];

            GetVector3d(center_line, center_sample, center_height, out float center_x, out float center_y, out float center_z);
            center_z *= flip;

            for (var slope_idx = slope_idx_start; slope_idx < slope_idx_stop; slope_idx++)
            {
                var slope = gpu_slope[slope_idx];

                // Work out the direction vector
                var ray_rad = XMath.PI * 2f * slope_idx / cpu_slope_size; // 0 deg in ME frame points toward the earth
                var ray_cos = XMath.Cos(ray_rad);                         // varies the line
                var ray_sin = XMath.Sin(ray_rad);                         // varies the sample

                // iterate over the ranges
                var range_limit = gpu_range_limit[slope_idx];
                for (var range_idx = 0; range_idx < range_limit; range_idx++)
                {
                    var range         = gpu_range[range_idx];
                    var caster_line   = center_line + ray_sin * range;
                    var caster_sample = center_sample + ray_cos * range;

                    var x1 = (int)caster_sample;  // Calculate the caster point by interpolating between four points from the points array
                    var y1 = (int)caster_line;
                    int x2 = x1 + 1;
                    int y2 = y1 + 1;

                    var q11_idx = y1 * TerrainSize + x1;
                    var q11     = gpu_terrain[q11_idx];

                    var q12_idx = q11_idx + TerrainSize;
                    var q12     = gpu_terrain[q12_idx];

                    // First interpolation across rows (line)
                    var q1_line = q11 + (caster_line - y1) * (q12 - q11);

                    var q21_idx = q11_idx + 1;
                    var q21     = gpu_terrain[q21_idx];

                    var q22_idx = q11_idx + TerrainSize + 1;
                    var q22     = gpu_terrain[q22_idx];

                    // Second interpolation across rows
                    var q2_line = q21 + (caster_line - y1) * (q22 - q21);

                    // Interpolate across samples and convert to meters
                    var caster_height = q1_line + (caster_sample - x1) * (q2_line - q1_line);
                    caster_height *= 0.5f;

                    GetVector3d(caster_line, caster_sample, caster_height, out float caster_x, out float caster_y, out float caster_z);
                    caster_z *= flip;

                    var dx = caster_x - center_x;
                    var dy = caster_y - center_y;
                    var d  = XMath.Sqrt(dx * dx + dy * dy);             // horizontal distance in moon radius units

                    var light_ray_height = caster_z - slope * d;        // negative slope gets higher as light ray goes toward the center
                    var ray_rise_height  = light_ray_height - center_z; // moon radius units
                    var ray_rise_meters  = ray_rise_height * 1000f;

                    // Alternative
                    //var dInMeters = d * 1000f;
                    //var deltaHeightInMeters = (caster_z - center_z) * 1000f;
                    //var rise2 = deltaHeightInMeters - dInMeters * slope;

                    rise = XMath.Max(rise, ray_rise_meters);
                }
            }

            gpu_rise[rise_idx] = rise;
        }
Exemplo n.º 9
0
        static double Evaluate(int individualIndex, int independentsRowIndex, ArrayView2D <double> independents, ArrayView <NodeGPU> nodes, ArrayView <int> nodeArrayStarts)
        {
            for (int nodeIndex = 0; nodeIndex < nodeArrayStarts.Length; nodeIndex++)
            {
                Index1 currentNodeIndex = new Index1(nodeArrayStarts[individualIndex] + nodeIndex);
                //NodeGPU currentNode = nodes[currentNodeIndex];
                if (nodes[currentNodeIndex].IndependentIndex >= 0)
                {
                    int independentIndex = nodes[currentNodeIndex].IndependentIndex;
                    nodes[currentNodeIndex].Number = independents[independentsRowIndex, independentIndex];
                }
                else if (nodes[currentNodeIndex].OperatorIndex >= 0)
                {
                    Index1 branchIndex1 = new Index1(nodeArrayStarts[individualIndex] + nodes[currentNodeIndex].Branch1);
                    Index1 branchIndex2 = new Index1(nodeArrayStarts[individualIndex] + nodes[currentNodeIndex].Branch2);
                    if (nodes[currentNodeIndex].OperatorIndex < 6)
                    {
                        if (nodes[currentNodeIndex].OperatorIndex < 4)
                        {
                            if (nodes[currentNodeIndex].OperatorIndex == 2)
                            {
                                nodes[currentNodeIndex].Number = nodes[branchIndex1].Number + nodes[branchIndex2].Number;
                            }
                            else if (nodes[currentNodeIndex].OperatorIndex == 3)
                            {
                                nodes[currentNodeIndex].Number = nodes[branchIndex1].Number - nodes[branchIndex2].Number;
                            }
                        }
                        else
                        {
                            if (nodes[currentNodeIndex].OperatorIndex == 4)
                            {
                                nodes[currentNodeIndex].Number = nodes[branchIndex1].Number * nodes[branchIndex2].Number;
                            }
                            else if (nodes[currentNodeIndex].OperatorIndex == 5)
                            {
                                nodes[currentNodeIndex].Number = nodes[branchIndex1].Number / nodes[branchIndex2].Number;
                            }
                        }
                    }
                    else if (nodes[currentNodeIndex].OperatorIndex >= 6 && nodes[currentNodeIndex].OperatorIndex <= 15)
                    {
                        if (nodes[currentNodeIndex].OperatorIndex == 6)
                        {
                            nodes[currentNodeIndex].Number = -nodes[branchIndex1].Number;
                        }
                        else if (nodes[currentNodeIndex].OperatorIndex == 8)
                        {
                            nodes[currentNodeIndex].Number = XMath.Sin(nodes[branchIndex1].Number);
                        }
                        else if (nodes[currentNodeIndex].OperatorIndex == 9)
                        {
                            nodes[currentNodeIndex].Number = XMath.Cos(nodes[branchIndex1].Number);
                        }
                        else if (nodes[currentNodeIndex].OperatorIndex == 14)
                        {
                            nodes[currentNodeIndex].Number = XMath.Pow(nodes[branchIndex1].Number, nodes[branchIndex2].Number);
                        }
                        else if (nodes[currentNodeIndex].OperatorIndex == 15)
                        {
                            nodes[currentNodeIndex].Number = XMath.Sign(nodes[branchIndex1].Number);
                        }
                    }
                    else
                    {
                        Index1 branchIndex3 = new Index1(nodeArrayStarts[individualIndex] + nodes[currentNodeIndex].Branch3);
                        Index1 branchIndex4 = new Index1(nodeArrayStarts[individualIndex] + nodes[currentNodeIndex].Branch4);
                        if (nodes[currentNodeIndex].OperatorIndex == 18)
                        {
                            if (nodes[branchIndex1].Number == nodes[branchIndex2].Number)
                            {
                                nodes[currentNodeIndex].Number = nodes[branchIndex3].Number;
                            }
                            else
                            {
                                nodes[currentNodeIndex].Number = nodes[branchIndex4].Number;
                            }
                        }
                        else if (nodes[currentNodeIndex].OperatorIndex == 19)
                        {
                            if (nodes[branchIndex1].Number < nodes[branchIndex2].Number)
                            {
                                nodes[currentNodeIndex].Number = nodes[branchIndex3].Number;
                            }
                            else
                            {
                                nodes[currentNodeIndex].Number = nodes[branchIndex4].Number;
                            }
                        }
                        else if (nodes[currentNodeIndex].OperatorIndex == 20)
                        {
                            if (nodes[branchIndex1].Number <= nodes[branchIndex2].Number)
                            {
                                nodes[currentNodeIndex].Number = nodes[branchIndex3].Number;
                            }
                            else
                            {
                                nodes[currentNodeIndex].Number = nodes[branchIndex4].Number;
                            }
                        }
                        else if (nodes[currentNodeIndex].OperatorIndex == 21)
                        {
                            if (nodes[branchIndex1].Number == 0)
                            {
                                nodes[currentNodeIndex].Number = nodes[branchIndex2].Number;
                            }
                            else
                            {
                                nodes[currentNodeIndex].Number = nodes[branchIndex3].Number;
                            }
                        }
                        else if (nodes[currentNodeIndex].OperatorIndex == 22)
                        {
                            if (nodes[branchIndex1].Number == 1)
                            {
                                nodes[currentNodeIndex].Number = nodes[branchIndex2].Number;
                            }
                            else
                            {
                                nodes[currentNodeIndex].Number = nodes[branchIndex3].Number;
                            }
                        }
                    }
                    if (nodes[currentNodeIndex].Number == double.NaN)
                    {
                        return(double.NaN);
                    }
                }

                if (nodes[currentNodeIndex].IsRoot == 1)
                {
                    return(nodes[currentNodeIndex].Number);
                }
            }
            return(double.NaN);
        }
Exemplo n.º 10
0
 static double Cos(double x) => XMath.Cos((float)x);
Exemplo n.º 11
0
        // This kernel runs very quickly and is called 128 x 128 times.   128 x 128 runs takes 8 sec ... longer than the 5 sec timeout.
        // It would be better if more work were done in the kernel and the kernel were called fewer times, I think.
        static void NearFieldKernel1(
            Index index,       // Horizon angle as integer
            int target_line,   // row within the 128 x 128 target patch
            int target_sample, // column
            int line_offset,
            int sample_offset,
            int points_rows,
            int points_columns,
            float d_min,
            float d_max,
            float d_step,
            float observer_height_in_km,
            ArrayView <float> points,
            ArrayView <float> matrices,
            ArrayView <float> horizon,
            ArrayView <float> test_floats)
        {
            //if (index == 0)
            //{
            //    var delme = 1;
            //}

            // Copy the matrix into registers
            var pos = (target_line * TerrainPatch.DefaultSize + target_sample) * 12;

            var row0x = matrices[pos++];
            var row1x = matrices[pos++];
            var row2x = matrices[pos++];
            var row3x = matrices[pos++];

            var row0y = matrices[pos++];
            var row1y = matrices[pos++];
            var row2y = matrices[pos++];
            var row3y = matrices[pos++];

            var row0z = matrices[pos++];
            var row1z = matrices[pos++];
            var row2z = matrices[pos++];
            var row3z = matrices[pos];

            // Work out the location of the central point in the point array
            float center_line   = target_line + line_offset;
            float center_sample = target_sample + sample_offset;

            var caster_line_max   = (float)points_rows - 1;
            var caster_sample_max = (float)points_columns - 1;

            // Work out the direction vector
            var ray_angle = 3.141592653589f * 2f * index / (TerrainPatch.NearHorizonOversample * Horizon.HorizonSamples);
            var ray_cos   = XMath.Cos(ray_angle);
            var ray_sin   = XMath.Sin(ray_angle);

            // Work out the direction in horizon space (the horizon offset).  This duplicates the calculation of the first point.
            // I'm duplicating code rather than refactoring, because there would be a lot of values to pass
            float azimuth_rad;
            {
                var d             = 1f;
                var caster_line   = center_line + ray_sin * d;
                var caster_sample = center_sample + ray_cos * d;

                var x1 = (int)caster_sample;  // Calculate the caster point by interpolating between four points from the points array
                var y1 = (int)caster_line;
                int x2 = x1 + 1;
                int y2 = y1 + 1;

                var q11_offset = 3 * (y1 * points_columns + x1);  // (y1, x1);
                var q11        = new Vector3(points[q11_offset], points[q11_offset + 1], points[q11_offset + 2]);

                var q12_offset = 3 * (y2 * points_columns + x1);  // (y2, x1);
                var q12        = new Vector3(points[q12_offset], points[q12_offset + 1], points[q12_offset + 2]);

                // First interpolation across rows (line)
                var q1_line = q11 + (caster_line - y1) * (q12 - q11);

                var q21_offset = 3 * (y1 * points_columns + x2);  // (y1, x2);
                var q21        = new Vector3(points[q21_offset], points[q21_offset + 1], points[q21_offset + 2]);

                var q22_offset = 3 * (y2 * points_columns + x2);  // (y2, x2);
                var q22        = new Vector3(points[q22_offset], points[q22_offset + 1], points[q22_offset + 2]);

                // Second interpolation across rows
                var q2_line = q21 + (caster_line - y1) * (q22 - q21);

                // Interpolate across samples
                var caster = q1_line + (caster_sample - x1) * (q2_line - q1_line);

                // Break out the coordinates
                var x_patch = caster.X;
                var y_patch = caster.Y;
                var z_patch = caster.Z;

                // Transform the point to the local frame
                var x = x_patch * row0x + y_patch * row1x + z_patch * row2x + row3x;
                var y = x_patch * row0y + y_patch * row1y + z_patch * row2y + row3y;
                //var z = x_patch * row0z + y_patch * row1z + z_patch * row2z + row3z;

                azimuth_rad = Atan2(y, x) + XMath.PI;  // [0,2PI]
            }

            var normalized_azimuth = (Horizon.HorizonSamples - 1) * azimuth_rad / (2d * Math.PI);  // range [0,1)
            var horizon_offset     = (int)(0.5d + normalized_azimuth);

            Debug.Assert(horizon_offset >= 0 && horizon_offset < Horizon.HorizonSamples);

            // index is which direction in [target_line,target_sample]'s horizon we're working on, but could be oversamples
            var horizon_index = (target_line * TerrainPatch.DefaultSize + target_sample) * Horizon.HorizonSamples + horizon_offset;
            var highest_slope = horizon[horizon_index];

            //test_floats[index] = ray_sin;

            for (var d = d_min; d <= d_max; d += d_step)
            {
                // Generate the location of the caster point in the points array
                var caster_line   = center_line + ray_sin * d;
                var caster_sample = center_sample + ray_cos * d;

                test_floats[index] = caster_sample;

                /*{
                 *  var idx = index == 2160 ? 7 : 11;
                 *  test_floats[idx] = d;
                 *  test_floats[idx + 1] = ray_angle;
                 *  test_floats[idx + 2] = caster_line - line_offset;
                 *  test_floats[idx + 3] = caster_sample - sample_offset;
                 * }*/

                if (caster_line < 1f || caster_line > caster_line_max || caster_sample < 1f || caster_sample > caster_sample_max)
                {
                    break;
                }

                // Calculate the caster point by interpolating between four points from the points array
                var x1 = (int)caster_sample;
                var y1 = (int)caster_line;
                int x2 = x1 + 1;
                int y2 = y1 + 1;

                var q11_offset = 3 * (y1 * points_columns + x1);  // (y1, x1);
                var q11        = new Vector3(points[q11_offset], points[q11_offset + 1], points[q11_offset + 2]);

                var q12_offset = 3 * (y2 * points_columns + x1);  // (y2, x1);
                var q12        = new Vector3(points[q12_offset], points[q12_offset + 1], points[q12_offset + 2]);

                // First interpolation across rows (line)
                var q1_line = q11 + (caster_line - y1) * (q12 - q11);

                var q21_offset = 3 * (y1 * points_columns + x2);  // (y1, x2);
                var q21        = new Vector3(points[q21_offset], points[q21_offset + 1], points[q21_offset + 2]);

                var q22_offset = 3 * (y2 * points_columns + x2);  // (y2, x2);
                var q22        = new Vector3(points[q22_offset], points[q22_offset + 1], points[q22_offset + 2]);

                // Second interpolation across rows
                var q2_line = q21 + (caster_line - y1) * (q22 - q21);

                // Interpolate across samples
                var caster = q1_line + (caster_sample - x1) * (q2_line - q1_line);

                // Break out the coordinates
                var x_patch = caster.X;
                var y_patch = caster.Y;
                var z_patch = caster.Z;

                // Transform the point to the local frame
                var x = x_patch * row0x + y_patch * row1x + z_patch * row2x + row3x;
                var y = x_patch * row0y + y_patch * row1y + z_patch * row2y + row3y;
                var z = x_patch * row0z + y_patch * row1z + z_patch * row2z + row3z;

                // Adjust for solar array height (this is temporary, and I'm not sure we want this in the final version)
                z -= observer_height_in_km;

                var alen  = XMath.Sqrt(x * x + y * y);
                var slope = z / alen;

                if (slope > highest_slope)
                {
                    highest_slope = slope;
                }

                /*if (target_line==0 && target_sample==0 && index == 0)
                 * {
                 *  test_floats[0] = slope;
                 *  test_floats[1] = x_patch;
                 *  test_floats[2] = y_patch;
                 *  test_floats[3] = z_patch;
                 *  test_floats[4] = x;
                 *  test_floats[5] = y;
                 *  test_floats[6] = z;
                 * }*/
            }

            horizon[horizon_index] = highest_slope;
        }