简体   繁体   中英

How do I draw a filled circle with OpenGL ES on iPhone?

How do I draw a filled circle with openGl on iPhone ?

I've found many solutions but none of them work. Probably because there are many ways to do it. But what's the method with shortest code ?

For a truly smooth circle, you're going to want a custom fragment shader. For example, the following vertex shader:

 attribute vec4 position;
 attribute vec4 inputTextureCoordinate;

 varying vec2 textureCoordinate;

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

and 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;     
 }

will draw a smooth red circle within a square that you draw to the screen. You'll need to supply vertices for your square to the position attribute and coordinates that range from 0.0 to 1.0 in X and Y to the inputTextureCoordinate attribute, but this will draw a circle that's as sharp as your viewport's resolution allows and do so very quickly.

One way would be to use GL_POINTS:

glPointSize(radius);
glBegin(GL_POINTS); 
glVertex2f(x,y); 
glEnd(); 

Another alternative would be to use GL_TRIANGLE_FAN:

radius = 1.0;
glBegin(GL_TRIANGLE_FAN);
glVertex2f(x, y);
for(int angle = 1; angle <= 360; angle = angle + 1)
glVertex2f(x + sind(angle) * radius, y + cosd(angle) * radius);
glEnd();

To get the verices of a circle:

     float[] verts=MakeCircle2d(1,100,0,0)

     public static float[] MakeCircle2d(float rad,int points,float x,float y)//x,y  ofsets
     {
            float[] verts=new float[points*2+2];
            boolean first=true;
            float fx=0;
            float fy=0;
            int c=0;
            for (int i = 0; i < points; i++)
            {
                    float fi = 2*Trig.PI*i/points;
                    float xa = rad*Trig.sin(fi + Trig.PI)+x ;
                    float ya = rad*Trig.cos(fi + Trig.PI)+y ;
                    if(first)
                    {
                        first=false;
                        fx=xa;
                        fy=ya;
                    }
                    verts[c]=xa;
                    verts[c+1]=ya;
                    c+=2;
            }
            verts[c]=fx;
            verts[c+1]=fy;
            return verts;
      }

Draw it as GL10.GL_LINES if you want a empty circle

 gl.glDrawArrays(GL10.GL_LINES, 0, verts.length / 2);

Or draw it as GL10.GL_TRIANGLE_FAN if you want a filled one

 gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, verts.length / 2);

Its java but it is really easy to convert to c++/objc

Here is a super fast way using shaders... Just make a Quad with a vertex buffer and set the UV's from -1 to 1 for each corner of the quad.

The vertex buffer in floats should look like: NOTE: this needs a index buffer too.

var verts = new float[20]
{
    -1, -1, 0,   -1, -1,
    -1, 1, 0,   -1, 1,
    1, 1, 0,   1, 1,
    1, -1, 0,   1, -1,
};


#VS
attribute vec3 Position0;
attribute vec2 Texcoord0;

varying vec4 Position_VSPS;
varying vec2 Texcoord_VSPS;

uniform vec2 Location;

void main()
{
    vec3 loc = vec3(Position0.xy + Location, Position0.z);
    gl_Position = Position_VSPS = vec4(loc, 1);
    Texcoord_VSPS = loc.xy;
}
#END

#PS
varying vec4 Position_VSPS;
varying vec2 Texcoord_VSPS;

uniform vec2 Location;

void main()
{
    float dis = distance(Location, Texcoord_VSPS);
    if (.1 - dis < 0.0) discard;

    gl_FragData[0] = vec4(0, 0, 1, 1);
}
#END

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM