Exemplo n.º 1
0
 public void Draw(int startWidth, int endWidth, int startHeight, int endHeight, int height, int width, ref byte[] rgbValues)
 {
     for (int j = startHeight; j < endHeight; j++)
     {
         for (int i = startWidth; i < endWidth; i++)
         {
             double x    = (2 * (i + 0.5) / width - 1) * Math.Tan(field / 2) * width / height;
             double y    = -(2 * (j + 0.5) / height - 1) * Math.Tan(field / 2);
             Ray    beam = new Ray(new Point(0, 0, 0), new Point(x, y, 1));
             SetPixel(i, j, ref rgbValues, width, ColorHandler.VectorToColor(TraceRay(beam, 0)));
         }
     }
 }
Exemplo n.º 2
0
        private Vector TraceRay(Ray beam, int depth)
        {
            Vector   result            = new Vector(0.2, 0.7, 0.8);
            double   diffuseIntensity  = 0;
            double   specularIntensity = 0;
            Material material          = new Material();
            Vector   normal            = new Vector(0, 0, 0);
            Point    litSpot           = new Point(0, 0, 0);

            /*Возвращаем фоновый цвет, если на пути луча нет объекта*/
            if (depth >= maxDepth || !ShapeMet(beam, ref litSpot, ref normal, ref material, out var shape))
            {
                return(result);
            }
            else
            {
                result = material.Pattern.ColorFromPoint(shape.Translate(litSpot));
            }

            Material tmpMaterial  = new Material();
            Vector   shadowNormal = new Vector(0, 0, 0);
            Vector   reflectColor = new Vector(0, 0, 0);

            if (material.Albedo[2] != 0) //Проверка объекта на зеркальность
            {
                Point  reflectSpot = new Point(litSpot.X, litSpot.Y, litSpot.Z);
                Vector reflectDir  = Reflect(beam.Direction, normal);
                /*Сдвиг освещенной точки вдоль нормали, чтобы избежать повторного пересечения с тем же объектом*/
                Offset(reflectSpot, reflectDir, normal);
                Ray reflect = new Ray(reflectSpot, reflectDir);
                reflectColor = TraceRay(reflect, depth + 1);
            }

            Vector refractColor = new Vector(0, 0, 0);

            if (material.Albedo[3] != 0) //Проверка объекта на прозрачность
            {
                Vector refractDir = Refract(beam.Direction, normal, material.RefractiveIndex);
                if (refractDir.Length != 0)
                {
                    Point refractSpot = new Point(litSpot.X, litSpot.Y, litSpot.Z);
                    /*Сдвиг освещенной точки вдоль нормали, чтобы избежать повторного пересечения с тем же объектом*/
                    Offset(refractSpot, refractDir, normal);
                    Ray refract = new Ray(refractSpot, refractDir);
                    refractColor = TraceRay(refract, depth + 1);
                }
            }

            Vector illuminationColor = new Vector(0, 0, 0);

            foreach (var light in lights)
            {
                Vector lightColor = new Vector(1, 1, 1);
                double intensity  = light.Intensity;
                Vector lightDir   = new Vector(litSpot, light.Position).Normalize();
                Point  shadowSpot = new Point(litSpot.X, litSpot.Y, litSpot.Z);
                Offset(shadowSpot, lightDir, normal); // Сдвиг освещенной точки вдоль нормали, чтобы избежать повторного пересечения с тем же объектом
                Ray shadowRay = new Ray(shadowSpot, lightDir);
                /*Вычисление теней*/
                if (ShapeMet(shadowRay, ref shadowSpot, ref shadowNormal, ref tmpMaterial, out var shadowShape))
                {
                    if (tmpMaterial.Albedo[3] == 0) // Проверка объекта но прозрачность
                    {
                        continue;
                    }
                    intensity *= tmpMaterial.Albedo[3]; // Приглушение света в соответствии с прозрачностью объекта
                    if (tmpMaterial.Albedo[0] != 0)     // Придание лучу цвета прозрачного объекта
                    {
                        lightColor = tmpMaterial.Pattern.ColorFromPoint(shadowSpot) * tmpMaterial.Albedo[3];
                    }
                }
                else
                {
                    specularIntensity += Math.Pow(Math.Max(0, Reflect(lightDir, normal) * beam.Direction), // Вычисление интенсивности бликов
                                                  material.SpecularExponent) * light.Intensity;
                }
                illuminationColor += lightColor; // Суммарный цвет освещения в точке
                diffuseIntensity  += Math.Max(0, intensity * (lightDir * normal));
            }
            ColorHandler.NormalizeColor(ref illuminationColor); // Приведение цвета освещения к стандартному виду
            result = ColorHandler.Calculate(illuminationColor, result, reflectColor,
                                            refractColor, diffuseIntensity, specularIntensity, material);
            ColorHandler.NormalizeColor(ref result); // Предотвращение засветки
            return(result);
        }