如何计算glsl中两条法线之间的角度?

发布于 2024-07-09 04:13:26 字数 1096 浏览 11 评论 0原文

如何计算glsl中两条法线之间的角度? 我正在尝试将菲涅耳效果添加到对象的外边缘(将该效果与 phong 阴影相结合),并且我认为角度是我唯一缺少的东西。

片段着色器:

varying vec3 N;
varying vec3 v;

void main(void) {
  v = vec3(gl_ModelViewMatrix * gl_Vertex);
  N = normalize(gl_NormalMatrix * gl_Normal);
  gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

顶点着色器:

varying vec3 N;
varying vec3 v;

void main(void) {
  vec3 L = normalize(gl_LightSource[0].position.xyz - v);
  vec3 E = normalize(-v);
  vec3 R = normalize(-reflect(L,N));

  vec4 Iamb = gl_FrontLightProduct[0].ambient
  vec4 Idiff = gl_FrontLightProduct[0].diffuse * max(dot(N,L), 0.0);
  vec4 Ispec = gl_FrontLightProduct[0].specular * pow(max(dot(R,E),0.0), gl_FrontMaterial.shininess);
  vec4 Itot = gl_FrontLightModelProduct.sceneColor + Iamb + Idiff + Ispec;

  vec3 A = //calculate the angle between the lighting direction and the normal//
  float F = 0.33 + 0.67*(1-cos(A))*(1-cos(A))*(1-cos(A))*(1-cos(A))*(1-cos(A));
  vec4 white = {1.0, 1.0, 1.0, 1.0};

  gl_FragColor = F*white + (1.0-F)*Itot;
}

变化的 vec3

How do you calculate the angle between two normals in glsl? I am trying to add the fresnel effect to the outer edges of an object (combining that effect with phong shading), and I think that the angle is the only thing I am missing.

Fragment Shader:

varying vec3 N;
varying vec3 v;

void main(void) {
  v = vec3(gl_ModelViewMatrix * gl_Vertex);
  N = normalize(gl_NormalMatrix * gl_Normal);
  gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

Vertex Shader:

varying vec3 N;
varying vec3 v;

void main(void) {
  vec3 L = normalize(gl_LightSource[0].position.xyz - v);
  vec3 E = normalize(-v);
  vec3 R = normalize(-reflect(L,N));

  vec4 Iamb = gl_FrontLightProduct[0].ambient
  vec4 Idiff = gl_FrontLightProduct[0].diffuse * max(dot(N,L), 0.0);
  vec4 Ispec = gl_FrontLightProduct[0].specular * pow(max(dot(R,E),0.0), gl_FrontMaterial.shininess);
  vec4 Itot = gl_FrontLightModelProduct.sceneColor + Iamb + Idiff + Ispec;

  vec3 A = //calculate the angle between the lighting direction and the normal//
  float F = 0.33 + 0.67*(1-cos(A))*(1-cos(A))*(1-cos(A))*(1-cos(A))*(1-cos(A));
  vec4 white = {1.0, 1.0, 1.0, 1.0};

  gl_FragColor = F*white + (1.0-F)*Itot;
}

varying vec3

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

层林尽染 2024-07-16 04:13:26

两个向量之间的点积将返回角度的余弦(在 GLSL 中为 dot(a,b))。 对其取反余弦将返回以弧度为单位的角度(在 GLSL 中为 acos(x))。

点积非常便宜,反余弦则相当昂贵。

然而,菲涅尔效应实际上并不需要角度。 只需在向量之间有点结果就足够了。 菲涅尔效应有很多近似方法,最便宜的一种是直接使用点。 或对其进行平方 (x*x),或求其他幂。

在上面的着色器中,看起来您只想将点提高到 5 次方。 就像是:

float oneMinusDot = 1.0 - dot(L, N);
float F = pow(oneMinusDot, 5.0);

dot product between two vectors will return the cosine of the angle (in GLSL it's dot(a,b)). Taking arc-cosine of that will return angle in radians (in GLSL it's acos(x)).

Dot product is very cheap, arc-cosine is quite expensive.

However, Fresnel effect does not really need the angle. Just having dot result between the vectors is enough. There are many approximations for the Fresnel effect, one of the cheapest is just using the dot directly. Or squaring it (x*x), or raising to some other power.

In your shader above, it looks like you just want to raise dot to 5th power. Something like:

float oneMinusDot = 1.0 - dot(L, N);
float F = pow(oneMinusDot, 5.0);
演多会厌 2024-07-16 04:13:26

从两个向量的点积,你可以得到它们之间角度的余弦

cos A = DotProduct(v1, v2) / (Length(v1) * Length(v2))

使用这个,你在计算F时不需要计算余弦。由于你的向量是单位向量,例如长度为1,你甚至可以避免该部门。

From the dot product of two vectors you can get the cosine of the angle between them

cos A = DotProduct(v1, v2) / (Length(v1) * Length(v2))

Using this, you don't need to calculate the cosine when calculating F. Since your vectors are unit vectors, e.g., have length one, you can even avoid the division.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文