在片段着色器中是否有可能访问表面法线 - 与片段所在平面相关联的法线?或者这可以在顶点着色器中完成吗?
当我们进入着色器管道时,所有关于相关几何形状的信息是否都丢失了,还是有一些巧妙的方法可以在顶点或片段着色器中恢复这些信息?
提前致谢。
祝好,
道格
Twitter: @dugla
dFdx
和 dFdy
得到。需要使用 OpenGL ES 3.0 或 OES_standard_derivatives
扩展来实现此功能:in vec3 view_position;
void main()
{
vec3 normalvector = cross(dFdx(view_position), dFdy(view_position));
nv = normalize(normalvector * sign(normalvector.z));
.....
}
一般来说,可以在几何着色器中计算曲面的法向量(自OpenGL ES 3.2起)。 例如,如果您绘制三角形,则可以在几何着色器中获得所有三个点。 三个点定义了一个平面,可以从中计算出法向量。 只需注意点的排列是顺时针还是逆时针。
三角形的法向量是由三角形的角点定义的两个向量的归一化叉积。 以下是逆时针三角形的示例:
#version 400
layout (location = 0) in vec3 inPos;
out vec3 vertPos;
uniform mat4 u_projectionMat44;
uniform mat4 u_modelViewMat44;
void main()
{
vec4 viewPos = u_modelViewMat44 * vec4( inPos, 1.0 );
vertPos = viewPos.xyz;
gl_Position = u_projectionMat44 * viewPos;
}
#version 400
layout( triangles ) in;
layout( triangle_strip, max_vertices = 3 ) out;
in vec3 vertPos[];
out vec3 geoPos;
out vec3 geoNV;
void main()
{
vec3 leg1 = vertPos[1] - vertPos[0];
vec3 leg2 = vertPos[2] - vertPos[0];
geoNV = normalize( cross( leg1, leg2 ) );
geoPos = vertPos[0];
EmitVertex();
geoPos = vertPos[1];
EmitVertex();
geoPos = vertPos[2];
EmitVertex();
EndPrimitive();
}
#version 400
in vec3 geoPos;
in vec3 geoNV;
void main()
{
// ...
}
顶点着色器与上述相同。
#version 400
layout( vertices=3 ) out;
in vec3 vertPos[];
out vec3 tctrlPos[];
void main()
{
tctrlPos[gl_InvocationID] = vertPos[gl_InvocationID];
if ( gl_InvocationID == 0 )
{
gl_TessLevelOuter[0] = ;
gl_TessLevelOuter[1] = ;
gl_TessLevelOuter[2] = ;
gl_TessLevelInner[0] = ;
}
}
#version 400
layout(triangles, ccw) in;
in vec3 tctrlPos[];
out vec3 tevalPos;
out vec3 tevalNV;
void main()
{
vec3 leg1 = tctrlPos[1] - tctrlPos[0];
vec3 leg2 = tctrlPos[2] - tctrlPos[0];
tevalNV = normalize( cross( leg1, leg2 ) );
tevalPos = tctrlPos[0] * gl_TessCoord.x + tctrlPos[1] * gl_TessCoord.y + tctrlPos[2] * gl_TessCoord.z;
}
#version 400
in vec3 tevalPos;
in vec3 tevalNV;
void main()
{
// ...
}
如果你将顶点法线传递到片段着色器中作为“varying”,那么你将得到一个插值的片段法线。
编辑:您需要在应用程序中计算法线,并将它们作为每个三角形顶点的属性传递到着色器中。
通常计算三角形法线的方法是使用叉积。
这将给出三角形平面的法线。 V2应该在V1的“左侧”,否则您的法线将指向“内部”而不是“外部”。有关详细信息,请参见维基百科关于叉积的文章。
进一步编辑:好的,我现在明白你的问题了。是的,对于共享顶点,您实际上不能在每个顶点上拥有多个法线。
我能想到的唯一可能有用的方法是使用几何着色器,因为它可以获取三角形的所有三个顶点。但是我没有使用过几何着色器。