public static AABB surrounding_box(AABB box0, AABB box1)
    {
        Vec3 small = new Vec3(XMath.Min(box0.min.x, box1.min.x), XMath.Min(box0.min.y, box1.min.y), XMath.Min(box0.min.z, box1.min.z));
        Vec3 big   = new Vec3(XMath.Max(box0.max.x, box1.max.x), XMath.Max(box0.max.y, box1.max.y), XMath.Max(box0.max.z, box1.max.z));

        return(new AABB(small, big));
    }
Beispiel #2
0
        // https://developer.download.nvidia.com/cg/atan2.html
        public static float Atan2(float y, float x)
        {
            float t0, t1, t3, t4;

            t3 = XMath.Abs(x);
            t1 = XMath.Abs(y);
            t0 = XMath.Max(t3, t1);
            t1 = XMath.Min(t3, t1);
            t3 = 1f / t0;
            t3 = t1 * t3;

            t4 = t3 * t3;
            t0 = -0.013480470f;
            t0 = t0 * t4 + 0.057477314f;
            t0 = t0 * t4 - 0.121239071f;
            t0 = t0 * t4 + 0.195635925f;
            t0 = t0 * t4 - 0.332994597f;
            t0 = t0 * t4 + 0.999995630f;
            t3 = t0 * t3;

            t3 = (XMath.Abs(y) > XMath.Abs(x)) ? 1.570796327f - t3 : t3;
            t3 = (x < 0) ? 3.141592654f - t3 : t3;
            t3 = (y < 0) ? -t3 : t3;

            return(t3);
        }
        public void RenderPseudoColor(ref WriteableBitmap bmp, short max = -1)
        {
            var redBand   = 11 - 1;
            var greenBand = 17 - 1;
            var blueBand  = 38 - 1;

            double[] minMax = new double[2];
            _dataset.GetRasterBand(redBand).ComputeRasterMinMax(minMax, 0);
            short redMax = (short)(minMax[1]);

            _dataset.GetRasterBand(greenBand).ComputeRasterMinMax(minMax, 0);
            short greenMax = (short)(minMax[1]);

            _dataset.GetRasterBand(blueBand).ComputeRasterMinMax(minMax, 0);
            short blueMax = (short)(minMax[1]);

            if (max == -1)
            {
                max = XMath.Max(blueMax, Math.Max(redMax, greenMax));
            }

            uint[] data = CalculationWrappers.CalculatePseudoColor(_datasetV.View, redBand, greenBand, blueBand, max);

            bmp = new WriteableBitmap(new PixelSize(width, height), new Vector(1, 1), Avalonia.Platform.PixelFormat.Rgba8888);

            using (var buf = bmp.Lock())
            {
                IntPtr ptr = buf.Address;
                Marshal.Copy((int[])(object)data, 0, ptr, data.Length);
            }
        }
        public static void CalculateSignatureLengthDerivative(Index2 index, ArrayView3D <float> output, ArrayView3D <byte> input)
        {
            var x = index.X;
            var y = index.Y;

            if (x == 0)
            {
                x = 1;
            }
            if (x == input.Width - 1)
            {
                x = input.Width - 2;
            }
            if (y == 0)
            {
                y = 1;
            }
            if (y == input.Height - 1)
            {
                y = input.Height - 2;
            }

            var depth = input.Depth;

            float xDiffComponentSum = 0;
            float yDiffComponentSum = 0;

            for (int i = 0; i < depth; i++)
            {
                var val1 = input[x - 1, y, i]; if (val1 < 0)
                {
                    val1 = 0;
                }
                var val2 = input[x + 1, y, i]; if (val2 < 0)
                {
                    val1 = 0;
                }
                var xDiff = val2 - val1;
                xDiffComponentSum += xDiff * xDiff;

                val1 = input[x, y - 1, i]; if (val1 < 0)
                {
                    val1 = 0;
                }
                val2 = input[x, y + 1, i]; if (val2 < 0)
                {
                    val1 = 0;
                }
                var yDiff = val2 - val1;
                yDiffComponentSum += yDiff * yDiff;
            }

            var xDiffLength = XMath.Sqrt(xDiffComponentSum);
            var yDiffLength = XMath.Sqrt(yDiffComponentSum);

            output[index.X, index.Y, 0] = xDiffLength;
            output[index.X, index.Y, 1] = yDiffLength;
            output[index.X, index.Y, 2] = XMath.Max(xDiffLength, yDiffLength);
        }
        public static PicturesData CalculateSignatureLengthDerivative(ArrayView3D <byte> imageView, bool normalize)
        {
            PicturesData result   = new PicturesData();
            var          slice    = imageView.GetSliceView(0);
            var          picIndex = new Index3(slice.Extent.X, slice.Extent.Y, 3);

            using (var calcBuffer = GpuContext.Instance.Accelerator.Allocate <float>(picIndex))
                using (var byteBuf = GpuContext.Instance.Accelerator.Allocate <byte>(picIndex))
                    using (var imageBuffer = GpuContext.Instance.Accelerator.Allocate <uint>(picIndex))
                    {
                        if (normalize)
                        {
                            BCalculateSignatureLengthDerivativeWithNormalizationKernel(slice.Extent, calcBuffer.View, imageView);
                        }
                        else
                        {
                            BCalculateSignatureLengthDerivativeKernel(slice.Extent, calcBuffer.View, imageView);
                        }
                        GpuContext.Instance.Accelerator.Synchronize();

                        var array    = calcBuffer.GetAsArray();
                        var maxBand1 = array.Take(slice.Extent.Size).Max();
                        var maxBand2 = array.Skip(slice.Extent.Size).Take(slice.Extent.Size).Max();
                        //var maxBand3 = array.Skip(slice.Extent.Size * 2).Max();
                        var maxBand3 = XMath.Max(maxBand1, maxBand2);

                        NormalizeLengthMapKernel(slice.Extent, calcBuffer, 0, maxBand1); GpuContext.Instance.Accelerator.Synchronize();
                        NormalizeLengthMapKernel(slice.Extent, calcBuffer, 1, maxBand2); GpuContext.Instance.Accelerator.Synchronize();
                        NormalizeLengthMapKernel(slice.Extent, calcBuffer, 2, maxBand3); GpuContext.Instance.Accelerator.Synchronize();

                        FloatToByteKernel(calcBuffer.Extent.Size, calcBuffer.AsLinearView(), byteBuf.AsLinearView());
                        GpuContext.Instance.Accelerator.Synchronize();

                        result.rawPicture = byteBuf.GetAsArray().Skip(slice.Extent.Size * 2).ToArray();


                        PinConvertFromByteKernel(slice.Extent.Size, imageBuffer.GetSliceView(0).AsLinearView(), byteBuf.GetSliceView(0).AsLinearView(), 1.0, 0);
                        PinConvertFromByteKernel(slice.Extent.Size, imageBuffer.GetSliceView(1).AsLinearView(), byteBuf.GetSliceView(1).AsLinearView(), 1.0, 0);
                        PinConvertFromByteKernel(slice.Extent.Size, imageBuffer.GetSliceView(2).AsLinearView(), byteBuf.GetSliceView(2).AsLinearView(), 1.0, 0);
                        GpuContext.Instance.Accelerator.Synchronize();

                        var img  = imageBuffer.GetAsArray();
                        var size = slice.Extent.Size;

                        var buf = new uint[size];
                        Array.Copy(img, 0, buf, 0, size);
                        result.xPicture = buf;

                        buf = new uint[size];
                        Array.Copy(img, size, buf, 0, size);
                        result.yPicture = buf;

                        buf = new uint[size];
                        Array.Copy(img, size * 2, buf, 0, size);
                        result.xyPicture = buf;
                    }

            return(result);
        }
Beispiel #6
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);
        }
        public static void AccumulateEdges(Index2 index, ArrayView2D <uint> output, ArrayView2D <byte> pearson, ArrayView2D <byte> canny, ArrayView2D <byte> signLengthByte, ArrayView2D <byte> signLengthShort)
        {
            uint r = (uint)XMath.Max(pearson[index] / 3, canny[index]); if (r > 254)
            {
                r = 254;
            }
            uint g = (uint)(XMath.Max(pearson[index] / 3, signLengthByte[index])); if (g > 254)
            {
                g = 254;
            }
            uint b = (uint)(XMath.Max(pearson[index] / 3, signLengthShort[index])); if (b > 254)
            {
                b = 254;
            }

            uint value = (uint)(r + (g << 8) + (b << 16) + (255 << 24));

            output[index] = value;
        }
    public bool hit(Ray ray, float tMin, float tMax)
    {
        float minV = (min.x - ray.a.x) / ray.b.x;
        float maxV = (max.x - ray.a.x) / ray.b.x;
        float t1   = XMath.Max(minV, maxV);
        float t0   = XMath.Min(minV, maxV);

        tMin = XMath.Max(t0, tMin);
        tMax = XMath.Min(t1, tMax);

        if (tMax <= tMin)
        {
            return(false);
        }

        minV = (min.y - ray.a.y) / ray.b.y;
        maxV = (max.y - ray.a.y) / ray.b.y;
        t1   = XMath.Max(minV, maxV);
        t0   = XMath.Min(minV, maxV);
        tMin = XMath.Max(t0, tMin);
        tMax = XMath.Min(t1, tMax);

        if (tMax <= tMin)
        {
            return(false);
        }

        minV = (min.z - ray.a.z) / ray.b.z;
        maxV = (max.z - ray.a.z) / ray.b.z;
        t1   = XMath.Max(minV, maxV);
        t0   = XMath.Min(minV, maxV);
        tMin = XMath.Max(t0, tMin);
        tMax = XMath.Min(t1, tMax);

        if (tMax <= tMin)
        {
            return(false);
        }

        return(true);
    }
