2012-07-12 109 views
4

如何在iPhone上使用openGl绘制实心圆?如何在iPhone上用OpenGL ES绘制实心圆?

我发现了很多解决方案,但都没有工作。可能是因为有很多方法可以做到这一点。但是最短代码的方法是什么?

+0

“它们都不起作用”哦?怎么会这样? – genpfault 2012-07-12 13:36:51

+0

听说您找到的解决方案以及迄今为止尝试过的解决方案将是非常有趣的。如果它们都不起作用,我怀疑你的实现中有一些错误! – kroneml 2012-07-13 08:12:57

回答

16

对于一个真正的流畅型圈,你会希望有一个自定义的片段着色器。例如,下面的顶点着色器:

attribute vec4 position; 
attribute vec4 inputTextureCoordinate; 

varying vec2 textureCoordinate; 

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

和片段着色器:

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

将吸引你画到屏幕上一个正方形内的光滑红色圆圈。您需要为您的方块提供顶点,并将position属性的坐标和X和Y范围从0.0到1.0的坐标提供给inputTextureCoordinate属性,但这会绘制一个与您的视口分辨率允许的速度一样锐利的圆,并且可以非常快地完成。

+0

我非常喜欢这个解决方案。 – 2012-07-12 18:38:05

+0

我也认为这是最好的解决方案。请注意,您可以使用(三角形)广告牌绘制正方形,也可以只绘制正确点大小的点。第二种解决方案的优点是只需传输点位置和半径(即一个“vec4”)。如果您有3D场景,您也不必担心您的方形面向相机。 – kroneml 2012-07-13 08:10:27

+0

但是如何避免正方形的黑色部分被绘制? E.g,如果你想在屏幕上画出几个这样的球体,并且它们重叠,那么正方形的“黑色”部分将覆盖其他球体,如下图所示:http://imgur.com/e7Z4ugb – OMH 2014-03-13 20:50:16

2

一种方法是使用GL_POINTS:

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

另一种方法是使用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(); 
+0

谢谢,我得到了“隐式声明函数glBegin在c99中无效”警告。这是什么意思 ? – aneuryzm 2012-07-14 09:17:13

+0

我们真的需要看你的代码,看看你错在哪里。 – StuGrey 2012-07-14 14:59:39

+0

Ios似乎不支持glBegin调用。记住这是ES2,他们已经消除了一些功能。似乎也没有glEnd功能。 – 2012-12-03 20:45:12

1

为了得到一个圆的verices:

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

它画成GL10.GL_LINES如果你想有一个空的圆形

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

或者,如果你想有一个填充绘制成GL10.GL_TRIANGLE_FAN一个

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

它的Java,但它是很容易转换为C++/objc

0

这是一个使用着色器的超快速方法...只需使用顶点缓冲区制作四边形,并将四边形的每个角的UV从-1设置为1即可。

浮点数中的顶点缓冲区应如下所示: 注意:这也需要一个索引缓冲区。

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