Beispiel #1
0
        public (bool, HitRecord) Hit(Ray ray, double tmin, double tmax)
        {
            bool      anyHits    = false;
            var       closestOne = tmax;
            HitRecord result     = new HitRecord();

            foreach (var hittable in this)
            {
                var(hit, temp) = hittable.Hit(ray, tmin, closestOne);
                if (hit)
                {
                    anyHits    = true;
                    closestOne = temp.T;
                    result     = temp;
                }
            }

            return(anyHits, result);
        }
Beispiel #2
0
        public override bool Scatter(Scene scene, Ray ray, HitRecord hit, out Attenuation attenuation, out Ray scattered)
        {
            var     direction = Vector3.Normalize(ray.direction);
            Vector3 reflected = Vector3.Reflect(direction, hit.normal);

            scattered = new Ray(hit.position, reflected + fuzz * Sphere.RandomInUnitSphere());

            Vector3 diffuseColor  = Vector3.Zero;
            Vector3 SpecularColor = Vector3.Zero;

            foreach (var light in scene.lights)
            {
                if (CastShadow(scene, light, hit))
                {
                    continue;
                }

                Vector3 lightDir   = -Vector3.Normalize(hit.position - light.position);
                Vector3 reflectDir = Vector3.Reflect(-lightDir, hit.normal);

                diffuseColor  += light.color * light.insensity * Vector3.Dot(hit.normal, lightDir);
                SpecularColor += light.color * light.insensity * specularIndex *
                                 MathF.Pow(Math.Clamp(Vector3.Dot(reflectDir, -direction), 0, 1), glossIndex);
            }

            //环境光 + 光源
            var textureColor = GetTextureColor(hit.uv);
            var allColor     = (scene.ambientColor + diffuseColor) * albedo * textureColor + SpecularColor;

            attenuation = Attenuation.Blend(allColor, blendPercent, albedo * textureColor);
            attenuation.attenuationType = attenuationType;

            //兼容easyPipeline
            if (fuzz == 0 && specularIndex == 1)
            {
                attenuation.forceToDoAnotherPass = true;
            }

            //attenuation = Attenuation.None(new Vector3(hit.uv.X, hit.uv.Y,0));

            return(true);//(Vector3.Dot(scattered.direction, hit.normal) > 0);
        }
Beispiel #3
0
        public override bool Hit(Ray ray, float tMin, float tMax, out HitRecord rec)
        {
            rec = null;
            bool  hitAnything  = false;
            float closestSoFar = tMax;

            foreach (var ob in fragments)
            {
                if (ob.Hit(ray, tMin, tMax, out HitRecord recTemp))
                {
                    hitAnything = true;
                    if (closestSoFar > recTemp.t)
                    {
                        closestSoFar = recTemp.t;
                        rec          = recTemp;
                    }
                }
            }
            return(hitAnything);
        }
Beispiel #4
0
        public bool Hit(Ray ray, out HitRecord rec, float tMin = 0.001f, float tMax = 10000)
        {
            rec = null;
            bool  hitAnything  = false;
            float closestSoFar = tMax;

            foreach (var ob in hitableObjects)
            {
                if (ob.Hit(ray, tMin, tMax, out HitRecord recTemp))
                {
                    hitAnything = true;
                    if (closestSoFar > recTemp.t)
                    {
                        closestSoFar = recTemp.t;
                        rec          = recTemp;
                    }
                }
            }
            return(hitAnything);
        }
Beispiel #5
0
        private Color32 Diffusing(Ray ray, HitableList hitableList, int depth)
        {
            var record = new HitRecord();

            if (hitableList.Hit(ray, 0.0001f, float.MaxValue, ref record))
            {
                var r           = new Ray(Vector3.zero, Vector3.zero);
                var attenuation = Color32.black;
                if (depth < MAX_SCATTER_TIME && record.material.scatter(ray, record, ref attenuation, ref r))
                {
                    var c = Diffusing(r, hitableList, depth + 1);
                    return(new Color32(c.r * attenuation.r, c.g * attenuation.g, c.b * attenuation.b));
                }
                else
                {
                    return(Color32.black);
                }
            }

            var t = 0.5f * ray.normalDirection.y + 1f;

            return((1 - t) * new Color32(1, 1, 1) + t * new Color32(0.5f, 0.7f, 1));
        }
