阴影位置不正确,基于CPU的光线追踪

问题描述 投票:0回答:1

我正在尝试在基于CPU的光线追踪中计算阴影,但是我没有将阴影放置在确切的位置,我正在设计著名的康奈尔盒子,

此外,图中的球体阴影不正确,

我已经粘贴了整个代码。我在场景中使用了2个球体和10个三角形,我想我的阴影跟踪算法或正常计算有问题


class Figure{
public:
    Vec3 position;
    Vec3 cl;
    Vec3 normal;

    Figure(void);
    Figure(Vec3 pos,Vec3 col,Vec3 Normal);
    virtual bool intersection(float* t,Vec3 origin,Vec3 direction);
    virtual Vec3 calculateNormal(Vec3 p0,float *intensity,Vec3* Diffusecolor,Vec3* Specular);
    virtual bool intersectionShadow(float* t,Vec3 origin,Vec3 direction);

};

Figure::Figure(){
    position = Vec3(0,0,0);
    cl = Vec3(0,0,0);
    normal = Vec3(0,0,0);
}

Figure::Figure(Vec3 post, Vec3 coli,Vec3 Normal){
    position = post;
    cl = coli;
    normal = Normal;
}

bool Figure::intersection(float *t, Vec3 origin,Vec3 direction){
    return false;
}
Vec3 Figure::calculateNormal(Vec3 p0, float *intensity, Vec3 *Diffusecolor, Vec3 *Specular){
    return normal;
}
bool Figure::intersectionShadow(float *t, Vec3 origin, Vec3 direction){
    return false;
}

class Plane:public Figure{
public:
    Vec3 planeNormal;

    Plane(void);
    Plane(Vec3 pos,Vec3 norm,Vec3 c);
    bool intersection(float *t, Vec3 origin, Vec3 direction);
    Vec3 Plane::calculateNormal(Vec3 p0, float *intensity, Vec3 *Diffusecolor, Vec3 *Specular);

                       };
Plane::Plane(void){
    planeNormal=Vec3(0,0,0);
}
Plane::Plane(Vec3 pos,Vec3 norm,Vec3 c){
    position = pos;
    planeNormal = norm;
    cl = c;
}
bool Plane::intersection(float *t, Vec3 origin, Vec3 direction){
    float denom = planeNormal.dot(direction);
    if(abs(denom)<0.0001f){
        return false;
    }
    else{
        Vec3 p_or = position-origin;
        float res = p_or.dot(planeNormal)/denom;
        *t = res;
    }

}
Vec3 Plane::calculateNormal(Vec3 p0, float *intensity, Vec3 *Diffusecolor, Vec3 *Specular){

    *intensity = 0;
    *Diffusecolor = Vec3(0.7, 0.7, 0.7);
    *Specular = cl;
    return planeNormal;

}

class Sphere:public Figure{
 public:
    float radius;
    Sphere(void);
    Sphere(Vec3 pos,float rad,Vec3 col);
    bool intersection(float* t,Vec3 origin,Vec3 direction);
    Vec3 calculateNormal(Vec3 p0, float *intensity, Vec3 *Diffusecolor, Vec3 *Specular);


};

Sphere::Sphere(){
    position = Vec3(0,0,-2);
    radius = 0.3f;
    cl = Vec3(1.0,0,0);
}

Sphere::Sphere(Vec3 pos, float rad, Vec3 col){
    position = pos;
    radius = rad;
    cl = col;
}

bool Sphere::intersection(float *t, Vec3 origin,Vec3 direction){
    Vec3 oc = origin - position;
    float a = direction.dot(direction);
    float b = 2.0f * oc.dot(direction);
    float c = oc.dot(oc) - radius*radius;
    float discriminant = b*b - 4*a*c;
    if (discriminant < 0) {
        return false;
    }
    else {
        float t0;
        t0 = std::max((-b + sqrt(discriminant) ) / (2.0f*a),(-b - sqrt(discriminant) ) / (2.0f*a));
        *t = t0;
        return true;
    }
}

Vec3 Sphere::calculateNormal(Vec3 p0, float *intensity, Vec3 *Diffusecolor, Vec3 *Specular){
    *intensity = 50.0f;
    *Diffusecolor = cl;
    *Specular = Vec3(0.7f, 0.7f, 0.7);
    return (p0-position);

}

class Triangle:public Figure{
public:

    Vec3 v0;
    Vec3 v1;
    Vec3 v2;
    Vec3 norm;
    Vec3 ed0,ed1;
    float u,v,w;

