OpenGL GLSL 插值

发布于 2024-07-23 10:56:43 字数 1368 浏览 11 评论 0原文

我尝试使用 GLSL 在 OpenGL 中实现点光源。 我将所有需要的数据发送到着色器。 为简单起见,我在这里仅使用漫射光。

我的示例显示了一个巨大的三角形,我想用单个光源照亮它。 光源显示为一个蓝色小三角形。

对于漫射光,我需要知道光与表面之间的角度。 因此,我计算法线和光线的方向。 然后点积会给我一个 -1 到 1 之间的数字,而 0 到 1 之间的所有数字都会被照亮。

然而,我在这里陷入困境,因为在我的示例中这个角度计算不正确。 由于调试着色器很困难,因此我使用了多个输出作为表面的颜色。 我使用法线作为三角形的颜色,无论光线在哪里,表面总是绿色的。 也就是说,法线指向 y 轴上方,因此计算正确。 也就是说,光线的方向一定是错误的。 但是,我找不到错误的原因。 灯光的位置和顶点的位置在世界空间中传递给顶点着色器,然后将它们转换为眼睛空间,计算灯光的方向并将其传递给片段着色器:

顶点着色器:

vec4 pos = modelview_matrix * <input vertex>;
vec4 lightPos = modelview_matrix * <light position>;

vec3 lightDir = normalize(lightPos.xyz - pos.xyz);

片段着色器:

float NdotL = max(dot(normalize(<correct normal>), normalize(lightDir)), 0.0);
gl_FragColor = vec4(1.0, NdotL, 0.0, 1.0);

我附加了一些图片这个例子明确表明,插值确实很奇怪。 我知道想知道我粘贴的代码是否正确或者您是否需要了解更多代码。 此外,这种插值行为是正常的还是我的代码中的错误?

http://img41.imageshack.us/img41/3566/interpolation.png http://img189.imageshack.us/img189/3566/interpolation.png

特别是第一张图片显示,灯光的中心点不是直接位于灯光下方,而是稍微移动到三角形的中心。

如果我将“pos”传递给片段着色器(即,它是插值的),然后在片段着色器中计算“lightDir”,则一切正常。

I try to implement point lights in OpenGL with GLSL. I send all the required data to the shaders. For simplicity I only use the diffuse light here.

My example shows a huge triangle which I want to illuminate with a single light source. The light source is shown as a small blue triangle.

For diffuse light I need to know the angle between the light and the surface. Therefore, I compute the normals and the light's direction. The dot-product will then give me a number between -1 and 1 whereas everything between 0 and 1 is illuminated.

However, here I am stuck because this angle is computed incorrectly in my example. Since it is hard to debug shaders, I used several outputs as the color of my surface. I used the normal as the color for the triangle and wherever the light was, the surface was always green. That is, the normals point up the y-axis and therefore they are computed right. That is, the light's direction must be wrong. However, I can't find the reason why it is wrong. The light's position and the vertex' position are passed in world space to the vertex shader, which then transforms them to eye space, compute the light's direction and pass this to the fragment shader:

vertex shader:

vec4 pos = modelview_matrix * <input vertex>;
vec4 lightPos = modelview_matrix * <light position>;

vec3 lightDir = normalize(lightPos.xyz - pos.xyz);

fragment shader:

float NdotL = max(dot(normalize(<correct normal>), normalize(lightDir)), 0.0);
gl_FragColor = vec4(1.0, NdotL, 0.0, 1.0);

I've appended some pictures of this example which definitely show, that the interpolation is really weird. I know want to know whether the code I pasted is correct or whether you need to know more of the code. FUrthermore, is this interpolation behaviour normal or is it a bug in my code?

http://img41.imageshack.us/img41/3566/interpolation.png
http://img189.imageshack.us/img189/3566/interpolation.png

Especially the first picture shows that the center spot of the light is NOT directly under the light but slightly moved to the center of the triangle.

If I pass "pos" to the fragment shader (that is, it is interpolated) and then compute "lightDir" in the fragment shader, everything works fine.

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

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

发布评论

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

评论(1

萌吟 2024-07-30 10:56:44

我认为在顶点着色器中标准化你的 lightDir 会影响你在插值向量时得到的结果,因为它从方程中取出长度,从而影响插值的“速度”。

如果您想要(视觉)解释,请尝试在纸上以 2D 形式绘制它。 首先画一条线(三角形)和一个点(光源)。 为线的两端添加两条线 (lightDir) 到光源,然后收缩(标准化)这些 lightDir 线,使它们具有相同的长度并且都在光源处相交。 如果连接标准化 lightDir 线的两端,您将得到一条非平行线(如果光源不完全位于第一条线的中间)。
现在,如果您绘制一条恰好穿过其中一条线中间的线,您会发现它不会穿过另一条线的中间,而是会向左或向右稍微碰到一点。

I think that normalizing your lightDir in the vertex shader affects the result you get when interpolating the vectors because it takes the length out of the equation and thus affects the "speed" of the interpolation.

If you want a (visual) explanation, try to draw it in 2D on paper. First draw a line (your triangle) and a point (light source). Add two lines (lightDir) for both ends of the line to the light source and then shrink (normalize) those lightDir lines so that they have the same length and both meet at the light source. If you connect both ends of the normalized lightDir lines you will get a non-parallel line (if the light source isn't exactly in the middle of your first line).
Now if you draw a line that goes exactly through the middle of one of the lines you will see that it doesn't go through the middle of the other line but will hit it a bit to the left or right.

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