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); }
public double DotProduct(Vector3D v) { return X*v.X + Y*v.Y + Z*v.Z; }
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); }
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; }
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); }
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); }
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; }
public void Translate(Vector3D pos) { _data[TX] += pos.X; _data[TY] += pos.Y; _data[TZ] += pos.Z; }
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); }
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 }
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); }
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])); }