Beispiel #9
0
        public static float Schlick(Vector3 nrm, Vector3 dir, float n1, float n2)
        {
            float r0 = (n1 - n2) / (n1 + n2);

            r0 *= r0;
            float cosI = XMath.Max(Vector3.Dot(-nrm, dir), 0f);

            if (n1 > n2)
            {
                float n     = n1 / n2;
                float sinT2 = n * n * (1f - cosI * cosI);
                if (sinT2 > 1.0)
                {
                    return(1f);
                }
                cosI = XMath.Sqrt(1f - sinT2);
            }
            float x = 1f - cosI;

            return(r0 + (1f - r0) * x * x * x * x * x);
        }
        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;
        }
        public static void CalculateSignatureLengthDerivativeWithNormalization(Index2 index, ArrayView3D <float> output, ArrayView3D <short> input, short maxValue)
        {
            var x = index.X;
            var y = index.Y;

            if (x == 0)
            {
                x = 1;
            }
            if (x == input.Width - 1)
            {
                x = input.Width - 2;
            }
            if (y == 0)
            {
                y = 1;
            }
            if (y == input.Height - 1)
            {
                y = input.Height - 2;
            }

            var depth = input.Depth;

            int x1ComponentSum = 0;
            int x2ComponentSum = 0;

            int y1ComponentSum = 0;
            int y2ComponentSum = 0;

            for (int i = 0; i < depth; i++)
            {
                var val1 = XMath.Clamp(input[x - 1, y, i], (short)0, maxValue);
                var val2 = XMath.Clamp(input[x + 1, y, i], (short)0, maxValue);
                x1ComponentSum += val1 * val1;
                x2ComponentSum += val2 * val2;

                val1            = XMath.Clamp(input[x, y - 1, i], (short)0, maxValue);
                val2            = XMath.Clamp(input[x, y + 1, i], (short)0, maxValue);
                y1ComponentSum += val1 * val1;
                y2ComponentSum += val2 * val2;
            }

            float x1Length = XMath.Sqrt(x1ComponentSum);
            float x2Length = XMath.Sqrt(x2ComponentSum);
            float y1Length = XMath.Sqrt(y1ComponentSum);
            float y2Length = XMath.Sqrt(y2ComponentSum);

            float xDiffComponentSum = 0;
            float yDiffComponentSum = 0;

            for (int i = 0; i < depth; i++)
            {
                var   val1  = XMath.Clamp(input[x - 1, y, i], (short)0, maxValue);
                var   val2  = XMath.Clamp(input[x + 1, y, i], (short)0, maxValue);
                float xDiff = (val2 / x2Length) - (val1 / x1Length);
                xDiffComponentSum += xDiff * xDiff;

                val1 = XMath.Clamp(input[x, y - 1, i], (short)0, maxValue);
                val2 = XMath.Clamp(input[x, y + 1, i], (short)0, maxValue);
                float yDiff = (val2 / y2Length) - (val1 / y1Length);
                yDiffComponentSum += yDiff * yDiff;
            }

            var xDiffLength = XMath.Sqrt(xDiffComponentSum);
            var yDiffLength = XMath.Sqrt(yDiffComponentSum);

            output[index.X, index.Y, 0] = xDiffLength;
            output[index.X, index.Y, 1] = yDiffLength;
            output[index.X, index.Y, 2] = XMath.Max(xDiffLength, yDiffLength);
        }
