2015-09-23 150 views
3

當我使用照明進行渲染時,我在我的球體上得到了奇怪的黑色環。我只是添加了燈光,我無法弄清楚爲什麼黑色戒指正在創建。光線追蹤:出現暗環

Ray Trace

這是我爲我的追蹤代碼。

public class Tracer { 

    public Camera Cam; 
    public int Width, Height; 
    public BufferedImage Image; 
    public Color BackGroundColor; 
    public int StartX, StartY, EndX, EndY,RowCount,ColCount; 
    public ArrayList<GeometricObject> GeoObjects; 
    public ArrayList<LightObject> LightObjects; 
    public boolean Tracing; 
    public double AmbientLight; 

    public Tracer(Camera cam, int width, int height, BufferedImage image, Color backGroundColor, int startX, int startY, int endX, int endY, int rowCount, int colCount, ArrayList<GeometricObject> Geoobjects,ArrayList<LightObject> Lightobjects,double ambientLight) { 
     super(); 
     Cam = cam; 
     Width = width; 
     Height = height; 
     Image = image; 
     BackGroundColor = backGroundColor; 
     StartX = startX; 
     StartY = startY; 
     EndX = endX; 
     EndY = endY; 
     RowCount = rowCount; 
     ColCount = colCount; 
     GeoObjects = Geoobjects; 
     LightObjects = Lightobjects; 
     if(ambientLight > 1){ 
      AmbientLight = 1; 
     }else if(ambientLight < 0){ 
      AmbientLight = 0; 
     }else{ 
      AmbientLight = ambientLight; 
     } 
    } 

    public void TracePixelFast(int x, int y) { 
     Color color = new Color(BackGroundColor.r,BackGroundColor.g,BackGroundColor.b); 
     for(int o = 0;o < GeoObjects.size();o++){ 
      GeometricObject GO = GeoObjects.get(o); 
      Ray r = new Ray(Cam.GetRayPos(Width, Height, x, y, 1, 1, RowCount, ColCount), Cam.GetRayDir(Width, Height, x, y, 1,1, RowCount, ColCount)); 
      double hit = GO.hit(r); 
      if (hit != 0.0) { 
       color = Cal_Pixel(x,y); 
       Image.setRGB(x, y, color.toInt()); 
       break; 
      } 
     } 
    } 

    public void TracePixelSmooth(int x, int y) { 
     Image.setRGB(x, y,Cal_Pixel(x,y).toInt()); 
    } 

    public Color Cal_Pixel(int x,int y){ 
     Color color = new Color(BackGroundColor); 
     Color colorh = new Color(BackGroundColor); 
     Color bgc = new Color(BackGroundColor); 
     int HIT = 0; 
     int MISS = 0; 
     for (int row = 0; row < RowCount; row++) { 
      for (int col = 0; col < ColCount; col++) { 
       double min = Double.MAX_VALUE; 
       for (int o = 0; o < GeoObjects.size(); o++) { 
        GeometricObject GO = GeoObjects.get(o); 
        Ray r = new Ray(Cam.GetRayPos(Width, Height, x, y, row, col, RowCount, ColCount),Cam.GetRayDir(Width, Height, x, y, row, col, RowCount, ColCount)); 
        double hit = GO.hit(r); 
        if (hit != 0.0 && hit < min) { 
         min = hit; 
         colorh = ShadePixel(GO, r, hit); 
         HIT++; 
        } else { 
         double min2 = Double.MAX_VALUE; 
         for (int o2 = 0; o2 < GeoObjects.size(); o2++) { 
          if(o!=o2){ 
          GeometricObject GO2 = GeoObjects.get(o2); 
          double hit2 = GO2.hit(r); 
          if (hit2 != 0.0 && hit2 < min2) { 
          min2 = hit2; 
          bgc = ShadePixel(GO2, r, hit2); 
          } 
         } 
         } 
         MISS++; 
        } 
       } 
      } 
     } 

     for(int h = 0;h < HIT;h++){ 
      color.Add(colorh); 
     } 
     for(int m = 0;m < MISS;m++){ 
      color.Add(bgc); 
     } 
     color.Divide(RowCount * ColCount); 
     return color; 
    } 

    public Color ShadePixel(GeometricObject GO,Ray ray,double t){ 
     ArrayList<Color> PixelShade = new ArrayList<Color>(); 
     Normal normal = GO.Cal_Normal(ray, t); 
     for(int l = 0;l < LightObjects.size();l++){ 
      LightObject light = LightObjects.get(l); 
      Vector3D r_Dir = light.Pos.Sub(normal.Origin); 
      r_Dir.normalize(); 
      Ray raytolight = new Ray(normal.Origin,r_Dir); 
      int WAS_HIT = 0; 
      for(int o = 0;o < GeoObjects.size();o++){ 
       GeometricObject NGO = GeoObjects.get(o); 
       double hit = NGO.hit(raytolight); 
       if (hit != 0.0) { 
        WAS_HIT = 1; 
       } 
      } 
      if(WAS_HIT == 0){ 
       double Dot = normal.Direction.Dot(r_Dir); 
       if(Dot < 0){ 
        Dot = 0; 
       } 
       double Diffuse = 1 - AmbientLight; 
       Color color = new Color(GO.Color); 
       double Shade = AmbientLight + Diffuse*Dot; 
       color.Mul(Shade); 
       PixelShade.add(color); 
      }else{ 
       Color color = new Color(GO.Color); 
       double Shade = AmbientLight; 
       color.Mul(Shade); 
       PixelShade.add(color); 
      } 
     } 
     Color Final = new Color(); 
     for(int s = 0;s < PixelShade.size();s++){ 
      Final.Add(PixelShade.get(s)); 
     } 
     Final.Divide(PixelShade.size()); 
     return Final; 
    } 

