[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; 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) { 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]; }
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); glm::vec3 rayDirection(coord.x, coord.y, -1.0f); float radius = 0.5f;
float a = glm::dot(rayDirection, rayDirection); float b = 2.0f * glm::dot(rayOrigin, rayDirection); float c = glm::dot(rayOrigin, rayOrigin) - radius * radius;
float discriminant = b * b - 4.0f * a * c;
if (discriminant >= 0.0f) return 0xffff00ff;
return 0xff000000; }
|