《一周学完光线追踪》学习 三 光线相机和背景

news/2024/11/15 3:41:38/

蒙特卡洛光线追踪技术系列 见 蒙特卡洛光线追踪技术

所有光线跟踪器都有一个光线类,以及计算沿光线看到的颜色。让我们把射线看作一个函数,p(t)=A+t*B,这里p是3D中沿直线的3D位置,a是射线的原点,B是射线的方向。射线参数t是实数(代码中的浮点数)。插入不同的t和p(t)沿射线移动点。

加上负t,你就可以得到3D线上的任何地方。对于正t,你只得到A前面的部分,这就是通常所说的半线或射线。示例C=p(2)如下所示:

现在我们准备好转弯,做一个光线跟踪器。光线跟踪器的核心是通过像素发送光线,并计算在光线方向上看到的颜色。它的形式是计算从眼睛到像素的光线,计算光线与像素相交的部分,并计算该相交点的颜色。在第一次开发光线跟踪器时,我总是用一个简单的相机来启动和运行代码。我还做了一个简单的颜色(光线)函数,返回背景的颜色(一个简单的渐变)。

我经常在使用正方形图像进行调试时遇到麻烦,因为我经常转换x和y,所以我将坚持使用200x100图像(这里我还是用的512*512的图像)。我将把“眼睛”(或者相机中心,如果你想到相机的话)设为(0,0,0)。我让y轴向上,x轴向右。为了尊重右手坐标系的对流,进入屏幕的是负z轴。我将从左下角遍历屏幕,并使用沿屏幕边的两个偏移向量来移动屏幕上的光线端点。请注意,我没有将光线方向设置为单位长度向量,因为我认为不这样做会使代码更简单、速度略快。

在下面的代码中,光线r接近像素中心(我现在不担心精确性,因为我们稍后将添加抗锯齿):

#ifndef RAY_H
#define RAY_H#include "Vector3.h"class Ray  {
public:Ray() {}Ray(const Vector3& a, const Vector3& b) { data[0] = a; data[1] = b; data[2] = Vector3(1.0f / b.x(), 1.0f / b.y(), 1.0f / b.z());posneg[0] =  (data[1].x() > 0 ? 0 : 1);posneg[1] = posneg[0] ^ 1;posneg[2] =  (data[1].y() > 0 ? 0 : 1);posneg[3] = posneg[2] ^ 1;  posneg[4] =  (data[1].z() > 0 ? 0 : 1);posneg[5] = posneg[4] ^ 1;  }Ray(const Ray& r) {*this = r;}Vector3 origin() const {return data[0];}Vector3 direction() const {return data[1];}Vector3 invDirection() const {return data[2];}void setOrigin(const Vector3& v) {data[0] = v;}void setDirection(const Vector3& v) {data[1] = v;data[2] = Vector3(1.0f / v.x(), 1.0f / v.y(), 1.0f / v.z());posneg[0] =  (data[1].x() > 0 ? 0 : 1);posneg[1] = posneg[0] ^ 1;posneg[2] =  (data[1].y() > 0 ? 0 : 1);posneg[3] = posneg[2] ^ 1;  posneg[4] =  (data[1].z() > 0 ? 0 : 1);posneg[5] = posneg[4] ^ 1;  }Vector3 pointAtParameter(float t) const { return data[0] + t*data[1]; }Vector3 data[3];int posneg[6]; 
};#endif

写个程序测试一下:

	Vector3 lower_left_corner(-2.0, -1.0, -1.0);Vector3 horizontal(4.0,0.0,0.0);Vector3 vertical(0.0,2.0,0.0);Vector3 origin(0.0, 0.0, 0.0);for (int j = HEIGHT-1;j >= 0;j--) {for (int i = 0;i < WIDTH;i++) {int offset = (WIDTH*i + j) * 4;float u = float(i) / float(WIDTH);float v = float(j) / float(HEIGHT);Ray r(origin, lower_left_corner+u*horizontal+v*vertical);Vector3 col((u-0.5)*(u-0.5)+(v-0.5)*(v-0.5),0.0,0.0);Pixels[offset + 0] = (unsigned char)255.99*col[0];Pixels[offset + 1] = (unsigned char)255.99*col[1];Pixels[offset + 2] = (unsigned char)255.99*col[2];Pixels[offset + 3] = 255;}}

得到效果如图:


http://www.ppmy.cn/news/659850.html

相关文章

月球探测车-DIY

月球探测车-DIY 提示&#xff1a;内容为作者原创&#xff0c;转载请标明出处 概述 随着我国的航天事业蒸蒸日上&#xff0c;浩航星辰离我们不再那么遥远。你的内心是否也开始对探索外面未知的世界充满好奇。当勇气号、毅力号、天问一号、玉兔降落在遥远的地外星球时&#xff0…

arduino 警灯DIY教程

材料准备&#xff1a; ws2812B灯珠偶数个。 arduino开发板任意一个。 锡焊工具和导线若干。&#xff08;也可以直接买网上的ws2812灯条&#xff0c;贵了些但不用焊了。&#xff09; 具体步骤如下&#xff1a; 安装arduino IDE。CSDN教程很多且很详细&#xff0c;不再赘述。…

ESP8266-01实战三——月球灯

基于Unity UDP通信的esp8266-01月球灯 一、介绍二、准备2.1原理方案分析2.1.1外壳2.1.2灯2.1.3主控2.1.4上位机 三、制作3.1月球灯外壳3.2月球灯PCB3.3APP 四、BUG4.1AP模式看门狗复位4.2AP模式无法被PC连接 五、总结 一、介绍 先看看是个什么东西吧&#xff0c;这是一个3D打印…

圣诞节这么浪漫的日子,教你用Python制作表白神器—照片墙,操作起来哦

哈喽。大家好&#xff0c;我是恰恰~今天教大家用Python来制作一个表白神器—照片墙&#xff0c;属于我们程序员的小浪漫&#xff0c;虽然来的晚&#xff0c;但是收藏学会了&#xff0c;以后都用的到哦~ 看一下效果图&#xff1a; 要什么样的&#xff0c;图案都可以自定义的 在…

七夕礼物 | 全网最火的钉子绕线图制作教程

最近在抖音经常看到这类视频&#xff0c; 仔细一想&#xff0c;也对七夕快到了&#xff0c;男同胞们该准备给小姐姐送小礼物了&#xff0c;大邓提前给大家分享一个idea-制作钉子绕线画教程&#xff0c;制作步骤如下 打开StringArtGenerator网站选择一张高对比度的大头照上传&am…

用Python制作会跳动的心,体验理工男李峋的浪漫

前言 最近有个剧挺火的 就是那个程序员的剧&#xff0c;叫什么温暖你来着 咳咳&#xff0c;剧情我没怎么看&#xff0c;但是吧&#xff0c;里面有个爱心代码&#xff0c;最近可是蛮火的&#xff0c;今天就用Python来尝试一下吧 搞这个表白也是不错滴&#xff0c;之前还写了篇…

再不玩Midjourney Ai 绘画你就落伍了 超详细入门指南

本文来源&#xff1a;chatgoo 认识的设计朋友&#xff0c;他已经用Midjourney&#xff0c;从每天工作6小时&#xff0c;变成每天工作2小时了。 尤其是当甲方自己都不明确需求时&#xff0c;可以快速给出多种风格图片&#xff0c;确定后进行精修。标准版也就30美刀而已。 设计、…

自制月球灯第一期之无线充电篇

10块钱在家自制手机无线充电器&#xff0c;可以用么&#xff1f; 建议看到最后;-) 无线充电近年大火&#xff0c;市面上已经出现了各种无线充电器&#xff0c;最贵的多功能无线充电器甚至超过了1000元。 最便宜的也不低于40元 。 而这些无线充电器的功率都不超过10W&#xff…