【问题标题】:GLSL - Calculate the surface normal given its vertex normalGLSL - 给定顶点法线计算表面法线
【发布时间】:2021-12-19 13:39:35
【问题描述】:

我想在 OpenGL 上实现平面着色。我搜索了一下,发现了这个问题:How to achieve flat shading with light calculated at centroids?

我了解最佳答案的想法,我正在尝试实施它。但是,在给定三角形每个顶点的法线的情况下,我无法弄清楚如何找到表面法线。

顶点着色器中的相关代码:

#version 400 core

...

layout(location = 0) in vec4 position;
layout(location = 1) in vec3 normal;

uniform mat4 Mm;
uniform mat3 normalMatrix;

out vec3 vertexN;
out vec3 vertexP;

... 

int main() {
     ...
     vertexN = normalize(normalMatrix * normal);
     vertexP = vec3(Mm * position);
     ...
}

几何着色器中的相关代码:

#version 400 core

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

in vec3 vertexP[3];
in vec3 vertexN[3];

...

void main(){
    ...
    vec3 centroidPosition(0.0);
    for(int i = 0; i < 3; i++) centroidPosition += vertexP[i];
    centroidPosition/=3.0;

    // calculate surface normal
    
    ...
}

【问题讨论】:

    标签: c++ opengl glsl


    【解决方案1】:

    可以使用表面上的 2 个向量的Cross product 计算表面法线。以下代码用于逆时针三角形:

    vec3 v1 = vertexP[1] - vertexP[0];
    vec3 v2 = vertexP[2] - vertexP[0];
    vec3 surfNormal = normalize(cross(v1, v2));
    

    如果三角形的缠绕顺序是顺时针,则必须交换v1v2

    vec3 surfNormal = normalize(cross(v2, v1));
    

    使用Dot product 确保在混合三角形的缠绕顺序时表面法线的方向正确:

    surfNormal *= sign(dot(surfNormal, vertexN[0]+vertexN[1]+vertexN[2]));
    

    【讨论】:

    • 这非常有效!谢谢。
    猜你喜欢
    • 2013-08-14
    • 2013-02-15
    • 1970-01-01
    • 2015-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-16
    • 2021-12-05
    相关资源
    最近更新 更多