使用逆变换的OpenGL光线跟踪

时间:2018-11-25 11:42:04

标签: c++ opengl raytracing

我有一个使用模型,视图和投影矩阵渲染三角形网格的管道。

我正在尝试实现一个光线跟踪器,该射线跟踪器通过变换的逆投影来投影射线的原点和方向,从而挑选出我单击的对象。

当我在顶点着色器中只有一个模型(没有视图或投影)时,

Vector4f ray_origin = model.inverse() * Vector4f(xworld, yworld, 0, 1);
Vector4f ray_direction = model.inverse() * Vector4f(0, 0, -1, 0);

,一切正常。但是,我添加了一个视图和投影矩阵,然后将代码更改为

Vector4f ray_origin = model.inverse() * view.inverse() *  projection.inverse() * Vector4f(xworld, yworld, 0, 1);
Vector4f ray_direction = model.inverse() * view.inverse() *  projection.inverse() * Vector4f(0, 0, -1, 0);

,什么都没有了。我在做什么错了?

1 个答案:

答案 0 :(得分:2)

如果使用透视投影,则建议在归一化设备空间中,通过近平面上的一个点和远平面上的另一个点定义射线。近平面的z坐标为-1,远平面的z坐标为1。x和y坐标必须是屏幕上[-1,1]范围内的“单击”位置。左边是(-1,-1),右上角的坐标是(1,1)。窗口或鼠标坐标可以线性映射到NDC的x和y坐标:

float x_ndc = 2.0 * mouse_x/window_width - 1.0;
flaot y_ndc = 1.0 - 2.0 * mouse_y/window_height; // flipped

Vector4f p_near_ndc = Vector4f(x_ndc, y_ndc, -1, 1); // z near = -1
Vector4f p_far_ndc  = Vector4f(x_ndc, y_ndc,  1, 1); // z far = 1

归一化设备空间中的一个点可以通过逆投影矩阵,然后是逆视图矩阵,最后是逆模型矩阵转换为模型空间:

Vector4f p_near_h = model.inverse() * view.inverse() *  projection.inverse() * p_near_ndc;
Vector4f p_far_h  = model.inverse() * view.inverse() *  projection.inverse() * p_far_ndc;

这之后的点是Homogeneous coordinates,可以由Perspective divide转换为Cartesian coordinate

Vector3f p0 = p_near_h.head<3>() / p_near_h.w();
Vector3f p1 = p_far_h.head<3>()  / p_far_h.w();

由点r和归一化方向d定义的模型空间中的“射线”最终为:

Vector3f r = p0;
Vector3f d = (p1 - p0).normalized()