gpt4 book ai didi

GLSL - 计算表面法线

转载 作者:行者123 更新时间:2023-12-02 11:02:40 28 4
gpt4 key购买 nike

我有一个简单的顶点着色器,用 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 );

法线的规范化可能不是必需的(因为我们无论如何都对转换后的法线进行规范化),但目前我不确定非规范化法线在存在非规范的情况下是否会正确运行- 统一缩放。当然,如果您希望法线指向负 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 - 计算表面法线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9577868/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com