我开始认为GL ES(Android)中的z缓冲区不适用于GL_POINTS(?),但我在文档中找不到任何内容。

我正在寻找一个由点组成的立方体本色,并使用Z缓冲区将它们渲染到场景中的方法-我有一个类似的类(三角形),它渲染并使用z缓冲区?

PS:我知道我的代码很乱(对此我感到很烦),我已经整理了一下。

下面列出的代码:

class MyGLRenderer implements GLSurfaceView.Renderer {

private final String vertexShaderCode =
        "uniform mat4 uMVPMatrix;" +
        "attribute vec4 vPosition;" +
        "uniform float vSpatical;" +
        "uniform vec3 vCamPos;" +
        "float vDistance;" +
        "float vDisX;" +
        "float vDisY;" +
        "float vDisZ;" +
        "float vA;" +
                "void main() {" +
                "  gl_Position = vPosition * uMVPMatrix;" +
                "  vDisX = vCamPos.x-vPosition.x;" +
                "  vDisY = vCamPos.y-vPosition.y;" +
                "  vDisZ = vCamPos.z-vPosition.z;" +
                "  vA = 3.14159265359 * (vSpatical*vSpatical);" +
                "  vDistance = sqrt((vDisX*vDisX) + (vDisY*vDisY) + (vDisZ*vDisZ));" +
                "  gl_PointSize = 1.0 * vA / (vDistance*vDistance);" +
                "}";

private final String fragmentShaderCode =
        "precision mediump float;" +
                "uniform vec4 vColor;" +
                "void main() {" +
                "  gl_FragColor = vColor;" +
                "}";

private final float[] mMVPMatrix = new float[16];
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
private final float[] mRotationMatrix = new float[16];
float[] mCamPos = {0f, 0f, 6f};

Triangle mTriangle;
Cube mCube;
int mProgram;
float mAngle = 0;

@Override
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
    // Set the background frame color
    int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
    int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
    mProgram = GLES20.glCreateProgram();
    GLES20.glAttachShader(mProgram, vertexShader);
    GLES20.glAttachShader(mProgram, fragmentShader);
    GLES20.glLinkProgram(mProgram);

    GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    mTriangle = new Triangle();
    mCube = new Cube();

    GLES20.glClearColor(0.0f, 0.4f, 0.4f, 1.0f);

    GLES20.glClearDepthf(1.0f);
    GLES20.glEnable(GL10.GL_DEPTH_TEST);
    GLES20.glDepthFunc(GL10.GL_LEQUAL);
    GLES20.glDepthMask(true);
    GLES20.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
    GLES10.glShadeModel(GL10.GL_SMOOTH);

}

@Override
public void onDrawFrame(GL10 unused) {
    float[] scratch = new float[16];

    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);

    Matrix.setLookAtM(mViewMatrix, 0, mCamPos[0], mCamPos[1], mCamPos[2], 0f, 0f, 0f, 0f, 1.0f, 0.0f);

    Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);


    Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0f, 1.0f, 1.0f);
    mAngle += 0.09f;

    Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0);

    mTriangle.draw(mProgram, scratch);
    mCube.draw(mProgram, scratch, mCamPos);
}

@Override
public void onSurfaceChanged(GL10 unused, int width, int height) {
    GLES20.glViewport(0, 0, width, height);
    float ratio = (float) width / height;
    Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}

public static int loadShader(int type, String shaderCode){

    int shader = GLES20.glCreateShader(type);

    GLES20.glShaderSource(shader, shaderCode);
    GLES20.glCompileShader(shader);

    return shader;
}
}

