private void InitPrimitiveProperties()
        {
            RTColor lastAmbient   = _currentMaterial?.Properties.Ambient;
            RTColor lastDiffuse   = _currentMaterial?.Properties.Diffuse;
            RTColor lastEmission  = _currentMaterial?.Properties.Emission;
            RTColor lastSpecular  = _currentMaterial?.Properties.Specular;
            float?  lastShininess = _currentMaterial?.Properties.Shininess;

            _currentMaterial = new Material();
            if (lastAmbient != null)
            {
                _currentMaterial.Properties.Ambient = lastAmbient;
            }
            if (lastDiffuse != null)
            {
                _currentMaterial.Properties.Diffuse = lastDiffuse;
            }
            if (lastEmission != null)
            {
                _currentMaterial.Properties.Emission = lastEmission;
            }
            if (lastSpecular != null)
            {
                _currentMaterial.Properties.Specular = lastSpecular;
            }
            if (lastShininess.HasValue)
            {
                _currentMaterial.Properties.Shininess = lastShininess.Value;
            }
        }
Exemple #2
0
        public Ray GenerateRay(LocalGeo geo, out RTColor color)
        {
            color = Color;
            RTVector ray = Source - geo.Point;

            return(new Ray(geo.Point, ray.Normalize(), 1e-3f, ray.Length, false));
        }
Exemple #3
0
        private RTColor Shading(LocalGeo geo, ShadingInfos si, Ray camRay, Ray lightRay, RTColor lightCol)
        {
            float   nDotL   = RTVector.DotProduct(geo.Normal, lightRay.Vector);
            RTColor lambert = lightCol * si.Diffuse * (nDotL > 0 ? nDotL : 0.0f);

            RTVector half  = (lightRay.Vector - camRay.Vector.Normalize()).Normalize();
            float    nDotH = RTVector.DotProduct(geo.Normal, half);
            RTColor  phong = lightCol * si.Specular * (float)Math.Pow((nDotH > 0 ? nDotH : 0.0f), si.Shininess);

            float   r   = lightRay.Directional ? 0 : lightRay.TMax; // Dans le cas d'un point, le t max est la distance entre le point et la source
            RTColor res = (lambert + phong) / (Attenuation.Constant + Attenuation.Linear * r + Attenuation.Quadratic * (float)Math.Pow(r, 2));

            return(res);
        }
