如何获得一个立方体平法线(How to get flat normals on a cube)

2019-07-20 05:25发布

我使用OpenGL不推荐使用的功能和我的光计算在片段着色器完成。 所以,我做平滑阴影。

我的问题是,当我画一个立方体,我需要平法线。 由扁平法线我的意思是在一个面生成的每个片段具有相同的正常。

我对这个解决方案到目前为止是产生每个面不同的顶点。 这样,代替具有8个顶点,我现在有24(6×4)的顶点。

但是,这似乎是我错了,复制的顶点。 有没有更好的方式来获得平坦的法线?

更新:我使用的OpenGL版本3.3.0,我没有对OpenGL 4支持呢。

Answer 1:

如果您在摄像机空间做照明,可以使用dFdx / dFdy来计算正常的脸从顶点的摄像机空间位置。

所以片段着色器看起来有点像这样。

varying vec3 v_PositionCS; // Position of the vertex in camera/eye-space (passed in from the vertex shader)

    void main()
    { 
      // Calculate the face normal in camera space
      vec3 normalCs = normalize(cross(dFdx(v_PositionCS), dFdy(v_PositionCS)));

      // Perform lighting 
      ...
      ...
    }


Answer 2:

由于几何着色器可以“看到”一个三角形的三个顶点的同时,您可以使用几何着色器来计算法线并将它们发送到您的片段着色器。 这样,您就不必重复顶点。

// Geometry Shader

#version 330 

layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;

out vec3 gNormal;

// You will need to pass your untransformed positions in from the vertex shader
in vec3 vPosition[];

uniform mat3 normalMatrix;

void main()
{
    vec3 side2 = vPosition[2] - vPosition[0];
    vec3 side0 = vPosition[1] - vPosition[0];
    vec3 facetNormal = normalize(normalMatrix * cross(side0, side2));

    gNormal = facetNormal;
    gl_Position = gl_in[0].gl_Position;
    EmitVertex();

    gNormal = facetNormal;
    gl_Position = gl_in[1].gl_Position;
    EmitVertex();

    gNormal = facetNormal;
    gl_Position = gl_in[2].gl_Position;
    EmitVertex();

    EndPrimitive();
}


Answer 3:

另一种选择是通过MV-矩阵和未旋转AxisAligned坐标到片段着色器:

 attribute aCoord;
 varying vCoord;
 void main() {
    vCoord = aCoord;
    glPosition = aCoord * MVP;
 }

在片段着色器可以通过计算vCoord的主导轴,该设定为1.0(或-1.0),另一个坐标为零识别正常 - 这是正常的,其具有由所述MV - 矩阵旋转。



文章来源: How to get flat normals on a cube