JerSci
JerSci

Reputation: 197

RayTracing, how to deal with distortion?

My spheres look oval due to perspective distortion, and I've tried varying the vertical fov but the distortion doesn't get corrected. I've also tried varying the distance of the camera from the image plane. Is there something wrong with the code? I used the raytracing in one weekend's camera but they aren't getting the same distortion. Don't mind the black part, i'm still working on the shadow. Any help to deal with this?enter image description here

camera.cpp

#include "camera.h"

Camera::Camera(vec lookat, vec lookfrom, vec vup, float vfov, float aspect_ratio)
{
    vec u, v, w;
    vfov = (vfov/180)*M_PI;
    float half_height = tan(vfov/2)* 10;
    float half_width = half_height * aspect_ratio;
    origin = lookfrom;
    w = unit_vector(lookfrom - lookat);
    u = unit_vector(cross(w, vup));
    v = cross(w, u);
    lower_left_corner = origin - half_width*u - half_height*v - w;
    horizontal = 2*half_width*u;
    vertical = 2*half_height*v;
}

ray Camera::CreateRay(float u, float v)
{
    vec dir = unit_vector(lower_left_corner + v*vertical + u*horizontal - origin);
    return ray(origin, dir);
}

main.cpp part that generates rays

int main()
{
    const int w = 200, h = 100;
    FILE *fp;
    fp = fopen("img.ppm", "wb");
    fprintf(fp, "P6\n%d %d\n255\n", w, h);
    Camera cam(vec(0,0,-3), vec(-2,2,1), vec(0,1,0), 45, float(w)/float(h));
    for(int j = h - 1; j >= 0; j--)
    {
        for(int i = 0; i < w; i++)
        {
            vec col(0, 0, 0);
            static unsigned char pixel[3];
            for(int s = 0; s < 200; s++){
                float u = 1.0 - 2.0*float(i + 0.5)/float(w);
                float v = 2.0*float(j + 0.5)/float(h) - 1.0;
                ray r = cam.CreateRay(u, v);
                col += color(r);
            }
            col /= float(200);
            pixel[0] = int(clamp(col.r() * 255));
            pixel[1] = int(clamp(col.g() * 255));
            pixel[2] = int(clamp(col.b() * 255));
            fwrite(pixel, 3, 1, fp);
        }


    }
    fclose(fp);
    return 0;
}

Upvotes: 2

Views: 633

Answers (1)

codetiger
codetiger

Reputation: 2779

I've spent enough time fighting with the same problem. The camera class goes below. Please refer the repository for other classes. Ray tracing implementation

struct Camera {
    Vec3fa position, direction;
    float fovDist, aspectRatio;
    double imgWidth, imgHeight;
    SGRTMat4 camMatrix;

    Camera(Vec3fa pos, Vec3fa cRot, Vec3fa cDir, float cfov, int width, int height) {
        position = pos;
        aspectRatio = width / (float)height;
        imgWidth = width;
        imgHeight = height;

        Vec3fa angle = Vec3fa(cRot.x, cRot.y, -cRot.z);
        camMatrix.setRotationRadians(angle * M_PI / 180.0f);

        direction = Vec3fa(0.0f, 0.0f, -1.0f);
        camMatrix.rotateVect(direction);

        fovDist = 2.0f * tan(M_PI * 0.5f * cfov / 180.0);
    }

    Vec3fa getRayDirection(float x, float y) {
        Vec3fa delta = Vec3fa((x-0.5f) * fovDist * aspectRatio, (y-0.5f) * fovDist, 0.0f);
        camMatrix.rotateVect(delta);
        return (direction + delta);
    }
};

Upvotes: 3

Related Questions