class Cube {

private final FloatBuffer vertexBuffer, vBuff2, vBuff3;
private int mPositionHandle;
private int mColorHandle;
private int mMVPMatrixHandle;
private int vertexCount;
private final int vertexStride = COORDS_PER_VERTEX * 4;
private float mSpaticalExtent[];

static final int COORDS_PER_VERTEX = 3;
static float triangleCoords[];
static float sides[];
static float topbottom[];

float color[] = { 0.93671875f, 0.46953125f, 0.22265625f, 1.0f };
float color2[] = { 0.43671875f, 0.96953125f, 0.22265625f, 1.0f };
float color3[] = { 0.33671875f, 0.46953125f, 0.82265625f, 1.0f };

public Cube() {

    MakeCube(0, 0, 0, 10);


    ByteBuffer bb = ByteBuffer.allocateDirect(
            triangleCoords.length * 4);
    bb.order(ByteOrder.nativeOrder());
    vertexBuffer = bb.asFloatBuffer();
    vertexBuffer.put(triangleCoords);
    vertexBuffer.position(0);


    ByteBuffer bb2 = ByteBuffer.allocateDirect(
            sides.length * 4);
    bb2.order(ByteOrder.nativeOrder());
    vBuff2 = bb2.asFloatBuffer();
    vBuff2.put(sides);
    vBuff2.position(0);


    ByteBuffer bb3 = ByteBuffer.allocateDirect(
            topbottom.length * 4);
    bb3.order(ByteOrder.nativeOrder());
    vBuff3 = bb3.asFloatBuffer();
    vBuff3.put(topbottom);
    vBuff3.position(0);
}

private void MakeCube(float x, float y, float z, float width) {
    triangleCoords = new float[(int)width*(int)width*6]; // Width * Width * 6 Points * 3 Float per point
    sides = new float[(int)width*(int)width*6];
    topbottom = new float[(int)width*(int)width*6];

    vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
    mSpaticalExtent = new float[1];
    mSpaticalExtent[0] = width;
    x -= width/2f;
    y -= width/2f;
    z -= width/2f;
    int currentArrayPoint = 0;
    for (int i = 0; i < width; i++)
    {
        for (int j = 0; j < width; j++)
        {
            // FRONT AND BACK WALLS- X AND Y CHANGE Z DOESN'T
            //
            triangleCoords[currentArrayPoint++] = (x + j) / width;
            triangleCoords[currentArrayPoint++] = (y + i) / width;
            triangleCoords[currentArrayPoint++] = z / width;
            //
            triangleCoords[currentArrayPoint++] = (x + j) / width;
            triangleCoords[currentArrayPoint++] = (y + i) / width;
            triangleCoords[currentArrayPoint++] = (z + width) / width;
        }
    }
    currentArrayPoint = 0;
    for (int i = 0; i < width; i++)
    {
        for (int j = 0; j < width; j++)
        {
            // SIDE WALLS, Y AND Z CHANGE X DOESN'T
            //
            sides[currentArrayPoint++] = x / width;
            sides[currentArrayPoint++] = (y + i) / width;
            sides[currentArrayPoint++] = (z + j) / width;
            //
            sides[currentArrayPoint++] = (x + width) / width;
            sides[currentArrayPoint++] = (y + i) / width;
            sides[currentArrayPoint++] = (z + j) / width;
        }
    }
    currentArrayPoint = 0;
    for (int i = 0; i < width; i++)
    {
        for (int j = 0; j < width; j++)
        {
            // TOP AND BOTTOM WALLS, X AND Z CHANGE Y DOESN'T
            //
            topbottom[currentArrayPoint++] = (z + j) / width;
            topbottom[currentArrayPoint++] = (y) / width;
            topbottom[currentArrayPoint++] = (x + i) / width;
            //
            topbottom[currentArrayPoint++] = (z + j) / width;
            topbottom[currentArrayPoint++] = (y + width) / width;
            topbottom[currentArrayPoint++] = (x + i) / width;
        }
    }
}

public void draw(int mProgram, float[] mvpMatrix, float[] mCamPos) {
    GLES20.glUseProgram(mProgram);

    mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
    GLES20.glEnableVertexAttribArray(mPositionHandle);
    int mCamHandle = GLES20.glGetUniformLocation(mProgram, "vCamPos");
    GLES20.glUniform3fv(mCamHandle, 1, mCamPos, 0);


    GLES20.glVertexAttribPointer(
            mPositionHandle, COORDS_PER_VERTEX,
            GLES20.GL_FLOAT, false,
            vertexStride, vertexBuffer);
    mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
    GLES20.glUniform4fv(mColorHandle, 1, color, 0);
    int mSpaticalHandle = GLES20.glGetUniformLocation(mProgram, "vSpatical");
    GLES20.glUniform1fv(mSpaticalHandle, 1, mSpaticalExtent, 0);
    mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
    GLES20.glDrawArrays(GLES20.GL_POINTS, 0, vertexCount);



    GLES20.glVertexAttribPointer(
            mPositionHandle, COORDS_PER_VERTEX,
            GLES20.GL_FLOAT, false,
            vertexStride, vBuff2);
    mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
    GLES20.glUniform4fv(mColorHandle, 1, color2, 0);
    mSpaticalHandle = GLES20.glGetUniformLocation(mProgram, "vSpatical");
    GLES20.glUniform1fv(mSpaticalHandle, 1, mSpaticalExtent, 0);
    mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
    GLES20.glDrawArrays(GLES20.GL_POINTS, 0, vertexCount);



    GLES20.glVertexAttribPointer(
            mPositionHandle, COORDS_PER_VERTEX,
            GLES20.GL_FLOAT, false,
            vertexStride, vBuff3);
    mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
    GLES20.glUniform4fv(mColorHandle, 1, color3, 0);
    mSpaticalHandle = GLES20.glGetUniformLocation(mProgram, "vSpatical");
    GLES20.glUniform1fv(mSpaticalHandle, 1, mSpaticalExtent, 0);
    mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
    GLES20.glDrawArrays(GLES20.GL_POINTS, 0, vertexCount);


    GLES20.glDisableVertexAttribArray(mPositionHandle);
}
}

最佳答案

在查看了您的着色器之后,我注意到了以下几点:

gl_Position = vPosition * uMVPMatrix; // D3D convention


对于OpenGL(使用列主矩阵和后乘运算),这是完全错误的。

它应该是:

gl_Position = uMVPMatrix * vPosition; // OpenGL convention


我检查了用于发送MVP矩阵的代码,它没有转置矩阵,因此您的着色器是向后的。

您也可以通过将transpose中的GLES20.glUniformMatrix4fv参数设置为true来解决此问题,但是最好坚持使用传统的OpenGL约定并使用以列为主的矩阵。如果这样做,诊断这类事情要容易得多。

09-04 23:36