GLSL Circle gets eliptical on Rendering on screen?

584 views Asked by At

I am trying to render a circle on my mobile uisng farment shader. Also followed this as i got the best answer.

Vertex Shader:

attribute vec4 position;
 attribute vec4 inputTextureCoordinate;

 varying vec2 textureCoordinate;

 void main()
 {
    gl_Position = position;
    textureCoordinate = inputTextureCoordinate.xy;
 }

Fragment Shader:

 varying highp vec2 textureCoordinate;

 const highp vec2 center = vec2(0.5, 0.5);
 const highp float radius = 0.5;

 void main()
 {
     highp float distanceFromCenter = distance(center, textureCoordinate);
     lowp float checkForPresenceWithinCircle = step(distanceFromCenter, radius);

     gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0) * checkForPresenceWithinCircle;     
 }

attribute vec4 position; is passed -1 to +1 and attribute vec4 inputTextureCoordinate; is passed 0 to 1.

But while rendering I get a ellipse on Mobile Screen? I think this might be because of the screen aspect ratio. How to render perfect circle on screen?

1

There are 1 answers

0
derhass On BEST ANSWER

I think this might be because of the screen aspect ratio.

Yes, this is exactly the problem.

The viewinf voulme iis [-1,1] in all 3 dimensions. That is mapped to the viewport for window space coordinates. Since you do not use any other transformations, you are direcly drawin in clip space, and your clip space is identical to the NDC space.

To get this right, you have to take the aspect ratio into account. You can either directly change your attribute values, or correct for it in the vertex shader, or still draw the full-screen quad and take account for it in the fragment shader.

The latter one would be the most inefficient way. I would actually recommend adding a 2D scale vector uniform to the vertex shader.

attribute vec4 position;
attribute vec4 inputTextureCoordinate;

varying vec2 textureCoordinate;

uniform vec2 scale;

void main()
{
    gl_Position = vec4(scale, 1.0, 1.0) * position;
    textureCoordinate = inputTextureCoordinate.xy;
}

On your client side, you can set the uniform to (1.0/aspect_ratio, 1.0) if aspect_ratio is >= 1.0, and to (1.0, aspect_ratio) if it is below 1. That way, no matter what screen orientation you use, the circle will always be a circle and fit to the screen.