简体   繁体   中英

Android OpenGL ES 2.0

Im trying to get a simple trinangle showing in a Android OpenGL ES 2.0 example. But nothing appears and i just dont get why:), i get no errors or anything, just a blue screen (that is my clear color). Maybe theres something wrong with the projection matrix placing my model outside?

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);
    }
}

My shaders looks like this

Vertex

attribute vec3 aVertexPosition;
        uniform mat4 uMVMatrix;
        uniform mat4 uPMatrix;

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

Fragment

precision highp float; 
        void main() {
          gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
        }

Make sure to disable back face culling (by glDisable(GL_CULL_FACE) ), as at the moment you're looking at the back of your geometry, or try using 5 instead of -5 in the look at. It should actually be disabled by default, but I'm not sure about that.

Otherwise it could be your projection matrix. Keep in mind, that the parameters to frustum are in generic (3d world) units and not necessarily in pixels, so you should not take the same values you put into glViewport if you don't want the world units to represent pixels. So at the moment your image plane is (2*width)x(2*height) and your triangle occupies only a pixel (actually even less, due to perspective distortion). Try something like Matrix.frustumM(mPMatrix, 0, -1, 1, -1, 1, 3, 7) or use an equivalent to gluPerspective where you can just put in the desired viewing angle and the window's aspect ratio, which is much more natural than the direct frustum parameters.

EDIT: Just found the problem. In glGetUniformLocation you wrote mPMatrix instead of uPMatrix , so you never got a valid uniform location for the projection matrix. Strange that GL didn't throw an error on this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM