I have a simple GLSL TOP with undesirable results when using uTD2DInfos[0].res.z instead of 1./uTD2DInfos[0].res.x

I prefer uTD2DInfos[0].res.z because it doesn’t need a division, but do I need to start using 1./uTD2DInfos[0].res.x as a precaution?

uTD2DInfos_question.tox (1.08 KB)

The components are defined as:

vec4 res; // contains (1.0 / width, 1.0 / height, width, height)

So doing 1.0 / x is double reciprocating the width, which is going to introduce some floating point error, which is why you get a different result than just using z straight. Not 100% sure on what you are doing in this case but if there is an error, I expect it’s elsewhere. Z should just be the straight width of the input.

Thanks but unexpectedly, the floating point error is with using uTD2DInfos[0].res.z not with the inverse of the reciprocal. Isn’t that weird?

uTD2DInfos_question_1.tox (1.12 KB)

To help me diagnose this, can you be specific about what tells you one answer is wrong vs the other being right?

Sure thanks for staying with me on it.

`vec2 uv = (vec2(0.5)+vec2(mod(id,uTD2DInfos[0].res.z),floor(id*uTD2DInfos[0].res.x)))*uTD2DInfos[0].res.xy;`

Regardless of what this color is, shouldn’t it stay the same if I replace calls to uTD2DInfos[0].res.z etc with hardcoded values? The input texture is 75x80, so I have this line for comparision

`vec2 uv = (vec2(0.5)+vec2(mod(id,75.),floor(id/75.)))/vec2(75.,80.);`

But it has a different color, and this different color happens to be the one I want to see. I expect that using uTD2DInfos[0].res.z (not a double reciprocal) would lead to the same result as hard-coded values.

uTD2DInfos_question_2.tox (1.5 KB)

David - color me crazy, but if you add 0.5 to id instead of in uv in the “bad” example I think the issue is resolved:

`float id = floored.x + floored.y*uTDOutputInfo.res.z + 0.5;`

Does that do what you’re after?

I’m not sure. I replaced that line like you said in “shader_bad”, but the result isn’t the same as in “shader_good”.

By the way, this code is very similar to what I’d use in a samplerBuffer call.

[code]out vec4 fragColor;

uniform samplerBuffer posBuffer;

void main() {

vec2 floored = floor(gl_FragCoord.xy);

```
int id = int(floored.x + floored.y*uTDOutputInfo.res.z);
vec4 color = texelFetch(posBuffer, id);
fragColor = TDOutputSwizzle(color);
```

}

[/code]

The difference is that I need to reshape the one-dimensional id value into a 2D UV space, and the dimensions of the UV space are known from uTD2DInfos.

well shucks - it sure would be nice if it was that simple though.

I thought for sure these looked the same.

uTD2DInfos_question_3.toe (4.78 KB)

I see you modified this line too

`vec2 uv = (vec2(mod(id,uTD2DInfos[0].res.z),floor(id*uTD2DInfos[0].res.x)))*uTD2DInfos[0].res.xy;`

The reason I had the vec2(0.5) was to lookup the exact center of a pixel without relying on nearest sampling to do it automatically.

It’s almost certainly a boundary case occurring somewhere here.

Values are 96.99999 instead of 97.0000 (for example) due to floating point error.

Narrowing it down more.

I actually think you are running into a GLSL/driver bug here. I’ve narrowed it down to the mod() operation.

I’m getting mod(2100, 75) = 75 out of a shader, if the source of the 75 is a uniform. This is obviously wrong.

To work around, and I think this is more ‘correct’ anyways, you should be working with integers whenever you are dealing with integer pixel coordinates. For example:

[code]out vec4 fragColor;

void main() {

vec2 floored = floor(gl_FragCoord.xy);

```
int id = int(floored.x + floored.y*uTDOutputInfo.res.z);
int w = int(uTD2DInfos[0].res.z);
int div = id / w;
vec2 uv = (vec2(0.5)+vec2(id % w, floor(id/w))) / vec2(uTD2DInfos[0].res.zw);
vec4 color = texture(sTD2DInputs[0], uv);
fragColor = TDOutputSwizzle(color);
```

}

[/code]

And to be even more correct, I’d suggest using texelFetch() instead of texture() and not re-normalizing your coordinates. Avoid as much floating point math as possible.

Or even simpler, use % instead of mod(), since mod() is meant to be used with floating point numbers. I’ve edited the above shader to use that

Great thanks for the tips. It’s working for me.