GLSL - 给定顶点法线计算表面法线
GLSL - Calculate the surface normal given its vertex normal
我想在 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
...
}
表面法线可以用表面上 2 个向量的 Cross product 来计算。以下代码用于逆时针三角形:
vec3 v1 = vertexP[1] - vertexP[0];
vec3 v2 = vertexP[2] - vertexP[0];
vec3 surfNormal = normalize(cross(v1, v2));
如果三角形的缠绕顺序是顺时针,则必须交换v1
和v2
:
vec3 surfNormal = normalize(cross(v2, v1));
使用Dot product确保在混合三角形的缠绕顺序时表面法线的方向正确:
surfNormal *= sign(dot(surfNormal, vertexN[0]+vertexN[1]+vertexN[2]));
我想在 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
...
}
表面法线可以用表面上 2 个向量的 Cross product 来计算。以下代码用于逆时针三角形:
vec3 v1 = vertexP[1] - vertexP[0];
vec3 v2 = vertexP[2] - vertexP[0];
vec3 surfNormal = normalize(cross(v1, v2));
如果三角形的缠绕顺序是顺时针,则必须交换v1
和v2
:
vec3 surfNormal = normalize(cross(v2, v1));
使用Dot product确保在混合三角形的缠绕顺序时表面法线的方向正确:
surfNormal *= sign(dot(surfNormal, vertexN[0]+vertexN[1]+vertexN[2]));