MIT 6.837
Assignment0:
Hint:
1 2 3 4 5 6
| float sum(0), t(drand48()); for (int k = 0; k < num_trans; k++){ sum += probability[k]; if (sum > t) break; } do_transform[k]_to_Vec();
|
- 需要特判仿射变换后点坐标是否在图像内
- int atoi(const char *str); 将字符串数字变为int
Result:
1
| ./ifs -input src/fern.txt -points 50000 -iters 30 -size 400 -output fern.tga
|

1
| ./ifs -input src/dragon.txt -points 50000 -iters 30 -size 400 -output dragon.tga
|

1
| ./ifs -input src/giant_x.txt -points 50000 -iters 30 -size 400 -output giant_x.tga
|

1
| ./ifs -input src/sierpinski_triangle.txt -points 10000 -iters 30 -size 200 -output sierpinski_triangle_30.tga
|

Assignment1:
原理:相机从每个像素发出射线,显示最早击中物体的贴图
Hint:

- 在坐标运算时,最好在[0,1]标准化空间坐标进行,在遇到实际的屏幕时,可以用x = x’ widht; y = y’ height来换算
- Image类中颜色坐标范围是[0,1]
- 输出t在[depth_min, depth_max]之间的灰度,要在Clamp之后,作如下变换:
1 2 3 4 5 6
| if (t >= depth_min && t <= depth_max){ float grey = 1 - (t - depth_min) / (depth_max - depth_min); Vec3f color(grey, grey, grey); }
|
隐式表示的球体求交点:

- Ray: direction is an unit vector


如果d比球半径要大,说明Ray与Sphere不相交,反之Ray与Sphere相交
相交在参数t时刻,射线原点在球内:

射线原点在球外:

判断物体射线交点,如果得到t比hit的t小,那么同时更新t和Material
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| bool Sphere::intersect(const Ray &r, Hit &h, float tmin){ Vec3f o2c = center - r.getOrigin(); float tp = o2c.Dot3(r.getDirection()); float o2c2 = o2c.Dot3(o2c); float d2 = o2c2 - tp*tp; if (d2 > radius*radius) return false; float t = sqrt(radius*radius - d2); if (tp - t < tmin){ if (tp + t > tmin){ if (h.getMaterial() == NULL || h.getT() > tp+t){ h.set(tp + t, material, r); } return true; } else return false;
} else { if (h.getMaterial() == NULL || h.getT() > tp+t){ h.set(tp - t, material, r); } return true; } }
|
- 类Group中的ObjectList应该用Object3D**类型,因为ObjectList应当是存Object3D的指针的数组,赋予ObjectList内存空间:
1
| ObjectList = new Object3D*[n];
|
- std::numeric_limits\::max 返回float最大值
- 三个向量定义相机:Up, Right, LookAt,当Up和LookAt不垂直时要修正Up:
- Right = LookAt x Up: 通过叉乘得到Right向量
- Up = Right x LookAt: 通过上一步得到的Right向量和LookAt向量,修正Up向量
- 相机的三个向量需要标准化
Result:
1
| ./raytracer -input src/scene1_01.txt -size 200 200 -output output1_01.tga -depth 9 10 depth1_01.tga
|


1
| ./raytracer -input src/scene1_02.txt -size 200 200 -output output1_02.tga -depth 9 10 depth1_02.tga
|


1
| ./raytracer -input src/scene1_07.txt -size 200 200 -output output1_07.tga -depth -2 2 depth1_07.tga
|


Task
- [x] Implement the new rendering mode, normal visualization:

读取射线击中点的法向量,取法向量分量的绝对值作为rgb分量的值
1 2 3 4 5
| Vec3f normal = h.getNormal(); float r = abs(normal.r()); float g = abs(normal.g()); float b = abs(normal.b()); image_normal->SetPixel(i, j, Vec3f(r, g, b));
|
任务要求加入diffuse(依赖光线与法线向量)与ambient,物体在该点最终的颜色为diffuse color + ambient color:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| if (group->intersect(r, h, camera->getTMin())){ assert(h.getMaterial() != NULL); Vec3f ambient_color = sceneParser.getAmbientLight(); Vec3f diffuse_color; Vec3f hit_pos = r.pointAtParameter(h.getT()); for (int i = 0; i < num_light; i++){ sceneParser.getLight(i)->getIllumination(hit_pos, light_dir[i], light_color[i]); float diffuse = light_dir[i].Dot3(h.getNormal()); if (diffuse < 0){ if (shade_back) diffuse = -diffuse; else diffuse = 0; } diffuse_color += diffuse * light_color[i]; } Vec3f pixel_color = (diffuse_color + ambient_color) * h.getMaterial()->getDiffuseColor(); image->SetPixel(i, j, pixel_color); }
|