    Triangle(void);
    Triangle(Vec3 a,Vec3 b,Vec3 c,Vec3 col);
    bool intersection(float* t,Vec3 origin,Vec3 direction);
    bool intersectionShadow(float* t,Vec3 origin,Vec3 direction);
    Vec3 calculateNormal(Vec3 p0, float *intensity, Vec3 *Diffusecolor, Vec3 *Specular);



};
Triangle::Triangle(){
    v0 = Vec3(0,0,0);
    v1 = Vec3(0,0,0);
    v2 = Vec3(0,0,0);
}

Triangle::Triangle(Vec3 a, Vec3 b, Vec3 c, Vec3 col){
    v0 = a;
    v1 = b;
    v2 = c;
    cl = col;



}

bool Triangle::intersection(float *t, Vec3 origin,Vec3 direction){
    ed0 = v1-v0;
    ed1 = v2-v0;
    Vec3 r_o = origin-v0;
    Vec3 r_ed = direction.cross(ed1);
    u = r_o.dot(r_ed)/ed0.dot(r_ed);

    Vec3 r0_ed0 = r_o.cross(ed0);
    float rd_r0_ed0 = direction.dot(r0_ed0);
    v = rd_r0_ed0/ed0.dot(r_ed);
    float ed_r0_ed0 = ed1.dot(r0_ed0);
    float t0 = ed_r0_ed0/ed0.dot(r_ed);

    w = 1-u-v;

    if((u<0) || (u>1)){
        return false;
    }
    else if((v<0) || (u+v>1)){
        return false;
    }
    else {

        *t = t0;
        return true;
    }
}

Vec3 Triangle::calculateNormal(Vec3 p0, float *intensity, Vec3 *Diffusecolor, Vec3 *Specular){

    *intensity = 0;
    *Diffusecolor = Vec3(0.7, 0.7, 0.7);
    *Specular = cl;

    //https://www.tjhsst.edu/~dhyatt/supercomp/n310.html
    Vec3 d1 = Vec3(v1.x()-v0.x(),v1.y()-v0.y(),v1.z()-v0.z());
    Vec3 d2 = Vec3(v2.x()-v1.x(),v2.y()-v1.y(),v2.z()-v1.z());
    Vec3 n = (d1.cross(d2));
    return n ;

}
bool Triangle::intersectionShadow(float* t,Vec3 origin,Vec3 direction){
return false;
}

using Colour = Vec3; // RGB Value
Colour red() { return Colour(1.0f, 0.0f, 0.0f); }
Colour white() { return Colour(1.0f, 1.0f, 1.0f); }
Colour black() { return Colour(0.0f, 0.0f, 0.0f); }

