// public double rayDepth; public Material(SColor color) { this.color = color; this.ambient = .1; // making default ambient value to be 1 this.reflectionCoefficient = .3; //this.specularCoefficient = .3; // .5 this.smoothness = 50; // 50 this.diffuseCoefficient = .3; // .4 //this.rayDepth = 10; }
public Material(SColor color, double ambient, double reflectionCoefficient, double specularCoefficient) : this(color) { this.ambient = ambient; this.reflectionCoefficient = reflectionCoefficient; this.specularCoefficient = specularCoefficient; }
public Material(SColor color, double ambient, double reflectionCoefficient) : this(color) { this.ambient = ambient; // making ambient to be optional and assigning it's default value this.reflectionCoefficient = reflectionCoefficient; }
//constructor initializer list public Material(SColor color, double ambient) : this(color) { this.ambient = ambient; // making ambient to be optional and assigning it's default value }
public SColor color2; // assigning different colors for fantastic stripes public Stripes(SColor color1, SColor color2) : base(color1) { this.color2 = color2; }
public Light(Vector location, double Intensity, SColor lightColor) { this.location = location; this.Intensity = Intensity; this.lightColor = lightColor; }
public void Render(Scene scene, Bitmap bmp) { //creating a array for storing different types of combinations for jittered sampling double[] possibleCombinations = new double[numberOfJittered]; //if jittered is given then only it will push variables to the array if (numberOfJittered > 1) { for (int l = 0; l < numberOfJittered; l++) { possibleCombinations[l] = (double)(2 * l + 1) / (numberOfJittered * 2); } } // getting the color of the for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { // for getting random values from 0 to 1 for super sampling or random sampling Random randomNumber = new Random(); // creating one empty color space for averaging the color for that pixel in multi sampling SColor samplingColor = new SColor(); //giving background color as black at first bmp.SetPixel(j, i, Color.FromArgb(255, 0, 0, 0)); //this is the loop for anti-aliasing(AA) that is number of samples if (numberOfJittered > 1) { numberOfSamples = (int)Math.Pow(numberOfJittered, 2); } double dz = (height / 2) / (Math.Tan(Algebra.convertToRad(fov * 0.5))); // calculating dz if (DOFUsed) { pixelSize = focalLength / dz; } else { pixelSize = 1 / dz; } Vector pointInThePixel = (new Vector((-width / 2), (height / 2), 0) + new Vector(0.5, -0.5, 0) + new Vector(j, -i, position.z)) * pixelSize; // changing the basis i.e. in terms of i and j of the image Double wOffset = 1; if (DOFUsed) { wOffset = focalLength; } for (int k = 0; k < numberOfSamples; k++) { Ray ray = new Ray(position, new Vector()); //checking number of jittered is given or not through it's default value //that is if number of jittered is not given than calculating as usual number of sampling way //otherwise that is if number of jittered is given than calculating number of jitterd out of it and checking through midpoints of those number of samples of each pixel if (numberOfJittered == 1) { double m = randomNumber.NextDouble(); // gives random number between 0 and 1 //// //Vector coordinate = new Vector((-width / 2), (height / 2), 0) + new Vector(0.5, -0.5, 0) + new Vector(j, -i, position.z); // changing the basis i.e. in terms of i and j of the image //// //if number of samplings is 1 then here the value of m will be 0.5 otherwise it will be m which is the random number from 0 to 1 double dx = (j - (width / 2) + (numberOfSamples == 1 ? 0.5 : m)) * pixelSize; // calculating dx double dy = (((height / 2) - i) + (numberOfSamples == 1 ? 0.5 : m)) * pixelSize; // calculating dy //double dz = 1;// (height / 2) / (Math.Tan(Algebra.convertToRad(fov * 0.5))); // calculating dz pointInThePixel = new Vector(dx, dy, wOffset); ray.direction = convertCameraToWorldCoordinates(pointInThePixel).Normalize(); // so vector (dx, dy, dz) will be the direction of the ray which is normalized } else { int kX = (k % numberOfJittered); // this is for finding the index of the array for giving possible value of mid points of jittered grid int kY = (k / numberOfJittered); // this is for finding the next index of the array for giving possible value pf mid points of jittered grid //Debug.Assert(kX == 0.25); double dx = j - (width / 2) + (numberOfSamples == 1 ? 0.5 : possibleCombinations[kX]); // calculating dx where possible combination is given by indexing the array double dy = ((height / 2) - i) + (numberOfSamples == 1 ? 0.5 : possibleCombinations[kY]); // calculating dy //double dz = 1;// (height / 2) / (Math.Tan(Algebra.convertToRad(fov * 0.5))); // calculating dz ray.direction = convertCameraToWorldCoordinates(new Vector(dx, dy, 1)).Normalize(); // so vector (dx, dy, dz) will be the direction of the ray which is normalized } if (DOFUsed) { ray = FindDOFRay(pointInThePixel); } // adding all the color of the samples that is given for multi sampling samplingColor += TraceRay(ray, scene, 0); } //taking the average of the color of those all samples SColor colorSampling = samplingColor / numberOfSamples; //now giving that average color of all those samples bmp.SetPixel(j, i, Color.FromArgb(colorSampling.GetAlphaColor(), colorSampling.GetRedColor(), colorSampling.GetGreenColor(), colorSampling.GetBlueColor())); } } }
SColor TraceRay(Ray ray, Scene scene, int rayDepth) { int maximumNumberOfReflections = 10; if (rayDepth >= maximumNumberOfReflections) { return(new SColor(0, 0, 0, 0)); } SColor shapeColor = new SColor(); SColor reflectionColor = new SColor(); SColor averageReflectionColor = new SColor(); Shape closestShape = scene.shapes[0]; // rendering multiple objects so searching for the closest shape to render double closestT = double.MaxValue; // shape which has closest T need to be rendered at first foreach (Shape shape in scene.shapes) { //transforming the ray origin along with the given tranformation matrices // origin is transformed like the point tranformation whereas ray direction is transformed like the vector transformation Vector newOrigin = FindNewPoint(shape.inverseTransformMatrix, ray.origin); Vector newDirection = (shape.inverseTransformMatrix * ray.direction).Normalize(); double t = shape.DoesIntersect(newOrigin, newDirection); // passing transformed origin and transformed direction if ((t < closestT) && (t >= 0.0001)) { closestT = t; closestShape = shape; } } Vector closeOrigin = FindNewPoint(closestShape.inverseTransformMatrix, ray.origin); Vector closeDirection = (closestShape.inverseTransformMatrix * ray.direction).Normalize(); if (closestShape.DoesIntersect(closeOrigin, closeDirection) >= 0) // checking whether the ray hits the sphere or not { Vector point = closeOrigin + (closeDirection * closestT); // point of intersection SColor color = closestShape.material.ColorAtPoint(point); double ambient = closestShape.material.ambient; double specularCoefficient = closestShape.material.specularCoefficient; SColor lightContribution = new SColor(); //transforming the point of intersection according to the transformation matrices point = FindNewPoint(closestShape.transformMatrix, point); Vector normal = closestShape.NormalAtPoint(point); // also transforming the normal of the shapes according to the transformation matrix normal = Matrix4By4.Transpose(closestShape.inverseTransformMatrix) * normal; // for multiple lighting foreach (Light light in scene.lights) { // for also checking shadows Vector shadowRayDirection = (light.location - point).Normalize(); // calculating the direction of the ray of the shadow // at first assigning inShadow variable boolean value false so that we can check whether any shape is in shadow or not bool inShadow = false; foreach (Shape shape in scene.shapes) { //checking whether each shape is in shadow or not // also checking whether the distance from the point of intersection and the direction of the ray is greater than the ray intersection distance //transforming the ray origin along with the given tranformation matrices Vector transformedShadowRayDirection = (shape.inverseTransformMatrix * shadowRayDirection).Normalize(); if (shape.DoesIntersect(point + (normal * 0.5), transformedShadowRayDirection) >= 0 && Math.Abs((light.location - point).Magnitude()) > shape.DoesIntersect(position, closeDirection)) { inShadow = true; break; // giving break point if it's in in shadow } } if (inShadow) { continue; // if it's in shadow than continuing that is casting a shadow } Vector lightToPoint = point - light.location; // position vector from light to point of intersection Vector lightDriection = lightToPoint.Normalize(); // and then normalizing it to get the direction of that vector double cosineAngle = -(lightDriection * normal); // finding the scalar value which gives the light intensity if (cosineAngle < 0) { cosineAngle = 0; } // for specular highlight Vector cameraToIntersectionPoint = (position - point).Normalize(); Vector reflectedRayDirection = (closestShape.material.ReflectedRay(ray.origin, ray.direction, closestShape).direction).Normalize(); //averageReflectionColor = reflectionColor * (1 / rayDepth); //color = averageReflectionColor + color; double specularFactor = Math.Pow((cameraToIntersectionPoint * reflectedRayDirection), closestShape.material.smoothness); if (specularFactor < 0) { specularFactor = 0; } if (cosineAngle >= 0 || specularFactor >= 0) { lightContribution = lightContribution + (light.lightColor * color * (cosineAngle * closestShape.material.diffuseCoefficient + specularFactor * closestShape.material.specularCoefficient) * light.Intensity); } } /* * if (rayDepth < maximumNumberOfReflections) * { * Ray reflectedRay = closestShape.material.ReflectedRay(closeOrigin, closeDirection, closestShape); * reflectionColor = TraceRay(reflectedRay, scene, rayDepth + 1); // recursive method * } */ shapeColor = lightContribution + (color * ambient); } return(shapeColor + closestShape.material.reflectionCoefficient * reflectionColor); }