GLSL-计算曲面法线
我有一个简单的顶点着色器,用GLSL编写,我想知道是否有人可以帮助我计算曲面的法线。我正在“升级”平面,因此当前的灯光模型看起来。。。奇怪的这是我目前的代码:GLSL-计算曲面法线,glsl,Glsl,我有一个简单的顶点着色器,用GLSL编写,我想知道是否有人可以帮助我计算曲面的法线。我正在“升级”平面,因此当前的灯光模型看起来。。。奇怪的这是我目前的代码: varying vec4 oColor; varying vec3 oEyeNormal; varying vec4 oEyePosition; uniform float Amplitude; // Amplitude of sine wave uniform float Phase; // Phase of
varying vec4 oColor;
varying vec3 oEyeNormal;
varying vec4 oEyePosition;
uniform float Amplitude; // Amplitude of sine wave
uniform float Phase; // Phase of sine wave
uniform float Frequency; // Frequency of sine wave
varying float sinValue;
void main()
{
vec4 thisPos = gl_Vertex;
thisPos.z = sin( ( thisPos.x + Phase ) * Frequency) * Amplitude;
// Transform normal and position to eye space (for fragment shader)
oEyeNormal = normalize( vec3( gl_NormalMatrix * gl_Normal ) );
oEyePosition = gl_ModelViewMatrix * thisPos;
// Transform vertex to clip space for fragment shader
gl_Position = gl_ModelViewProjectionMatrix * thisPos;
sinValue = thisPos.z;
}
有人有什么想法吗?好的,让我们从微分几何的角度来看这个问题。得到了一个参数为s和t的参数化曲面:
X(s,t) = ( s, t, A*sin((s+P)*F) )
我们首先计算这个曲面的切线,这是两个参数后的偏导数:
Xs(s,t) = ( 1, 0, A*F*cos((s+P)*F) )
Xt(s,t) = ( 0, 1, 0 )
然后我们只需要计算这些的叉积就可以得到法线:
N = Xs x Xt = ( -A*F*cos((s+P)*F), 0, 1 )
因此,法线可以完全通过分析计算,实际上不需要gl\u normal
属性:
float angle = (thisPos.x + Phase) * Frequency;
thisPos.z = sin(angle) * Amplitude;
vec3 normal = normalize(vec3(-Amplitude*Frequency*cos(angle), 0.0, 1.0));
// Transform normal and position to eye space (for fragment shader)
oEyeNormal = normalize( gl_NormalMatrix * normal );
normal
的规范化可能不是必需的(因为我们无论如何都要规范化转换后的法线),但就目前而言,我不确定在存在非均匀缩放的情况下,未规范化的法线是否会正常工作。当然,如果你想让法线指向负的z方向,你需要对它求反
嗯,穿越太空表面的方法是不必要的。我们也可以只考虑x-z平面内的正弦曲线,因为法线的y部分无论如何都是零,因为只有z依赖于x。所以我们只取曲线的切线,它的斜率是z的导数,是x-z向量
(1,A*F*cos((x+P)*F))
,这条曲线的法线就是(-A*F*cos((x+P)*F),1)
(切换坐标并取反一),即(非标准化)法线的x和z。没有3D向量和偏导数,但结果是一样的。此外,你应该调整你的性能:
oEyeNormal = normalize(vec3(gl_NormalMatrix * gl_Normal));
非常感谢你!一旦我启动到我的Win7分区,我将很快尝试这个方法。我在灯光和GLSL上玩得很开心!1. - 嗯,强制转换是不必要的,但这两种转换都不会带来任何性能损失,因为vec3到vec3的强制转换应该是不可操作的(GLSL编译器在这里复制不会那么愚蠢)。但你是对的,这完全没有必要。2这显然是错误的。他不规范化传入的法线(这确实不是一个好主意,因为应用程序当然应该提供规范化的法线)。但是他规范化了变换后的法线(与
gl_NormalMatrix
相乘后),这是解释任何缩放和剪切变换所必需的。当然,您知道,在曲面上插值非标准化法线会导致错误的每片段法线。所以最后这里没有太多的性能需要调整。最后它甚至没有回答实际问题,可能更适合作为评论。@ChristianRau我的回答更适合作为评论,因为它离题了,我同意。但你应该再仔细阅读我的回答。我说过,在顶点着色器中不需要对其进行规格化,除非在特殊计算中使用它,例如顶点着色器中的lightning!是的,不需要在顶点着色器中规格化输入法线。但是OP无论如何都不会这么做。他所做的是对变换后的法线进行归一化(在乘以gl_NormalMatrix
之后),这对于考虑缩放等是必要的,因为需要将适当的归一化法线放入变量中,以便为片段获得适当的插值法线。请仔细阅读我的评论。