【问题标题】:Draw a circle stroke using OpenGLES使用 OpenGLES 绘制圆形笔划
【发布时间】:2019-08-13 02:36:17
【问题描述】:

我想画一个这样的描边圆:

我尝试过使用普通的顶点着色器和片段着色器,例如 google samples,顶点坐标为 364 点:

vertices = new float[364 * 3];
vertices[0] = 0;
vertices[1] = 0;
vertices[2] = 0;

for (int i =1; i <364; i++){
    vertices[(i * 3)+ 0] = (float) (0.5 * Math.cos((3.14/180) * (float)i ));
    vertices[(i * 3)+ 1] = (float) (0.5 * Math.sin((3.14/180) * (float)i ));
    vertices[(i * 3)+ 2] = 0;
}

然后使用:

int COORDS_PER_VERTEX = 3;
int vertexCount = 364 * 3 / COORDS_PER_VERTEX;
int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);

GLES20.glDrawArrays(GLES20.GL_LINE_LOOP, 1, vertexCount - 1);

但结果并不如预期,我的圈子里有4个缺失的部分。

我怎样才能像上面的例子一样画一个描边的圆圈?

【问题讨论】:

    标签: android opengl-es opengl-es-2.0


    【解决方案1】:

    问题在于glLineWidth 的实现方式。根据spec

    宽度不是 1 的非抗锯齿线段通过在次要方向上偏移来栅格化(对于 x 主线,次要方向是 y,对于 y 主要线,次要方向是x) 并在次要方向上复制片段(见图 3.3)。

    这 4 个缺失部分对应于您的圆线从 x 方向变为 y 方向的位置。如果你仔细观察,你会发现你的圆圈在接近 x 大调和 y 大调之间的切换时也会变细。

    您最好的选择可能是放弃画线并使用三角形条来渲染实心带。即来自this webpage 的“三角线”示例,它也提出了一些更高级的解决方案。

    【讨论】:

      【解决方案2】:

      大多数库使用“三角线”,我认为这是绘制笔划线的最佳方式,因为您可以设置渐变颜色,控制线条不同部分的线宽并绘制平滑线。

      但如果你想用单一颜色创建笔画圆,你可以做的一个技巧是创建多个 strokeWidth1f 的圆,并改变半径以这样的方式循环,即下一个圆的半径比前一个圆大 +(1f/2)。

      我创建了一个OpenGL library,它可以创建多种类型的形状,如三角形、圆形、三角形......等等。下面是使用library生成多个圆圈的代码,结果如上图所示。

           lateinit var circles: Circles // OpenGL circles object
      
           fun createCircles() {
      
              val coordinatesInfo = generateCoordinateInfo(400f, 400f, 100f, 20)
      
              // set object for the OpenGL circles
              circles = Circles(
                  // in format: [cx1,cy1,radius1,angle1,  cx2,cy2,radius2,angle2,...]
                  coordinatesInfo = coordinatesInfo,
                  colors = intArrayOf(Color.RED),
                  style = STYLE_STROKE,
                  strokeWidth = 1f,
                  preloadProgram = program,
                  gestureDetector = mainGestureDetector,
                  useSingleColor = true
              )
           }
      
          /**
           * Get the coordinates for the stroke circles
           * @param x x coordinate of the circle
           * @param y y coordinate of the circle
           * @param r radius of the circle
           * @param strokeWidth stroke width of the circle
           */
          fun generateCoordinateInfo(x: Float, y: Float, r: Float, strokeWidth: Int = 20): FloatArray {
      
              val coordinatesInfo = FloatArray((strokeWidth * 2) * 4)
      
              for (i in 0 until strokeWidth) {
                  val j = i * 4
                  coordinatesInfo[j] = x                // x
                  coordinatesInfo[j + 1] = y            // y
                  coordinatesInfo[j + 2] = r - i / 2f   // radius
                  coordinatesInfo[j + 3] = 0f           // angle
              }
      
              for (i in 0 until strokeWidth) {
                  val j = (strokeWidth + i) * 4
                  coordinatesInfo[j] = x                // x
                  coordinatesInfo[j + 1] = y            // y
                  coordinatesInfo[j + 2] = r + i / 2f   // radius
                  coordinatesInfo[j + 3] = 0f           // angle
              }
      
              return coordinatesInfo
          }
      
          fun draw(transformedMatrixOpenGL: FloatArray) {
      
              // draw circles
              if (::circles.isInitialized) {
                  circles.draw(transformedMatrixOpenGL)
              } 
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-02
        • 2013-02-12
        • 2016-08-19
        • 1970-01-01
        • 2011-01-11
        • 1970-01-01
        相关资源
        最近更新 更多