java - Android Open GL ES z 缓冲区无法在 GL_POINTS 上工作(?)

标签 java android opengl-es

我开始认为 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 矩阵的代码,它没有转置矩阵,因此您的着色器是向后的。

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

关于java - Android Open GL ES z 缓冲区无法在 GL_POINTS 上工作(?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21210872/

相关文章:

javascript - Spring 带有 Thymeleaf 和 DataTables 插件

Java 无限循环

java - 如何在 Java 程序中访问 DQL count() 查询的值

android - 如何从一个地方 flutter 中挑选图像或视频?

java - 强制 OpenGL 缓冲区使用 GL 1.0 或 1.1?

java - 二叉树中的 contains-method 总是返回 false java

android - CardView 项目不可点击?

android - 存储gps数据的格式

android - OpenGL ES 1.1 奇怪的光照问题

opengl-es - 根据到最近边缘的距离对矩形进行着色会在对角线中产生奇怪的结果