Android OpenGL ES 2.0

3

我正在尝试在Android OpenGL ES 2.0示例中显示一个简单的三角形。但是什么也没有出现,我不知道为什么:),我没有收到任何错误信息,只有一个蓝色的屏幕(这是我的清除颜色)。也许投影矩阵有问题,导致我的模型被放置在外面了?

package dk.madslee.modelviewer;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.ConfigurationInfo;
import android.content.res.Resources;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import android.os.Bundle;
import android.util.Log;

// http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/graphics/GLES20TriangleRenderer.html

public class MainActivity extends Activity
{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        final Resources resources = getResources();
        GLSurfaceView surfaceView = new GLSurfaceView(this);
        surfaceView.setEGLContextClientVersion(2); // enable OpenGL 2.0

        Log.e("opengl", Boolean.toString(detectOpenGLES20()));

        surfaceView.setRenderer(new GLSurfaceView.Renderer()
        {   
            public static final int FLOAT_BYTE_LENGTH = 4;

            private int mProgram;
            private int mVertexPositionAttributeLocation;
            private int mMVMatrixUniformLocation;
            private int mPMatrixUniformLocation;

            private float[] mMVMatrix = new float[16];
            private float[] mPMatrix = new float[16];

            private float[] mVertices = {
                1.0f,  1.0f,  0.0f,
                -1.0f,  1.0f,  0.0f,
                1.0f, -1.0f,  0.0f,
            };
            private FloatBuffer mVertexBuffer;

            @Override
            public void onSurfaceCreated(GL10 gl, EGLConfig config)
            {
                mVertexBuffer = ByteBuffer.allocateDirect(mVertices.length * FLOAT_BYTE_LENGTH).order(ByteOrder.nativeOrder()).asFloatBuffer();
                mVertexBuffer.put(mVertices);
                mVertexBuffer.position(0);

                mProgram = createProgram();
                mVertexPositionAttributeLocation = GLES20.glGetAttribLocation(mProgram, "aVertexPosition");
                mMVMatrixUniformLocation = GLES20.glGetUniformLocation(mProgram, "uMVMatrix");
                mPMatrixUniformLocation = GLES20.glGetUniformLocation(mProgram, "mPMatrix");
                checkGlError("glGetUniformLocation");

                Matrix.setLookAtM(mMVMatrix, 0, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
            }

            @Override
            public void onSurfaceChanged(GL10 gl, int width, int height)
            {
                GLES20.glViewport(0, 0, width, height);

                Matrix.frustumM(mPMatrix, 0, -1, 1, -1, 1, 3, 7); // [UPDATED but didnt solve the problem]
            }

            @Override
            public void onDrawFrame(GL10 gl)
            {
                GLES20.glClearColor(0, 0, 1.0f, 1.0f);
                GLES20.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

                GLES20.glUseProgram(mProgram);
                checkGlError("glUseProgram");

                mVertexBuffer.position(0);

                GLES20.glVertexAttribPointer(mVertexPositionAttributeLocation, 3, GLES20.GL_FLOAT, false, 3 * FLOAT_BYTE_LENGTH, mVertexBuffer);
                checkGlError("glVertexAttribPointer");

                GLES20.glEnableVertexAttribArray(mVertexPositionAttributeLocation);
                checkGlError("glEnableVertexAttribArray");

                GLES20.glUniformMatrix4fv(mMVMatrixUniformLocation, 1, false, mMVMatrix, 0);
                GLES20.glUniformMatrix4fv(mPMatrixUniformLocation, 1, false, mPMatrix, 0);
                checkGlError("glUniform4fv");

                GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
                checkGlError("glDrawArrays");
            }

            private int createProgram()
            {
                int program = GLES20.glCreateProgram();

                int vertexShader = getShader(GLES20.GL_VERTEX_SHADER, R.string.vertex_shader);
                int fragmentShader = getShader(GLES20.GL_FRAGMENT_SHADER, R.string.fragment_shader);

                GLES20.glAttachShader(program, vertexShader);
                GLES20.glAttachShader(program, fragmentShader);
                GLES20.glLinkProgram(program);
                GLES20.glUseProgram(program);

                return program;
            }

            private int getShader(int type, int source) 
            {
                int shader = GLES20.glCreateShader(type);
                String shaderSource = resources.getString(source);
                GLES20.glShaderSource(shader, shaderSource);
                GLES20.glCompileShader(shader);

                int[] compiled = new int[1];
                GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
                if (compiled[0] == 0) 
                {
                    Log.e("opengl", "Could not compile shader");
                    Log.e("opengl", GLES20.glGetShaderInfoLog(shader));
                    Log.e("opengl", shaderSource);
                }

                return shader;
            }

            private void checkGlError(String op) {
                int error;
                while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
                    Log.e("opengl", op + ": glError " + error);
                    throw new RuntimeException(op + ": glError " + error);
                }
            }
        });

        setContentView(surfaceView);   
    }

    private boolean detectOpenGLES20() {
        ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        ConfigurationInfo info = am.getDeviceConfigurationInfo();
        return (info.reqGlEsVersion >= 0x20000);
    }
}

我的着色器看起来像这样:
顶点
attribute vec3 aVertexPosition;
        uniform mat4 uMVMatrix;
        uniform mat4 uPMatrix;

        void main() {
            gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
        }

片段

precision highp float; 
        void main() {
          gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
        }
1个回答

6
请确保禁用背面剔除(通过glDisable(GL_CULL_FACE)),因为此时您正在查看几何图形的背面,或者尝试在观察时使用5而不是-5。它实际上应该默认禁用,但我不确定。
否则可能是您的投影矩阵有问题。请记住,frustum的参数是通用(3D世界)单位,不一定是像素,因此如果您不希望世界单位表示像素,则不应将相同的值放入glViewport中。因此,此时您的图像平面为(2 * 宽度)x(2 * 高度),您的三角形仅占用一个像素(实际上甚至更少,由于透视失真)。尝试类似于Matrix.frustumM(mPMatrix, 0, -1, 1, -1, 1, 3, 7)这样的内容,或者使用等效于gluPerspective的内容,其中您只需输入所需的视角和窗口的宽高比即可,这比直接使用frustum参数要自然得多。
编辑:刚找到问题。在glGetUniformLocation中,您写成了mPMatrix而不是uPMatrix,因此您从未获得投影矩阵的有效统一位置。奇怪的是GL没有抛出错误。

代码中有一个地方我不太确定是否正确,那就是在调用GLES20.glVertexAttribPointer(mVertexPositionAttributeLocation, 3, GLES20.GL_FLOAT, false, 3 * FLOAT_BYTE_LENGTH, mVertexBuffer)时,也许我做错了什么?或者我应该尝试使用缓冲区呢? - Mads Lee Jensen
@madsleejensen 如果那是你唯一更改的东西,那听起来真的很奇怪。哦,我明白了,我会更新我的答案。 - Christian Rau
很抱歉,我创建了一个新的示例,您可以在此处查看:http://pastebin.com/0GNL5gCu - Mads Lee Jensen
Christian,我不确定你的意思,制服似乎已经正确绑定了,我没有任何名为“mPMatrix”的变量? - Mads Lee Jensen
@madsleejensen 这就是我在更新的答案中所指的。你在glGetUniformLocation中意外地写了"mPMatrix"(至少在问题代码中),所以从未获得投影矩阵的有效统一位置。我想这就是错误所在,还有错误的平截头体参数。 - Christian Rau
显示剩余5条评论

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