路径跟踪阴影错误

时间:2015-02-19 21:41:08

标签: raytracing montecarlo

我真的不知道还有什么可以解决这个问题。我在c ++中使用显式光采样编写了一个路径跟踪器,我不断得到这个奇怪的黑色阴影,我知道这是错误的。我已经做了一切来修复它但我仍然坚持不懈,即使是在更高的样品上。我做错了什么?下面是场景的图像。

enter image description here

和光辉主要代码

RGB Radiance(Ray PixRay,std::vector<Primitive*> sceneObjects,int depth,std::vector<AreaLight> AreaLights,unsigned short *XI,int E)
{
    int MaxDepth = 10;

    if(depth > MaxDepth) return RGB();

    double nearest_t = INFINITY;
    Primitive* nearestObject = NULL;

    for(int i=0;i<sceneObjects.size();i++)
    {
        double root = sceneObjects[i]->intersect(PixRay);
        if(root > 0)
        {
            if(root < nearest_t)
            {
                nearest_t = root;
                nearestObject = sceneObjects[i];
            }
        }
    }

    RGB EstimatedRadiance;

    if(nearestObject)
    {    
        EstimatedRadiance = nearestObject->getEmission() * E;    
        Point intersectPoint = nearestObject->intersectPoint(PixRay,nearest_t);
        Vector intersectNormal = nearestObject->surfacePointNormal(intersectPoint).Normalize();

        if(nearestObject->getBRDF().Type == 1)
        {    
            for(int x=0;x<AreaLights.size();x++)
            {

                Point pointOnTriangle = RandomPointOnTriangle(AreaLights[x].shape,XI);
                Vector pointOnTriangleNormal = AreaLights[x].shape.surfacePointNormal(pointOnTriangle).Normalize();
                Vector LightDistance = (pointOnTriangle - intersectPoint).Normalize();

                //Geometric Term
                RGB Geometric_Term = GeometricTerm(intersectPoint,pointOnTriangle,sceneObjects);
                //Lambertian BRDF
                RGB LambertianBRDF =  nearestObject->getColor() * (1. / M_PI);
                //Emitted Light Power
                RGB Emission = AreaLights[x].emission;

                double MagnitudeOfXandY = (pointOnTriangle - intersectPoint).Magnitude() * (pointOnTriangle - intersectPoint).Magnitude();
                RGB DirectLight = Emission * LambertianBRDF  * Dot(intersectNormal,-LightDistance) * 
                    Dot(pointOnTriangleNormal,LightDistance) * (1./MagnitudeOfXandY) * AreaLights[x].shape.Area() * Geometric_Term;

                EstimatedRadiance = EstimatedRadiance + DirectLight;
            }
            //
            Vector diffDir = CosWeightedRandHemiDirection(intersectNormal,XI);
            Ray diffRay = Ray(intersectPoint,diffDir);    
            EstimatedRadiance = EstimatedRadiance + ( Radiance(diffRay,sceneObjects,depth+1,AreaLights,XI,0) * nearestObject->getColor() * (1. / M_PI) * M_PI );    
        }

        //Mirror
        else if(nearestObject->getBRDF().Type == 2)
        {
            Vector reflDir = PixRay.d-intersectNormal*2*Dot(intersectNormal,PixRay.d);
            Ray reflRay = Ray(intersectPoint,reflDir);

            return nearestObject->getColor() *Radiance(reflRay,sceneObjects,depth+1,AreaLights,XI,0);
        }
    }

    return EstimatedRadiance;    
}

1 个答案:

答案 0 :(得分:1)

我还没有调试你的代码,所以当然可能有任何数量的错误,但我可以给你一些提示:首先,看看SmallPT,看看你做了什么别&#39;吨。它很小但仍然很容易阅读。

从它的外观来看,似乎存在采样和/或伽马校正的问题。最简单的一种是伽玛:当在0..2范围内将RGB强度转换为0..25范围内的RGB时,请记住始终进行伽马校正。使用2.2

的伽玛
R = r^(1.0/gamma)
G = g^(1.0/gamma)
B = b^(1.0/gamma)

错误的伽玛将使任何路径跟踪图像看起来很糟糕。 第二:抽样。从代码中可以看出采样的加权方式并不明显。我只熟悉使用俄罗斯轮盘抽样的路径追踪。使用RR,辐射基本上如下:

  if (depth > MaxDepth)
     return RGB();

  RGB color = mat.Emission;

  // Russian roulette:
  float survival = 1.0f;
  float pContinue = material.Albedo();
  survival = 1.0f / pContinue;
  if (Rand.Next() > pContinue)
     return color;

  color += DirectIllumination(sceneIntersection);
  color += Radiance(sceneIntersection, depth+1) * survival;

RR基本上是一种随机终止光线的方法,但仍保持对真实辐射的无偏估计。因为它增加了间接术语的权重,并且球体的阴影和底部只是间接点亮,我怀疑它与它有关(如果它不仅仅是伽玛)。 / p>