使用OpenGLES绘制圆形轮廓线。

3

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

enter image description here

我曾尝试使用普通的顶点着色器和片段着色器,类似于谷歌示例,其中有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个缺失的部分。

enter image description here

我该如何绘制像上面例子中的描边圆形?
2个回答

3
问题在于glLineWidth函数的实现方式。根据规范,非反锯齿线段的宽度不为一时,通过在次要方向(对于x-major线来说,次要方向是y,对于y-major线来说,次要方向是x)上偏移并在此方向上复制片段的方式进行栅格化(见图3.3)。这四个缺失的部分对应于您的圆形线条从x-major到y-major的切换位置。如果您仔细观察,您会发现当圆形接近x-major和y-major之间的切换点时,其也变得更细。

可能最好放弃线条绘制,使用三角带来渲染实心带。即使用此网页中提供的“三角形线条”示例的方法,并提供了一些高级解决方案。


0

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

但是,如果您想创建单色描边圆圈,一个技巧是创建多个具有strokeWidth1f的圆圈,并以这样一种方式变化半径,即每个下一个圆圈的半径比前一个圆圈大+(1f/2)。

enter image description here

我创建了一个OpenGL库,可以创建多种类型的形状,如三角形、圆形、三角形等等。下面是使用生成多个圆的代码,并且结果显示在上面的图像中。

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接