Android 使用不透明度渲染的 OpenGL ES2 三角形

Android OpenGL ES2 triangles rendered with opacity

我正在从服务器以 [​​=27=] 格式加载模型,这是我在 Three.js BufferGeometry 中创建的,并将位置和 uv 属性存储在 JSON 文件中,当我将所有内容加载到 openGL ES2 时很好,但是如果视图有纹理,或者如果它有颜色,则在我旋转视图之前不会出现某些面孔,或者如果它有颜色则显示为半透明。 从 Three.js 生成的顶点值和顺序没有任何变化,所以我假设它们的顺序是正确的,所以它应该没有颠倒的面。

这是片段着色器:

precision mediump float;

varying vec4 v_Color;
uniform sampler2D u_TextureUnit;
varying vec2 v_TextureCoordinates;

void main() {
    vec4 tex=texture2D(u_TextureUnit, v_TextureCoordinates);
    gl_FragColor=v_Color+tex;
}

和渲染代码:

    private static final int BYTES_PER_FLOAT = 4;
// private static final int BYTES_PER_SHORT = 2;
private static final int POSITION_COMPONENT_COUNT = 3;
private static final int COLOR_COMPONENT_COUNT = 4;
private static final int UV_COMPONENT_COUNT = 2;
private static final int ALL_COMPONENT_COUNT = POSITION_COMPONENT_COUNT + COLOR_COMPONENT_COUNT + UV_COMPONENT_COUNT;
private static final int STRIDE = ALL_COMPONENT_COUNT * BYTES_PER_FLOAT;

private VertexArray vertexArray;

private float[] modelMatrix = new float[16];
private final float[] modelViewProjectionMatrix = new float[16];

TextureShaderProgram shaderProgram;
int textureid;
// ShortBuffer indexBuffer;

public Geometry(Context context, JSONObject element) throws JSONException {     
    /*
     * JSONArray indecies = element.getJSONArray("indexes"); short[] indexes
     * = new short[indecies.length()]; for (int y = 0; y <
     * indecies.length(); y++) { indexes[y] = (short) indecies.getInt(y); }
     */
    // indexBuffer = ByteBuffer.allocateDirect(indexes.length *
    // BYTES_PER_SHORT).order(ByteOrder.nativeOrder()).asShortBuffer();
    // indexBuffer.put(indexes).position(0);
    JSONArray vertices = element.getJSONArray("vertices");
    JSONArray uvs = element.getJSONArray("uvs");
    JSONArray matrix = element.getJSONArray("matrix");
    for (int y = 0; y < matrix.length(); y++) {
        modelMatrix[y] = (float) matrix.getDouble(y);
    }
    JSONObject material = element.getJSONObject("material");
    int color = Color.parseColor(material.getString("color"));
    String bmpString = material.getString("map");
    int n = vertices.length() / 3;
    float[] data;
    data = new float[n * STRIDE];
    int k = 0;
    for (int i = 0; i < n; i++) {
        data[i * ALL_COMPONENT_COUNT] = (float) vertices.getDouble(i * 3);
        data[i * ALL_COMPONENT_COUNT + 1] = (float) vertices.getDouble(i * 3 + 1);
        data[i * ALL_COMPONENT_COUNT + 2] = (float) vertices.getDouble(i * 3 + 2);
        data[i * ALL_COMPONENT_COUNT + 3] = Color.red(color) / 255f;
        data[i * ALL_COMPONENT_COUNT + 4] = Color.green(color) / 255f;
        data[i * ALL_COMPONENT_COUNT + 5] = Color.blue(color) / 255f;
        data[i * ALL_COMPONENT_COUNT + 6] = Color.alpha(color) / 255f;
        data[i * ALL_COMPONENT_COUNT + 7] = bmpString.equals("") ? 0f : (float) uvs.getDouble(k);
        data[i * ALL_COMPONENT_COUNT + 8] = bmpString.equals("") ? 0f : (float) uvs.getDouble(k + 1);
        k += 2;
    }
    vertexArray = new VertexArray(data);

    shaderProgram = new TextureShaderProgram(context, R.raw.texture_vertex_shader, R.raw.texture_fragment_shader);
    textureid = bmpString.equals("") ? 0 : TextureHelper.loadTexture(TextureHelper.decodeBase64(bmpString));
}

private void bindData(TextureShaderProgram shaderProgram) {
    vertexArray.setVertexAttribPointer(0, shaderProgram.getPositionAttributeLocation(), POSITION_COMPONENT_COUNT, STRIDE);
    vertexArray.setVertexAttribPointer(POSITION_COMPONENT_COUNT, shaderProgram.getColorAttributeLocation(), COLOR_COMPONENT_COUNT, STRIDE);
    vertexArray.setVertexAttribPointer(POSITION_COMPONENT_COUNT + COLOR_COMPONENT_COUNT, shaderProgram.getTextureCoordinatesAttributeLocation(), UV_COMPONENT_COUNT, STRIDE);
}

public void draw(float[] projectionMatrix) {
    multiplyMM(modelViewProjectionMatrix, 0, projectionMatrix, 0, modelMatrix, 0);
    shaderProgram.useProgram();
    shaderProgram.setUniforms(modelViewProjectionMatrix, textureid);
    bindData(shaderProgram);
    glDrawArrays(GL_TRIANGLES, 0, vertexArray.getCapacity() / ALL_COMPONENT_COUNT);
    // glDrawElements(GL_TRIANGLES, indexBuffer.capacity(),
    // GL_UNSIGNED_SHORT, indexBuffer);
}

顶点数据class:

    private final FloatBuffer floatBuffer;
private final int capacity;

public VertexArray(float[] vertexData) {
    floatBuffer = ByteBuffer.allocateDirect(vertexData.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer().put(vertexData);
    capacity = floatBuffer.capacity();
}

public void setVertexAttribPointer(int dataOffset, int attributeLocation, int componentCount, int stride) {
    floatBuffer.position(dataOffset);
    glVertexAttribPointer(attributeLocation, componentCount, GL_FLOAT, false, stride, floatBuffer);
    glEnableVertexAttribArray(attributeLocation);
    floatBuffer.position(0);
}

public final int getCapacity() {
    return capacity;
}

没有设置深度函数,所以OpenGL ES是根据索引数据按照三角形的顺序绘制的。您必须启用深度测试,这将根据来自相机的深度信息对三角形进行排序。

glEnable(GL_DEPTH_TEST);