-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
Am 2014-10-28 00:44, schrieb Joachim Priesner:
{0, D3DFOG_NONE, D3DFOG_LINEAR, C_UNFOGGED, C_HALF_FOGGED, C_HALF_FOGGED, C_FOGGED},
{0, D3DFOG_LINEAR, D3DFOG_LINEAR, C_UNFOGGED, C_HALF_FOGGED, C_HALF_FOGGED, C_FOGGED},
...
- /* We are using an affine projection matrix, so pixel fog assumes fog start and end
* to be in device space coordinates. Pixel fog will therefore be calculated from
* z=-1 to z=1, whereas vertex fog will be calculated from z=0 to z=1. */
- start.f = 0.0f;
- end.f = 1.0f;
I think this comment is wrong. In d3d normalized Z coordiantes go from 0.0 to 1.0. In GL (sans GL_ARB_clip_control) they go from -1.0 to 1.0. The fog results above agree with this - otherwise you'd get C_UNFOGGED for table fog in the middle of the quad with the given projection matrix and fogstart and end.
Strictly speaking you don't have to set start = 0, end = 1, those are the default values. A comment stating that is enough.
{0, D3DFOG_NONE, D3DFOG_LINEAR, C_UNFOGGED, C_HALF_FOGGED, C_HALF_FOGGED, C_FOGGED},
{0, D3DFOG_LINEAR, D3DFOG_LINEAR, C_UNFOGGED, C_HALF_FOGGED, C_HALF_FOGGED, C_FOGGED},
{0, D3DFOG_LINEAR, D3DFOG_NONE, C_FOGGED, C_UNFOGGED, C_FOGGED, C_FOGGED},
{0, D3DFOG_NONE, D3DFOG_NONE, C_FOGGED, C_FOGGED, C_FOGGED, C_FOGGED},
There's a space missing in line 3.
Otherwise this patch looks good to me. It also passes on my Radeon X1600 GPU. I didn't retest the HD 5770, I assume it passes there as well. I also tested it on Vista with my GeForce 7400, it works as expected.
The Radeon 9000 GPU crashes on the vs1 ("non-foggy") + table fog tests. The other non-foggy shader tests run, but don't pass. I have attached the output in case you're interested, but otherwise don't bother about this. If I have time some day I'll try to find out where the driver's limitations are. I guess it's generally broken when fog is on and the shader does not write a fog coordinate. This is not the only fog-related problem on this card on Windows.
Thanks again for your hard work. I hope I didn't miss anything this time :-)
Cheers, Stefan
- /* We are using an affine projection matrix, so pixel fog assumes fog start and end
* to be in device space coordinates. Pixel fog will therefore be calculated from
* z=-1 to z=1, whereas vertex fog will be calculated from z=0 to z=1. */
- start.f = 0.0f;
- end.f = 1.0f;
I think this comment is wrong. In d3d normalized Z coordiantes go from 0.0 to 1.0. In GL (sans GL_ARB_clip_control) they go from -1.0 to 1.0. The fog results above agree with this - otherwise you'd get C_UNFOGGED for table fog in the middle of the quad with the given projection matrix and fogstart and end.
Okay, my train of thought was as follows: The upper quads' z coordinates are -1.0 (left), 0.0 (middle) and 1.0 (right). These coordinates are transformed (by the projection matrix) to 0.0, 0.5, and 1.0, respectively (let's call these w coordinates).
If we assume fogstart and fogend refer to z coordinates, the top quad must have an unfogged middle (z=0=fogstart). If we assume they refer to w coordinates, it must have a half fogged middle (because w=0.5=(fogstart+fogend)/2).
With vertex fog, we have an unfogged middle => vertex fog uses z coordinates. With table fog, we have a half fogged middle => table fog uses w coordinates. This is also true on Windows, so GL's behavior should be insignificant here. So, what did I miss?
--
I also found this in the docs:
http://msdn.microsoft.com/en-us/library/windows/desktop/bb205332%28v=vs.85%2...
Direct3D checks the fourth column of the projection matrix. If the coefficients are [0,0,0,1] (for an affine projection) the system will use z-based depth values for fog. In this case, you must also specify the start and end distances for linear fog effects in device space, which ranges from 0.0 at the nearest point to the user, and 1.0 at the farthest point.
This sounds to me like normally fogstart/fogend are specified in z coordinates, but for the combination of vertex fog and an affine projection matrix they are interpreted as w coordinates.
Best Joachim
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
Hi,
I hope my answers are right, I'm a bit rusty on the topic of GL / D3D coordinate systems. It may be a confusion about what "z" in your comment means.
Am 2014-10-28 14:35, schrieb Joachim Priesner:
If we assume fogstart and fogend refer to z coordinates, the top quad must have an unfogged middle (z=0=fogstart). If we assume they refer to w coordinates, it must have a half fogged middle (because w=0.5=(fogstart+fogend)/2).
With vertex fog, we have an unfogged middle => vertex fog uses z coordinates. With table fog, we have a half fogged middle => table fog uses w coordinates. This is also true on Windows, so GL's behavior should be insignificant here. So, what did I miss?
I think one of us mixed up the two cases. You wrote "Pixel fog will therefore be calculated from z=-1 to z=1, whereas vertex fog will be calculated from z=0 to z=1". Due to your projection matrix, the input range for fog coordinates into the fog equation in the vertex fog case is -1.0 to 1.0 if it weren't for the abs. The input range for fog coordinates into the fog equation for the pixel fog case is 0.0 to 1.0
But maybe you meant this in the sense that you apply the inverse projection matrix to fog start and fog end in the pixel fog case and then look at fog in eye coordinates in both cases. In this case fog start would indeed be -1.0.
Okay, my train of thought was as follows: The upper quads' z coordinates are -1.0 (left), 0.0 (middle) and 1.0 (right). These coordinates are transformed (by the projection matrix) to 0.0, 0.5, and 1.0, respectively (let's call these w coordinates).
"w coordinates" is a bad term because there's the homogenous w in each vertex.
The OpenGL terms are "eye coordinates" for the coordinates before the projection matrix is applied, "Clip coordinates" after the projection matrix and before the perspective division (x=x/w, y=y/w, z=z/w, rhw=1/w), and "normalized device coordinates" after the perspective division. Since w is always 1.0 in your test there's no difference between clip coordinates and normalized device coordinates. I cannot find the D3D docs, but I think the names are the same. The coordinates before the view matrix is applied are called "object coordinates", but since your view matrix is the identity matrix object coordinates == eye coordinates. (Btw, you could remove the view matrix and the associated DP4s from the shader entirely since they're a no-op)
Since we're interested in the Z coordinate only I'd say eye_z and dev_z are better terms.
In the vertex fog case, the fog coordinate is abs(eye_z). Your eye_z ranges from -1.0 to 1.0 due to your projection matrix. Fog start and fog end are therefore specified in eye coordinates as well, except that the abs() causes slightly different behavior. Due to the abs eye_z=-1.0 is fully fogged instead of unfogged. If you set fog_start=-1.0, fog_end=1.0, the left side(z=-1.0) would be fully fogged, the middle (z=0.0) half fogged and the right side (z=1.0) fully fogged. Without the abs the left side would be unfogged.
In D3D, the far clip plane is at z = 1.0 and the near clip plane at z = 0.0. dev_z is therefore in the range of 0.0 and 1.0. In the w coefficient [0,0,0,1] case dev_z is used. fog start and fog end are therefore specified in device coordinates. If you specify a fog end > 1.0 you'll never get a fully fogged fragment because such a fragment would be clipped.