View Full Version : selfmade centroid gl_FragCoord

skynet

07-26-2011, 10:47 AM

Hi,

I'm trying to detect pixels that are located on multisampled polygon edges. Therefore I'm trying to produce a centroid-sampled version of gl_FragCoord. If the centroid-sampled pixel coordinate does not lie on the pixel center (0.5, 0.5), it must be near an edge.

But I'm having troubles generating the pixel coordinate as needed...

In the vertex shder I'm doing:

noperspective centroid varying vec3 v_pixelpos;

...

gl_Position = ftransform();

v_pixelpos = gl_Position.xyw;

...

The fragment shader looks this way:

noperspective centroid varying vec3 v_pixelpos;

//do perspective divide, transform from NDC to 0..1 range

vec2 pixelpos = ((v_pixelpos.xy/v_pixelpos.z) + 1.0)*0.5;

//multiply by viewport size

pixelpos = pixelpos*vec2(1280.0, 768.0);

//debug output. Most pixels should produce some yellow (0.5, 0.5)

//the edge pixels should produce something different

gl_FragColor=vec4(fract(pixelpos), 0.0, 1.0);

Unfortunately, I only get garbage... what's wrong with the approach?

Ilian Dinev

07-26-2011, 11:10 AM

Make v_pixelpos be vec2; then in vtx shader:

#define SCREEN_SIZE vec2(1280.0,720.0)

v_pixelpos = (gl_Position.xy/gl_Position.w)*0.5*SCREEN_SIZE + 0.5*SCREEN_SIZE + 0.5;

And in frag-shader, simply:

vec2 pixelpos = v_pixelpos;

skynet

07-26-2011, 12:25 PM

Update:

@Ilian:

Doing the full transform in the vertex shader and using 'noperspective centroid' does not work. Large polygons that need to be clipped by the near plane go completely crazy. I think basically, because out-of-screen polygons produce 'impossible' screen coordinates.

That's why I'm doing the transform in the fragment shader. But I guess, I can shuffle much more of the calculation into the vertex shader, except the perspective divide.

I have now found a way to get it working: Basically, since I'm doing the _perspective divide_ in the fragment shader, I cannot use 'noperspective'. After I removed that, it started to work.

Vertex shader:

centroid varying vec3 v_pixelpos;

...

vi_pixelpos = gl_Position.xyw;

...

Fragment shader:

centroid varying vec3 v_pixelpos;

...

//perspective divide, NDC to 0..1

vec2 pixelpos = (vi_pixelpos.xy/vi_pixelpos.z)*0.5 + 0.5;

//viewport size

pixelpos = pixelpos*vec2(1280.0, 1024.0);

//distance from pixel center

pixelpos = fract(pixelpos)-0.5;

float d=dot(pixelpos, pixelpos);

//pink colour when sampling outside the polygon

if (d>0.01)

gl_FragData[1]=vec4(d, 0.0, d, 1.0);

It works quite well now. But really large polygons that clip the near plane still produce artifacts. I guess due to polygon clipping and inexact interpolation, the computed pixel coordinates start to differ too much from the real pixel coordinate.

Ilian Dinev

07-26-2011, 01:36 PM

Try this:

precision highp float;

#if IS_VERTEX

uniform mat4 mvp;

in vec4 inVertex;

in vec2 inCoord;

noperspective centroid out vec2 v_pixelpos;

noperspective out vec2 v_pixelpos2;

void main(){

gl_Position = mvp * inVertex;

v_pixelpos = ((gl_Position.xy/gl_Position.w)*0.5+0.5)*vec2(1280,720);

v_pixelpos2 = v_pixelpos;

}

#endif

#if IS_FRAGMENT

noperspective centroid in vec2 v_pixelpos;

noperspective in vec2 v_pixelpos2;

out vec4 glFragColor;

centroid in vec4 gl_FragCoord;

void main(){

vec2 pixelpos = v_pixelpos.xy;

glFragColor = vec4((v_pixelpos2-v_pixelpos)+0.5,0,1);

}

#endif

Or you could abs(v_pixelpos2-v_pixelpos)*100 to visualize/detect edges. I noted on the pitfalls of this here: http://www.opengl.org/discussion_boards/...true#Post271462 (http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=271462&Searchpa ge=1&Main=52473&Words=centroid&Search=true#Post271 462)

skynet

07-27-2011, 04:25 AM

Your method indeed works quite well! None of the artifacts I was seeing occur.

Maybe this is because I was insisting on generating pixel-perfect coordinates, which suffered from interpolation and clipping precision issues.

With your method, I just compare two values which get generated and interpolated the same way. Their absolute (interpolated) values have no meaning, though.

Ilian Dinev

07-27-2011, 11:37 AM

Btw, you can still get the centroid-FragCoord, by simply:

vec2 ce_FragCoord = gl_FragCoord.xy + (v_pixelpos-v_pixelpos2);

skynet

07-27-2011, 12:24 PM

Nice! :-D

Powered by vBulletin® Version 4.2.3 Copyright © 2017 vBulletin Solutions, Inc. All rights reserved.