Exemple #1
0
 private Primitive RenderRay(Vector3D screenPos, ref Color3D acc)
 {
     Vector3D dir = (screenPos - _origin).Normalize();
     Ray r = new Ray(_origin, dir);
     RaysCast++;
     double dist = 0;
     //trace ray
     return Raytrace(r, ref acc, 1, 1.0, ref dist, Constants.Samples, 1.0 / Constants.Samples);
 }
Exemple #2
0
        public bool RenderTiles()
        {
            //render scene
            long ticks = DateTime.Now.Ticks;
            // render remaining tiles
            int tx = _currCol, ty = _currRow;
            Vector3D tdir = _p1 + (tx * Constants.TileSize) * _dX + (ty * Constants.TileSize) * _dY;

            while (true) {
                Vector3D ldir = tdir;
                for (int y = 0; y < Constants.TileSize; y++) {
                    Vector3D pdir = ldir;
                    for (int x = 0; x < Constants.TileSize; x++) {
                        Color3D acc = new Color3D(0, 0, 0);
                        RenderRay(pdir, ref acc);
                        int red = (int) (acc.R*256);
                        int green = (int) (acc.G*256);
                        int blue = (int) (acc.B*256);
                        if (red > 255) red = 255;
                        if (green > 255) green = 255;
                        if (blue > 255) blue = 255;

                        int pX = tx*Constants.TileSize + x;
                        int pY = ty*Constants.TileSize + y;
                        _frameBuffer.SetPixel(pX, pY, Color.FromArgb(red, green, blue));
                        pdir += _dX;
                    }
                    ldir += _dY;
                }
                tdir += _dX*Constants.TileSize;
                if (++tx == _xTiles) {
                    tx = 0;
                    ty++;
                    tdir = _p1 + (ty*Constants.TileSize)*_dY;
                }

                if (ty < _yTiles) {
                    //See if we've been drawing for a while now
                    if (DateTime.Now.Ticks - ticks > 200) {
                        //Return temporary to windows to let it redraw itself
                        _currCol = tx;
                        _currRow = ty;
                        return false; //possibly still work to do
                    }
                }
                else
                    break;
            }

            //done
            return true;
        }
Exemple #3
0
        private Primitive Raytrace(Ray ray, ref Color3D acc, int depth, double rIndex, ref double distance, double samples, double sScale)
        {
            //trace primary ray
            distance = Constants.Maxdouble;
            Primitive prim = null;

            //find the nearest intersection
            RayHitDetection result = FindNearest(ray, ref distance, ref prim);

            //No hit? Return null then
            if (result == RayHitDetection.Miss || prim == null)
                return null;

            //Determine color at point of intersection
            Vector3D pi = ray.Origin + ray.Direction * distance;
            Color3D color = prim.GetColor(pi);
            Vector3D n = prim.GetNormal(pi);

            //trace lights
            foreach (Light light in _scene.Lights) {
                Vector3D l = null;
                double shade = CalcShade(light, pi, ref l, samples, sScale);
                if (shade > 0) {
                    //calculate diffuse shading
                    if (prim.Material.Diffuse > 0) {
                        double dot = l.DotProduct(n);
                        if (dot > 0) {
                            double diff = dot * prim.Material.Diffuse * shade;
                            //add diffuse component to ray color
                            acc += diff*color*light.Color;
                        }
                    }
                    // determine specular component using Schlick's BRDF approximation
                    if (prim.Material.Specular > 0) {
                        //point light source: sample once for specular highlight
                        Vector3D r = l - 2 * l.DotProduct(n) * n;
                        double dot = ray.Direction.DotProduct(r);
                        if (dot > 0) {
                            double spec = dot*prim.Material.Specular*shade/(50 - 50*dot + dot);
                            //add specular component to ray color
                            acc += spec*light.Color;
                        }
                    }
                }
            }

            //Calculate reflections
            if (Constants.ReflectionsEnabled) {
                double refl = prim.Material.Reflection;
                if (refl > 0 && depth < Constants.TraceDepth) {
                    double drefl = prim.Material.DiffuseReflection;
                    if (drefl > 0 && depth < 3) {
                        //calculate diffuse reflection
                        Vector3D rp = ray.Direction - 2*ray.Direction.DotProduct(n)*n;
                        Vector3D rn1 = new Vector3D(rp.Z, rp.Y, -rp.X);
                        Vector3D rn2 = rp.CrossProduct(rn1);
                        refl *= sScale;
                        for (int i = 0; i < Constants.Samples; i++) {
                            double xoffs, yoffs;
                            do {
                                xoffs = (_twister.Rand - .5)*drefl;
                                yoffs = (_twister.Rand - .5)*drefl;
                            } while (xoffs*xoffs + yoffs*yoffs > drefl*drefl);

                            Vector3D r = (rp + rn1*xoffs + rn2*yoffs*drefl).Normalize();
                            Color3D rCol = new Color3D(0, 0, 0);
                            double dist = 0;
                            Raytrace(new Ray(pi + r*Constants.Epsilon, r), ref rCol, depth + 1, rIndex, ref dist,
                                     samples*.25, sScale*4);
                            RaysCast++;
                            acc += refl*rCol*color;
                        }
                    }
                    else {
                        //calculate perfect reflection
                        Vector3D r = ray.Direction - 2*ray.Direction.DotProduct(n)*n;
                        Color3D rCol = new Color3D(0, 0, 0);
                        double dist = 0;
                        Raytrace(new Ray(pi + r*Constants.Epsilon, r), ref rCol, depth + 1, rIndex, ref dist, samples*.5,
                                 sScale*2);
                        RaysCast++;
                        acc += refl*rCol*color;
                    }
                }
            }

            //Calculate refraction
            if (Constants.RefractionsEnabled) {
                double refr = prim.Material.Refraction;
                if (refr > 0 && depth < Constants.TraceDepth) {
                    double localRIndex = prim.Material.RefractionIndex;
                    double indexDiff = rIndex/localRIndex;
                    Vector3D vN = prim.GetNormal(pi)*(double) result;
                    double cosI = -(vN.DotProduct(ray.Direction));
                    double cosT2 = 1f - indexDiff*indexDiff*(1f - cosI*cosI);
                    if (cosT2 > 0) {
                        Vector3D t = indexDiff*ray.Direction + (indexDiff*cosI - Math.Sqrt(cosT2))*vN;
                        Color3D rCol = new Color3D();
                        double dist = 0;
                        Raytrace(new Ray(pi + t*Constants.Epsilon, t), ref rCol, depth + 1, localRIndex, ref dist,
                                 samples*.5, sScale*2);
                        RaysCast++;

                        //Apply Beer's law
                        Color3D absorbance = prim.Material.Color*.15*-dist;
                        Color3D transparency = new Color3D(Math.Exp(absorbance.R), Math.Exp(absorbance.G),
                                                           Math.Exp(absorbance.B));
                        acc += rCol*transparency;
                    }
                }
            }

            return prim;
        }
Exemple #4
0
 public void SetColor(Color3D c)
 {
     R = c.R;
     G = c.G;
     B = c.B;
 }