예제 #1
0
        //======================================================================================================================
        //==            INTERSECT TREE - test l'intersection du rayon r avec un arbre de boîtes englobantes                   ==
        //======================================================================================================================
        public ResIntersect intersectTree(AABBTree tree, Ray r)
        {
            ResIntersect res;

            res.t   = -1;
            res.sph = null;

            if (tree.leaf)
            {
                res = Intersect(r, tree.sph);
            }
            else
            {
                if (AABBoxIntersect(tree.box, r))
                {
                    ResIntersect res1 = intersectTree(tree.tree1, r);
                    ResIntersect res2 = intersectTree(tree.tree2, r);

                    if (res1.t != -1)
                    {
                        if (res2.t != -1)
                        {
                            if (res1.t < res2.t)
                            {
                                res = res1;
                            }
                            else
                            {
                                res = res2;
                            }
                        }
                        else
                        {
                            res = res1;
                        }
                    }
                    else if (res2.t != -1)
                    {
                        res = res2;
                    }
                }
            }

            return(res);
        }
예제 #2
0
        public ResIntersect Intersects(Ray r)
        {
            ResIntersect res = intersectTree(spheresTree, r);

            foreach (Sphere s in bigSpheres)
            {
                ResIntersect res2 = Intersect(r, s);
                if (res2.t != -1)
                {
                    if (res.t == -1 || res2.t < res.t)
                    {
                        res.t   = res2.t;
                        res.sph = res2.sph;
                    }
                }
            }
            return(res);
        }
예제 #3
0
        //======================================================================================================================
        //==            DIRECT LIGHTING - renvoi la lumière directe reçue au point d'intersection du rayon                    ==
        //======================================================================================================================
        public Vector3 directLighting(Vector3 interPoint, Vector3 normal, ResIntersect resInter)
        {
            Vector3 directLight = new Vector3(0.0f, 0.0f, 0.0f);

            foreach (Sphere l in lights)
            {
                Vector3      lightNormal      = Vector3.Normalize(Vector3.Subtract(interPoint, l.center));
                Vector3      rdmDir           = transformToNewONBase(randomDirectionOnHemisphere(), NewONBase(lightNormal));
                Vector3      rdmPoint         = Vector3.Add(l.center, Vector3.Multiply(rdmDir, l.radius + 0.1f));
                Vector3      directionToLight = Vector3.Subtract(rdmPoint, interPoint);
                Ray          ray       = new Ray(interPoint, directionToLight);
                ResIntersect resInterL = Intersects(ray);
                if (!(resInterL.t != -1 && resInterL.t <= 1.0f && resInterL.sph.material.type != MaterialType.Light))
                {
                    directLight = Vector3.Add(directLight, Vector3.Multiply(powerReceived(directionToLight, l), lightEmmited(Vector3.Normalize(directionToLight), normal, resInter.sph)));
                }
            }
            return(directLight);
        }
