【Ray Tracing in One Weekend】(ch9)Dielectrics

Chapter 9: Dielectrics

这章是关于折射的,看不太懂,这里转一篇别人的技术文章,讲的很好:

http://blog.csdn.net/libing_zeng/article/details/72599121

我在这就贴贴代码和图片吧。

首先是在 Material.h 中,新添如下代码:

float Schlick(float cosine, float ref_idx) {
    float r0 = (1 - ref_idx) / (1 + ref_idx);
    r0 = r0*r0;
    return r0 + (1 - r0)*pow((1 - cosine), 5);
}

//计算折射光线的方向向量。ni_over_nt 为入射介质的折射指数和折射介质的折射指数的比值。
bool Refract(const Vec3& v, const Vec3& n, float ni_over_nt, Vec3& refracted) {
    Vec3 uv = unit_vector(v);
    float dt = dot(uv, n);
    float discriminant = 1.0 - ni_over_nt*ni_over_nt*(1 - dt*dt);
    if (discriminant > 0) {
        refracted = ni_over_nt*(uv - n*dt) - n*sqrt(discriminant);
        return true;
    }
    //根号里面的内容小于零,说明折射光线的方向向量无实根,即没有折射光线,即出现全反射。所以,折射光线函数return false
    else
        return false;
}

class Dielectric : public Material {
public:
    Dielectric(float ri) : ref_idx(ri) {}
    virtual bool Scatter(const Ray& r_in, const hit_record& rec, Vec3& attenuation, Ray& scattered) const {
        Vec3 outward_normal;
        Vec3 reflected = Reflect(r_in.direction(), rec.normal);
        float ni_over_nt;
        attenuation = Vec3(1.0, 1.0, 1.0);
        Vec3 refracted;
        float reflect_prob;
        float cosine;
        if (dot(r_in.direction(), rec.normal) > 0) {
            outward_normal = -rec.normal;
            ni_over_nt = ref_idx;
            //cosine = ref_idx * dot(r_in.direction(), rec.normal) / r_in.direction().length();
            cosine = dot(r_in.direction(), rec.normal) / r_in.direction().length();
            cosine = sqrt(1 - ref_idx*ref_idx*(1 - cosine*cosine));
        }
        else {
            outward_normal = rec.normal;
            ni_over_nt = 1.0 / ref_idx;
            cosine = -dot(r_in.direction(), rec.normal) / r_in.direction().length();
        }
        if (Refract(r_in.direction(), outward_normal, ni_over_nt, refracted))
            reflect_prob = Schlick(cosine, ref_idx);
        else
            reflect_prob = 1.0;
        if ((rand() % (100) / (float)(100)) < reflect_prob)
            scattered = Ray(rec.p, reflected);
        else
            scattered = Ray(rec.p, refracted);
        return true;
    }

    float ref_idx;
};

Main方法中代码修改如下:

    Hitable *list[5];
    list[0] = new Sphere(Vec3(0.0f, 0.0f, -1.0f), 0.5f, new Lambertian(Vec3(0.8f, 0.3f, 0.3f)));
    list[1] = new Sphere(Vec3(0.0f, -100.5f, -1.0f), 100.0f, new Lambertian(Vec3(0.8f, 0.8f, 0.0f)));
    list[2] = new Sphere(Vec3(1.0f, 0.0f, -1.0f), 0.5f, new Metal(Vec3(0.8f, 0.6f, 0.2f),0.3f));
    list[3] = new Sphere(Vec3(-1.0f, 0.0f, -1.0f), 0.5f, new Dielectric(1.5f));
    list[4] = new Sphere(Vec3(-1.0f, 0.0f, -1.0f), -0.45f, new Dielectric(1.5f));
    Hitable *world = new HitableList(list, 5);

所得如图:

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Ray Tracing(光线追踪)是一种在计算机图形学中使用的技术,用于生成高度逼真的图像。它通过跟踪光线从视点开始的路径,来模拟光在场景中的运动,计算出光线与物体的交点以及光线在经过物体时的反射、折射等效果,并最终生成图像。 以下是光线追踪的基本步骤[^1]: 1. 从相机位置发出一条光线。 2. 确定该光线与场景中物体的交点。 3. 计算该交点处的光照强度,包括直接光照和间接光照。 4. 根据物体的表面特性,计算反射或折射光线的方向和强度。 5. 递归计算反射或折射光线的路径,直到达到最大递归深度或光线不再与物体相交。 6. 将所有光线的颜色值组合在一起,得到最终的图像。 下面是一个简单的 Python 代码示例,演示了如何使用 Pygame 和 PyOpenGL 库实现简单的光线追踪效果[^2]: ```python import pygame from OpenGL.GL import * # 初始化 Pygame 和 PyOpenGL pygame.init() display = (800, 600) pygame.display.set_mode(display, pygame.DOUBLEBUF | pygame.OPENGL) # 设置相机位置和方向 glMatrixMode(GL_MODELVIEW) glLoadIdentity() gluLookAt(0, 0, 0, 0, 0, -1, 0, 1, 0) # 设置场景中的物体 glColor3f(1, 1, 1) glBegin(GL_TRIANGLES) glVertex3f(-1, -1, -5) glVertex3f(1, -1, -5) glVertex3f(0, 1, -5) glEnd() # 定义光线追踪函数 def raytrace(x, y): glReadBuffer(GL_BACK) color = glReadPixels(x, y, 1, 1, GL_RGB, GL_FLOAT) return color # 创建主循环 while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() quit() # 绘制场景和光线 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glBegin(GL_LINES) glVertex3f(0, 0, 0) glVertex3f(0, 0, -5) glEnd() # 调用光线追踪函数 x, y = pygame.mouse.get_pos() w, h = display color = raytrace(w - x, h - y) # 输出光线追踪结果 print("Color at (%d, %d): %s" % (x, y, color)) # 更新 Pygame 显示窗口 pygame.display.flip() ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值