ipadglsl。从片段着色器中,如何获得曲面-而不是顶点-法线

ipadglsl。从片段着色器中,如何获得曲面-而不是顶点-法线,ipad,opengl-es,glsl,shader,Ipad,Opengl Es,Glsl,Shader,是否可以从片段着色器中访问曲面法线(与片段平面关联的法线)?或者这可以在顶点着色器中完成 当我们进入着色器管道时,相关几何体的所有知识都丢失了吗?或者在片段着色器的顶点中是否有一些聪明的方法来恢复这些信息 提前谢谢 干杯, 道格 twitter:@dugla如果以“可变”的方式将顶点法线传递给片段着色器,则会得到插值片段法线 编辑:必须计算应用程序中的法线,并将其作为三角形每个顶点的属性传递到着色器中 计算三角形法线的常用方法是使用叉积 调用构成三角形P1、P2和P3的三个点 计算V1,即从P1

是否可以从片段着色器中访问曲面法线(与片段平面关联的法线)?或者这可以在顶点着色器中完成

当我们进入着色器管道时,相关几何体的所有知识都丢失了吗?或者在片段着色器的顶点中是否有一些聪明的方法来恢复这些信息

提前谢谢

干杯,
道格

twitter:@dugla

如果以“可变”的方式将顶点法线传递给片段着色器,则会得到插值片段法线

编辑:必须计算应用程序中的法线,并将其作为三角形每个顶点的属性传递到着色器中

计算三角形法线的常用方法是使用叉积

  • 调用构成三角形P1、P2和P3的三个点
  • 计算V1,即从P1到P2的矢量
  • 计算V2,即从P1到P3的矢量
  • 计算V1和V2的叉积
  • 这将为您提供三角形平面的法线。V2应该在V1的左边,否则你的正常人会指向“in”而不是“out”。有关详细信息,请参阅

    进一步编辑:对,我现在理解你的问题了。是的,对于共享顶点,每个顶点不能有多个法线


    我唯一能想到的另一件事是,也许几何体着色器可以有所帮助,因为它可以通过三角形的所有三个顶点。不过,我对它们没有任何经验。

    只需使用一个“variable”(在较新的OpenGL中,它只是in/out)变量,就可以从顶点法线得到每像素的法线插值。但别忘了让这一切正常化!插值法线的长度不能再为1。这些法线在锐边上也会产生不好的结果


    如果要使用分辨率更高的自定义法线,常用的技术是法线贴图。为对象创建具有烘焙法线的纹理。然后,可以使用纹理查找访问碎片纹理中的法线。

    可以通过frgament着色器中视图空间位置的偏导数近似计算曲面法线向量。利用这些函数可以得到偏导数。为此,需要OpenGL es 3.0或其扩展:

    in vec3 view_position;
    
    void main()
    {
        vec3 normalvector = cross(dFdx(view_position), dFdy(view_position));
        nv = normalize(normalvector * sign(normalvector.z));
    
        .....
    }
    

    通常,可以在几何体着色器中计算曲面的法向量(因为OpenGL ES 3.2)。 例如,如果绘制三角形,将在几何体着色器中获得所有三个点。 三个点定义了可以从中计算法向量的平面。 如果这些点是顺时针或逆时针排列的,你只需要小心

    三角形的法向量是定义的2个向量的归一化叉积 通过三角形的角点。 有关逆时针三角形,请参见以下示例:

    顶点著色引擎 几何著色器 片段着色器 当然,也可以在细分着色器中计算法线向量(因为OpenGL ES 3.2)。 但这只有在您出于其他原因已经需要细分着色器并进行额外计算时才有意义 面的法向量:

    顶点著色引擎 顶点着色器与上面的相同

    细分控制着色器 细分评估着色器 Fragmant着色器
    我要找的是三角形平面的法线,插值是在这个平面上进行的。通过定义平面中的线来细分曲面的每个三角形。我在该平面的法线之后。这在我的情况下不起作用,因为我有共享顶点(顶点数组)。如果我一次发送一个三角形到GPU,我可以简单地将平面系数附加到每个顶点(冗余,我知道),我很好。使用顶点数组,着色器(顶点或片段,无所谓)如何消除共享顶点的三角形之间的歧义?平面方程各不相同,我没有办法通知着色器使用哪个平面方程系数。这一点很好!我忘了提到需要在片段着色器中重新规范化法线+1.
    #version 400
    
    layout (location = 0) in vec3 inPos;
    
    out vec3 vertPos;
    
    uniform mat4 u_projectionMat44;
    uniform mat4 u_modelViewMat44;
    
    void main()
    {
        vec4 viewPos = u_modelViewMat44 * vec4( inPos, 1.0 );
        vertPos = viewPos.xyz;
        gl_Position = u_projectionMat44 * viewPos;
    }
    
    #version 400
    
    layout( triangles ) in;
    layout( triangle_strip, max_vertices = 3 ) out;
    
    in vec3 vertPos[];
    
    out vec3 geoPos;
    out vec3 geoNV;
    
    void main()
    {
        vec3 leg1 = vertPos[1] - vertPos[0];
        vec3 leg2 = vertPos[2] - vertPos[0];
        geoNV = normalize( cross( leg1, leg2 ) ); 
    
        geoPos = vertPos[0];
        EmitVertex();
        geoPos = vertPos[1];
        EmitVertex();
        geoPos = vertPos[2];
        EmitVertex();
        EndPrimitive();
    }
    
    #version 400
    
    in vec3 geoPos;
    in vec3 geoNV;
    
    void main()
    {
        // ...
    }
    
    #version 400
    
    layout( vertices=3 ) out;
    
    in  vec3 vertPos[];
    out vec3 tctrlPos[];
    
    void main()
    {
        tctrlPos[gl_InvocationID] = vertPos[gl_InvocationID];
    
        if ( gl_InvocationID == 0 )
        {
            gl_TessLevelOuter[0] =  ;
            gl_TessLevelOuter[1] =  ;
            gl_TessLevelOuter[2] =  ;
            gl_TessLevelInner[0] =  ;
        }
    }
    
    #version 400
    
    layout(triangles, ccw) in;
    
    in vec3 tctrlPos[];
    
    out vec3 tevalPos;
    out vec3 tevalNV;
    
    void main()
    {
      vec3 leg1 = tctrlPos[1] - tctrlPos[0];
      vec3 leg2 = tctrlPos[2] - tctrlPos[0];
      tevalNV = normalize( cross( leg1, leg2 ) ); 
    
      tevalPos = tctrlPos[0] * gl_TessCoord.x + tctrlPos[1] * gl_TessCoord.y + tctrlPos[2] * gl_TessCoord.z;
    }
    
    #version 400
    
    in vec3 tevalPos;
    in vec3 tevalNV;
    
    void main()
    {
        // ...
    }