为什么 optix 中的相机视图与 OpenGL 中的不同?

Why camera view in optix is different from in OpenGL?

我正在使用 Nvidia Optix 样本在 3D 模型中拍照。我修改了 Optix SDK progressivePhotonMap 以达到我的目标。 我的 progressovePhotonMap 代码和 OpenGL 代码中有相同的相机位置、相同的相机方向和相同的视野 (FOV)。 然而,相机的视角却大相径庭,如下图。

输出图像:

左边是progressivePhotonMap输出的图片,另一边是OpenGL输出的。可以看到左下方的电源点(两条红线的交点)在两张图上不在同一个位置。

我知道Optix是基于OpenGL编写的,所以我很困惑为什么这两张图片(相机视图)在相同的相机参数下不相同。

这是我认为的原因:

1.Maybe 问题是 near 和 far 参数,因为在 GlutDisplay.cpp 中显示帧,gluPerspective() 没有用。我不能给出 near 和 far 参数。(即使在 ppm.cpp 中)那么我如何以及在哪里添加这两个参数?

2.Maybe optix投影平面不在近平面?在 OpenGL 中,我们可以将近平面视为投影平面,但在 optix 中却看不到?

3.Maybeoptix中3D模型的呈现与OpenGL不同??? (我发现这两张图的失真度不一样)所以我也无法避免这种情况?

我追踪了整个项目,但没有找到任何有用的信息,任何人都可以帮助我或提供一些 idea/advice 为什么会发生这种情况?我将非常感谢任何回应。谢谢!

有一些简短的源代码,希望对您有所帮助。

在 OpenGL 中:

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluPerspective(FOV,(GLdouble)windWidth / (GLdouble)windHeight , NEAR, FAR);
gluLookAt(camera_pos[0],camera_pos[1],camera_pos[2],
        look_at_target[0],look_at_target[1],look_at_target[2],
        up_vector[0], up_vector[1], up_vector[2]);

在优化中:

InitialCameraData init_camera;
init_camera = InitialCameraData( make_float3( camera_pos[0], camera_pos[1],camera_pos[2]),make_float3(look_at_target[0],look_at_target[1],look_at_target[2]),make_float3( 0.0f, 1.0f,  0.0f )/*up*/,FOV );
GLUTDisplay::setCamera(init_camera);
signalCameraChanged();

4 月 21 日更新 16:11 Reoutput images

我重新输出图片,发现 hfov(horizo​​ntal FOV) 可能是这个原因,在我看来,两张图片 window 的高度是相同的 screen.In 我的知识,hfov 和 vfov 是相同的OpenGL 中的 gluPerspective。所以我认为 hfov 是我的 optix 代码中这两个相机视图不同的原因。

但是,我还是不知道如何修改ppm.cpp中的hfov。我一直认为我给 InitialCameraData 的 FOV 可以表示 hfov 和 vfov。如果这个想法是错误的,我应该在哪里修改hfov?我只能调整 vfov 参数作为源代码显示。任何熟悉 progressivePhotonMap 示例的人都可以告诉我在哪里修改 hfov 吗? 感谢任何回复!

主要difference/problem是在Optix中,我没有看到投影矩阵。充其量,我看到 Optix 在设置相机信息的同时设置了视野,但是缺少纵横比参数让我很困扰,尤其是在更近距离地观察 Optix 图像后,椅子似乎严重变形在水平轴上,这在 OpenGL 渲染中问题不大(它正确提供了有关纵横比的信息)。

我要观察的另一件事是,您应该检查 Optix 如何期望提供视野参数。 GLU 期望它以度为单位,并将其视为 y-Field-Of-View。我不知道 Optix 如何期望它,但许多 API 期望提供相对于 x 轴的视野。

Optix 中没有相机,它只是一个光线追踪框架。 "shoots" 相机光线是您的应用程序,换句话说,您应该对相机行为进行编码。

特别是在渐进光子映射 (PPM) 示例中,有一个 ppm_rtpass.cu 文件。射出光线的函数是:

RT_PROGRAM void rtpass_camera()
{
  float2 screen = make_float2( rtpass_output_buffer.size() );
  /*
  uint   seed   = image_rnd_seeds[index];                       // If we start writing into this buffer here we will
  float2 sample = make_float2( rnd(seed.x), rnd(seed.y) );      // need to make it an INPUT_OUTPUT buffer.  For now it
  image_rnd_seeds[index] = seed;                                // is just INPUT
  */
  float2 sample = make_float2( 0.5f, 0.5f ); 

  float2 d = ( make_float2(launch_index) + sample ) / screen * 2.0f - 1.0f;
  float3 ray_origin = rtpass_eye;
  float3 ray_direction = normalize(d.x*rtpass_U + d.y*rtpass_V + rtpass_W);

  optix::Ray ray(ray_origin, ray_direction, rtpass_ray_type, scene_epsilon);

  HitPRD prd;
  // rec.ray_dir = ray_direction; // set in rtpass_closest_hit
  prd.attenuation = make_float3( 1.0f );
  prd.ray_depth   = 0u; 
  rtTrace( top_object, ray, prd );
}

float2 d 变量包含归一化的当前像素坐标,这些值用于计算 2 行后的光线方向。如果你想修复 GPU 代码,那是你应该查看的地方。否则,FOV 是隐式的,取决于您如何缩放 U 和 V 向量。