public Color Trace(Vector3D start, Vector3D direction, double tmin,
			double tmax, double perlinRandom, int depth){
		direction = Vector3D.Normalize(direction);
		Color color;
		
		HitRecord hitRecord = getHitSpherePt(start, direction, tmin, tmax);
		if(hitRecord != null){ //trace to bubble
			Vector3D hitPt = hitRecord.getHitPt();
			Sphere surface = (Sphere)hitRecord.getSurface();
			Vector3D normal = surface.getNormal(hitPt);
			//reflection
			double nd = Vector3D.DotProduct(normal, direction);
			Vector3D reflectDirection = Vector3D.Add(direction,
					Vector3D.Scale(normal, nd * -2));
			Color reflectColor;// = new Color(0.5,0.5,0.5);
			if(depth != MAX_DEPTH){
				reflectColor = Trace(hitPt, reflectDirection, tmin, tmax, perlinRandom, depth + 1);
			} 
			else {
				reflectColor = Scene.skyBox.HitColor(hitPt, reflectDirection);
				//reflectColor = new Color(0.5,0.5,0.5);
			} 
			
			//interference
			double thickness = surface.getThickness(hitPt, perlinRandom);
			reflectColor = getInterfereLight2(reflectDirection, normal, reflectColor, thickness, scene.testMaterial);
			color = reflectColor;
			
			//refraction
			Color refractColor;
			if(depth != MAX_DEPTH){
				 refractColor = Trace(hitPt, direction, tmin, tmax, perlinRandom, depth+1);
			}
			else {
				refractColor = Scene.skyBox.HitColor(surface.getCenter(), direction);
				//refractColor = new Color(0.5,0.5,0.5);
			}
			
			//mix
			double cos = Math.abs(Vector3D.cos(normal, direction));
			double R0 = Scene.testMaterial.getR0();
			double R = R0 + (1 - R0) * Math.pow(1 - cos, 5);
			//R += 0.05;
			reflectColor.Scale(R);
			refractColor.Scale(1-R);
			
			color = Color.Add(reflectColor, refractColor); 
			
			
		}else{ //trace to skybox
			color = scene.skyBox.HitColor(start, direction);
		}
		
		
		return color;
	}