user868935
user868935

Reputation:

Circle stretched when rendered in OpenGL ES 2

I've rendered a plain white circle on on my device, but it proportionately stretches it across my device based on the screen dimensions. Scouring around 2D examples & possible answers, I have not been able scale it correctly.

My Renderer class:

@Override
public void onSurfaceChanged(GL10 gl, int width, int height)
{
    float scaleX = (float) width / Screen.getScreenWidthPx();
    float scaleY = (float) height / Screen.getScreenHeightPx();
    final int vpWidth = (int)(Screen.getScreenWidthPx() * scaleX);
    final int vpHeight = (int)(Screen.getScreenHeightPx() * scaleY);

    GLES20.glViewport(0, 0, vpWidth, vpHeight);

    mCam.setProjection(Screen.getScreenWidthPx(), Screen.getScreenHeightPx());
}

My Camera class:

public void setProjection(float width, float height)
{        
    final float ratio = width / height;
    Matrix.orthoM(mProjection, 0, 0, width, height, 0, -1, 1);
}

Vertex Shader:

private String mVSCode =
        "attribute vec4 vPosition;" +
                "uniform float sWidth;" +
                "uniform float sHeight;" +
                "void main() {" +
                "gl_Position = vPosition;" +                  
                "}";

Result:

enter image description here

Upvotes: 1

Views: 185

Answers (1)

Rabbid76
Rabbid76

Reputation: 210968

You have to decide what you want to do. If you want to draw the vertex coordinates 1:1 to window coordinates (pixel), the your orthographic projection is correct.
But if you just want to take care of the aspect ratio, then the projection has to be:

public void setProjection(float width, float height)
{        
    final float ratio = width / height;
    Matrix.orthoM(mProjection, 0, -1, 1, 1/ratio, -1/ratio, -1, 1);
}

Anyway, you have to transform the vertex coordinate by the orthographic projection matrix in the vertex shader.

Add a matrix uniform (mat4 uProjection) to the vertex shader. Set the uniform by mProjection. Multiply the vertex coordinate by uProjection in the vertex shader:

attribute vec4 vPosition;

uniform uProjection;

void main() {
    gl_Position = uProjection* vPosition;
}

Alternatively you can manually set the orthographic projection matrix in the vertex shader:
(Of course you have to set the uniforms sWidth respectively sHeight)

attribute vec4 vPosition;

uniform float sWidth;
uniform float sHeight;

void main() {

    mat4 projection = mat4(1.0);
    projection[1][1] = -sHeight/sWidth;

    gl_Position = projection * vPosition;            
};

Or if you want to use window coordinates:

attribute vec4 vPosition;

uniform float sWidth;
uniform float sHeight;

void main() {

    mat4 projection = mat4(
        vec4( 2.0/sWidth,  0.0,         0.0, 0.0),
        vec4( 0.0,        -2.0/sHeight, 0.0, 0.0),
        vec4( 0.0,         0.0,         1.0, 0.0),
        vec4(-1.0,         1.0,         0.0, 1.0));

    gl_Position = projection * vPosition;            
};

Upvotes: 1

Related Questions