首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >路径跟踪遮蔽错误

路径跟踪遮蔽错误
EN

Stack Overflow用户
提问于 2015-02-20 05:41:08
回答 1查看 304关注 0票数 1

我真的不知道还能做什么来解决这个问题。我在c++中写了一个使用显式光线采样的路径跟踪器,我一直得到这个奇怪的、真正的黑色阴影,我知道这是错误的。我已经做了所有的事情来解决它,但我仍然得到它,即使在更高的samples.What上,我做错了吗?下面是场景的图像。

和Radiance主代码

代码语言:javascript
复制
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;    
}
EN

回答 1

Stack Overflow用户

发布于 2015-02-20 06:35:46

我还没有调试过你的代码,所以当然可能有很多bug,但我可以给你一些提示:首先,去看看SmallPT,看看它做了什么,你没有做什么。它很小,但仍然很容易阅读。

从外观上看,似乎在采样和/或伽马校正方面存在问题。最简单的是gamma:将范围为0..1的RGB强度转换为范围为0..255的RGB时,请记住始终进行gamma校正。使用2.2的gamma

代码语言:javascript
复制
R = r^(1.0/gamma)
G = g^(1.0/gamma)
B = b^(1.0/gamma)

使用错误的gamma将使任何路径跟踪图像看起来都很糟糕。第二:抽样。从代码中看不出采样是如何加权的。我只熟悉使用俄罗斯轮盘赌采样的路径跟踪。在RR中,辐射基本上是这样工作的:

代码语言:javascript
复制
  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基本上是一种随机终止光线的方法,但仍然保持对真实辐射度的无偏估计。由于它增加了间接项的权重,而speheres的阴影和底部只是间接照明,我怀疑这与它有关(如果不只是gamma)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28617480

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档