PDA

View Full Version : Shader/fragment position precision



WickedP
09-02-2015, 05:19 AM
Hi folks,

I'm noticing some drawn elements in my viewport are not drawn on the same pixels as what something behind it is drawn on, despite them using the same position values. Scaling or moving the viewport results in a difference of a pixel off between the two in some cases (and a bit of flickering while you're doing it). It's not much I know, but it's a presentation thing and it's going to become an issue for me soon.

As an example, I drew some lines at the edge of a polygon to demonstrate the issue, see attached image below. The left side of the image is what ogl gives me, and the right side is what I would like to achieve (in terms of accuracy). I've scaled the image up so that it is easier to see.

2078

I'm using two shaders, one for the polygons, one for the lines/points. Each use the same matrix, and each are using floating point "3d world" position values.

Is this a shader thing? Or a fragment thing? Is there a way to get better precision with things like this?

Cheers,

WP.

Alfonse Reinheart
09-02-2015, 07:55 AM
To do what you're trying to do is, well, not possible in OpenGL. Or at least, not guaranteed.

What you're trying to do is draw lines and polygons so that there are no pixel gaps between them. However, the polygon and line rasterization algorithms do not require that there is a way to do that.

Now, OpenGL does guarantee that if two lines share a vertex in common, there will be no gap at the joint. And OpenGL does guarantee that if two triangles share two vertices in common, there will be no gap at the shared edge between them. But no such guarantee is made for a line sharing its vertices with triangles.

That being said, you can resolve this issue by rendering triangles instead of lines. Each "line" would just be a quad of some width (one pixel, for example).

If you do that, you'll quickly encounter another problem: how to make sure that the edge of the "line" matches up with the edge of the triangle exactly. This requires something called "invariance".

If you were using the same shader for the "line" and the triangle, invariance would be a non-issue. All you would need to do is make sure that the uniforms and input vertices you provide to both are binary identical. The math would therefore result in the same gl_Position value and thus the rasterizer would guarantee that the two edges would be gapless.

If the two vertex shaders in the two different programs are the same (meaning compiled from the exact same source strings), then OpenGL will consider them to be the "same shader" and thus guaratnee gapless rendering.

However, if you're using different vertex shaders, things get complicated. OpenGL doesn't guarantee anything about different shaders.

So you have to do it yourself. This is done by qualifiying the output variable with invariant (https://www.opengl.org/wiki/Type_Qualifier_%28GLSL%29#Invariance_qualifiers). If you qualify gl_Position with invariant, and use the exact same expression to compute the position in both shaders, and provide the exact same, binary identical, uniform and input values to that expression, then OpenGL will again guarantee gapless rendering for you.

WickedP
09-03-2015, 07:11 PM
Hi Alfonse,

could you expand on this thought a little: if I was to make them quad polys, how would this affect the colour data if I want one colour per polygon? Will I have to expand the colour data to cover 4x the vertices (points-to-quads)? Or will the shaders still work off one colour per 4 vertices? How would this affect gl_VertexID in the shader?

How might this affect draw times as well?

WP.

EDIT: rephrasing some text

Alfonse Reinheart
09-03-2015, 10:42 PM
Hi Alfonse,

could you expand on this thought a little: if I was to make them quad polys, how would this affect the colour data if I want one colour per polygon? Will I have to expand the colour data to cover 4x the vertices (points-to-quads)? Or will the shaders still work off one colour per 4 vertices?

This is confusing. Lines don't "work off one colour" per 2 vertices. Each vertex gets its own color, so you already have to replicate the colors 2x. You just need to do it 4x for quads rather than 2x for lines.


How would this affect gl_VertexID in the shader?

... what do you mean by that? gl_VertexID will be what it always was (https://www.opengl.org/wiki/Vertex_Shader#Other_inputs): the index for that vertex. So it will be affected in the obvious way.


How might this affect draw times as well?

Profile it and let us know.

WickedP
09-06-2015, 01:15 AM
Well, a few things, firstly,


This is confusing. Lines don't "work off one colour" per 2 vertices. Each vertex gets its own color

I should have used one point for one colour in the context of what I was trying to say, my mistake.


... what do you mean by that? gl_VertexID will be what it always was (https://www.opengl.org/wiki/Vertex_Shader#Other_inputs): the index for that vertex. So it will be affected in the obvious way.

I was hoping you could setup a different indexing system that you could use on some buffer objects. I won't elaborate here.


Profile it and let us know.

Performance is slower, but I was expecting this. It's around 20-35% of the original frame rate pre-quads. This may become unworkable for some users when they start getting into the billions of data bits at the lower refresh rate. So, in light of this, I've built in some quality flags for the user to switch between. Probably doesn't hurt to have this available in any case.

Just on another note, is it possible to change the timeout on our accounts? Every time I post a reply, I have to log back in..

Cheers,

WP.