public PhongMaterial(PhongMaterial m) { Color = (double[])m.Color.Clone(); Ka = m.Ka; Kd = m.Kd; Ks = m.Ks; H = m.H; Kt = m.Kt; n = m.n; }
/// <summary> /// Infinite plane with two spheres on it (one of them is transparent) /// </summary> public static void TwoSpheres( IRayScene sc ) { Debug.Assert( sc != null ); // CSG scene: CSGInnerNode root = new CSGInnerNode( SetOperation.Union ); root.SetAttribute( PropertyName.REFLECTANCE_MODEL, new PhongModel() ); root.SetAttribute( PropertyName.MATERIAL, new PhongMaterial( new double[] { 1.0, 0.8, 0.1 }, 0.1, 0.6, 0.4, 128 ) ); sc.Intersectable = root; // Background color: sc.BackgroundColor = new double[] { 0.0, 0.05, 0.07 }; // Camera: sc.Camera = new StaticCamera( new Vector3d( 0.7, 0.5, -5.0 ), new Vector3d( 0.0, -0.18, 1.0 ), 50.0 ); // Light sources: sc.Sources = new LinkedList<ILightSource>(); sc.Sources.Add( new AmbientLightSource( 0.8 ) ); sc.Sources.Add( new PointLightSource( new Vector3d( -5.0, 4.0, -3.0 ), 1.2 ) ); // --- NODE DEFINITIONS ---------------------------------------------------- // Transparent sphere: Sphere s; s = new Sphere(); PhongMaterial pm = new PhongMaterial( new double[] { 0.0, 0.2, 0.1 }, 0.05, 0.05, 0.1, 128 ); pm.n = 1.6; pm.Kt = 0.9; s.SetAttribute( PropertyName.MATERIAL, pm ); root.InsertChild( s, Matrix4d.Identity ); // Opaque sphere: s = new Sphere(); root.InsertChild( s, Matrix4d.Scale( 1.2 ) * Matrix4d.CreateTranslation( 1.5, 0.2, 2.4 ) ); // Infinite plane with checker: Plane pl = new Plane(); pl.SetAttribute( PropertyName.COLOR, new double[] { 0.3, 0.0, 0.0 } ); pl.SetAttribute( PropertyName.TEXTURE, new CheckerTexture( 0.6, 0.6, new double[] { 1.0, 1.0, 1.0 } ) ); root.InsertChild( pl, Matrix4d.RotateX( -MathHelper.PiOver2 ) * Matrix4d.CreateTranslation( 0.0, -1.0, 0.0 ) ); }
public double[] ColorReflection(IMaterial material, Vector3d normal, Vector3d input, Vector3d output, ReflectionComponent comp) { if (!(material is PhongMaterial)) { return(null); } PhongMaterial mat = (PhongMaterial)material; int bands = mat.Color.Length; double[] result = new double[bands]; bool viewOut = Vector3d.Dot(output, normal) > 0.0; double coef; if (input.Equals(Vector3d.Zero)) // ambient term only.. { // dim ambient light if viewer is inside coef = viewOut ? mat.Ka : (mat.Ka * mat.Kt); for (int i = 0; i < bands; i++) { result[i] = coef * mat.Color[i]; } return(result); } // directional light source: input.Normalize(); double cosAlpha = Vector3d.Dot(input, normal); bool lightOut = cosAlpha > 0.0; double ks = mat.Ks; double kd = mat.Kd; double kt = mat.Kt; Vector3d r = Vector3d.Zero; coef = 1.0; if (viewOut == lightOut) // viewer and source are on the same side.. { if ((comp & ReflectionComponent.SPECULAR_REFLECTION) != 0) { double cos2 = cosAlpha + cosAlpha; r = normal * cos2 - input; if (!lightOut && // total reflection check -cosAlpha <= mat.cosTotal) { if ((ks += kt) + kd > 1.0) { ks = 1.0 - kd; } } } } else // opposite sides => use specular refraction { if ((comp & ReflectionComponent.SPECULAR_REFRACTION) != 0) { r = Geometry.SpecularRefraction(normal, mat.n, input); } coef = kt; } double diffuse = (comp & ReflectionComponent.DIFFUSE) == 0 ? 0.0 : coef *kd *Math.Abs(cosAlpha); double specular = 0.0; if (r != Vector3d.Zero) { double cosBeta = Vector3d.Dot(r, output); if (cosBeta > 0.0) { specular = coef * ks * Arith.Pow(cosBeta, mat.H); } } for (int i = 0; i < bands; i++) { result[i] = diffuse * mat.Color[i] + specular; } return(result); }
/// <summary> /// Creates default ray-rendering scene. /// </summary> public static IRayScene Init(IRayScene sc, string param) { // !!!{{ TODO: .. and use your time-dependent objects to construct the scene // This code is based on Scenes.TwoSpheres(): // CSG scene: CSGInnerNode root = new CSGInnerNode(SetOperation.Union); root.SetAttribute(PropertyName.REFLECTANCE_MODEL, new PhongModel()); root.SetAttribute(PropertyName.MATERIAL, new PhongMaterial(new double[] { 1.0, 0.8, 0.1 }, 0.1, 0.6, 0.4, 128)); sc.Intersectable = root; // Background color: sc.BackgroundColor = new double[] { 0.0, 0.05, 0.07 }; // Camera: AnimatedCamera cam = new AnimatedCamera(new Vector3d(0.7, -0.4, 0.0), new Vector3d(0.7, 0.8, -6.0), 50.0); cam.End = 20.0; // one complete turn takes 20.0 seconds AnimatedRayScene asc = sc as AnimatedRayScene; if (asc != null) { asc.End = 20.0; } sc.Camera = cam; //sc.Camera = new StaticCamera( new Vector3d( 0.7, 0.5, -5.0 ), // new Vector3d( 0.0, -0.18, 1.0 ), // 50.0 ); // Light sources: sc.Sources = new LinkedList <ILightSource>(); sc.Sources.Add(new AmbientLightSource(0.8)); sc.Sources.Add(new PointLightSource(new Vector3d(-5.0, 4.0, -3.0), 1.2)); // --- NODE DEFINITIONS ---------------------------------------------------- // Params dictionary: Dictionary <string, string> p = Util.ParseKeyValueList(param); // n = <index-of-refraction> double n = 1.6; Util.TryParse(p, "n", ref n); // Transparent sphere: Sphere s; s = new Sphere(); PhongMaterial pm = new PhongMaterial(new double[] { 0.0, 0.2, 0.1 }, 0.03, 0.03, 0.08, 128); pm.n = n; pm.Kt = 0.9; s.SetAttribute(PropertyName.MATERIAL, pm); root.InsertChild(s, Matrix4d.Identity); // Opaque sphere: s = new Sphere(); root.InsertChild(s, Matrix4d.Scale(1.2) * Matrix4d.CreateTranslation(1.5, 0.2, 2.4)); // Infinite plane with checker: Plane pl = new Plane(); pl.SetAttribute(PropertyName.COLOR, new double[] { 0.3, 0.0, 0.0 }); pl.SetAttribute(PropertyName.TEXTURE, new CheckerTexture(0.6, 0.6, new double[] { 1.0, 1.0, 1.0 })); root.InsertChild(pl, Matrix4d.RotateX(-MathHelper.PiOver2) * Matrix4d.CreateTranslation(0.0, -1.0, 0.0)); // !!!}} return(sc); }
public PhongMaterial( PhongMaterial m ) { Color = (double[])m.Color.Clone(); Ka = m.Ka; Kd = m.Kd; Ks = m.Ks; H = m.H; Kt = m.Kt; n = m.n; }