如何在立方体上获得平坦法线

And*_*uel 5 opengl glsl opengl-3

我使用的是没有弃用功能的OpenGL,我的光计算是在片段着色器上完成的.所以,我正在做平滑的阴影.

我的问题是,当我画一个立方体时,我需要平坦的法线.平面法线表示面部生成的每个碎片具有相同的法线.

到目前为止,我的解决方案是为每个面生成不同的顶点.所以,现在我有24个(6*4)顶点,而不是有8个顶点.

但这对我来说似乎是错误的,复制了顶点.是否有更好的方法来平常?

更新:我使用的是OpenGL版本3.3.0,我还没有支持OpenGL 4.

小智 9

如果在相机空间中进行照明,则可以使用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 
      ...
      ...
    }
Run Code Online (Sandbox Code Playgroud)


bwr*_*oga 6

由于几何着色器可以同时"看到"三角形的所有三个顶点,因此您可以使用几何着色器计算法线并将它们发送到片段着色器.这样,您不必复制顶点.

// 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();
}
Run Code Online (Sandbox Code Playgroud)