Exemple #4
0
        public RTColor Trace(Ray ray, int depth)
        {
            RTColor res = new RTColor();

            float lastT = float.MaxValue;
            bool  shadow;

            // TODO: initialiser l'arbre autrepart
            // TODO: corriger la bounding box des spheres
            if (_tree == null)
            {
                _tree = new BBTree(Primitives);
            }
            IEnumerable <HitResult> hits = _tree.Hit(ray);

            //IList<HitResult> hits = Primitives.Select(p =>
            //{
            //    if (p.Intersect(ray, true, out LocalGeo geo, out float t))
            //    {
            //        return new HitResult { Primitive = p, Geo = geo, T = t };
            //    }

            //    return null;
            //}).Where(h => h != null).ToList();

            foreach (HitResult h in hits)
            {
                if (h.T < lastT)
                {
                    lastT = h.T;

                    ShadingInfos si = h.Primitive.GetShading(h.Geo);

                    // Ambient & emission
                    res = si.Emission + si.Ambient;

                    // Phong shading
                    foreach (ILight light in Lights)
                    {
                        shadow = false;
                        RTColor lightCol;
                        Ray     lightRay = light.GenerateRay(h.Geo, out lightCol);

                        foreach (IPrimitive pShadow in Primitives)
                        {
                            if (pShadow.Intersect(lightRay, false, out _, out _))
                            {
                                shadow = true;
                            }
                        }

                        if (!shadow)
                        {
                            res += Shading(h.Geo, si, ray, lightRay, lightCol);
                        }
                    }

                    // Reflection
                    if ((si.Specular.Red > 0 || si.Specular.Green > 0 || si.Specular.Blue > 0) && depth < MaxDepth)
                    {
                        Ray reflected = new Ray(h.Geo.Point, ray.Vector - 2.0f * RTVector.DotProduct(ray.Vector, h.Geo.Normal) * h.Geo.Normal, 1e-3f, float.MaxValue, false);
                        res += si.Specular * Trace(reflected, depth + 1);
                    }
                }
            }

            return(res);
        }
        public Scene BuildScene()
        {
            SceneBuilder sb = new SceneBuilder();

            string line;

            InitPrimitiveProperties();
            _transStack            = new Stack <Transformation>();
            _currentTransformation = new Transformation();

            using (FileStream fs = new FileStream(_path, FileMode.Open, FileAccess.Read, FileShare.Read))
                using (StreamReader sr = new StreamReader(fs))
                {
                    while (!sr.EndOfStream)
                    {
                        line = sr.ReadLine().TrimStart(" \t".ToCharArray()).ToLowerInvariant();

                        if (string.IsNullOrWhiteSpace(line) || line[0] == '#')
                        {
                            continue;
                        }

                        string[] split = line.Split(" \t".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

                        switch (split[0])
                        {
                            #region General/Camera
                        case "size":
                            int width  = int.Parse(split[1]);
                            int height = int.Parse(split[2]);
                            sb.SetSize(width, height);
                            break;

                        case "maxdepth":
                            int maxDepth = int.Parse(split[1]);
                            sb.SetMaxDepth(maxDepth);
                            break;

                        case "output":
                            sb.SetOutputPath(split[1]);
                            break;

                        case "camera":
                            RTPoint  lFrom = PointFromConfig(split);
                            RTPoint  lAt   = PointFromConfig(split, 4);
                            RTVector up    = VectorFromConfig(split, 7);
                            float    fovy  = float.Parse(split[10]);
                            sb.SetCamera(lFrom, lAt, up, fovy);
                            break;
                            #endregion

                            #region Geometry
                        case "sphere":
                            RTPoint center = PointFromConfig(split);
                            float   radius = float.Parse(split[4]);
                            Sphere  s      = new Sphere(center, radius, _currentTransformation);

                            sb.AddGeoPrimitive(s, _currentMaterial);
                            InitPrimitiveProperties();
                            break;

                        case "maxverts":
                            int maxverts = int.Parse(split[1]);
                            _currentVertex = new List <Vertex>(maxverts);
                            break;

                        case "maxvertsnorms":
                            int maxvertsnorms = int.Parse(split[1]);
                            _currentVertex = new List <Vertex>(maxvertsnorms);
                            break;

                        case "vertex":
                            RTPoint vertex = PointFromConfig(split);
                            _currentVertex.Add(new Vertex(vertex));
                            break;

                        case "vertexnormal":
                            RTPoint  vertexnorm = PointFromConfig(split);
                            RTVector normal     = VectorFromConfig(split, 3);
                            _currentVertex.Add(new Vertex(vertexnorm, normal));
                            break;

                        case "tri":
                        case "trinormal":
                            int v1 = int.Parse(split[1]);
                            int v2 = int.Parse(split[2]);
                            int v3 = int.Parse(split[3]);

                            List <Vertex> vList = new List <Vertex>();
                            vList.Add(_currentVertex[v1]);
                            vList.Add(_currentVertex[v2]);
                            vList.Add(_currentVertex[v3]);

                            Triangle tri = new Triangle(vList, _currentTransformation);
                            sb.AddGeoPrimitive(tri, _currentMaterial);
                            InitPrimitiveProperties();
                            break;
                            #endregion

                            #region Transforms
                        case "translate":
                            RTVector transvec = VectorFromConfig(split);
                            _currentTransformation.AddTransform(new Translation(transvec));
                            break;

                        case "rotate":
                            RTVector rotaxis = VectorFromConfig(split);
                            float    degrees = float.Parse(split[4]);
                            _currentTransformation.AddTransform(new Rotation(rotaxis, degrees));
                            break;

                        case "scale":
                            _currentTransformation.AddTransform(new Scaling(float.Parse(split[1]), float.Parse(split[2]), float.Parse(split[3])));
                            break;

                        case "pushtransform":
                            _transStack.Push(new Transformation(_currentTransformation));
                            break;

                        case "poptransform":
                            _currentTransformation = _transStack.Pop();
                            break;
                            #endregion

                            #region Lights
                        case "directional":
                            RTVector dir    = VectorFromConfig(split);
                            RTColor  dirCol = ColorFromConfig(split, 4);
                            sb.AddLight(new DirLight(dir, dirCol));
                            break;

                        case "point":
                            RTPoint source   = PointFromConfig(split);
                            RTColor pointCol = ColorFromConfig(split, 4);
                            sb.AddLight(new PointLight(source, pointCol));
                            break;

                        case "attenuation":
                            Attenuation att = new Attenuation
                            {
                                Constant  = float.Parse(split[1]),
                                Linear    = float.Parse(split[2]),
                                Quadratic = float.Parse(split[3])
                            };
                            sb.SetAttenuation(att);
                            break;

                        case "ambient":
                            RTColor ambient = ColorFromConfig(split);
                            _currentMaterial.Properties.Ambient = ambient;
                            break;
                            #endregion

                            #region Materials
                        case "diffuse":
                            RTColor diffuse = ColorFromConfig(split);
                            _currentMaterial.Properties.Diffuse = diffuse;
                            break;

                        case "specular":
                            RTColor spec = ColorFromConfig(split);
                            _currentMaterial.Properties.Specular = spec;
                            break;

                        case "shininess":
                            float shine = float.Parse(split[1]);
                            _currentMaterial.Properties.Shininess = shine;
                            break;

                        case "emission":
                            RTColor emission = ColorFromConfig(split);
                            _currentMaterial.Properties.Emission = emission;
                            break;
                            #endregion
                        }
                    }
                }

            return(sb.Build());
        }
Exemple #6
0
        public Ray GenerateRay(LocalGeo geo, out RTColor color)
        {
            color = Color;

            return(new Ray(geo.Point, Direction.Normalize(), 1e-3f, float.MaxValue, true));
        }
Exemple #7
0
 public DirLight(RTVector dir, RTColor color)
 {
     Direction = dir;
     Color     = color;
 }
Exemple #8
0
 public PointLight(RTPoint source, RTColor color)
 {
     Source = source;
     Color  = color;
 }