2014-12-11 6 views
-1

그래서 모든 벡터 수학 및 교차 계산에 익숙해 지도록 작은 경로 추적기를 작성하고 싶습니다. 그래서 C#에서 Windows Forms 응용 프로그램을 만들고 PictureBox를 사용하여 비트 맵을 표시합니다.Pathtracing 코드가 작동하지 않습니다. 내가 올바르게했을 것 같아요.

내 클래스는 "renderScene"입니다. 비트 맵을 생성하고 모든 픽셀을 반복하며 픽셀에 따라 광선을 계산합니다. 광선을 만든 후에는 반복적으로 세계를 추적하고 마지막으로 픽셀의 색상을 반환합니다.

public Color Trace(Ray ray, int depth, BaseObject missObject = null) 
    { 
     float distance = 5000.0f; 
     BaseObject lastHitObject = null; 
     Vector3D HitPoint = null; 

     foreach (BaseObject obj in this.scene.Objects) 
     { 
      if (obj == missObject) 
       continue; 
      float currentDistance = obj.Intersect(ray); 
      if (currentDistance < distance && currentDistance > 0) 
      { 
       distance = currentDistance; 
       lastHitObject = obj; 
      } 
     } 

     if (distance == 5000.0f) //Kein Objekt wurde getroffen 
      return Color.Black; 
     if (lastHitObject.isEmitter) //Eine Lichtquelle wurde getroffen 
      return lastHitObject.surfaceColor; 
     if (depth == MAX_DEPTH) 
      return Color.Black; 


     HitPoint = ray.origin.add(ray.direction.multiply(distance)); 
     Vector3D normal = lastHitObject.Normal(HitPoint); 

     Ray reflectionRay = null; 

     if (lastHitObject.mat == Material.Diffuse) 
     { 
      Vector3D randomVector = Vector3D.getRandomVectorInHemisphere(); 
      if (randomVector.Dotproduct(normal) < 0.0) 
       randomVector = randomVector.negate(); 
      reflectionRay = new Ray(HitPoint, randomVector.normalize()); 
     } 

     Color returnColor = Trace(reflectionRay, depth + 1, lastHitObject); 

     float r = lastHitObject.surfaceColor.R * returnColor.R; 
     float g = lastHitObject.surfaceColor.G * returnColor.G; 
     float b = lastHitObject.surfaceColor.B * returnColor.B; 

     r /= 255.0f; 
     g /= 255.0f; 
     b /= 255.0f; 

     return Color.FromArgb(255, (int)r, (int)g, (int)b); 
    } 

내가 그래서 마지막을 확인하지 않는 일부 부동 소수점 수학 부정확성을 방지하기 위해 "missObject"매개 변수를 사용

public void renderScene() 
    { 
     Bitmap drawArea = new Bitmap(pB_Result.Size.Width, pB_Result.Size.Height); 
     pB_Result.Image = drawArea; 

     int height = pB_Result.Size.Height; 
     int width = pB_Result.Size.Width; 

     float fov = 160 * (float)Math.PI/180; 
     float zdir = 1.0f/(float)Math.Tan(fov); 
     float aspect = (float)height/(float)width; 

     //BWorker.RunWorkerAsync(new Tuple<int, int, Bitmap, float, float, float>(height, width, drawArea, fov, zdir, aspect)); 

     for (int y = 0; y < pB_Result.Height; y++) 
     { 
      for (int x = 0; x < pB_Result.Width; x++) 
      { 
       float xdir = (x/(float)width) * 2.0f - 1.0f; 
       float ydir = ((y/(float)height) * 2.0f - 1.0f) * aspect; 
       Ray ray = new Ray(Camera, new Vector3D(xdir, ydir, zdir).normalize()); 

       float r = 0, g = 0, b = 0; 
       System.Threading.Tasks.Parallel.For(0, RAYS_PER_PIXEL, i => 
       { 
        Color c = Trace(ray, 0); 
        r += c.R; 
        g += c.G; 
        b += c.B; 
       }); 

       //for (int i = 0; i < RAYS_PER_PIXEL; i++) 
       //{ 
       // Color c = Trace(ray, 0); 
       // r += c.R; 
       // g += c.G; 
       // b += c.B; 
       //} 

       drawArea.SetPixel(x, y, Color.FromArgb(255, (int)r/RAYS_PER_PIXEL, (int)g/RAYS_PER_PIXEL, (int)b/RAYS_PER_PIXEL)); 
      } 
     } 
     pB_Result.Image = drawArea; 
    } 

