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; } }
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)); }
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); }
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()); }
public Ray GenerateRay(LocalGeo geo, out RTColor color) { color = Color; return(new Ray(geo.Point, Direction.Normalize(), 1e-3f, float.MaxValue, true)); }
public DirLight(RTVector dir, RTColor color) { Direction = dir; Color = color; }
public PointLight(RTPoint source, RTColor color) { Source = source; Color = color; }