예제 #4
0
        //======================================================================================================================
        //==            RADIANCE - lance un rayon dans la scene et renvoi la couleur obtenue                                  ==
        //======================================================================================================================
        public Vector3 Radiance(Ray ray, int rebound)
        {
            Vector3 color = new Vector3(0, 0, 0);

            if (rebound != 5)
            {
                ResIntersect resInter = Intersects(ray);
                if (resInter.t != -1)
                {
                    Vector3 interPoint = Vector3.Add(ray.point, Vector3.Multiply(ray.direction, resInter.t));
                    Vector3 normal     = Vector3.Subtract(interPoint, resInter.sph.center);
                    normal     = Vector3.Normalize(normal);
                    interPoint = Vector3.Add(interPoint, Vector3.Multiply(normal, 0.1f));
                    Vector3 newDir;
                    Ray     reflection;
                    switch (resInter.sph.material.type)
                    {
                    case MaterialType.Difuse:
                        Vector3 directLight = directLighting(interPoint, normal, resInter);
                        newDir     = transformToNewONBase(randomDirectionOnHemisphere(), NewONBase(normal));
                        reflection = new Ray(interPoint, newDir);
                        color      = Vector3.Add(directLight, Vector3.Multiply(Radiance(reflection, ++rebound), lightEmmited(newDir, normal, resInter.sph)));
                        break;

                    case MaterialType.Mirror:
                        newDir     = Vector3.Add(Vector3.Multiply(2 * -Vector3.Dot(ray.direction, normal), normal), ray.direction);
                        reflection = new Ray(interPoint, newDir);
                        color      = Vector3.Multiply(resInter.sph.material.albedo, Radiance(reflection, ++rebound));
                        break;

                    case MaterialType.Light:
                        color = Vector3.Divide(resInter.sph.material.albedo, 1000000);
                        break;
                    }
                }
            }

            return(color);
        }
        //public Vector3 Radiance(Ray ray, int stop)
        public Vector3 Radiance(Ray ray, int stop, Tree arbre)
        {
            Vector3 color     = new Vector3(0, 0, 0);
            float   nb_rebond = 10.0f;

            //tant qu'on a pas eu 100 rebonds
            if (stop != 10)
            {
                //recherche d'intersection pour sphere
                //ResIntersect resInter = Intersects(ray);

                //recherche d'intersection pour sphere AVEC structure acceleratrice
                ResIntersect resInter = IntersectTree(arbre, ray);


                //si on a une intersection
                if (resInter.t != -1)
                {
                    //interpoint, coordonnées du point t'intersection
                    Vector3 interPoint = Vector3.Add(ray.point, Vector3.Multiply(ray.direction, resInter.t));
                    //normal, vecteur normal a la surface de la sphere
                    Vector3 normal = Vector3.Subtract(interPoint, resInter.sph.center);
                    normal = Vector3.Normalize(normal);
                    //ajout du petit décalage pour ne pas avoir d'interesection d'un point d'une sphere avec un autre point de la sphere
                    interPoint = Vector3.Add(interPoint, Vector3.Multiply(normal, 0.1f));

                    //selon le materiau
                    switch (resInter.sph.material.type)
                    {
                    //DIFFUS
                    case MaterialType.Difuse:
                        //directionToLight, vecteur poitant vers la lumiere à partir du point d'intersection sur la sphere
                        Vector3 directionToLight = Vector3.Subtract(light.origin, interPoint);
                        //création d'un Rayon à partir de cette direction
                        ray = new Ray(interPoint, directionToLight);
                        //cherche s'il y a un obstacle entre la lumiere et le point de la sphere
                        ResIntersect resInterL = Intersects(ray);
                        //lightPower contiendra les albedo additionnés à chaque rebond
                        Vector3 lightPower = new Vector3(0.0f, 0.0f, 0.0f);

                        //s'il n'y a pas d'obstacle et s'il ne s'agit pas de la lampe
                        if (!(resInterL.t != -1 && resInterL.t <= 1.0f && resInterL.sph.material.type != MaterialType.Light))
                        {
                            lightPower = ReceiveLight(light, interPoint, resInter.sph);
                        }

                        //calcul des coordonnées d'un point d'une sphere fictive sur le point d'intersection de la shpere pour calculer une nouvelle direction
                        Vector3 mini_sphere_coord = RandomVector(interPoint);

                        //création d'une base à partir du vecteur normal au point d'intersection de la sphere
                        Vector3 randVect = new Vector3((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble());
                        Vector3 xBase    = Vector3.Cross(normal, randVect);
                        Vector3 yBase    = Vector3.Cross(normal, xBase);
                        Vector3 zBase    = normal;

                        //calcul d'une nouvelle direction grace à la nouvelle base
                        Vector3 newDirect       = Vector3.Add(Vector3.Add(xBase * mini_sphere_coord.X, yBase * mini_sphere_coord.Y), zBase * mini_sphere_coord.Z);
                        Vector3 normalNewDirect = Vector3.Normalize(newDirect);


                        //dans la generation de la direction aléatoire du rebond, pour ne pas avoir de vecteur qui va dans la sphere
                        if (Vector3.Dot(normalNewDirect, normal) < 0)
                        {
                            newDirect = -newDirect;
                        }

                        //création d'un nouveau rayon faire le prochain rebond
                        Ray rebond = new Ray(interPoint, newDirect);
                        //cumul des albedo de toutes les surfaces sur lesquelles on rebondit
                        color = Vector3.Add(lightPower, Vector3.Multiply(Vector3.Dot(normalNewDirect, normal), Vector3.Add(resInter.sph.material.albedo, Radiance(rebond, ++stop, arbre))));


                        //division du cumul d'albedo par le nombre de rebond
                        color = Vector3.Divide(color, nb_rebond);

                        break;


                    //MIRROIR
                    case MaterialType.Mirror:
                        //calcul de la nouvelle direction
                        Vector3 newDir     = Vector3.Add(Vector3.Multiply(2 * -Vector3.Dot(ray.direction, normal), normal), ray.direction);
                        Ray     reflection = new Ray(interPoint, newDir);
                        color = Vector3.Multiply(resInter.sph.material.albedo, Radiance(reflection, ++stop, arbre));
                        break;

                    case MaterialType.Light:
                        color = resInter.sph.material.albedo;
                        break;
                    }
                }
            }
            return(color);
        }