    public void TraceArea(boolean SmoothTracing) { 
     Tracing = true; 
     if(SmoothTracing){ 
      for (int x = StartX; x < EndX; x++) { 
       for (int y = StartY; y < EndY; y++) { 
        TracePixelSmooth(x,y); 
       } 
      } 
     }else{ 
      for (int x = StartX; x < EndX; x++) { 
       for (int y = StartY; y < EndY; y++) { 
        TracePixelFast(x,y); 
       } 
      } 
     } 
    } 
} 

這裏是球的代碼。

public class Sphere extends GeometricObject{ 

    public Vector3D Center; 
    public double Radius; 

    public Sphere(Vector3D Center,double Radius,Color Color){ 
     this.Center = Center; 
     this.Radius = Radius; 
     this.Color = Color; 
    } 

    public double hit(Ray ray) { 
     double a = ray.Direction.Dot(ray.Direction); 
     double b = 2 * ray.Origin.Sub(Center).Dot(ray.Direction); 
     double c = ray.Origin.Sub(Center).Dot(ray.Origin.Sub(Center))-Radius*Radius; 
     double discreminant = b*b-4*a*c; 
     if(discreminant < 0.0f){ 
      return 0.0; 
     }else{ 
      double t = (-b - Math.sqrt(discreminant))/(2*a); 
      if(t > 10E-9){ 
       return t; 
      }else{ 
       return 0.0; 
      } 
     } 
    } 

    public Normal Cal_Normal(Ray ray,double t) { 
     Vector3D NPos = new Vector3D(ray.Origin.x + ray.Direction.x*t,ray.Origin.y + ray.Direction.y*t,ray.Origin.z + ray.Direction.z*t); 
     Vector3D NDir = NPos.Sub(Center).Div(Radius); 
     return new Normal(NPos,NDir); 
    } 
} 

我確定問題出在shadepixel(),但我可能是錯的。 我剛剛發現,我添加的戒指越多,對象越多:
1對象沒有戒指。
2個對象1個戒指。
3個物品2個戒指。

如果您需要我發表更多我的代碼。請問我會如何。

當我從學校回來時,我會發布我的色彩課,並解決顏色問題。我仍然不明白爲什麼我添加的對象(球體)越多,那裏的環就越多。任何人都可以向我解釋爲什麼發生這種情況?

這是我的顏色代碼。

public class Color { 

public float r,g,b; 

public Color(){ 
    r = 0.0f; 
    g = 0.0f; 
    b = 0.0f; 
} 

public Color(float fr,float fg,float fb){ 
    r = fr; 
    g = fg; 
    b = fb; 
} 

public Color(Color color){ 
    r = color.r; 
    g = color.g; 
    b = color.b; 
} 

public void Add(Color color){ 
    r += color.r; 
    g += color.g; 
    b += color.b; 
} 

public void Divide(int scalar){ 
    r /= scalar; 
    g /= scalar; 
    b /= scalar; 
} 

public void Mul(double mul){ 
    r *= mul; 
    g *= mul; 
    b *= mul; 
} 

public int toInt(){ 
    return (int) (r*255)<<16 | (int) (g*255)<<8 | (int) (b*255); 
} 
+0

晚安傢伙,我必須去上學tomorrow.I希望你自己看着辦吧,而我走了它必須對場景中的物體數量做一些事情,我90%確定問題出在陰影中。良好的夜晚祝你好運! –

+1

你的Color類是什麼樣的?看起來這是你寫的一堂課。好奇,看起來像什麼。 –

回答

2

該代碼有多個問題,但環的直接原因是色彩分量值溢出0-255範圍。這反過來是由於我在Cal_Pixel()中嘗試抗鋸齒的錯誤計算以及ShadePixel()的數字範圍的任何控制而導致的。

+0

謝謝man.It是顏色不在範圍內。 –

+0

但我仍然不明白爲什麼它會爲我在場景中的任何物體制造響鈴。 –

+0

有些東西會導致mod('color%256')發生,這會產生鋸齒圖案。 – weston

0

想想你如何可以直觀地調試這個場景。

首先是法線正確嗎?將它們顯示爲要查看的顏色。

考慮的範圍內爲每個組件[-1..1]的範圍[0..255]

r = 255*(n.x + 1)/2; 
g = 255*(n.y + 1)/2; 
b = 255*(n.z + 1)/2; 

一旦你認爲他們看起來對下一階段正確的舉措,逐步建立起來的階段。

例如你可以看看,如果你的點積爲預期(再次[-1..1]因爲載體是所謂標準化):

r = 255*(dot + 1)/2; 
g = 255*(dot + 1)/2; 
b = 255*(dot + 1)/2; 
+0

我目前在學校,但當我回家時,我會嘗試。 –