OpenGL奇怪的顶点着色器问题

时间:2014-09-14 17:21:45

标签: c++ opengl glsl

在我开始提问之前,先介绍一下背景。我不久前开始学习OpenGL,并且我已经学到了大部分关于它的知识here。我只是真的得到了2个教程,是的,我知道我最终还是要学习矩阵,但就目前来说,没什么特别的。所以让我们继续吧。

好吧,所以,我简化了我的程序,但不用担心,它仍然会重现同样的问题。就我的例子而言,我们制作了一个紫色三角形。我按照惯例,初始化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);

然后我创建了我的窗口:

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

这些是我的顶点:

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

我的着色器:

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);"
    "}";

一切都很好,我编译整个程序,瞧!紫色三角形!

Purple Triangle.png

顺便说一句,左上方的黄色计数器是FRAPS。

所以,无论如何,我的大脑得到了这个 awesome 的想法(不是真的),如果我这样做:vec4(vp, vp.z)在顶点着色器中?然后我想通过改变我的缓冲区中的z来获得一些排序的深度。请注意,我并没有考虑更换透视矩阵,这只是一种实验。 请不要恨我

它有效,通过改变数值,我得到的东西看起来像深度,就像看起来它越来越远。看一下,我将顶部顶点从1.0更改为6.0:

Purple Triangle Depth

现在问题出现了:我将值更改为999999999(9个9),我明白了:

Purple Triangle Depth 2

似乎工作。与z = 6的差别不大。将其更改为999999999999999999999999(24个9)?没有不同。看看你自己:

I have run out of ideas to call my images

所以这很奇怪。数字差异很大,但视觉上差别不大。准确性问题可能吗? 349的多个24个九,我得到相同的结果。踢球者:将24个9乘以350,三角形消失。这对我来说是一个惊喜,因为我认为这种变化是可见的和渐进的。显然不是。但是,在顶点着色器中手动更改w而不是执行vp.z确实会产生渐进结果,而不是突然消失。我希望有人能够阐明这一点。如果你到目前为止,你是一个很棒的人,可以阅读我所有的废话,为此,我感谢你。

2 个答案:

答案 0 :(得分:4)

您的模型可以看作针孔相机的简单形式,其中深度方向的消失点是窗口中心。因此,如果延伸的话,与z轴平行的线在中心相交。窗口中心代表无限深度的点。

将顶点的z(或w)分量从1更改为6是深度的非常大的变化(顶点距离相机的距离比之前的距离大6倍)。这就是为什么得到的顶点比以前更靠近屏幕中心的原因。如果再次将z分量加倍,它将移动一点距离屏幕中心(距离将减半)。但显然已经非常接近中心,所以这种变化难以辨认。这同样适用于999999 ...深度值。

您可以在大多数自然图像上观察此属性,尤其是道路:

Road Image [来源:http://www.benetemps.com/road-warriors.htm]

如果你走在路上 - 让我们说 - 5米,你最终会到达图像底部的某个地方。如果再走五米,则继续前往图像中心。又过了五米,你就更近了。但是你可以看到屏幕上的距离变得越来越短,离你越远越远。

答案 1 :(得分:1)

Nico为您提供了一个很好的视觉解释。同样的事情也可以通过使用简单数学来解释,使用齐次坐标的定义。

您的输入坐标的格式为:

(x, y, z)

通过在顶点着色器中使用vec4(vp, vp.z),可以将这些坐标映射到:

(x, y, z, z)

在从剪辑坐标转换为规范化设备坐标时发生w除法后,将其映射到:

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

只要z的值为1.0f,这显然与(x, y, z)相同,这就解释了为什么第二个和第三个顶点不会在实验中发生变化

现在,当您更改z值时将其应用于第一个顶点,它将映射为:

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

当您使用z值接近无穷大时,y坐标会收敛到0.5f / infinity,即0.0f。由于屏幕中心位于(0.0f, 0.0f),因此映射的顶点会聚到屏幕中心。

此外,随着z值的增加,顶点移动越来越少。选择几个值:

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

例如,当您将z100.0f更改为1000.0f时,y会更改0.0045,或者只会略高于您{0.2}的0.2%窗户高度。窗口高度为500像素,大约只有1个像素。

为什么三角形在某个值处完全消失有点神秘。我怀疑它在剪辑过程中一定是某种溢出/舍入问题。