Beispiel #12
0
        private static void ColorRay(int index,
                                     Ray ray,
                                     dFramebuffer framebuffer,
                                     dWorldBuffer world,
                                     XorShift64Star rng, Camera camera)
        {
            Vec3 attenuation = new Vec3(1f, 1f, 1f);
            Vec3 lighting    = new Vec3();

            Ray  working             = ray;
            bool attenuationHasValue = false;

            float minT = 0.1f;

            for (int i = 0; i < camera.maxBounces; i++)
            {
                HitRecord rec = GetWorldHit(working, world, minT);

                if (rec.materialID == -1)
                {
                    if (i == 0 || attenuationHasValue)
                    {
                        framebuffer.DrawableIDBuffer[index] = -2;
                    }

                    float t = 0.5f * (working.b.y + 1.0f);
                    attenuation *= (1.0f - t) * new Vec3(1.0f, 1.0f, 1.0f) + t * new Vec3(0.5f, 0.7f, 1.0f);
                    break;
                }
                else
                {
                    if (i == 0)
                    {
                        framebuffer.ZBuffer[index]          = rec.t;
                        framebuffer.DrawableIDBuffer[index] = rec.drawableID;
                    }

                    ScatterRecord sRec = Scatter(working, rec, rng, world.materials, minT);
                    if (sRec.materialID != -1)
                    {
                        attenuationHasValue = sRec.mirrorSkyLightingFix;
                        attenuation        *= sRec.attenuation;
                        working             = sRec.scatterRay;
                    }
                    else
                    {
                        framebuffer.DrawableIDBuffer[index] = -1;
                        break;
                    }
                }

                for (int j = 0; j < world.lightSphereIDs.Length; j++)
                {
                    Sphere    s         = world.spheres[world.lightSphereIDs[j]];
                    Vec3      lightDir  = s.center - rec.p;
                    HitRecord shadowRec = GetWorldHit(new Ray(rec.p, lightDir), world, minT);

                    if (shadowRec.materialID != -1 && (shadowRec.p - rec.p).length() > lightDir.length() - (s.radius * 1.1f)) // the second part of this IF could probably be much more efficent
                    {
                        MaterialData material = world.materials[shadowRec.materialID];
                        if (material.type != 1)
                        {
                            lightDir  = Vec3.unitVector(lightDir);
                            lighting += material.color * XMath.Max(0.0f, Vec3.dot(lightDir, rec.normal));
                            lighting *= XMath.Pow(XMath.Max(0.0f, Vec3.dot(-Vec3.reflect(rec.normal, -lightDir), ray.b)), material.reflectivity) * material.color;
                        }
                    }
                }
            }

            int rIndex = index * 3;
            int gIndex = rIndex + 1;
            int bIndex = rIndex + 2;

            framebuffer.ColorFrameBuffer[rIndex] = attenuation.x;
            framebuffer.ColorFrameBuffer[gIndex] = attenuation.y;
            framebuffer.ColorFrameBuffer[bIndex] = attenuation.z;

            framebuffer.LightingFrameBuffer[rIndex] = lighting.x;
            framebuffer.LightingFrameBuffer[gIndex] = lighting.y;
            framebuffer.LightingFrameBuffer[bIndex] = lighting.z;
        }
 private static float GPUProximalOperator(float x, float lipschitz, float lambda, float alpha) => XMath.Max(x - lambda * alpha, 0.0f) / (lipschitz + lambda * (1 - alpha));