【Ray Tracing in One Weekend】(ch6)Ray Tracer 里的反走样

Chapter 6: Antialiasing

先回顾一下在上一章我们得到的图

这里写图片描述

把局部放大一下

这里写图片描述

可以看到球体边缘呈现比较明显的锯齿状。解决这个问题的过程就叫做反走样。其实就是让前景和背景交叉的边缘变得更平滑而已。具体应该怎么做呢?

从代码中我们知道,我们共发射出了200*100条射线,对应了200*100个像素格子(从上图中可以隐隐看出像素格子),这样在前景与背景交叉的像素格子上必定只有一种颜色,这样就会出现明显的锯齿状(锯齿其实就是一个个像素格子)。在不改变图像分辨率的情况下,如何改善这种状况呢?

其实,每个像素格子的颜色并不代表着那一块区域真正的颜色,只是我们采用了发射一条射线碰撞到的一点返回的颜色代替了那一小块区域的颜色,那么,解决这个问题就变得简单了,我们多发射一些射线到这个格子里,然后取这些射线返回颜色的均值就好啦!

首先为了方便,我们先把搁置了很久的 Camera 类封装起来:

#pragma once

#include "Ray.h"

class Camera 
{
public:
    Camera()
    {
        lower_left_corner = Vec3(-2.0f, -1.0f, -1.0f);
        horizontal = Vec3(4.0f, 0.0f, 0.0f);
        vertical = Vec3(0.0f, 2.0f, 0.0f);
        origin = Vec3(0.0f, 0.0f, 0.0f);
    }

    Ray getRay(float u, float v) 
    {
        return Ray(origin, lower_left_corner + u*horizontal + v*vertical - origin);
    }

    Vec3 lower_left_corner;
    Vec3 origin;
    Vec3 horizontal;
    Vec3 vertical;
};

接着修改Main方法为:

int main()
{

    ofstream outfile;
    outfile.open("ch6Image.ppm");

    int nx = 200;
    int ny = 100;
    //采样次数
    int ns = 100;
    outfile << "P3\n" << nx << " " << ny << "\n255\n";

    Hitable *list[2];
    list[0] = new Sphere(Vec3(0.0f, 0.0f, -1.0f), 0.5f);
    list[1] = new Sphere(Vec3(0.0f, -100.5f, -1.0f), 100.0f);
    Hitable *world = new HitableList(list, 2);

    Camera cam;

    //随机数引擎
    default_random_engine reng;
    uniform_real_distribution<float> uni_dist(0.0f, 1.0f);

    for (int j = ny - 1; j >= 0; j--)
    {
        for (int i = 0; i < nx; i++)
        {
            Vec3 col(0.0f, 0.0f, 0.0f);
            //每个区域采样ns次
            for (int s = 0; s < ns; s++)
            {
                float u = float(i + uni_dist(reng)) / float(nx);
                float v = float(j + uni_dist(reng)) / float(ny);
                Ray r = cam.getRay(u,v);
                //Vec3 p = r.point_at_parameter(2.0);
                //将本区域((u,v)到(u+1,v+1))的颜色值累加
                col += Color(r, world);
            }
            //获得区域的颜色均值
            col /= float(ns);

            int ir = int(255.99*col[0]);
            int ig = int(255.99*col[1]);
            int ib = int(255.99*col[2]);
            outfile << ir << " " << ig << " " << ib << "\n";
        }
    }
    outfile.close();
    return 0;
}

最后所得图片为:

这里写图片描述

将局部放大一下做一下对比:

这里写图片描述

可以看到,下面的圆的边缘明显出现了“过渡色”的像素块,比较好的解决了走样问题。

同时我们也要注意到,开启反走样之后,渲染速率变慢了非常多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值