c++ - GLSL - 给定顶点法线计算表面法线

标签 c++ opengl glsl

我想在 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
    
    ...
}

最佳答案

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

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]));

关于c++ - GLSL - 给定顶点法线计算表面法线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69854268/

相关文章:

opengl-es - 在 OpenGL 中实现铅笔画笔纹理以用于绘图应用

c++ - 打印字符数组 C++

c++ - GLSL着色器即使没有明显的错误也不会编译

c++ - 使用 GLuint 而不是 unsigned int 有什么好处?

c - opengl:如何在调整大小时将对象保留在窗口中

java - 为什么我的 uniform 没有在 openGL 中初始化?

c++ - 我想创建一个函数来读取输入的每一行并生成其总和并使用 C++ 将其保存为 sum.txt

c++ - 哪种虚拟机调度方法更有效?

c++ - 如何对齐来自数组的不同长度的输出?

c++ - OpenGL 核心和兼容性