Beispiel #6
0
        public (bool isHit, HitRecord hitDetail) Hit(Ray ray, double tmin, double tmax)
        {
            var oc    = ray.Origin - _center;
            var a     = ray.Direction.LengthSquared();
            var halfB = Vector.Dot(oc, ray.Direction);
            var c     = oc.LengthSquared() - _radius * _radius;

            var discriminant = halfB * halfB - a * c;

            if (discriminant < 0)
            {
                return(false, new HitRecord());
            }

            var sqrtd = Math.Sqrt(discriminant);

            var root = (-halfB - sqrtd) / a;

            if (root < tmin || tmax < root)
            {
                root = (-halfB + sqrtd) / a;
                if (root < tmin || tmax < root)
                {
                    return(false, new HitRecord());
                }
            }

            var hit = new HitRecord();

            hit.T = root;
            hit   = GetHitPoint(ray, hit);
            var outwardNormal = (hit.Point - _center) / _radius;

            hit.SetFaceNormal(ray, outwardNormal);

            return(true, hit);
        }
Beispiel #7
0
 public abstract bool Scatter(ref Ray ray, ref HitRecord hit, out Vector3 attenuation, out Ray scattered);
Beispiel #8
0
 public abstract bool Hit(Ray r, float tMin, float tMax, out HitRecord rec);
Beispiel #9
0
        public override bool Hit(Ray r, float tMin, float tMax, out HitRecord rec)
        {
            //Plane plane = Plane.CreateFromVertices(points[0], points[1], points[2]);
            var normal = Vector3.Normalize(Vector3.Cross((points[0] - points[1]), (points[1] - points[2])));

            r.direction = Vector3.Normalize(r.direction);
            rec         = new HitRecord();
            //面片背面剔除
            var cos = Vector3.Dot(r.direction, normal);

            if (cos == 0)
            {
                return(false);
            }
            if (cullBack && cos < 0)
            {
                return(false);
            }


            //计算t(距离)
            rec.t = Vector3.Dot(points[0] - r.from, normal) / Vector3.Dot(r.direction, normal);
            //rec.t = (Vector3.Dot(normal,points[0]) - Vector3.Dot(normal, r.from) )/ Vector3.Dot(normal,r.direction );

            if (float.IsNaN(rec.t) || rec.t < tMin || rec.t > tMax)
            {
                return(false);
            }

            //计算p(平面交点)
            var p = r.from + rec.t * r.direction;

            //光栅剔除
            points.Add(points[0]);
            Vector3 firstTowards = Vector3.Zero;

            for (int i = 0; i < points.Count - 1; i++)
            {
                var oa      = Vector3.Normalize(points[i] - points[i + 1]);
                var op      = Vector3.Normalize(points[i] - p);
                var towards = Vector3.Normalize(Vector3.Cross(oa, op));
                if (firstTowards == Vector3.Zero)
                {
                    firstTowards = towards;
                }
                else if (Vector3.Dot(firstTowards, towards) < 0.999999)
                {
                    points.RemoveAt(points.Count - 1);
                    return(false);
                }
            }
            points.RemoveAt(points.Count - 1);
            rec.position = p;

            //是否有normal记录
            if (normals.Count == points.Count)
            {
                if (uvs.Count == 3)
                {
                    rec.normal = GetAvgNormalInTriangle(p);
                }
                else
                {
                    rec.normal = GetAvgNormal(p);
                }
            }
            else
            {
                rec.normal = normal;
            }



            //是否有uv记录
            if (uvs.Count == points.Count)
            {
                if (uvs.Count == 3)
                {
                    rec.uv = GetAvgUVInTriangle(p);
                }
                else
                {
                    rec.uv = GetAvgUV(p);
                }
            }


            rec.material = material;


            return(true);
        }
Beispiel #10
0
 public abstract bool Scatter(Scene scene, Ray ray, HitRecord hit, out Attenuation attenuation, out Ray scattered);