# 光线追踪器完善
## 简介
对光线追踪器进行完善,实现了光源添加,纹理添加,三角形模型引入,bvh 树实现,以及多线程加速
## 项目实现方法简述
### 添加纹理
```c++
virtual vec3 value(double u, double v, const vec3& p) const {
int i = static_cast<int>(u * m_width);
int j = static_cast<int>((1.0f - v)*m_height) - 0.001;
if (i < 0) i = 0;
if (j < 0) j = 0;
if (i > m_width - 1) i = m_width - 1;
if (j > m_height - 1) j = m_height - 1;
int index = (j * m_width + i) * m_channel;
float r = static_cast<int>(m_data[index + 0]) / 255.0f;
float g = static_cast<int>(m_data[index + 1]) / 255.0f;
float b = static_cast<int>(m_data[index + 2]) / 255.0f;
return vec3(r, g, b);
}
```
具体思路为在材料中添加一个指向纹理的指针,这样在计算材料表面颜色的时候,不是返回默认值,而是调用 value 函数,根据 u,v 值来获取相应的值。上述代码为图片纹理的 value 函数实现。
### 添加光源
```c++
class diffuse_light :public material{//光源材质,将碰撞到该材质的光线设为光源颜色,光源颜色的分量可以大于1,如(4,4,4)
public:
diffuse_light(std::shared_ptr<texture> a) : albedo(a) {};
virtual bool scatter(const ray& r_in, const hit_record& rec, vec3& attenuation,
ray& scattered) const {
return false;
}
virtual vec3 emitted(const float &u,const float &v, const vec3 &p) const
{
return albedo->value(u, v, p);
}
std::shared_ptr<texture> albedo;
};
```
这里,我们把光源当成一种特殊的材质,这种材质不反射光线,而是直接发射相应的颜色,强度的光线。
### 三角形渲染
```c++
bool triangle::hit(const ray& r, float t_min, float t_max, hit_record& rec) const{
if (dot(normal, r.direction()) == 0.0f)//光线与平面平行
return false;
float t = -(dot(normal, r.origin()) + d) / dot(normal, r.direction());
if (t < t_min || t > t_max)
return false;
rec.t = t;
rec.point = r.point_at_parameter(t);
rec.mat_ptr = mat_ptr;
//判断点是否在三角形内
vec3 R = rec.point - point0;
vec3 Q1 = point1 - point0;
vec3 Q2 = point2 - point0;
float dot_Q1_Q1 = dot(Q1, Q1);
float dot_Q2_Q2 = dot(Q2, Q2);
float dot_Q1_Q2 = dot(Q1, Q2);
float dot_R_Q1 = dot(R, Q1);
float dot_R_Q2 = dot(R, Q2);
float determinant = 1.0f / (dot_Q1_Q1*dot_Q2_Q2 - dot_Q1_Q2*dot_Q1_Q2);
//获取当前点的信息,由三个顶点和omega,1omega2得到
float omega1 = determinant*(dot_Q2_Q2*dot_R_Q1 - dot_Q1_Q2*dot_R_Q2);
float omega2 = determinant*(-dot_Q1_Q2*dot_R_Q1 + dot_Q1_Q1*dot_R_Q2);
if (omega1 + omega2 > 1.0f || omega1 < 0.0f || omega2 < 0.0f)
return false;
rec.normal = normal0* (1.0f - omega1 - omega2) + normal1 * omega1 + normal2 *
omega2;
rec.u = u0* (1.0f - omega1 - omega2) + u1 * omega1 + u2 * omega2;
rec.v = v0* (1.0f - omega1 - omega2) + v1 * omega1 + v2 * omega2;
if (dot(rec.normal, r.direction()) > 0.0f)
rec.normal = -rec.normal;
return true;
}
```
这里,我们把光源当成一种特殊的材质,这种材质不反射光线,而是直接发射相应的颜色,强度的光线。
### 加载网格模型
```c++
virtual bool hit(const ray& r, float t_min, float t_max, hit_record& rec) const{
hit_record temp_rec;
bool hit_anything = false;
float closest_so_far = t_max;
for (int i = 0; i < mod.size(); i++){
if (mod.at(i).hit(r, t_min, closest_so_far, temp_rec)){
hit_anything = true;
closest_so_far = temp_rec.t;
rec = temp_rec;
}
}
return hit_anything;
}
vector<triangle> mod;
```
一个模型拥有一个 vector 用来储存三角形,具体的处理思路在没有处理优化的时候其实和 hitable_list 差不多。在 obj 文件读取时,会碰到四边形面片处理,如(p0,p1,p2,p3).这里我们就要把它当成 2 个三角形(p0,p1,p2)和(p0,p3,p2)就能刚好组成一个四边形面片,即两个三角形的公共边需要是四边形中的对角线。
### 构建 BVH 树
```c++
auto comparator = (index == 0) ? box_x_compare
: (index == 1) ? box_y_compare
: box_z_compare;
size_t length = end - start;
if (length == 1){
left = right = objects[start];
}
else if (length == 2){
if (comparator(objects[start], objects[start+1])){
left = objects[start];
right = objects[start + 1];
}
else{
left = objects[start + 1];
right = objects[start];
}
}
else{
std::sort(objects + start, objects + end, comparator);
auto mid = start + length / 2;
left = new bvh_node(objects, start, mid, t0, t1);
right = new bvh_node(objects, mid, end, t0, t1);
}
```
首先利用层次包围盒的概念,利用 bvh 树对求交进行简化,可以理解为 B(左节点),C(右节点)两个小的包围盒组合成一个大的包围盒 A(父节点),在判断求交的时候,先判断是否和 A(父节点)相交,若相交,再判断子节点。
那么主要的难点就是如何构建 bvh 树,这里利用了递归的思想,每次将数组二分,直到只剩两个物体分别为左右节点,同时,在每次二分前,随机选择一个轴对物体进行排序。
### 多线程加速
```c++
# pragma omp parallel for
```
通过在 for 循环前添加上述语句,然后在项目属性的语言,C++ 中,openMP 支持改为是~,就可以自动将下面的 for 循环分成 N 份,(N 为电脑 CPU 核数),然后把每份指派给一个核去执行,而且多核之间为并行执行
### 结果
![](https://www.writebug.com/myres/static/uploads/2021/12/20/bf2aa497954c5944693206aab7789719.writebug)
没有合适的资源?快使用搜索试试~ 我知道了~
基于C++完善光线追踪器【100012093】
共62个文件
h:16个
tlog:12个
obj:7个
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
0 下载量 9 浏览量
2023-04-28
14:02:58
上传
评论
收藏 11.93MB ZIP 举报
温馨提示
对光线追踪器进行完善,实现了光源添加,纹理添加,三角形模型引入,bvh 树实现,以及多线程加速。具体思路为在材料中添加一个指向纹理的指针,这样在计算材料表面颜色的时候,不是返回默认值,而是调用 value 函数,根据 u,v 值来获取相应的值。上述代码为图片纹理的 value 函数实现。
资源推荐
资源详情
资源评论
收起资源包目录
100012093-基于C++完善光线追踪器.zip (62个子文件)
trace2
图形学作业五
hitable_list.h 1KB
model.h 4KB
ray.h 324B
Rock_1_Base_Color.jpg 2.97MB
图形学作业五.vcxproj.user 162B
PathTracer.h 736B
box.obj 12KB
earth.jpg 22KB
triangle.h 3KB
camera.h 1KB
vec3.h 4KB
stb_image_write.h 65KB
random_num.h 538B
Release
vc120.pdb 780KB
PathTracer.obj 1.51MB
图形学作业五.log 5KB
图形学作业五.tlog
CL.write.1.tlog 1KB
图形学作业五.lastbuildstate 163B
link.command.1.tlog 3KB
link.read.1.tlog 7KB
cl.command.1.tlog 1KB
link.write.1.tlog 338B
CL.read.1.tlog 12KB
main.obj 810KB
aabb.h 1KB
material.h 4KB
main.cpp 690B
diablo3_pose.obj 417KB
stb_image.h 261KB
result.png 38KB
bvh_node.h 3KB
PathTracer.cpp 6KB
diablo3_pose_diffuse.tga 2.83MB
图形学作业五.vcxproj.filters 2KB
sphere.h 2KB
texture.h 2KB
Rock_1.OBJ 97KB
Debug
vc120.pdb 380KB
PathTracer.obj 217KB
图形学作业五.log 4KB
图形学作业五.tlog
CL.write.1.tlog 822B
图形学作业五.lastbuildstate 161B
link.command.1.tlog 3KB
link.read.1.tlog 6KB
cl.command.1.tlog 1KB
link.write.1.tlog 394B
CL.read.1.tlog 11KB
vc120.idb 339KB
main.obj 236KB
图形学作业五.vcxproj 5KB
hitable.h 381B
.gitattributes 66B
LICENSE 1KB
Release
图形学作业五.exe 124KB
图形学作业五.pdb 1.04MB
图形学作业五.v12.suo 36KB
图形学作业五.sdf 15.63MB
Debug
图形学作业五.exe 121KB
图形学作业五.ilk 491KB
图形学作业五.pdb 811KB
README.md 5KB
图形学作业五.sln 978B
共 62 条
- 1
资源评论
神仙别闹
- 粉丝: 2667
- 资源: 7640
下载权益
C知道特权
VIP文章
课程特权
开通VIP
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功