예제 #1
0
파일: Engine.cs 프로젝트: pirho/RaySharp
        public void InitRenderer(Vector3D pos, Vector3D target)
        {
            // set eye and screen plane position
            _origin = new Vector3D( 0, 0, -5 );
            _p1 = new Vector3D( -4,  3, 0 );
            _p2 = new Vector3D(  4,  3, 0 );
            _p3 = new Vector3D(  4, -3, 0 );
            _p4 = new Vector3D( -4, -3, 0 );
            // calculate camera matrix
            Vector3D zaxis = (target - pos).Normalize();
            Vector3D up = new Vector3D( 0, 1, 0 );
            Vector3D xaxis = up.CrossProduct( zaxis );
            Vector3D yaxis = xaxis.CrossProduct( -zaxis );
            Matrix m = new Matrix();
            m[0] = xaxis.X;
            m[1] = xaxis.Y;
            m[2] = xaxis.Z;
            m[4] = yaxis.X;
            m[5] = yaxis.Y;
            m[6] = yaxis.Z;
            m[8] = zaxis.X;
            m[9] = zaxis.Y;
            m[10] = zaxis.Z;
            m.Invert();
            m[3] = pos.X;
            m[7] = pos.Y;
            m[11] = pos.Z;
            // move camera
            _origin = m.Transform(_origin);
            _p1 = m.Transform( _p1 );
            _p2 = m.Transform( _p2 );
            _p3 = m.Transform( _p3 );
            _p4 = m.Transform( _p4 );
            // calculate screen plane interpolation vectors
            _dX = (_p2 - _p1) * (1.0 / _width);
            _dY = (_p4 - _p1) * (1.0 / _height);

            // setup the tile renderer
            _currCol = 0;
            _currRow = 0; // 20 / Constants.TileSize;
            _xTiles = _width / Constants.TileSize;
            _yTiles = _height / Constants.TileSize; // (_height - 20) / Constants.TileSize;

            // reset counters
            Intersections = 0;
            RaysCast = 0;

            _twister = new Twister(0);
        }
예제 #2
0
파일: Vector3D.cs 프로젝트: pirho/RaySharp
 public double DotProduct(Vector3D v)
 {
     return X*v.X + Y*v.Y + Z*v.Z;
 }
예제 #3
0
파일: Vector3D.cs 프로젝트: pirho/RaySharp
 public Vector3D CrossProduct(Vector3D v)
 {
     return new Vector3D(Y*v.Z - Z * v.Y, Z * v.X - X * v.Z, X * v.Y - Y * v.X);
 }
예제 #4
0
파일: Engine.cs 프로젝트: pirho/RaySharp
        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;
        }
예제 #5
0
파일: Engine.cs 프로젝트: pirho/RaySharp
 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);
 }
예제 #6
0
파일: Matrix.cs 프로젝트: pirho/RaySharp
 public void Rotate(Vector3D pos, double rX, double rY, double rZ)
 {
     Matrix t = new Matrix();
     t.RotateX(rZ);
     RotateY(rY);
     Concatenate(t);
     t.RotateZ(rX);
     Concatenate(t);
     Translate(pos);
 }
예제 #7
0
파일: Engine.cs 프로젝트: pirho/RaySharp
        private double CalcShade(Light light, Vector3D ip, ref Vector3D direction, double samples, double sScale)
        {
            double retVal = 0;
            if (light.Type == Light.LightType.Point) {
                //Handle point light source
                retVal = 0;
                direction = light.Position - ip;
                double tdist = direction.Length;
                direction *= 1/tdist;
                tdist *= 1 - 4*Constants.Epsilon;
                RaysCast++;
                if (FindOccluder(new Ray(ip + direction * Constants.Epsilon, direction), ref tdist) == 0)
                    return 1;
            }
            else if (light.Type == Light.LightType.Area) {
                // Monte Carlo rendering
                retVal = 0;
                direction = (light.Position - ip).Normalize();
                Vector3D deltax = light.CellX;
                Vector3D deltay = light.CellY;
                for (int i = 0; i < samples; i++) {
                    Vector3D lp = light.GetGrid(i & 15) + _twister.Rand*deltax + _twister.Rand*deltay;
                    Vector3D dir = lp - ip;
                    double ldist = dir.Length;
                    dir *= 1/ldist;
                    ldist *= 1 - 4*Constants.Epsilon;
                    RaysCast++;
                    if (FindOccluder(new Ray(ip + dir * Constants.Epsilon, dir), ref ldist) == 0)
                        retVal += sScale;
                }
            }

            return retVal;
        }
예제 #8
0
파일: Matrix.cs 프로젝트: pirho/RaySharp
 public void Translate(Vector3D pos)
 {
     _data[TX] += pos.X;
     _data[TY] += pos.Y;
     _data[TZ] += pos.Z;
 }
