/// <summary> /// Convierte un modelo en un grafico con determinado material rugoso. /// </summary> public static Graphic AsGraphic(this Model model, vec4 diffuse) { return new ModelGraphic(model, Material.Rough(diffuse)); }
public static Graphic AsLight(this Model model, vec4 color) { return new ModelGraphic(model, EmissiveMaterial.Emissive(color)); }
/// <summary> /// Crea un material traslucido. /// </summary> //modificado para annadir densidad public static Material Translucent(vec4 diffuse, float shinness, float reflectance, float translucence, float density = 1.8f) { return new Material { Diffuse = Images.From(diffuse.ToColor()), Shinness = shinness, Reflectance = reflectance, Translucence = translucence, Density = density, }; }
public static EmissiveMaterial Emissive(vec4 lightColor, float shinness = 0, float reflectance = 0, float translucence = 0, float density = 1.8f, IImage diffuse = null) { return new EmissiveMaterial { Diffuse = diffuse ?? Images.From(lightColor.ToColor()), LightColor = lightColor, Shinness = shinness, Reflectance = reflectance, Density = density, Translucence = translucence }; }
public static vec4 BicubicSample(this IImage image, float x, float y) { vec4[,] p = new vec4[4, 4]; for (int i = 0; i < p.GetLength(0); i++) { for (int j = 0; j < p.GetLength(1); j++) { p[i, j] = image[(int)Math.Floor((((y * image.Height - 1) % image.Height) + image.Height)) % image.Height, (int)Math.Floor((((x * image.Width - 1) % image.Width) + image.Width)) % image.Width]; } } updateCoefficients(p); float x2 = x * x; float x3 = x2 * x; float y2 = y * y; float y3 = y2 * y; return (a00 + a01 * y + a02 * y2 + a03 * y3) + (a10 + a11 * y + a12 * y2 + a13 * y3) * x + (a20 + a21 * y + a22 * y2 + a23 * y3) * x2 + (a30 + a31 * y + a32 * y2 + a33 * y3) * x3; }
public static void updateCoefficients(vec4[,] p) { a00 = p[1, 1]; a01 = -.5f * p[1, 0] + .5f * p[1, 2]; a02 = p[1, 0] - 2.5f * p[1, 1] + 2 * p[1, 2] - .5f * p[1, 3]; a03 = -.5f * p[1, 0] + 1.5f * p[1, 1] - 1.5f * p[1, 2] + .5f * p[1, 3]; a10 = -.5f * p[0, 1] + .5f * p[2, 1]; a11 = .25f * p[0, 0] - .25f * p[0, 2] - .25f * p[2, 0] + .25f * p[2, 2]; a12 = -.5f * p[0, 0] + 1.25f * p[0, 1] - p[0, 2] + .25f * p[0, 3] + .5f * p[2, 0] - 1.25f * p[2, 1] + p[2, 2] - .25f * p[2, 3]; a13 = .25f * p[0, 0] - .75f * p[0, 1] + .75f * p[0, 2] - .25f * p[0, 3] - .25f * p[2, 0] + .75f * p[2, 1] - .75f * p[2, 2] + .25f * p[2, 3]; a20 = p[0, 1] - 2.5f * p[1, 1] + 2 * p[2, 1] - .5f * p[3, 1]; a21 = -.5f * p[0, 0] + .5f * p[0, 2] + 1.25f * p[1, 0] - 1.25f * p[1, 2] - p[2, 0] + p[2, 2] + .25f * p[3, 0] - .25f * p[3, 2]; a22 = p[0, 0] - 2.5f * p[0, 1] + 2 * p[0, 2] - .5f * p[0, 3] - 2.5f * p[1, 0] + 6.25f * p[1, 1] - 5 * p[1, 2] + 1.25f * p[1, 3] + 2 * p[2, 0] - 5 * p[2, 1] + 4 * p[2, 2] - p[2, 3] - .5f * p[3, 0] + 1.25f * p[3, 1] - p[3, 2] + .25f * p[3, 3]; a23 = -.5f * p[0, 0] + 1.5f * p[0, 1] - 1.5f * p[0, 2] + .5f * p[0, 3] + 1.25f * p[1, 0] - 3.75f * p[1, 1] + 3.75f * p[1, 2] - 1.25f * p[1, 3] - p[2, 0] + 3 * p[2, 1] - 3 * p[2, 2] + p[2, 3] + .25f * p[3, 0] - .75f * p[3, 1] + .75f * p[3, 2] - .25f * p[3, 3]; a30 = -.5f * p[0, 1] + 1.5f * p[1, 1] - 1.5f * p[2, 1] + .5f * p[3, 1]; a31 = .25f * p[0, 0] - .25f * p[0, 2] - .75f * p[1, 0] + .75f * p[1, 2] + .75f * p[2, 0] - .75f * p[2, 2] - .25f * p[3, 0] + .25f * p[3, 2]; a32 = -.5f * p[0, 0] + 1.25f * p[0, 1] - p[0, 2] + .25f * p[0, 3] + 1.5f * p[1, 0] - 3.75f * p[1, 1] + 3 * p[1, 2] - .75f * p[1, 3] - 1.5f * p[2, 0] + 3.75f * p[2, 1] - 3 * p[2, 2] + .75f * p[2, 3] + .5f * p[3, 0] - 1.25f * p[3, 1] + p[3, 2] - .25f * p[3, 3]; a33 = .25f * p[0, 0] - .75f * p[0, 1] + .75f * p[0, 2] - .25f * p[0, 3] - .75f * p[1, 0] + 2.25f * p[1, 1] - 2.25f * p[1, 2] + .75f * p[1, 3] + .75f * p[2, 0] - 2.25f * p[2, 1] + 2.25f * p[2, 2] - .75f * p[2, 3] - .25f * p[3, 0] + .75f * p[3, 1] - .75f * p[3, 2] + .25f * p[3, 3]; }
//modificado escogia el color por la pos del punto private vec4 CalculateIlumination(IntersectionInfo info, Ray r, int depth) { Material material = info.ModelGraphic.Material; //Ver si el material es emisivo vec4 result = new vec4(); if (material is EmissiveMaterial) result = ((EmissiveMaterial)material).LightColor; //Ver si el material es bump if (material is BumpMaterial) { var image = material.Diffuse; int px = (int)(info.TextureCoordenates.X * (image.Width - 1)); int py = (int)(info.TextureCoordenates.Y * (image.Height - 1)); info.Normal = info.Normal + 10 * (vec3)((BumpMaterial)material).Normals[px, py]; } //Buscando el color en el punto (se puede variar el modo de Sampling) vec4 colorOfPoint = material.Diffuse.BilinearSample(info.TextureCoordenates.X, 1-info.TextureCoordenates.Y); ; //Aporte de la luz ambiental result += (1 - material.Translucence) * colorOfPoint * Scene.AmbientLight; #region Aporte de cada luz al punto foreach (var light in Lights) { Ray ray = Ray.FromTo(info.Position, light.Position); bool eclipsedLight = false; //Detectar si la luz es eclipsada por otro objeto foreach (var graphic in Scene.Graphics) { IntersectionInfo infoAux; if (Intersect(ray, graphic, out infoAux) && (infoAux.Position - ray.From).Length < (light.Position - ray.From).Length && (infoAux.ModelGraphic != light.ModelGraphic) && (infoAux.ModelGraphic != info.ModelGraphic)) { eclipsedLight = true; break; } } //Procesar el aporte de la luz si no esta eclipsada if (!eclipsedLight) { //este vector tiene la direccion desde el pto a la luz vec3 lightDirection = (light.Position - info.Position).Normalized; //Aporte de la reflexion difusa //la intensidad de la luz es directamente proporcional al coseno del angulo entre el rayo de luz y la normal result += PutInRange(light.Intensity * colorOfPoint * (vec3.dot(lightDirection, info.Normal))); //Aporte de la reflexion especular result += PutInRange(light.Intensity * colorOfPoint * (float)Math.Pow(vec3.dot(info.Normal, lightDirection - r.Direction), material.Shinness)); } } #endregion if (depth > 0) { //Aporte de la luz reflejada por otros objetos Ray reflectionRay = Ray.FromDirection(info.Position, r.Direction - 2 * vec3.dot(r.Direction, info.Normal) * info.Normal); vec4 reflectionColor = GetRayColor(reflectionRay, depth - 1, false); result += material.Reflectance * reflectionColor; //Aporte de la luz refractada if(material.Translucence > 0) { float desc = (float)(1 + (Math.Pow(vec3.dot(-1 * r.Direction, info.Normal), 2) - 1) / Math.Pow(material.Density, 2)); if (desc > 0) { vec3 refractionDirection = (r.Direction*(1f/material.Density)) + ((vec3.dot(-1 * r.Direction, info.Normal) * (1f / material.Density)) - (float) Math.Sqrt(desc))*info.Normal; Ray refractionRay = Ray.FromDirection(info.Position, refractionDirection); vec4 refractionColor = GetRayColor(refractionRay, depth - 1, false); result += material.Translucence *refractionColor; } } } return PutInRange(result); }
private vec4 PutInRange( vec4 color) { color.X = Math.Min(Math.Max(color.X, 0), 1); color.Y = Math.Min(Math.Max(color.Y, 0), 1); color.Z = Math.Min(Math.Max(color.Z, 0), 1); color.W = Math.Min(Math.Max(color.W, 0), 1); return color; }
public static vec4 normalize(vec4 v) { float length = v.Length; if (length == 0) throw new InvalidOperationException(); return new vec4(v.X / length, v.Y / length, v.Z / length, v.W / length); }
//modificado public LightSource(vec3 position, vec4 intensity, ModelGraphic modelGraphicLight) { Position = position; Intensity = intensity; ModelGraphic = modelGraphicLight; }
public static float dot(vec4 v1, vec4 v2) { return v1.X * v2.X + v1.Y * v2.Y + v1.Z * v2.Z + v1.W * v2.W; }
public static vec4 cross(vec4 v1, vec4 v2, vec4 v3) { throw new NotSupportedException(); }
public SolidImage(vec4 color) { this.Color = color; }
/// <summary> /// Crea un material diffuse. /// </summary> public static Material Rough(vec4 diffuse) { return new Material { Diffuse = Images.From(diffuse.ToColor()), Shinness = 0, Reflectance = 0f, Translucence = 0 }; }
/// <summary> /// Crea un material brilloso /// </summary> public static Material Glossy(vec4 diffuse, float shinness, float reflectance) { return new Material { Diffuse = Images.From(diffuse.ToColor()), Shinness = shinness, Reflectance = reflectance, Translucence = 0 }; }