그리고 여기에 재귀 장면 광선을 교차 내 추적 기능입니다 다시 개체를 누르십시오.

그리고 여기 3D 공간에서 포인트를 나타내는 내 Vector3D 클래스가 있습니다.

public class Vector3D 
{ 
    public float x { get; set; } 
    public float y { get; set; } 
    public float z { get; set; } 

    public Vector3D() 
    { 

    } 

    public Vector3D(float x, float y, float z) { 
     this.x = x; 
     this.y = y; 
     this.z = z; 
    } 

    public float Dotproduct(Vector3D Dotvector) 
    { 
     return (Dotvector.x * this.x + Dotvector.y * this.y + Dotvector.z * this.z); 
    } 

    public float Length() 
    { 
     return (float)Math.Sqrt(x*x + y*y + z*z); 
    } 

    public Vector3D subtract(Vector3D subVec) 
    { 
     return new Vector3D(this.x - subVec.x, this.y - subVec.y, this.z - subVec.z); 
    } 

    public Vector3D add(Vector3D addVec) 
    { 
     return new Vector3D(this.x + addVec.x, this.y + addVec.y, this.z + addVec.z); 
    } 

    public Vector3D add(float value) 
    { 
     return add(new Vector3D(value, value, value)); 
    } 

    public Vector3D multiply(Vector3D multVec) 
    { 
     return new Vector3D(this.x * multVec.x, this.y * multVec.y, this.z * multVec.z); 
    } 

    public Vector3D multiply(float value) 
    { 
     return multiply(new Vector3D(value, value, value)); 
    } 

    public Vector3D divide(Vector3D divVec) 
    { 
     return new Vector3D(this.x/divVec.x, this.y/divVec.y, this.z/divVec.z); 
    } 

    public Vector3D divide(float value) 
    { 
     return divide(new Vector3D(value, value, value)); 
    } 

    public Vector3D CrossProduct(Vector3D crossVec) 
    { 
     return new Vector3D 
     { 
      x = this.y * crossVec.z - this.z * crossVec.y, 
      y = this.z * crossVec.x - this.x * crossVec.z, 
      z = this.x * crossVec.y - this.y * crossVec.x 
     }; 
    } 

    public Vector3D negate() 
    { 
     return new Vector3D 
     { 
      x = -x, 
      y = -y, 
      z = -z 
     }; 
    } 

    public Vector3D normalize() 
    { 
     float f = (float)(1.0f/Math.Sqrt(this.Dotproduct(this))); 

     x *= f; 
     y *= f; 
     z *= f; 

     return new Vector3D(x, y, z); 
    } 

    public static Vector3D getRandomVectorInHemisphere() 
    { 
     Random rnd = new Random(DateTime.Now.Millisecond); 

     Vector3D v = new Vector3D 
     { 
      x = (float)rnd.NextDouble() * 2.0f - 1.0f, 
      y = (float)rnd.NextDouble() * 2.0f - 1.0f, 
      z = (float)rnd.NextDouble() * 2.0f - 1.0f 
     }; 
     v = v.normalize(); 
     return v; 
    } 
} 
+0

이 도움이 될 수 있습니다 : http://ericlippert.com/2014/03/05/how-to-debug-small-programs/를 당신은 당신의 질문은 코드의 최소한의 금액이 포함되어 있는지 확인해야합니다 – Samuel

+0

문제를 재현하는 데 필요한 - 빈 생성자 거의 귀하의 문제와 관련이없는 것을 보장합니다. 그렇게 말하면서, 당신은 실제로 문제가 정확히 무엇인지 말하지 않았습니까? 현재하고있는 프로그램이 예상하지 못한 것은 무엇입니까? – Sayse

+0

정확히 무엇이 잘못되었는지 나는 모르겠다. 나는 모든 것을 올렸다. 5 개의 구체 (1 이미 터)가있는 간단한 장면을 렌더링하면 다음 결과가 나타납니다. http://img5.fotos-hochladen.net/uploads/studioray4imagwzndt723ql.png – binaryBigInt

답변

관련 문제