由于透视变形,我的球体看起来是椭圆形的,我尝试过改变垂直视场,但畸变没有得到纠正。我还尝试过改变相机与图像平面的距离。代码有问题吗?我在一个周末的相机中使用了光线追踪,但是它们没有得到相同的失真。不要介意黑色部分,我仍在处理阴影。有任何解决方法吗?
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部分
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;
}
我花了足够的时间来解决相同的问题。相机类别如下。请参考存储库以获取其他类。 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);
}
};