代码之家  ›  专栏  ›  技术社区  ›  Matt Kae

OpenGL/GLSL 4.1中的全向照明

  •  1
  • Matt Kae  · 技术社区  · 7 年前

    我的平行光可以正常使用阴影,但在点光源方面我有点困惑。我的想法是使用立方体贴图渲染灯光周围所有六个面的深度。到目前为止,一切都很好。我通过将多维数据集的每个面渲染为2D图像来验证这一步骤,它似乎是正确的。

    现在我正试图让阴影出现在这个世界上。为此,我使用GLSL的samplerCubeShadow数据类型。有了它,我可以:

    vec3 lightToFrag = light.position - fragPos
    float lenLightToFrag = length(lightToFrag)
    vec3 normLightToFrag = normalize(lightToFrag)
    float shadow = texture(depthTexture, vec4(normLightToFrag, lightToFrag))
    

    我尝试了许多配置,这总是以黑色渲染我的场景。有什么想法吗?我的fragPos只是模型矩阵乘以顶点位置。我应该将灯光的模型视图矩阵应用到它吗?或者,类似地,我应该将世界模型视图矩阵应用于灯光吗?非常感谢您的反馈!

    1 回复  |  直到 7 年前
        1
  •  2
  •   recp    7 年前

    假设您正在cubemap中存储深度值;

    AFAIK cubemap是世界空间中的一个AABB 您需要在世界空间中进行计算 . 在你的情况下 light.position fragPos 必须在世界空间中,或者如果您在其他地方的视图空间中使用这些名称(例如,每片段灯光计算),则提供替代变量/成员

    在传递到之前,还需要将lightToFrag转换为深度值 texture . 此答案显示了如何将lightToFrag转换为深度值: Omnidirectional shadow mapping with depth cubemap

    这里是我的实现(我删除了#ifdef SHAD\u CUBE,因为其他人使用相同的名称):

    uniform samplerCubeShadow uShadMap;
    uniform vec2              uFarNear;
    
    float depthValue(const in vec3 v) {
      vec3 absv = abs(v);
      float z   = max(absv.x, max(absv.y, absv.z));
      return uFarNear.x + uFarNear.y / z;
    }
    
    float shadowCoef() {
      vec3  L;
      float d;
    
      L = vPosWS - light.position_ws;
      d = depthValue(L);
    
      return texture(uShadMap, vec4(L, d));
    }
    

    如果只有ModelViewProjection(MVP),则可能需要统一的模型矩阵

    下面是如何计算客户端的uNearFar:

      float n, f, nfsub, nf[2];
    
      n = sm->near;
      f = sm->far;
    
      nfsub = f - n;
      nf[0] = (f + n) / nfsub * 0.5f + 0.5f;
      nf[1] =-(f * n) / nfsub;
    
      glUniform2f(gkUniformLoc(prog, "uFarNear"), nf[0], nf[1]);
    

    这只是优化,但你不必使用它,并遵循我之前提到的链接。

    您可能需要偏差值,相关答案使用偏差,但我不确定如何将其正确应用于立方体贴图。我不确定d-+0.0001是否正确。

    如果您想在cubemap中存储世界距离,那么本教程似乎是老一套: https://learnopengl.com/Advanced-Lighting/Shadows/Point-Shadows