2015-09-23 3 views
3

Я получаю странные кольца черного цвета на своих сферах, когда я делаю это с подсветкой. Я просто добавил освещение, и я не могу понять, почему создаются черные кольца.Raytracing: Появляются темные кольца

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

Каков ваш класс цветов? Похоже, это класс, который вы написали. Любопытно, как это выглядит. –

ответ

2

Есть несколько проблем с этим кодом, но непосредственной причиной колец является то, что значения цветовых компонентов переполнены 0-255 диапазон. Это, в свою очередь, вызвано неправильными вычислениями в попытке сглаживания в Cal_Pixel(), а также без какого-либо контроля числового диапазона в ShadePixel().

+0

Спасибо man.It был цвет не был в диапазоне. –

+0

Но я до сих пор не понимаю, почему это сделало бы кольцо навсегда объектов, которые у меня были в сцене. –

+0

Что-то вызывает модификацию ('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

Я сейчас в школе, но я попробую это, когда вернусь домой. –