GLSL-计算曲面法线 [英] GLSL - Calculate Surface Normal

查看:21
本文介绍了GLSL-计算曲面法线的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的顶点着色器,是用GLSL编写的,我想知道是否有人可以帮助我计算曲面的法线。我正在‘升级’一个平面,所以现在的灯光模型看起来.真奇怪。以下是我当前的代码:

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_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=A*sin((x+P)*F)的切线,它的斜率是z的导数,是x-z向量(1, A*F*cos((x+P)*F)),那么它的法线就是(-A*F*cos((x+P)*F), 1)(切换坐标,取一为负),就是(未归一化的)法线的x和z。嗯,没有3D矢量和偏导数,但是结果是一样的。

这篇关于GLSL-计算曲面法线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