1 2 3 4 5 6 7
| Ray PerspectiveCamera::generateRay(Vec2f point){ Vec3f pos = center; Vec3f ray_dir = direction + up * (point.y()-0.5) * tan(angle_randians/2) *2 + horizontal * (point.x()-0.5) * tan(angle_randians/2) * 2; ray_dir.Normalize(); return Ray(pos, ray_dir); }
|
通过平面一点和平面法向量可以确定平面方程,我们可以这样定义平面:P dot n = d,故通过normal和d可以唯一确定一个平面
- 射线相交判断:
- 射线方向向量与平面法向量垂直:射线与平面平行,不相交
- 将Ray的方程带入平面,得到t
- t >= tmin,相交;
- t < tmin,不相交;
1 2 3 4 5 6 7 8 9 10
| bool Plane::intersect(const Ray &r, Hit &h, float tmin){ if (dir_nor.Dot3(normal) == 0) return false; float t = (d - r.getOrigin().Dot3(normal)) / (dir_nor.Dot3(normal)); if (t < 0) return false; if (t < tmin) return false; if (h.getMaterial() != NULL && h.getT() < t) return true; h.set(t, material, normal, r); return true; }
|
射线与三角形求交判断:




对物体做变换后与Ray求交,可以通过对射线做变换实现


是否要标准化变换后的方向向量:
- Normalize: tOS ≠ tWS
- Don’t Normalize: tOS = tWS
纠正变换后物体的法向量:




纠正变换后的法向量需要用到法矩阵:

Hint
MIT提供的Transform相关的代码有点反人类,习惯上对向量做变换用矩阵M左乘向量v:Mv。例如对v先后做变换M1, M2, M3的M矩阵应为:
但scene_parser.C中解析变换矩阵时使用如下代码:
1
| matrix *= new_transform;
|
然后Matrix.C中的Transform(Vec4f)代码如下:
1 2 3 4 5 6 7 8 9 10
| void Matrix::Transform(Vec4f &v) const { Vec4f answer; for (int y=0; y<4; y++) { answer.data[y] = 0; for (int i=0; i<4; i++) { answer.data[y] += data[y][i] * v[i]; } } v = answer; }
|
相当与Mv,还是左乘,相当于列表中的变换顺序与我们想要的变换顺序是相反的
对Ray进行变换时,若单位化了direction向量,则需要改变Object3D的intersect函数,以Plane为例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| bool Plane::intersect(const Ray &r, Hit &h, float tmin){ Vec3f dir_nor = r.getDirection(); float dir_len = dir_nor.Length(); dir_nor.Normalize();
if (dir_nor.Dot3(normal) == 0) return false; float t = (d - r.getOrigin().Dot3(normal)) / (dir_nor.Dot3(normal)); t /= dir_len; if (t < 0) return false; if (t < tmin) return false; if (h.getMaterial() != NULL && h.getT() < t) return true; h.set(t, material, normal, r); return true; }
|
Result
maybe some bugs in normal shader?
1
| ./raytracer -input src/scene2_06_plane.txt -size 200 200 -output output2_06.tga -depth 8 20 depth2_06.tga -normals normals2_06.tga
|



1
| ./raytracer -input src/scene2_07_sphere_triangles.txt -size 200 200 -output output2_07.tga -depth 9 11 depth2_07.tga -normals normals2_07.tga -shade_back
|


- scene 7 don’t shade back:
1
| ./raytracer -input src/scene2_07_sphere_triangles.txt -size 200 200 -output output2_07_no_back.tga
|

1
| ./raytracer -input src/scene2_09_bunny_200.txt -size 200 200 -output output2_09.tga
|

1
| ./raytracer -input src/scene2_10_bunny_1k.txt -size 200 200 -output output2_10.tga
|

1
| ./raytracer -input src/scene2_13_rotated_squashed_sphere.txt -size 200 200 -output output2_13.tga -normals normals2_13.tga
|


1
| ./raytracer -input src/scene2_14_axes_cube.txt -size 200 200 -output output2_14.tga
|

1
| ./raytracer -input src/scene2_15_crazy_transforms.txt -size 200 200 -output output2_15.tga
|

some bugs in green sphere and purple sphere?
1
| ./raytracer -input src/scene2_16_t_scale.txt -size 200 200 -output output2_16.tga -depth 2 7 depth2_16.tga
|
