学习《Ray Tracing in One Weekend》第四章

第四章 画球

已经画出了基本的背景图了,现在可以学着加一些物体进去,作者给的是画一个球。
(一个光线代表着一个像素点)
画图的基本步骤

  1. 确定球的位置。(球上每个像素点的位置即为光线与球的交点,所有这些交点就组成了球。所以,问题转化为找光线和球的交点)
  2. 设置球的颜色。(光线和球交点的颜色)

球体方程

(p−c)⋅(p−c)=R*R

方程等价于:
在这里插入图片描述
球上任一点的坐标(向量)为p,而 c 表示小球圆心, R 表示小球半径
带入到光线公式得到
在这里插入图片描述
转化为
在这里插入图片描述

由此来改写之前的代码,将公式写进代码里,我们在z = − 1 处放置一个小球

#include <iostream>
#include <fstream>
#include "Ray.h"
using namespace std;

 //判断光线有没有撞上球体
bool hit_sphere(const Vec3& center, float radius, const Ray& r)
{
    Vec3 oc = r.origin() - center; //向量A-C=oc
    float a = dot(r.direction(), r.direction()); //a = (B·B)=dot(B,B),
    float b = 2.0f * dot(oc, r.direction()); // b=2*(B·(A-C))=2*dot(B,(A-C))
    float c = dot(oc, oc) - radius * radius; //c= (A-C)·(A-C) - R2=dot((A-C),(A-C)) - R2
    float discrimiant = b * b - 4.0f * a * c; //判别式
    return (discrimiant > 0.0f);//判别式>0,有实根,光线撞上球,返回1;
                               //判别式<0,没有实根,光线没有撞上球,返回0;
}

Vec3 Color(const Ray& r)
{
       // 小球位于(0,0,-1),半径为0.5
    if (hit_sphere(Vec3(0.0f, 0.0f, -1.0f), 0.5f, r))
        return Vec3(1.0f, 0.0f, 0.0f);
//此处判断这条光线是否撞上球。如果撞上,则执行vec3(1, 0, 0),将这个像素点设置为红色。

    Vec3 unit_direction = unit_vector(r.direction());
    // 标准化之后的y值值域为[-1, 1], 将其映射到[0, 1]
    float t = 0.5f * (unit_direction.y() + 1.0f);
    return (1.0f - t) * Vec3(1.0f, 1.0f, 1.0f) + t * Vec3(0.5f, 0.7f, 1.0f);
}


int main()
{

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

    int nx = 200;
    int ny = 100;
    outfile << "P3\n" << nx << " " << ny << "\n255\n";

    Vec3 lower_left_corner(-2.0f, -1.0f, -1.0f);
    Vec3 horizontal(4.0f, 0.0f, 0.0f);
    Vec3 vertical(0.0f, 2.0f, 0.0f);
    Vec3 origin(0.0f, 0.0f, 0.0f);


    for (int j = ny - 1; j >= 0; j--)
    {
        for (int i = 0; i < nx; i++)
        {
            float u = float(i) / float(nx);
            float v = float(j) / float(ny);
            Ray r(origin, lower_left_corner + u * horizontal + v * vertical);
            Vec3 col = Color(r);
            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;
}

得到的图片为
在这里插入图片描述

(锯齿明显)

可以更改小球的半径为0.8

    if (hit_sphere(Vec3(0.0f, 0.0f, -1.0f), 0.8f, r))
        return Vec3(1.0f, 0.0f, 0.0f);

得到
在这里插入图片描述
或者更改小球位置坐标

    if (hit_sphere(Vec3(0.0f, 0.0f, -5.0f), 0.5f, r))
        return Vec3(1.0f, 0.0f, 0.0f);

得到图片在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值