예제 #9
0
파일: Matrix.cs 프로젝트: pirho/RaySharp
 public Vector3D Transform(Vector3D v)
 {
     double x = _data[0] * v.X + _data[1] * v.Y + _data[2] * v.Z + _data[3];
     double y = _data[4] * v.X + _data[5] * v.Y + _data[6] * v.Z + _data[7];
     double z = _data[8] * v.X + _data[9] * v.Y + _data[10] * v.Z + _data[11];
     return new Vector3D(x, y, z);
 }
예제 #10
0
파일: Scene.cs 프로젝트: pirho/RaySharp
        public bool InitScene()
        {
            Material mat;
            int x;
            Vector3D p1, p2;
            switch (_state) {
                case 0:
                    //constructing geometry...
                    break;
                case 1:
                    // ground plane
                    mat = new Material();
                    //Changed to water
                    mat.SetParameters(0.3, 0.7, new Color3D(0, 128, 255), 0.2, 0.1);
                    mat.RefractionIndex = 1.33157;
                    mat.DiffuseReflection = .1;
                    //mat.SetParameters(0.0f, 0.0f, new Color3D(0.4f, 0.3f, 0.3f), 1.0f, 0.0f);
                    AddPlane(new Vector3D(-13, -4.4f, -5.5f), new Vector3D(13, -4.4f, -5.5f),
                              new Vector3D(13, -4.4f, 29), new Vector3D(-13, -4.4f, 29), mat);
                    // back plane
                    mat = new Material();
                    mat.SetParameters(0.0, 0.0, new Color3D(0.5, 0.3, 0.5), 0.6, 0.0);
                    AddPlane(new Vector3D(-13, -4.4f, 12), new Vector3D(13, -4.4f, 12),
                              new Vector3D(13, 7.4f, 12), new Vector3D(-13, 7.4f, 12), mat);

                    //AddPlane(new Vector3D(-13, -4.4f, 8), new Vector3D(13, -4.4f, 16),
                    //          new Vector3D(13, 7.4f, 16), new Vector3D(-13, 7.4f, 8), mat);

                    // ceiling plane
                    mat = new Material();
                    mat.SetParameters(0.0, 0.0, new Color3D(0.4, 0.7, 0.7), 0.5, 0.0);
                    AddPlane(new Vector3D(13, 7.4f, -5.5f), new Vector3D(-13, 7.4f, -5.5f),
                              new Vector3D(-13, 7.4f, 29), new Vector3D(13, 7.4f, 29), mat);

                    // big sphere
                    // m_Primitive[m_Primitives] = new Primitive( Primitive::SPHERE, vector3( 2, 0.8f, 3 ), 2.5f );
                    // m_Primitive[m_Primitives++]->GetMaterial()->SetParameters( 0.2f, 0.8f, Color( 0.7f, 0.7f, 1.0f ), 0.2f, 0.8f );
                    // small sphere
                    Primitive p = new Primitive(PrimitiveType.Sphere, new Vector3D(-5.5f, -0.5f, 7), 2);
                    p.Material.SetParameters(0.5f, 0.0f, new Color3D(.7f, .7f, 1), .1f, .8f);
                    Primitives.Add(p);

                    Light l;
                    /*
                    // area lights
                    l = new Light(Light.LightType.Area, new Vector3D(-1, 6, 4), new Vector3D(1, 6, 4), new Vector3D(-1, 6, 6), new Color3D(0.7f, 0.7f, 0.7f));
                    Lights.Add(l);
                    l = new Light(Light.LightType.Area, new Vector3D(-1, 6, -1), new Vector3D(1, 6, -1), new Vector3D(-1, 6, 1), new Color3D(0.7f, 0.7f, 0.7f));
                    Lights.Add(l);
                    */

                    // point lights
                    l = new Light(Light.LightType.Point, new Vector3D(0, 5, 5), new Color3D(0.4f, 0.4f, 0.4f));
                    Lights.Add(l);
                    l = new Light(Light.LightType.Point, new Vector3D(-3, 5, 1), new Color3D(0.6f, 0.6f, 0.8f));
                    Lights.Add(l);

                    // extra sphere
                    p = new Primitive(PrimitiveType.Sphere, new Vector3D(-1.5f, -3.8f, 1), 1.5f);
                    p.Material.SetParameters(0.0f, 0.8f, new Color3D(1.0f, 0.4f, 0.4f), 0.2f, 0.8f);
                    Primitives.Add(p);

                    // grid
                    for ( x = 0; x < 8; x++ ) {
                        for ( int y = 0; y < 7; y++ ) {
                            p = new Primitive(PrimitiveType.Sphere, new Vector3D(-4.5f + x*1.5f, -4.3f + y*1.5f, 10), 0.3f);
                            p.Material.SetParameters(0.0f, 0.0f, new Color3D(0.3f, 1.0f, 0.4f), 0.6f, 0.6f);
                            Primitives.Add(p);
                        }
                    }
                    for ( x = 0; x < 8; x++ ) {
                        for ( int y = 0; y < 8; y++ ) {
                            p = new Primitive(PrimitiveType.Sphere, new Vector3D(-4.5f + x*1.5f, -4.3f, 10.0f - y*1.5f), 0.3f);
                            p.Material.SetParameters(0.0f, 0.0f, new Color3D(0.3f, 1.0f, 0.4f), 0.6f, 0.6f);
                            Primitives.Add(p);
                        }
                    }
                    for ( x = 0; x < 16; x++ ) {
                        for ( int y = 0; y < 8; y++ ) {
                            p = new Primitive(PrimitiveType.Sphere, new Vector3D(-8.5f + x*1.5f, 4.3f, 10.0f - y), 0.3f);
                            p.Material.SetParameters(0.0f, 0.0f, new Color3D(0.3f, 1.0f, 0.4f), 0.6f, 0.6f);
                            Primitives.Add(p);
                        }
                    }
                    mat = new Material();
                    mat.SetParameters( 0.9f, 0, new Color3D( 0.9f, 0.9f, 1 ), 0.3f, 0.7f );
                    mat.RefractionIndex = 1.3f;
                    // mat->SetTexture( new Texture( "textures/wood.tga" ) );
                    //Load3DS("meshes\\knot.3ds", mat, new Vector3D(0, 0.5f, 4), 6);
                    break;
                case 2:
                    //building kdtree, please wait
                    break;
                case 3:
                    //Build the KD-tree
                    p1 = new Vector3D(-14, -6, -6);
                    p2 = new Vector3D(14, 8, 30);
                    Extends = new AxisAlignedBox(p1, p2 - p1);
                    KdTree = new KdTree();
                    KdTree.Build(this);
                    break;
                default:
                    return true; //done initializing
            }

            _state++;
            return false; //still initializing
        }
