Android Opengl圆形纹理

时间:2017-07-24 05:22:14

标签: android opengl-es texture-mapping texture2d render-to-texture

我一直在尝试添加纹理,但纹理如下所示:

texture image

Desire Output

这是我添加坐标和添加纹理坐标的代码。

for(int i=0; i<outerVertexCount; i++) {
    float percent=(i/(float)(outerVertexCount));
    float rad= (float) (percent*2*Math.PI);
    float outerX= (float) (centerX+radius*Math.cos(rad));
    float outerY=(float)(centerY+radius*Math.sin(rad));

    int previous=idx;
    circleCoordinates[idx++]=outerX;
    circleCoordinates[idx++]=outerY;
    circleCoordinates[idx++]=(circleCoordinates[previous])/(radius*2);
    circleCoordinates[idx++] = (circleCoordinates[previous+1])/(radius*2);
}

请帮帮我。

2 个答案:

答案 0 :(得分:1)

您正在画一个圆圈并使用&#39;标准化&#39;几乎相同的坐标采取纹理坐标。所以你需要做的是将纹理坐标标准化为纹理空间[0,1]。最简单的方法是检查顶部和左侧的纹理坐标是否分别为(0.5,0.0)和(0.0,0.5)。底部和右侧也应分别为(0.5,1.0)和(1.0,0.5)。 (触及边缘的点)。

代码中的问题是:

  circleCoordinates[idx++] = (circleCoordinates[previous])/(radius*2);
  circleCoordinates[idx++] = (circleCoordinates[previous+1])/(radius*2);

当您在圆圈中创建点时,这些点将低于0,在某些象限中将采用错误的纹理点。 你也可以通过centerX and centerY来偏移你的圆圈,这也会移动你的纹理。

工作代码应为:

  circleCoordinates[idx++] = (circleCoordinates[previous])/(radius*2) + 0.5 -  centerX / (radius * 2);
  circleCoordinates[idx++] = (circleCoordinates[previous+1])/(radius*2) + 0.5 - centerY / (radius * 2);

0.5是由于您使用radius * 2对其进行了标准化而没有添加centerPoint,它将映射到[-0.5,0.5]但是您还添加了中心点并对其进行了标准化,因此您必须减去{{1}删除工件。

TLDR;你的(0,0)是你想要它在上面,左边的第一个图像中的白色交叉点。相应地归一化。

答案 1 :(得分:1)

这是一个例子:

public class Circle {

private int[] textureIDs = new int[1];

private int numberOfVertices = 30;


private final float[][] vertices = new float[numberOfVertices][2];
private final float[][] texVertices = new float[numberOfVertices][2];


private FloatBuffer vertexBuffer; // Buffer for vertex-array
private FloatBuffer texBuffer;    // Buffer for texture-coords-array (NEW)


public Circle() {
    setUpVertices(1.0f);
    // Setup vertex-array buffer. Vertices in float. A float has 4 bytes
    ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4 * 2);
    vbb.order(ByteOrder.nativeOrder()); // Use native byte order
    vertexBuffer = vbb.asFloatBuffer(); // Convert byte buffer to float

    // Loop through the vertices and put them in the vertexbuffer
    for (int i = 0; i < numberOfVertices; i++) {
        for (int j = 0; j <= 1; j++) {
            vertexBuffer.put(vertices[i][j]); // Copy data into buffer
        }
    }
    vertexBuffer.position(0); // Rewind

    setUpTextureVertices(1.0f);

    // Setup texture-coords-array buffer, in float. An float has 4 bytes
    ByteBuffer tbb = ByteBuffer.allocateDirect(vertices.length * 4 * 2);
    tbb.order(ByteOrder.nativeOrder());
    texBuffer = tbb.asFloatBuffer();
    // Loop through the vertices and put them in the vertexbuffer
    for (int i = 0; i < numberOfVertices; i++) {
        for (int j = 0; j <= 1; j++) {
            texBuffer.put(texVertices[i][j]); // Copy data into buffer
        }
    }
    texBuffer.position(0);
}


public void draw(GL10 gl) {
    gl.glFrontFace(GL10.GL_CCW);    // Front face in counter-clockwise orientation
    gl.glEnable(GL10.GL_CULL_FACE); // Enable cull face
    gl.glCullFace(GL10.GL_BACK);    // Cull the back face (don't display)

    // Enable vertex-array and define its buffer
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); // Enable texture-coords-array
    gl.glVertexPointer(2, GL10.GL_FLOAT, 0, vertexBuffer);
    gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer); // Define texture-coords


    // Draw the primitives from the vertex-array directly

    gl.glPushMatrix();
    gl.glTranslatef(0.0f, 0.0f, 1.0f);
    gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, numberOfVertices);
    gl.glPopMatrix();

    gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glDisable(GL10.GL_CULL_FACE);

}


public void loadTexture(GL10 gl, Context context) {
    gl.glGenTextures(1, textureIDs, 0); // Generate texture-ID array
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[0]); // Bind to texture ID
    // Set up texture filters
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

    // Construct an input stream to texture image
    @SuppressLint("ResourceType")
    InputStream istream = context.getResources().openRawResource(R.drawable.circle);
    Bitmap bitmap;
    try {
        // Read and decode input as bitmap
        bitmap = BitmapFactory.decodeStream(istream);
    } finally {
        try {
            istream.close();
        } catch (IOException e) {
        }
    }

    // Build Texture from loaded bitmap for the currently-bind texture ID
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
    bitmap.recycle();
}

private void setUpTextureVertices(float radius) {
    float theta0 = (float) (2 * Math.PI / (numberOfVertices - 1));

    for (int i = 0; i < numberOfVertices; i++) {

        float theta = i * theta0;

        float c = (float) Math.cos(theta);
        float s = (float) Math.sin(theta);

        float x = radius * c;
        float y = radius * s;

        texVertices[i][0] = (x * 0.5f) + 0.5f;
        texVertices[i][1] = (y * 0.5f) + 0.5f;

    }
}

private void setUpVertices(float radius) {
    float theta0 = (float) (2 * Math.PI / (numberOfVertices - 1));

    for (int i = 0; i < numberOfVertices; i++) {

        float theta = i * theta0;

        float c = (float) Math.cos(theta);
        float s = (float) Math.sin(theta);

        float x = radius * c;
        float y = radius * s;

        vertices[i][0] = x;
        vertices[i][1] = y;

    }
}
}