uchar BoundPixelValue(int shading)
{
    if (shading < 0) return 0;
    if (shading >= 255) return 255;
    return shading;
}
Vec3 scalar_multiply(Vec3 b,float v){
    return Vec3(b.x()*v,b.y()*v,b.z()*v);
}
int main(int, char**){
    Vec3 v0 = Vec3(-1.0f,-1.0f,-1.0f);
    Vec3 v1 = Vec3(-1.0f,-1.0f,-2.0f);
    Vec3 v2 = Vec3(-1.0f,1.0f,-1.0f);
    Vec3 v3 = Vec3(-1.0f,1.0f,-2.0f);
    Vec3 v4 = Vec3(1.0f,-1.0f,-1.0f);
    Vec3 v5 = Vec3(1.0f,-1.0f,-2.0f);
    Vec3 v6 = Vec3(1.0f,1.0f,-2.0f);
    Vec3 v7 = Vec3(1.0f,1.0f,-1.0f);
    Vec3 point_0 = Vec3();



    Figure* figurelist[12];
    //sphere
    figurelist[0]=new Sphere(Vec3(-0.2f,0.3f,-1.5f),0.3f,Vec3(1.000f, 0.196f, 0.000f));
    figurelist[1]=new Sphere(Vec3(0.5f,-0.3f,-1.3f),0.4f,Vec3(0.054f, 0.172f, 0.847f));

    //floor
    figurelist[2]=new Triangle(v1,v0,v2,Vec3(0.752f, 0.713f, 0.823f));
    figurelist[3]=new Triangle(v2,v3,v1,Vec3(0.752f, 0.713f, 0.823f));
    //left
    figurelist[4]=new Triangle(v5,v1,v0,Vec3(0.749f, 0.105f, 0.101f));
    figurelist[5]=new Triangle(v0,v4,v5,Vec3(0.749f, 0.105f, 0.101f));
    //back
    figurelist[6]=new Triangle(v5,v1,v3,Vec3(0.925f, 0.639f, 0.454f));
    figurelist[7]=new Triangle(v3,v6,v5,Vec3(0.925f, 0.639f, 0.454f));
    //right
    figurelist[8]=new Triangle(v7,v6,v3,Vec3(0.415f, 0.733f, 0.164f));
    figurelist[9]=new Triangle(v3,v2,v7,Vec3(0.415f, 0.733f, 0.164f));
    //top
    figurelist[10]=new Triangle(v5,v6,v7,Vec3(0.925f, 0.639f, 0.454f));
    figurelist[11]=new Triangle(v7,v4,v5,Vec3(0.925f, 0.639f, 0.454f));










    int wResolution = 640;
    int hResolution = 480;
    // #rows = hResolution, #cols = wResolution
    Image<Colour> image(hResolution, wResolution);
    Vec3 llc=  Vec3(-1.0,-1.0,-1.0);
    Vec3 urc = Vec3(1.0,1.0,-1.0);
    Vec3 CameraPos = Vec3(0,0,0);
    Vec3 sphere_amient(0.960, 0.968, 0.811);



    for (int row = 0; row < image.rows(); ++row) {
        for (int col = 0; col < image.cols(); ++col) {
            float u = float(row+0.5)/float(image.rows());
            float v = float(col+0.5)/float(image.cols());

            Vec3 PointPos = Vec3(llc(0) + u * (urc.x() - llc.x()), llc.y() + v * (urc.y() - llc.y()), -1);
            Vec3 direction=(PointPos-CameraPos).normalized();



            float minT = INFINITY;
            int figureHit = -1;

            float t0=0.0;


            for (int k =0;k<sizeof (figurelist)/sizeof (figurelist[0]);k++){
                bool hit = figurelist[k]->intersection(&t0,CameraPos,direction);
                if(hit && t0<minT){
                    minT = t0;
                    figureHit = k;
                }
                if(figureHit != -1){
                    Vec3 p0 = CameraPos+minT*direction;
                    Vec3 lightSource=Vec3(2.0f,0.0f,-1.0f);
                    float lightIntensity=0.7f;
                    Vec3 diffuseColour(0.0f, 0.392f, 0.0f);
                    Vec3 specularColour(0.0,0.0,0.0);
                    float intensity = 0;

                    //ambient Colour for shadows
                    Vec3 AmbientColour = figurelist[figureHit]->cl.cross(Vec3(0.1f, 0.1f, 0.1f));

                    //Diffuse Lightning
                    Vec3 light_direction = (lightSource-p0).normalized();
                    Vec3 Normal = Vec3(figurelist[figureHit]->calculateNormal(p0,&intensity,&diffuseColour,&specularColour)).normalized();
                    float diffuse_term =std::max(0.0f,light_direction.dot(Normal));
                    Vec3 diffuse = (diffuseColour*lightIntensity*diffuse_term);

                    //Specular Highlights
                    Vec3 e = (p0-CameraPos).normalized();
                    Vec3 R = (e+light_direction).normalized();
                    float dot2 = std::max(0.0f,R.dot(Normal));
                    Vec3 specular = specularColour*lightIntensity*pow(dot2,intensity);



                    Vec3 shadow_direction = p0-light_direction;
                    float bias = 0.001f;
                    Vec3 p_shadow = p0+Normal;



              //For hard shadows


                    int lightHit = -1;
                    for ( int i=0;i<sizeof (figurelist)/sizeof (figurelist[0]);i++){

                        bool lightRayHit = figurelist[i]->intersection(&t0,p_shadow,shadow_direction);
                        if(lightRayHit && t0<minT){
                            minT = t0;
                            lightHit = i;
                        }
                    }
                        if(lightHit != -1){
                                image(row,col) = AmbientColour;
                            }
                        else{
                            image(row,col) = [enter image description here][1]specular+diffuse;
                        }

                }
             else {
                 image(row,col)=white();
             }


         }

    }
 }

 bmpwrite("../../out.bmp", image);
 imshow(image);

 return EXIT_SUCCESS;
}

已附上我得到的输出图像。应用阴影跟踪后的图像:

“

以及没有阴影的原始图像:

“

c++ class object graphics raytracing
1个回答
1
投票

这应该是问题:

Vec3 shadow_direction = p0-light_direction;

p0是位置,light_direction是方向,因此结果是position。但是您正在使用它作为方向。而是:

Vec3 shadow_direction = -light_direction;

float bias = 0.001f;
Vec3 p_shadow = p0+Normal;

原本应该是

Vec3 p_shadow = p0 + bias * Normal;
© www.soinside.com 2019 - 2024. All rights reserved.