Beispiel #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);
 }
Beispiel #2
0
        private int FindOccluder(Ray ray, ref double distance)
        {
            double tnear = Constants.Epsilon;
            double t;
            Vector3D o = ray.Origin;
            Vector3D d = ray.Direction;
            //init stack
            int entrypoint = 0;
            int exitpoint = 0;
            // init traversal
            KdTreeNode farchild;
            KdTreeNode currnode = _scene.KdTree.Root;
            _stack[entrypoint].T = tnear;
            _stack[entrypoint].Pb = o;
            _stack[exitpoint].T = distance;
            _stack[exitpoint].Pb = o + d * distance;
            _stack[exitpoint].Node = null;
            // traverse kd-tree
            while (currnode != null) {
                while (currnode.IsLeaf) {
                    //while (!currnode.IsLeaf) {
                    double splitpos = currnode.SplitPosition;
                    int axis = currnode.Axis;
                    if (_stack[entrypoint].Pb[axis] <= splitpos) {
                        if (_stack[exitpoint].Pb[axis] <= splitpos) {
                            currnode = currnode.Left;
                            continue;
                        }
                        if (_stack[exitpoint].Pb[axis] == splitpos) {
                            currnode = currnode.Right;
                            continue;
                        }
                        currnode = currnode.Left;
                        farchild = currnode.Right;
                    }
                    else {
                        if (_stack[exitpoint].Pb[axis] > splitpos) {
                            currnode = currnode.Right;
                            continue;
                        }
                        farchild = currnode.Left;
                        currnode = farchild.Right;
                    }
                    t = (splitpos - o[axis]) / d[axis];
                    int tmp = exitpoint;
                    if (++exitpoint == entrypoint)
                        exitpoint++;

                    _stack[exitpoint].Prev = tmp;
                    _stack[exitpoint].T = t;
                    _stack[exitpoint].Node = farchild;
                    _stack[exitpoint].Pb[axis] = splitpos;
                    int nextaxis = _mod[axis + 1];
                    int prevaxis = _mod[axis + 2];
                    _stack[exitpoint].Pb[nextaxis] = o[nextaxis] + t * d[nextaxis];
                    _stack[exitpoint].Pb[prevaxis] = o[prevaxis] + t * d[prevaxis];
                }
                ObjectList list = currnode.List;
                double dist = distance; // m_Stack[exitpoint].t;
                while (list != null && list.Primitive != null) {
                    Intersections++;
                    if (list.Primitive.Intersect(ray, ref dist) != RayHitDetection.Miss)
                        return 1;

                    list = list.Next;
                }

                entrypoint = exitpoint;
                currnode = _stack[exitpoint].Node;
                exitpoint = _stack[entrypoint].Prev;
            }

            return 0;
        }
Beispiel #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;
        }
Beispiel #4
0
        private RayHitDetection FindNearest(Ray ray, ref double distance, ref Primitive primitive)
        {
            RayHitDetection retval = RayHitDetection.Miss;
            double tnear = 0;
            double tfar = distance;
            double t;

            Vector3D p1 = _scene.Extends.Position;
            Vector3D p2 = p1 + _scene.Extends.Size;
            Vector3D d = ray.Direction;
            Vector3D o = ray.Origin;
            for (int i = 0; i < 3; i++) {
                if (d[i] < 0) {
                    if (o[i] < p1[i])
                        return RayHitDetection.Miss;
                }
                else if (o[i] > p2[i])
                    return RayHitDetection.Miss;
            }

            //Clip ray segment to box
            for (int i = 0; i < 3; i++) {
                double pos = o[i] + tfar * d[i];
                if (d[i] < 0) {
                    // clip end point
                    if (pos < p1[i]) tfar = tnear + (tfar - tnear) * ((o[i] - p1[i]) / (o[i] - pos));
                    // clip start point
                    if (o[i] > p2[i]) tnear += (tfar - tnear) * ((o[i] - p2[i]) / (tfar * d[i]));
                }
                else {
                    // clip end point
                    if (pos > p2[i]) tfar = tnear + (tfar - tnear) * ((p2[i] - o[i]) / (pos - o[i]));
                    // clip start point
                    if (o[i] < p1[i]) tnear += (tfar - tnear) * ((p1[i] - o[i]) / (tfar * d[i]));
                }
                if (tnear > tfar) return RayHitDetection.Miss;
            }

            // init stack
            int entrypoint = 0, exitpoint = 1;
            // init traversal
            KdTreeNode farchild;
            KdTreeNode currnode = _scene.KdTree.Root;

            _stack[entrypoint].T = tnear;
            if (tnear > 0.0f)
                _stack[entrypoint].Pb = o + d * tnear;
            else
                _stack[entrypoint].Pb = o;

            _stack[exitpoint].T = tfar;
            _stack[exitpoint].Pb = o + d * tfar;
            _stack[exitpoint].Node = null;

            // traverse kd-tree
            while (currnode != null) {
                while (currnode.IsLeaf) {
                    //while (!currnode.IsLeaf) {
                    double splitpos = currnode.SplitPosition;
                    int axis = currnode.Axis;
                    if (_stack[entrypoint].Pb[axis] <= splitpos) {
                        if (_stack[exitpoint].Pb[axis] <= splitpos) {
                            currnode = currnode.Left;
                            continue;
                        }
                        if (_stack[exitpoint].Pb[axis] == splitpos) {
                            currnode = currnode.Right;
                            continue;
                        }
                        currnode = currnode.Left;
                        farchild = currnode.Right;
                    }
                    else {
                        if (_stack[exitpoint].Pb[axis] > splitpos) {
                            currnode = currnode.Right;
                            continue;
                        }
                        farchild = currnode.Left;
                        currnode = farchild.Right;
                    }
                    t = (splitpos - o[axis]) / d[axis];
                    int tmp = exitpoint++;
                    if (exitpoint == entrypoint) exitpoint++;
                    _stack[exitpoint].Prev = tmp;
                    _stack[exitpoint].T = t;
                    _stack[exitpoint].Node = farchild;
                    _stack[exitpoint].Pb[axis] = splitpos;
                    int nextaxis = _mod[axis + 1];
                    int prevaxis = _mod[axis + 2];
                    _stack[exitpoint].Pb[nextaxis] = o[nextaxis] + t * d[nextaxis];
                    _stack[exitpoint].Pb[prevaxis] = o[prevaxis] + t * d[prevaxis];
                }
                ObjectList list = currnode.List;
                double dist = _stack[exitpoint].T;
                while (list != null && list.Primitive != null) {
                    Primitive pr = list.Primitive;
                    RayHitDetection result;
                    Intersections++;
                    if ((result = pr.Intersect(ray, ref dist)) != RayHitDetection.Miss) {
                        retval = result;
                        distance = dist;
                        primitive = pr;
                    }
                    list = list.Next;
                }

                if (retval != RayHitDetection.Miss)
                    return retval;

                entrypoint = exitpoint;
                currnode = _stack[exitpoint].Node;
                exitpoint = _stack[entrypoint].Prev;
            }

            return RayHitDetection.Miss;
        }