【RayTracingInOneWeekend】画圆

保持前一章的其他头文件不变,在main.cpp添加如下代码:

#include"vec3.h"
#include"ray.h"
#include"color.h"

#include<iostream>
//设球心为C = (Cx,Cy,Cz)
//球的一般表示公式:(x - Cx)^2 +(y - Cy)^2 +(z - Cz)^2 = r^2
//球上取任一点P(x,y,z) ,则有(P -C)(P -C) = r^2
//带入光线方程P(t) = A + tb,P是沿着这条线的3d位置,A是光线原点,b是光线方向,则有:(A + tb - C)(A + tb - C) = r^2
//解开方程得到:b*bt^2 + (2b * (A - C))t + (A - C)*(A - C) -r^2 = 0,t为未知数,只需要求根公式大于0,则得到光线是击中球的
bool Hit_Sphere(const point3& center, float radius, const ray& r)
{
	auto lightSourceToSphereCenter = r.origin() - center;
	auto a = dot(r.direction(), r.direction());
	auto b = 2 * dot(r.direction(), lightSourceToSphereCenter);
	auto c = dot(lightSourceToSphereCenter,lightSourceToSphereCenter) - radius * radius;

	auto rootFunction = b * b - 4 * a * c;
	return(rootFunction > 0);
}

color ray_color(const ray& r)
{
	if (Hit_Sphere(point3(0, 0, -1), 0.5, r))
	{
		return color(1,1,0);
	}
	vec3 unit_direction = unit_vector(r.direction());
	auto t = 0.5f * (unit_direction.y() + 1.0f);
	//(1−t)×c1 + t×c2 线性插值

	return (1.f - t) * color(1.f, 1.f, 1.f) + t * color(0.5f, 0.7f, 1.f);
}

int main()
{
	//定义了一个关于图像和相机的基本参数:

	//图像部分:定义了图像的宽高比,以及宽度和高度。宽高比是在之前的代码中定义的,宽度为400像素,高度根据宽高比计算得出。
	//相机部分:定义了视口的宽高以及焦距。视口是指相机能够看到的范围,这里的视口宽度是根据宽高比和视口高度计算得出的;
	// 焦距表示了相机的聚焦程度,这里设为1。还定义了相机的位置,以及一个水平方向向量、垂直方向向量和左下角的位置,这些都是
	// 计算相机拍摄视角时需要用到的基本参数。
	//image 
	const auto aspect_ratio = 16.f / 9.f;
	const int image_width = 400;
	const int image_height = static_cast<int>(image_width / aspect_ratio);

	//camera
	auto viewport_height = 2.f;
	auto viewport_width = aspect_ratio * viewport_height;
	auto focal_length = 1.f;

	auto origin = point3(0, 0, 0);
	auto horizontal = vec3(viewport_width, 0, 0);
	auto vertical = vec3(0, viewport_height, 0);
	auto lower_left_corner = origin - horizontal / 2 - vertical / 2 - vec3(0, 0, focal_length);

	//render
	std::cout << "P3\n" << image_width << ' ' << image_height << "\n255\n";

	//由于PPM文件格式规定像素行是从文件的底部开始写入的,而每一行的像素是从左向右依次排列的,
	//因此在遍历时需要先从最后一行开始循环遍历,再往上逐行遍历,以保证输出的像素数据符合PPM文件格式的要求
	for (int i = image_height - 1; i >= 0; --i)
	{
		//通过一个外层循环,从图像的最后一行开始,往前逐行扫描。
		//在内层循环中,对于每行中的每个像素,计算出其在图像中的位置(即相对于左下角的水平和垂直方向上的偏移量),从而确定了该像素对应的射线方向。
		//使用 ray_color() 函数计算出该射线的颜色,即该像素的颜色。
		//将该像素的颜色输出到标准输出流中,以便最终能够将其保存为图像文件。
		std::cerr << "\r Scanlines remaining: " << i << ' ' << std::flush;
		for (int j = 0; j < image_width; ++j)
		{
			auto u = float(j) / (image_width - 1);
			auto v = float(i) / (image_height - 1);
			ray r(origin, lower_left_corner + u * horizontal + v * vertical - origin);
			color pixel_color = ray_color(r);
			write_color(std::cout, pixel_color);
		}
	}
	std::cerr << "\nDone.\n";
}

得到如下图:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值