1

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. 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. 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:

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.

So, anyways, my brain gets this awesome idea (not really), what if I do this: vec4(vp, vp.z) in the vertex shader? Then I could get some sort of depth just by changing my z's in my buffer, I thought. 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:

Purple Triangle Depth

Now here's the problem: I change the value to 999999999 (9 nines), and I get this:

Purple Triangle Depth 2

Seems to work. Little difference from z = 6 though. Change it to 999999999999999999999999 (24 nines)? No difference. Take a look for yourself:

I have run out of ideas to call my images

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. The kicker: Multiply the 24 nines by 350 and the triangle disappears. 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. 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.

2 Answers 2

4

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. 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). 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). But it is obviously already very close to the center, so this change is hardly recognizable. The same applies to the 999999... depth value.

You can observe this property on most natural images, especially with roads:

Road Image [Source: 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. 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.

Sign up to request clarification or add additional context in comments.

4 Comments

This makes sense, thank you. I assume the vertex disappears when I hit the float limit?
Probably not. Even if floating point precision causes inaccurate results (even if they are outside of the screen), you still have two vertices inside the screen and the rasterizer will create a valid triangle from these vertices. Not sure what happens, if you have NaN or infinity, though.
Then why does it disappear?
Oh, I overlooked that part of your question. It's hard to tell what both the compiler and the GPU do because that's far from ordinary use. But it's probably related to floating-point issues.
1

Nico gave you a great visual explanation of what happens. 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:

(x, y, z, z)

After the division by w that happens when converting from clip coordinates to normalized device coordinates, this is mapped to:

(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.

Now, applying this to your first vertex as you vary the z value, it gets mapped as:

(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. Since the center of the screen is at (0.0f, 0.0f), the mapped vertex converges towards the center of the screen.

Also, the vertex moves less and less as the z value increases. 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. With a window height of 500 pixels, that would be just about 1 pixel.

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.