我正在寻找优化我拥有的一些光线追踪代码的方法。假设我有以下
Triangle
类,如下所示(为简洁起见,进行了简化):
class Triangle {
public:
Triangle(Vertex v0, Vertex v1, Vertex v2, bool smoothShading);
void intersect(Ray& ray)
{
if (smoothShading) {
ray.hit.n = normalize(ray.hit.uv[0] * v1.normal + ray.hit.uv[1] * v2.normal + w * v0.normal);
}
else {
ray.hit.n = -n;
};
};
private:
bool smoothShading;
Vertex<Tp> v0{};
Vertex<Tp> v1{};
Vertex<Tp> v2{};
vec3<Tp> n;
}
intersect()
成员函数需要被调用数十亿次,因此我认为每次都评估if (smoothShading)
是完全没有必要的,因为在构造Triangle
时就知道值是true
还是false
。最简单的解决方案是拥有单独的 SmoothTriangle
和 FlatTriangle
类,这样我就可以做到:
void SmoothTriangle::intersect(Ray& ray)
{
ray.hit.n = normalize(ray.hit.uv[0] * v1.normal + ray.hit.uv[1] * v2.normal + w * v0.normal);
};
void FlatTriangle::intersect(Ray& ray)
{
ray.hit.n = -n;
};
问题是我需要处理引用/指针才能使其工作,但我的许多函数都需要诸如
std::vector<Triangle>
之类的输入。我可以把它变成 std::vector<shared_ptr<Triangle>>
或类似的东西,但随后我会引入另一个指针间接,不是吗?
在所有这些情况下,各个类实际包含的成员数据都是相同的。我只是希望
intersect()
函数根据其构造方式进行更改,以避免在渲染时检查内容,因为渲染时许多函数被调用数十亿次。
您可以将行为隔离到单独的类成员函数中,然后使用指向所需函数的指针,例如:
class Triangle {
public:
Triangle(Vertex v0, Vertex v1, Vertex v2, bool smoothShading)
{
...
if (smoothShading)
m_intersect = &Triangle::interceptSmooth;
else
m_intersect = &Triangle::intersectFlat;
}
void intersect(Ray& ray)
{
(this->*m_intersect)(ray);
}
private:
void (Triangle::*m_intersect)(Ray&);
Vertex<Tp> v0{};
Vertex<Tp> v1{};
Vertex<Tp> v2{};
vec3<Tp> n;
void intersectSmooth(Ray& ray)
{
ray.hit.n = normalize(ray.hit.uv[0] * v1.normal + ray.hit.uv[1] * v2.normal + w * v0.normal);
}
void intersectFlat(Ray& ray)
{
ray.hit.n = -n;
}
};