简体   繁体   English

OpenGL奇怪的顶点着色器问题

[英]OpenGL weird vertex shader issue

Before I start my question, a little bit of background. 在开始提问之前,请先了解一下背景知识。 I started learning OpenGL not so long ago, and I have learned most of what I know about it here . 我不久前才开始学习OpenGL, 在这里我已经学到了大部分知识。 I have only really gotten past 2 tutorials, and yes, I know I will eventually have to learn about matrices, but for now, nothing fancy. 我实际上只过去了2个教程,是的,我知道我最终将不得不学习矩阵,但是目前还没有任何幻想。 So let's get on with it. 因此,让我们继续吧。

Okay, so, I simplified my program just a bit, but no worries, it still recreates the same problem. 好的,所以,我简化了程序,但不用担心,它仍然会产生相同的问题。 For my example, we are making a purple triangle. 对于我的示例,我们正在制作一个紫色三角形。 I do the usual, initializing GLFW and GLEW, and create a window with the following hints: 我照常进行初始化GLFW和GLEW的操作,并创建一个带有以下提示的窗口:

glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_SAMPLES, 8);

And then I create my window: 然后创建窗口:

GLFWwindow* Window = glfwCreateWindow(640, 480, "Foo", NULL, NULL);
glfwMakeContextCurrent(Window);
glfwSwapInterval(0);

These are my vertices: 这些是我的顶点:

float Vertices[] = {
    0.0f, 0.5f, 1.0f,
    0.5f, -0.5f, 1.0f,
    -0.5f, -0.5f, 1.0f
};

My shaders: 我的着色器:

const char* vertex_shader =
    "#version 330\n"
    "in vec3 vp;"
    "void main () {"
    "  gl_Position = vec4 (vp, 1.0);"
    "}";


const char* fragment_shader =
    "#version 330\n"
    "out vec4 frag_colour;"
    "void main () {"
    "  frag_colour = vec4 (0.5, 0.0, 0.5, 1.0);"
    "}";

All is good, I compile the whole program, and voila! 一切都很好,我编译了整个程序,瞧! Purple triangle! 紫色三角形!

Purple Triangle.png

The yellow counter on the top left is FRAPS, by the way. 顺便说一句,左上角的黄色计数器是FRAPS。

So, anyways, my brain gets this awesome idea (not really), what if I do this: vec4(vp, vp.z) in the vertex shader? 因此,无论如何,我的大脑vec4(vp, vp.z)这个很棒的主意(不是真的),如果我这样做的话:顶点着色器中的vec4(vp, vp.z)怎么办? Then I could get some sort of depth just by changing my z's in my buffer, I thought. 我想,然后我就可以通过更改缓冲区中的z来获得某种深度。 Note that I wasn't thinking of replacing a perspective matrix, it was just a sort of an experiment. 请注意,我并没有考虑替换透视图矩阵,这只是一种实验。 Please don't hate me . 请不要恨我

And it worked, by changing the values, I got something that looked like depth, as in it looked like it was getting farther into the distance. 通过更改值,它起作用了,我得到了一个看起来像深度的东西,好像它越来越远了。 Take a look, I changed the top vertex from 1.0 to 6.0: 看一下,我将最高顶点从1.0更改为6.0:

紫色三角形深度

Now here's the problem: I change the value to 999999999 (9 nines), and I get this: 现在是问题所在:我将值更改为999999999(9个9),我得到了:

紫色三角形深度2

Seems to work. 似乎可以工作。 Little difference from z = 6 though. 与z = 6的差值很小。 Change it to 999999999999999999999999 (24 nines)? 将其更改为999999999999999999999999(24个9)? No difference. 没有不同。 Take a look for yourself: 看一下自己:

我已经没有足够的想法来调用我的图片了

So this is weird. 所以这很奇怪。 Big difference in numbers, yet little difference visually. 数量差异很大,但外观差异很小。 Accuracy issues maybe? 准确性问题? Multiple 24 nines by 349 and I get the same result. 349乘以24个9,我得到相同的结果。 The kicker: Multiply the 24 nines by 350 and the triangle disappears. 踢法:将24个9乘以350,三角形消失。 This is a surprise to me because I thought that the change would be visible and gradual. 这让我感到惊讶,因为我认为这种变化将是可见的和渐进的。 It clearly wasn't. 显然不是。 However, changing the w manually in the vertex shader instead of doing vp.z does seem to give a gradual result, instead of just suddenly disappearing. 但是,在顶点着色器中手动更改w而不是执行vp.z似乎会产生渐进的结果,而不是突然消失。 I hope someone could shed light on this. 我希望有人能对此有所启发。 If you got this far, you're one awesome person for reading through all my crap, for that, I thank you. 如果您走到了这一步,那您就是一个很棒的人,可以阅读我所有的废话,为此,我表示感谢。

