如何在创建阴影卷时转换GLSL中的背面顶点

时间:2010-01-22 00:19:15

标签: opengl glsl shadow

我正在使用OpenGL编写游戏,我正在尝试实现阴影卷。

我想通过顶点着色器在GPU上构建模型的阴影体积。为此,我用VBO代表模型,其中:

  • 复制顶点,使每个三角形都有自己唯一的三个顶点
  • 每个顶点都有三角形的法线
    • 由于我不打算进入的原因,我实际上是在做以上两点,所以我不太担心顶点重复
  • 添加简并三角形以在每对“常规”三角形之间的边缘内形成四边形

使用此模型格式,在顶点着色器中,我能够找到顶点,这些顶点是远离光线的三角形的一部分,然后将它们移回以形成阴影体。

我还要弄清楚究竟应该将哪种转换应用于背面顶点。

我能够检测到顶点背离光线的时间,但我不确定应该应用哪种变换。这是我的顶点着色器到目前为止的样子:

uniform vec3 lightDir; // Parallel light.
                       // On the CPU this is represented in world
                       // space.  After setting the camera with
                       // gluLookAt, the light vector is multiplied by
                       // the inverse of the modelview matrix to get
                       // it into eye space (I think that's what I'm
                       // working in :P ) before getting passed to
                       // this shader.

void main()
{
    vec3 eyeNormal = normalize(gl_NormalMatrix * gl_Normal);
    vec3 realLightDir = normalize(lightDir);

    float dotprod = dot(eyeNormal, realLightDir);

    if (dotprod <= 0.0)
    {
        // Facing away from the light
        // Need to translate the vertex along the light vector to
        // stretch the model into a shadow volume

        //---------------------------------//
        // This is where I'm getting stuck //
        //---------------------------------//
        // All I know is that I'll probably turn realLightDir into a
        // vec4

        gl_Position = ???;
    }
    else
    {
        gl_Position = ftransform();
    }
}

我尝试过简单地将gl_position设置为ftransform() - (vec4(realLightDir, 1.0) * someConstant),但这会导致某种深度测试错误(当我用颜色渲染音量时,某些面孔似乎在其他面后可见)和{ {1}}似乎没有影响背面延伸的距离。

更新 - 1月22日

只是想澄清一下我可能在哪个空间的问题。我必须说,跟踪我所处的空间是我的着色器头痛的最大来源。

渲染场景时,我首先使用someConstant设置相机。相机可以是固定的,也可以四处移动;没关系。然后我使用gluLookAt之类的翻译函数来定位我的模型。

在程序中(即在CPU上),我代表世界空间中的光矢量(三个浮点数)。我在开发过程中发现,为了在我的着色器的正确空间中获得这个光矢量,我必须在设置相机之后和定位模型之前将它乘以模型视图矩阵的倒数。所以,我的程序代码是这样的:

  • 定位相机(glTranslated
  • 获取世界空间中的光矢量,并将其乘以当前模型视图矩阵的倒数并将其传递给着色器
  • 转换为定位模型
  • 绘制模型

这会让事情更清楚吗?

1 个答案:

答案 0 :(得分:1)

ftransform结果位于剪辑空间中。所以这不是你想要应用realLightDir的空间。我不确定你的光源在哪个空间(你的评论让我困惑),但可以肯定的是你想要添加在同一空间中的矢量。 / p>

  

在CPU上,这是世界上的代表   空间。用相机设置后   gluLookAt,光矢量乘以   得到的模型视图矩阵的逆   进入眼睛空间(我认为这就是我的意思   在工作之前:P)在被传递之前   这个着色器。

将矢量乘以mv矩阵的逆矩阵,将矢量从视图空间带到模型空间。所以你说你的光矢量(在世界空间中)应用了一个视图 - &gt;模型的变换。这对我来说没什么意义。

我们有4个空格:

  • 模型空间:定义gl_Vertex的空间。
  • 世界空间:GL一般不关心的空间,代表定位模型的任意空间。它通常是3d引擎的工作原理(它映射到我们对世界坐标的一般理解)。
  • 查看空间:与查看者的参考对应的空间。 0,0,0是观察者所在的位置,向下看Z.通过将gl_Vertex乘以模型视图获得
  • 剪辑空间:矩阵投影带给我们的神奇空间.ftransform的结果就在这个空间中(gl_ModelViewProjectionMatrix * gl_Vertex也是如此)

你能准确说明你的光照方向是哪个空间吗?

然而,您需要做的是在模型,世界或视图空间中添加光矢量:将操作的所有位置放在同一空间中。例如。对于模型空间,只需计算CPU上模型空间中的光照方向,然后执行:

vec3 vertexTemp = gl_Vertex + lightDirInModelSpace * someConst

然后您可以使用

将新的顶点位置放在剪辑空间中
gl_Position = gl_ModelViewProjectionMatrix * vertexTemp

最后一点,不要尝试在剪辑空间中应用向量添加。它通常不会做你认为应该做的事情,因为那时你必须用不统一的w来处理homogeneous coordinates