将 vec3 传递给 glm::lookAt 似乎修改了它

Passing a vec3 to glm::lookAt appears to modify it

我遇到过将 glm::vec3 传递给 glm::lookAt 函数似乎对其进行了修改的情况。

以下代码是关于C++/OpenGL游戏引擎中的阴影平截头体计算。问题出现在glm::lookAt函数中,最后。

void Shadows::updateFrustumBoundingBox()
{

  // Here we convert main camera frustum coordinates in light view space
  std::array<glm::vec3,8> points = {
    // Near plane points
    lightView * glm::vec4(cameraPtr->ntl, 1.0),
    lightView * glm::vec4(cameraPtr->ntr, 1.0),
    lightView * glm::vec4(cameraPtr->nbl, 1.0),
    lightView * glm::vec4(cameraPtr->nbr, 1.0),
    // Far plane points
    lightView * glm::vec4(cameraPtr->ftl, 1.0),
    lightView * glm::vec4(cameraPtr->ftr, 1.0),
    lightView * glm::vec4(cameraPtr->fbl, 1.0),
    lightView * glm::vec4(cameraPtr->fbr, 1.0)};

  // Here we find the shadow bounding box dimensions
  bool first = true;
  for (int i=0; i<7; ++i)
  {
    glm::vec3* point = &points[i];

    if (first)
    {
            minX = point->x;
            maxX = point->x;
            minY = point->y;
            maxY = point->y;
            minZ = point->z;
            maxZ = point->z;
      first = false;
    }

        if (point->x > maxX)
            maxX = point->x;
    else if (point->x < minX)
            minX = point->x;

        if (point->y > maxY)
            maxY = point->y;
    else if (point->y < minY)
            minY = point->y;

        if (point->z > maxZ)
            maxZ = point->z;
    else if (point->z < minZ)
            minZ = point->z;
  }

  frustumWidth = maxX - minX;
  frustumHeight = maxY - minY;
  frustumLength = maxZ - minZ;

  // Here we find the bounding box center, in light view space
  float x = (minX + maxX) / 2.0f;
  float y = (minY + maxY) / 2.0f;
  float z = (minZ + maxZ) / 2.0f;
  glm::vec4 frustumCenter = glm::vec4(x, y, z, 1.0f);

  // Here we convert the bounding box center in world space
  glm::mat4 invertedLight = glm::mat4(1.0f);
  invertedLight = glm::inverse(lightView);
  frustumCenter = invertedLight * frustumCenter;

  // Here we define the light projection matrix (shadow frustum dimensions)
  lightProjection = glm::ortho(
    -frustumWidth/2.0f, // left
    frustumWidth/2.0f, // right
    -frustumHeight/2.0f, // down
    frustumHeight/2.0f, // top
    0.01f, // near
    SHADOW_DISTANCE); // far


  // Here we define the light view matrix (shadow frustum position and orientation)
  lightDirection = glm::normalize(lightDirection);
  target =  glm::vec3(0.0f, 100.0f, 200.0f) + lightDirection;

  lightView = glm::lookAt(
                  // Shadow box center
                     glm::vec3(0.0f, 100.0f, 200.0f), // THIS LINE
                  // glm::vec3(frustumCenter), // ALTERNATIVELY, THIS LINE. Here I convert it as a vec3 because it is a vec4

                  // Light orientation
                  target,

                  // Up vector
                  glm::vec3( 0.0f, 1.0f,  0.0f));

  cout << "frustumCenter: " << frustumCenter.x << " " << frustumCenter.y << " " << frustumCenter.z << endl;

  // Final matrix calculation
  lightSpaceMatrix = lightProjection * lightView;
}

照原样,第一个 glm::lookAt 参数是 glm::vec3(0.0f, 100.0f, 200.0f),它工作正常。 glm::vec4 frustumCenter 变量未被 glm::lookAt 使用,并且每帧输出正确的值。

frustumCenter: 573.41 -93.2823 -133.848 1

但是如果我将第一个 glm::lookAt 参数更改为“glm::vec3(frustumCenter)”:

frustumCenter: nan nan nan nan

怎么可能?

I have encountered a situation where passing a glm::vec3 to the glm::lookAt function appears to modify it."

我不这么认为。您使用 frustumCenter 计算 lightView,但在此之前,您使用 lightView 计算 frustumCenterfrustumCenter = invertedLight * frustumCenter;

所以我有根据的猜测是:

lightView 矩阵未正确初始化/未初始化为奇异矩阵(如全零)。因此,倒数将不会被定义,导致 frustumCenter 变成全 NaN,进而导致 lightView 变成全 NaN

但是如果您在第一次迭代中不使用 frustumCenterlightView 将被正确初始化,并且 frustumCenter 将在下一次迭代中计算为合理的值。