如何理解这个RayTracer代码

时间:2014-02-20 14:16:57

标签: c++ raytracing

因此,此RT代码通过原始代码创建带有模糊的3D图像。如果没有任何建模工具,这实际上是如何完成的?

我目前正在努力了解RT的工作原理以及实现它们的不同方法,所以看到这么少的代码产生令人印象深刻的3D图像真是太酷了。

#include <stdlib.h>   // card > aek.ppm
#include <stdio.h>
#include <math.h>
#include <fstream>

typedef int i;
typedef float f;

struct v {
f x, y, z;
v operator+(v r) {
    return v(x + r.x, y + r.y, z + r.z);
}
v operator*(f r) {
    return v(x * r, y * r, z * r);
}
f operator%(v r) {
    return x * r.x + y * r.y + z * r.z;
}
v() {}
v operator^(v r) {
    return v(y * r.z - z * r.y, z * r.x - x * r.z, x * r.y - y * r.x);
}
v(f a, f b, f c) {x = a; y = b; z = c;}
v operator!() {
    return*this * (1 / sqrt(*this % *this));
}
};
i G[] = {247570, 280596, 280600, 249748, 18578, 18577, 231184, 16, 16};
f R()
{
return(f)rand() / RAND_MAX;
}
i T(v o, v d, f&t, v&n)
{
t = 1e9; i m = 0;
f p = -o.z / d.z;

if(.01 < p)t = p, n = v(0, 0, 1), m = 1;

for(i k = 19; k--;)
    for(i j = 9; j--;)if(G[j] & 1 << k) {
            v p = o + v(-k, 0, -j - 4);
            f b = p % d, c = p % p - 1, q = b * b - c;

            if(q > 0) {
                f s = -b - sqrt(q);

                if(s < t && s > .01)
                    t = s, n = !(p + d * t), m = 2;
            }
        }

return m;
} v S(v o, v d)
{
f t;
v n;
i m = T(o, d, t, n);

if(!m)return v(.7, .6, 1) * pow(1 - d.z, 4);

v h = o + d * t, l = !(v(9 + R(), 9 + R(), 16) + h * -1), r = d + n * (n % d * -2);

f b = l % n; if(b < 0 || T(h, l, t, n))b = 0;

f p = pow(l % r * (b > 0), 99);

if(m & 1) {
    h = h * .2;
    return((i)(ceil(h.x) + ceil(h.y)) & 1 ? v(3, 1, 1) : v(3, 3, 3)) * (b * .2 + .1);
} return v(p, p, p) + S(h, r) * .5;
} i

main()
{

FILE * pFile;
pFile = fopen("d:\\myfile3.ppm", "w");
fprintf(pFile,"P6 512 512 255 ");
v g = !v(-6, -16, 0), a = !(v(0, 0, 1) ^ g) * .002, b = !(g ^ a) * .002, c = (a + b) *  -256 + g;

for(i y = 512; y--;)
    for(i x = 512; x--;) {
        v p(13, 13, 13);

        for(i r = 64; r--;) {
            v t = a * (R() - .5) * 99 + b * (R() - .5) * 99;
            p = S(v(17, 16, 8) + t, !(t * -1 + (a * (R() + x) + b * (y + R()) + c) *        16)) * 3.5 + p;
        }

        fprintf(pFile, "%c%c%c", (i)p.x, (i)p.y, (i)p.z);

    }
}

2 个答案:

答案 0 :(得分:2)

亲爱的朋友,保罗·赫克伯特的代码是对的吗?

你至少可以提一下。

对于认为此代码不可读的人,原因如下:

这家伙制作的代码可以放在信用卡上,这就是目标:)

他的网站:http://www.cs.cmu.edu/~ph/

编辑:了解此代码的来源可能有助于您理解它。即使它扼杀了你的主要动机......

如果您对光线追踪真的感兴趣,请从其他来源开始。 看看这个网站http://www.scratchapixel.com/lessons/3d-basic-lessons/lesson-1-writing-a-simple-raytracer/source-code/(加上它谈论你的代码)

答案 1 :(得分:2)

这段代码并不特别。它基本上是一个光线跟踪器,被混淆成一个使其适合名片的形式(见https://www.cs.cmu.edu/~ph/)。

  

如果没有任何建模工具,这实际上是如何完成的?

您不需要工具来渲染任何东西。你甚至可以在没有任何建模工具的情况下创建一个完整的魔兽游戏(或者目前的时尚)。建模工具只是让你的生活更轻松w.r.t.某些场景(阅读:非常复杂的场景)。

您可以随时对这些数据进行硬编码,也可以手动将其破解为某些外部文件。

你也可以使用参数生成器; Perlin Noise是其中最受欢迎的例子之一。

在光线跟踪器中,没有建模工具就很容易开始,因为计算渲染图元“ray”和任何有限几何图元之间的几何交点非常简单。例如,交叉点是一个非近似的“完美”球体,只是几行代码。

tl; dr:数据只是数据。你如何创造和压缩它完全取决于你。