【问题标题】:Calculating raytracer rays - vectors converge to same output计算光线追踪器光线 - 向量收敛到相同的输出
【发布时间】:2014-08-24 19:36:36
【问题描述】:

我一直在写一个光线追踪器来取乐,并且投入了大量资金。我观看了教程、讲座和研究/其他代码,以透视计算投影到图像的矢量射线。不幸的是,根据我正在创建的图像的大小,在第 4-5 次迭代之后,它使用相同的矢量射线。虽然这应该会有所不同,具体取决于图像中正在查看的像素。

现在我正在做一个转换,根据创建图像的尺寸,基本上将像素的光线向左或向右移动x/y。具体来说,我查看了这两个Raytracer - Computing Eye Rays && calculation for ray generation in ray tracer 的答案,尝试实现它们,调整了我的代码,但没有得到任何结果。

附带说明,纵向和横向实现也不起作用。它被硬编码为宽度 = 10 和高度 = 10,因为这是我一直在玩的维度。它们可以更改,并且将来肯定会更改。

使用 VS2013 用 C++ 编写代码。

int WIDTH = 10;
int HEIGHT = 10;

int main(int argc, char **argv) {
    std::cout << "creating rays..." << std::endl;

    Vector Y(0, 1, 0);
    Vector camPos(3, 1.5, -4);
    Vector looking_at(0, 0, 0); // may change - but want to look at center for this scene
    Vector difference(camPos - looking_at);

    Vector camDir = difference.negative().normalize();
    Vector camRight = (Y.cross(camDir)).normalize();
    Vector camDown = camRight.cross(camDir);

    double aspectRatio = (double) WIDTH / (double) HEIGHT;
    double xAMT, yAMT;  //slightly left of right from direction of camera

    for (int x = 0; x < HEIGHT; x++) {
        for (int y = 0; y < WIDTH; y++) {
            if (WIDTH > HEIGHT) {
                // landscape
                xAMT = ((x + 0.5) / WIDTH) * aspectRatio - (((WIDTH - HEIGHT) / (double) HEIGHT) /2);
                yAMT = ((HEIGHT - y) + 0.5) / HEIGHT;
            }
            else if (HEIGHT > WIDTH) {
                // portrait
                xAMT = (y + 0.5) / WIDTH;
                yAMT = (((HEIGHT - y) + 0.5) / HEIGHT) / aspectRatio - (((HEIGHT - WIDTH) / (double) WIDTH) / 2);
            }
            else {
                // square
                xAMT = (x + 0.5) / WIDTH;
                yAMT = ((HEIGHT - y) + 0.5) / HEIGHT;
            }

            // YES - this indeed does work
            Vector camRayOrigin     = camPos;
            Vector camRightDir      = camRight * (yAMT - 0.5);
            Vector camDownDir       = camDown  * (xAMT - 0.5);
            Vector camRayDirection  = (camDir + (camRightDir + camDownDir)).normalize();

            Ray camRay(camRayOrigin, camRayDirection);
            camRayDirection.print_vector();
        }
    }           
}

上面代码产生的文字是:

creating rays...             
-0.173037 0.117114 0.977928  
-0.325543 -0.458438 0.826956 
-0.517036 -0.198503 0.832629 
-0.54971 -0.326274 0.769002  
-0.575177 -0.269626 0.772316 
-0.573114 -0.295291 0.764423 
-0.575342 -0.283767 0.76711  
-0.574404 -0.288958 0.765874 
-0.574826 -0.286623 0.766435 
-0.574637 -0.287674 0.766183 
-0.574716 -0.287234 0.766288 
-0.574689 -0.287388 0.766251 
-0.574698 -0.287334 0.766264 
-0.574695 -0.287353 0.76626  
-0.574696 -0.287346 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 
-0.574696 -0.287348 0.766261 

向量类:

#include <cmath>

class Vector {
    double x, y, z;
    int size = 3;

public:
    ~Vector() {};
    Vector() : x(0), y(0), z(0) {}
    Vector(double _x, double _y, double _z) : x(_x), y(_y), z(_z) {}

    Vector& operator=(Vector rhs);

    // Vector mathematical operations                                                                                                                                                                                               
    Vector operator+(const Vector& rhs);
    Vector& operator+=(const Vector& rhs);
    Vector operator-(const Vector& rhs);
    Vector& operator-=(const Vector& rhs);

    // Vector scalar operations
    Vector operator+(const double& rhs);
    Vector operator-(const double& rhs);
    Vector operator*(const double& rhs);
    Vector operator/(const double& rhs);

    Vector cross(const Vector& rhs); // Cross-Product
    double dot(const Vector& rhs); // Dot-Product
    Vector normalize(); // Normalize
    Vector negative(); // Negative 
    double mag(); // Magnitude

    void swap(Vector& rhs);
    void print_vector();
};

Vector& Vector::operator=(Vector rhs) {
    swap(rhs);
    return *this;
}

Vector Vector::operator+(const Vector& rhs) {
    Vector result(*this);
    result += rhs;
    return result;
}

Vector& Vector::operator+=(const Vector& rhs) {
    this->x += rhs.x;
    this->y += rhs.y;
    this->z += rhs.z;

    return *this;
}

Vector Vector::operator-(const Vector& rhs) {
    Vector result(*this);
    result -= rhs;
    return result;
}

Vector& Vector::operator-=(const Vector& rhs) {
    this->x -= rhs.x;
    this->y -= rhs.y;
    this->z -= rhs.z;

    return *this;
}

Vector Vector::operator+(const double& rhs) {
    this->x += rhs;
    this->y += rhs;
    this->z += rhs;

    return *this;
}

Vector Vector::operator-(const double& rhs) {
    this->x -= rhs;
    this->y -= rhs;
    this->z -= rhs;

    return *this;
}

Vector Vector::operator*(const double& rhs) {
    this->x *= rhs;
    this->y *= rhs;
    this->z *= rhs;

    return *this;
}

Vector Vector::operator/(const double& rhs) {
    this->x /= rhs;
    this->y /= rhs;
    this->z /= rhs;

    return *this;
}

Vector Vector::cross(const Vector& rhs) {
    double a = (y * rhs.z) - (z * rhs.y);
    double b = (z * rhs.x) - (x * rhs.z);
    double c = (x * rhs.y) - (y * rhs.x);
    Vector product(a, b, c);
    return product;
}

double Vector::dot(const Vector& rhs) {
    double scalar = (x * rhs.x) + (y * rhs.y) + (x * rhs.z);
    return scalar;
}

double Vector::mag() {
    return sqrt(pow(x, 2) + pow(y, 2) + pow(z, 2));
}

Vector Vector::normalize() {
    double mag = sqrt(pow(x, 2) + pow(y, 2) + pow(z, 2));

    if (mag != 0) {
        this->x /= mag;
        this->y /= mag;
        this->z /= mag;
    }
    return *this;
}

Vector Vector::negative() {
    this->x *= -1;
    this->y *= -1;
    this->z *= -1;
    return *this;
}

void Vector::swap(Vector& rhs) {
    using std::swap;

    swap(this->x, rhs.x);
    swap(this->y, rhs.y);
    swap(this->z, rhs.z);
}

void Vector::print_vector() {
    std::cout 
        << x 
        << " " 
        << y 
        << " "
        << z 
        << std::endl;
}

【问题讨论】:

  • 尽可能简化您的代码 sn-p 以使您的代码更易于阅读将非常有用。有很多代码基本上与您要处理的问题无关......
  • @MichalHosala 相反,代码失去了对相机和来自它的光线的重要方面的定义 - 当它需要使用线性代数时 - 错了吗?我认为实际查看数字和实现对了解正在发生的事情更有帮助。在过去的两天里,我一直在尝试调试这段特定的代码,这是最基本的,没有中断。我也知道横向和纵向的xAMTyAMT 被破坏了,想知道对于整个代码sn-p 可以提供哪些其他解决方案。
  • 好吧,你说风景/肖像也被破坏了,但是硬编码WIDTH == HEIGHT == 10 提供的代码将始终默认为方形模式......所以至少在某处提及会很好您的帖子表明您不仅对WIDTH == HEIGHT 时的解决方案感兴趣......而且,乍一看,camRay 除了被声明之外还有什么目的?另一方面,Y 声明在哪里,您正在使用它来计算 camRight ...?
  • @MichalHosala 我没有意识到Y 被忽略了。谢谢你指出这一点。其他一切都是固定的。我将在那里保留camRay,以表明新光线是从相机原点以新的特定方向设置的。印刷品是作为补充。
  • 对于纯文本输出,将其粘贴为文本会更合乎逻辑。 (并使用更好的标题:“此代码的确切输出是此图像”...)

标签: c++ raytracing


【解决方案1】:

问题出在Vector 类中。

您实现+-*/(double) 的方式与实现+=-=(const Vector&amp;) 的方式相同:您更改this 的值。

在实现二元运算符(第一个操作数是this,第二个操作数是rhs)时,您通常不想更改操作数的值。在这种情况下,我强烈建议您使用const 来警告操作员,以防出现此类错误。

Vector operator+(const double& rhs) const;

代替:

Vector operator+(const double& rhs);

那么,实现是:

Vector Vector::operator+(const double& rhs) const {
    Vector result(*this);
    result.x += rhs;
    result.y += rhs;
    result.z += rhs;

    return result;
}

【讨论】:

  • 只是。哇。谢谢!
猜你喜欢
  • 2012-05-23
  • 2012-11-13
  • 1970-01-01
  • 2016-08-23
  • 2023-03-07
  • 1970-01-01
  • 1970-01-01
  • 2011-08-29
  • 1970-01-01
相关资源
最近更新 更多