예제 #11
0
파일: Scene.cs 프로젝트: pirho/RaySharp
 private void AddPlane(Vector3D p1, Vector3D p2, Vector3D p3, Vector3D p4, Material mat)
 {
     Vertex[] v = new Vertex[4];
     v[0] = new Vertex(p1, 0, 0);
     v[1] = new Vertex(p2, 0, 0);
     v[2] = new Vertex(p3, 0, 0);
     v[3] = new Vertex(p4, 0, 0);
     Primitive p = new Primitive(PrimitiveType.Vertex, v[0], v[1], v[3]);
     p.Material = mat;
     Primitives.Add(p);
     p = new Primitive(PrimitiveType.Vertex, v[1], v[2], v[3]);
     p.Material = mat;
     Primitives.Add(p);
 }
예제 #12
0
파일: Scene.cs 프로젝트: pirho/RaySharp
 private void AddBox(Vector3D position, Vector3D size)
 {
     Vertex[] v = new Vertex[8];
     v[0] = new Vertex(new Vector3D(position.X, position.Y, position.Z), 0, 0);
     v[1] = new Vertex(new Vector3D(position.X + size.X, position.Y, position.Y), 0, 0);
     v[2] = new Vertex(new Vector3D(position.X + size.X, position.Y + size.Y, position.Z), 0, 0);
     v[3] = new Vertex(new Vector3D(position.X, position.Y + size.Y, position.Z), 0, 0);
     v[4] = new Vertex(new Vector3D(position.X, position.Y, position.Z + size.Z), 0, 0);
     v[5] = new Vertex(new Vector3D(position.X + size.X, position.Y, position.Z + size.Z), 0, 0);
     v[6] = new Vertex(new Vector3D(position.X + size.X, position.Y + size.Y, position.Z + size.Z), 0, 0);
     v[7] = new Vertex(new Vector3D(position.X, position.Y + size.Y, position.Z + size.Z), 0, 0);
     // front plane
     Primitives.Add(new Primitive(PrimitiveType.Vertex, v[0], v[1], v[3]));
     Primitives.Add(new Primitive(PrimitiveType.Vertex, v[1], v[2], v[3]));
     // back plane
     Primitives.Add(new Primitive(PrimitiveType.Vertex, v[5], v[4], v[7]));
     Primitives.Add(new Primitive(PrimitiveType.Vertex, v[5], v[7], v[6]));
     // left plane
     Primitives.Add(new Primitive(PrimitiveType.Vertex, v[4], v[0], v[3]));
     Primitives.Add(new Primitive(PrimitiveType.Vertex, v[4], v[3], v[7]));
     // right plane
     Primitives.Add(new Primitive(PrimitiveType.Vertex, v[1], v[5], v[2]));
     Primitives.Add(new Primitive(PrimitiveType.Vertex, v[5], v[6], v[2]));
     // top plane
     Primitives.Add(new Primitive(PrimitiveType.Vertex, v[4], v[5], v[1]));
     Primitives.Add(new Primitive(PrimitiveType.Vertex, v[4], v[1], v[0]));
     // bottom plane
     Primitives.Add(new Primitive(PrimitiveType.Vertex, v[6], v[7], v[2]));
     Primitives.Add(new Primitive(PrimitiveType.Vertex, v[7], v[3], v[2]));
 }