Your model can be seen as a simple form of a pinhole camera where the vanishing point for the depth direction is the window center. 您的模型可以看作是针孔摄像机的一种简单形式,其中深度方向的消失点是窗口中心。 So, lines that are parallel to the z-axis meet in the center if they are extended. 因此,如果平行于z轴的线延伸,则它们在中心会合。 The window center represents the point of infinite depth. 窗口中心代表无限深度的点。

Changing a vertex's z (or w) component from 1 to 6 is a very large change in depth (the vertex is 6 times farther away from the camera than before). 将顶点的z(或w)分量从1更改为6是深度上的很大变化(该顶点距摄影机的距离是以前的6倍)。 That's why the resulting vertex is closer to the screen center than before. 这就是为什么最终顶点比以前更靠近屏幕中心的原因。 If you double the z component again, it will move a bit closer to the screen center (the distance will be halved). 如果再次将z分量加倍,它将向屏幕中心稍微靠近一点(距离将减半)。 But it is obviously already very close to the center, so this change is hardly recognizable. 但是显然它已经非常靠近中心了,因此这种变化几乎无法识别。 The same applies to the 999999... depth value. 999999 ...深度值也是如此。

You can observe this property on most natural images, especially with roads: 您可以在大多数自然图像上观察到此属性,尤其是在道路上:

道路图片 [Source: http://www.benetemps.com/road-warriors.htm ] [来源: http//www.benetemps.com/road-warriors.htm ]

If you walk along the road for - let's say - 5 meters, you'll end up somewhere at the bottom of the image. 如果沿着这条路走-假设-5米,您将最终到达图片底部的某个位置。 If you walk five more meters, you continue to the image center. 如果再走五米,您将继续到达图像中心。 After another five meters you're even closer. 再过五米,您就更近了。 But you can see that the distance on the screen gets shorter and shorter the farther away you are. 但是您会看到屏幕上的距离越来越短,距离您越远。

Nico gave you a great visual explanation of what happens. Nico为您提供了很好的视觉效果说明。 The same thing can also be explained by using simple math, using the definition of homogeneous coordinates. 同样的事情也可以通过使用简单的数学,使用齐次坐标的定义来解释。

Your input coordinates have the form: 您输入的坐标具有以下形式:

(x, y, z)

By using vec4(vp, vp.z) in the vertex shader, you map these coordinates to: 通过在顶点着色器中使用vec4(vp, vp.z) ,可以将这些坐标映射到:

(x, y, z, z)

After the division by w that happens when converting from clip coordinates to normalized device coordinates, this is mapped to: 从剪辑坐标转换为规范化设备坐标时发生的除以w ,将其映射到:

(x / z, y / z, 1.0f)

As long as z has the value 1.0f , this is obviously still the same as (x, y, z) , which explains why the 2nd and 3rd vertex don't change in your experiment. 只要z的值为1.0f ,这显然仍然与(x, y, z) ,这说明了为什么第二和第三顶点在实验中不发生变化。

Now, applying this to your first vertex as you vary the z value, it gets mapped as: 现在,在改变z值时将其应用于第一个顶点,它将映射为:

(0.0f, 0.5f, z) --> (0.0f, 0.5f / z, 1.0f)

As you approach infinity with the z value, the y coordinate converges towards 0.5f / infinity , which is 0.0f . 当您使用z值逼近无穷大时, y坐标会收敛到0.5f / infinity (即0.0f Since the center of the screen is at (0.0f, 0.0f) , the mapped vertex converges towards the center of the screen. 由于屏幕的中心在(0.0f, 0.0f) ,因此映射的顶点向屏幕的中心收敛。

Also, the vertex moves less and less as the z value increases. 同样,顶点随着z值的增加而越来越少地移动。 Picking a few values: 选择一些值:

z =    1.0f --> y = 0.5f
z =   10.0f --> y = 0.05f
z =  100.0f --> y = 0.005f
z = 1000.0f --> y = 0.0005f

For example, when you change z from 100.0f to 1000.0f , y changes by 0.0045 , or only a little more than 0.2% of your window height. 例如,当您将z100.0f更改为1000.0fy更改0.0045 ,或仅多于窗口高度的0.2%。 With a window height of 500 pixels, that would be just about 1 pixel. 窗口高度为500像素时,大约只有1像素。

Why the triangle disappears completely at a certain value is somewhat more mysterious. 为什么三角形以一定的值完全消失更神秘。 I suspect that it must be some kind of overflow/rounding issue during clipping. 我怀疑在裁剪期间一定是某种溢出/舍入问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM