投射光线与投影顶点?
Casting ray vs projecting vertices?
我正在尝试为我的光线追踪图形引擎添加光栅化支持。但是,我希望无论采用何种方法都能获得相同的图像(当然不包括阴影)。
相反,我得到了以两种不同尺寸渲染的测试模型,所以我猜它一定与我为光线追踪投射光线的方式有关,或者与我构建投影矩阵的方式有关光栅化。
这是我的 "camera" 构造函数(负责构建投影矩阵):
Camera::Camera(float fLength, float fov, float targetRatio, float zNear, float zFar)
{
focalLength = fLength;
fieldOfView = fov;
aspectRatio = targetRatio;
scale = tan(fieldOfView * 0.5 * DEG_TO_RAD);
viewMatrix = Matrix4<float>();
projectionMatrix = Matrix4<float>();
float distance = zFar - zNear;
projectionMatrix.xx = scale / aspectRatio;
projectionMatrix.yy = scale;
projectionMatrix.zz = -(zFar + zNear) / distance;
projectionMatrix.zw = -1.0f;
projectionMatrix.wz = -2.0f * zNear * zFar / distance;
projectionMatrix.ww = 0.0;
//aperture = tan(fieldOfView / 2 * DEG_TO_RAD) * focalLength * 2;
//fieldOfView = atan((aperture / 2) / focalLength) * 2 * RAD_TO_DEG;
}
这就是我根据帧缓冲区尺寸和当前像素坐标投射光线的方式(我计算方向并从其最后的矩阵行获取相机位置):
Ray Camera::castRay(unsigned int width, unsigned int height, unsigned int x, unsigned int y)
{
float dirX = (2 * (x + 0.5) / (float)width - 1) * aspectRatio * scale;
float dirY = (1 - 2 * (y + 0.5) / (float)height) * scale;
Vector3<float> dir = (Vector3<float>(dirX, dirY, -1.0) * viewMatrix).normalize();
return Ray(Vector3<float>(viewMatrix.wx, viewMatrix.wy, viewMatrix.wz), dir);
}
另一方面,这是我使用光栅化方法对顶点进行光栅化的方式:
Vector4<float> vertexInRasterSpace;
Vector4<float> vertexInCameraSpace;
vertexInCameraSpace = currentVertex * camera.viewMatrix;
vertexInRasterSpace = vertexInCameraSpace * camera.projectionMatrix;
vertexInRasterSpace.x = std::min(width - 1, (int)((vertexInRasterSpace.x + 1) * 0.5 * width));
vertexInRasterSpace.y = std::min(height - 1, (int)((1 - (vertexInRasterSpace.y + 1) * 0.5) * height));
vertexInRasterSpace.z = -vertexInCameraSpace.z;
最后得到的结果:
-光线追踪 -> Ray tracing picture
-光栅化 -> Rasterization picture
不用说,两个图像使用相同的模型视图矩阵。我最初的假设是我会得到相同(尺寸)的图像吗?
~天空
取决于光栅化算法在做什么(您是将顶点提供给 3D 图形 API 还是自己进行光栅化?),但我的第一个怀疑是:
乘以透视矩阵后,但在光栅化之前,您需要执行透视除法:即将向量的 X、Y 和 Z 分量除以W 分量。那似乎不见了。
如果您将输出顶点馈送到 3D 图形 API,那么占 window 的宽度和高度可能不是您想要的(那是 硬件渲染管道的视口变换).
我正在尝试为我的光线追踪图形引擎添加光栅化支持。但是,我希望无论采用何种方法都能获得相同的图像(当然不包括阴影)。
相反,我得到了以两种不同尺寸渲染的测试模型,所以我猜它一定与我为光线追踪投射光线的方式有关,或者与我构建投影矩阵的方式有关光栅化。
这是我的 "camera" 构造函数(负责构建投影矩阵):
Camera::Camera(float fLength, float fov, float targetRatio, float zNear, float zFar)
{
focalLength = fLength;
fieldOfView = fov;
aspectRatio = targetRatio;
scale = tan(fieldOfView * 0.5 * DEG_TO_RAD);
viewMatrix = Matrix4<float>();
projectionMatrix = Matrix4<float>();
float distance = zFar - zNear;
projectionMatrix.xx = scale / aspectRatio;
projectionMatrix.yy = scale;
projectionMatrix.zz = -(zFar + zNear) / distance;
projectionMatrix.zw = -1.0f;
projectionMatrix.wz = -2.0f * zNear * zFar / distance;
projectionMatrix.ww = 0.0;
//aperture = tan(fieldOfView / 2 * DEG_TO_RAD) * focalLength * 2;
//fieldOfView = atan((aperture / 2) / focalLength) * 2 * RAD_TO_DEG;
}
这就是我根据帧缓冲区尺寸和当前像素坐标投射光线的方式(我计算方向并从其最后的矩阵行获取相机位置):
Ray Camera::castRay(unsigned int width, unsigned int height, unsigned int x, unsigned int y)
{
float dirX = (2 * (x + 0.5) / (float)width - 1) * aspectRatio * scale;
float dirY = (1 - 2 * (y + 0.5) / (float)height) * scale;
Vector3<float> dir = (Vector3<float>(dirX, dirY, -1.0) * viewMatrix).normalize();
return Ray(Vector3<float>(viewMatrix.wx, viewMatrix.wy, viewMatrix.wz), dir);
}
另一方面,这是我使用光栅化方法对顶点进行光栅化的方式:
Vector4<float> vertexInRasterSpace;
Vector4<float> vertexInCameraSpace;
vertexInCameraSpace = currentVertex * camera.viewMatrix;
vertexInRasterSpace = vertexInCameraSpace * camera.projectionMatrix;
vertexInRasterSpace.x = std::min(width - 1, (int)((vertexInRasterSpace.x + 1) * 0.5 * width));
vertexInRasterSpace.y = std::min(height - 1, (int)((1 - (vertexInRasterSpace.y + 1) * 0.5) * height));
vertexInRasterSpace.z = -vertexInCameraSpace.z;
最后得到的结果:
-光线追踪 -> Ray tracing picture
-光栅化 -> Rasterization picture
不用说,两个图像使用相同的模型视图矩阵。我最初的假设是我会得到相同(尺寸)的图像吗?
~天空
取决于光栅化算法在做什么(您是将顶点提供给 3D 图形 API 还是自己进行光栅化?),但我的第一个怀疑是:
乘以透视矩阵后,但在光栅化之前,您需要执行透视除法:即将向量的 X、Y 和 Z 分量除以W 分量。那似乎不见了。
如果您将输出顶点馈送到 3D 图形 API,那么占 window 的宽度和高度可能不是您想要的(那是 硬件渲染管道的视口变换).