Frage

Ich bin derzeit eine grundlegende Raytracer in C ++ Implementierung. Funktionieren recht gut, so weit, matte Materialien (mit Umgebungs- und diffusen BRDF) Arbeit als bisher erwartet.

Glanzlichter Hinzufügen im vollen würde Phong Modell und das ist genau das, was ich versuchte, tun.

Leider i begegnet Gamut Überlauf, mit allen Arten von Werten für die Spiegelreflexion Konstante ks und die Exponenten. Hier sind einige Beispiele.

// Sphere material definition:
ka    = 0.9;
kd    = 1.0;
ks    = 0.3;
exp   = 1.0;
color = rgb(1.0, 1.0, 0.98);

Bild: http://dl.dropbox.com/u/614366/cornell_1.png

// Sphere material definition:
ka    = 0.9;
kd    = 1.0;
ks    = 0.3;
exp   = 20.0;                  // only changed exp
color = rgb(1.0, 1.0, 0.98);

Bild: http://dl.dropbox.com/u/614366/cornell_2.png

// Sphere material definition:
ka    = 0.9;
kd    = 1.0;
ks    = 0.1;                  // only changes here
exp   = 0.1;                  // and here
color = rgb(1.0, 1.0, 0.98);

Bild: http://dl.dropbox.com/u/614366/cornell_3.png

und hier sind einige relevante Auszüge des Codes:

in raycast.cpp

namespace {
    const float floatmax = std::numeric_limits<float>::max();
}

rgb
RayCast::trace ( const Ray& ray ) const
{
    HitRecord rec(scene_ptr_);
    float tmax = floatmax;
    float tmin = 0.0;

    if ( scene_ptr_->shapes.hit(ray,tmin,tmax,rec) )
    {
        rec.ray = ray;
        return rec.material_ptr->shade(rec);
    }

    return scene_ptr_->bgcolor;
}

in phong.cpp

rgb
Phong::shade ( HitRecord& hitrec ) const
{
    Vector wo = - hitrec.ray.dir();

    rgb L = ambient_brdf_ptr_->rho(hitrec,wo) *
        hitrec.scene_ptr->ambient_ptr->L(hitrec);

    int num_lights = hitrec.scene_ptr->lights.size();

    for (int i = 0; i < num_lights; ++i)
    {
        Vector wi     = hitrec.scene_ptr->lights[i]->get_direction(hitrec);
        float  ndotwi = dot(hitrec.normal, wi);

        if ( ndotwi > 0.0 )
        {
            L += ( diffuse_brdf_ptr_->f (hitrec, wo, wi)  +
                   specular_brdf_ptr_->f(hitrec, wo, wi)
                 ) * hitrec.scene_ptr->lights[i]->L(hitrec) * ndotwi;
        }
    }

    return L;
}

in specular.cpp

namespace {
    const rgb black(0.0,0.0,0.0);
}

rgb
Specular::f ( const HitRecord& hitrec, const Vector& wo, const Vector& wi ) const
{
    rgb L(0,0,0);
    float ndotwi = dot(hitrec.normal, wi);

    Vector r = -wi + 2.0 * hitrec.normal * ndotwi;
    float rdotwo = dot(r, wo);

    // reflection detected
    if ( rdotwo > 0.0 )
        L = ks_ * pow(rdotwo, exp_);

    return L;
}

rgb
Specular::rho ( const HitRecord& hitrec, const Vector& wo ) const
{
    return black;
}

in sphere.cpp

bool
Sphere::hit ( const Ray& ray, interval_t tmin, interval_t tmax, HitRecord& hitrec ) const
{
    Vector org = ray.origin() - center_;
    Vector dir = ray.dir();
    float a = dot(dir, dir);
    float b = dot(dir, org) * 2;
    float c = dot(org, org) - pow(radius_, 2);
    float discriminant = pow(b,2) - 4*a*c;

    if ( discriminant > 0 )
    {
        discriminant = sqrt(discriminant);
        double t = ( -b - discriminant ) / ( 2*a );

        if ( t < tmin )
            t = ( -b + discriminant ) / ( 2*a );

        if ( t > tmin and t < tmax )
        {
            // hit detected
            hitrec.t            = t;
            hitrec.hit          = true;
            hitrec.normal       = unify( t*ray.dir() + org );
            hitrec.material_ptr = material_ptr_;
            hitrec.hitpoint     = ray.origin() + t * ray.dir();
            hitrec.ray          = ray;

            return true;
        }
    }

    return false;
}

Haben Sie Ideen, wo der Fehler verursacht werden könnte? Was sind mögliche Faktoren, die führen zu solchen Ergebnissen?

Vielen Dank im Voraus, patrick.

War es hilfreich?

Lösung

Die Lösung des Problems besteht darin, dass Sie die wo Vektor zu vereinigen haben (in Phong :: Schatten).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top