[toc] https://www.baidu.com/link?url=NV5sFLdJTrizgjWcTkrOGVeNf7fCBOgpTI5NAK22gFMyANQqa8iG2QConDRQLHWS&wd=&eqid=ccc38590000002820000000463f1e1f8 公式可视化 ↑

# Ray 的公式

我们可以将线的公式解释为 y = ax + b RatTraing 中的 Ray (也是射线) 的定义是: 有起点和终点的线 Ray 的描述为:

# RGB 编码方式

r8g8b8a9 就是每个单位 8 位,最后一个颜色会转换成一个整数,int color = r (g<<8) (b<<16) (a<<24)

# CPU 端逐像素着色器 (非光栅化)

RayTracing 不是从模型和光源层反向对像素着色的。 而是从像素的角度进行反向的向场景内的物体进行查找着色的,通常会从一个像素点出发随机射出很多 ray 来进行颜色的混合。 所以需要实现一个简单的像素着色器,但不是光栅化 如下方代码,在 Render 时,遍历 X,y, 同时将屏幕空间 UV 转换到 -1,1,同时为了保证内存局部性,图片一定是存储成单维数组的。
下面的例子是在生成的图片上渲染一个圆球 (相机在 0,0,-2 的位置)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include "Renderer.h"
#include "Walnut/Random.h"

void Renderer::Render() {
//逐像素设置图片信息
for (uint32_t y = 0; y < m_FinalImage->GetHeight(); ++y) {
for (uint32_t x = 0; x < m_FinalImage->GetWidth(); ++x) {
glm::vec2 coord = {
(float)x / m_FinalImage->GetWidth(),
(float)y / m_FinalImage->GetHeight()
};
coord = coord * 2.0f - 1.0f;// 屏幕UV 转换到 -1 -> 1
m_ImageData[x + y*m_FinalImage->GetWidth()] = PerPixel(coord);
}
}


m_FinalImage->SetData(m_ImageData);
}

void Renderer::OnResize(uint32_t width,uint32_t height) {
if (m_FinalImage) {
//No resize necessary
if (m_FinalImage->GetWidth() == width && m_FinalImage->GetHeight() == height) {
return;
}
m_FinalImage->Resize(width, height);
}
else {
m_FinalImage = std::make_shared<Walnut::Image>(width, height, Walnut::ImageFormat::RGBA);
}

delete[] m_ImageData;
m_ImageData = new uint32_t[width * height];
}

/// <summary>
/// 可以理解为片元着色器
/// </summary>
/// <param name="coord"></param>
/// <returns></returns>
uint32_t Renderer::PerPixel(glm::vec2 coord)
{
uint8_t r = (uint8_t)(coord.x * 255.0f);
uint8_t g = (uint8_t)(coord.y * 255.0f);

//射线开始的地方,在这里同样是摄像机的位置
glm::vec3 rayOrigin(0.0f,0.0f,-2.0f);
//只在2D空间内进行,但是给一个虚拟的z轴(固定的)
glm::vec3 rayDirection(coord.x, coord.y, -1.0f);
float radius = 0.5f;

// (bx^2 + by^2)t^2 + (2(axbx + ayby))t + (ax^2 + ay^2 - r^2) = 0
// where
// a = ray origin
// b = ray direction
// r = radius
// t = hit distance

float a = glm::dot(rayDirection, rayDirection);
float b = 2.0f * glm::dot(rayOrigin, rayDirection);
float c = glm::dot(rayOrigin, rayOrigin) - radius * radius;

// Quadratic forumula discriminant(求解的个数);
// b^2 - 4ac

float discriminant = b * b - 4.0f * a * c;

if (discriminant >= 0.0f)
return 0xffff00ff;

//rgb编码方式
return 0xff000000;
}