简体   繁体   English

为什么我的代码在 opengl 中没有显示在顶点数组 object 的手机模拟器上

[英]Why is my code not displaying on phone emulator with vertex array object in opengl

I'm new to this but what I'm trying to do is using vertex array object to display something on a phone emulator.我是新手,但我想做的是使用顶点数组 object 在手机模拟器上显示一些东西。 But the problem is that it isn't displaying anything on the phone.但问题是它没有在手机上显示任何内容。 What I have understood of using vertex array objects is that a VAO is something like a folder that can points to different buffers and inside the VAO there is vertex buffer objects.我对使用顶点数组对象的理解是,VAO 类似于一个文件夹,可以指向不同的缓冲区,并且在 VAO 内部有顶点缓冲区对象。 What I have done in the code is create two buffers and a VAO.我在代码中所做的是创建两个缓冲区和一个 VAO。 Bind the buffers to an array called mVBOIds.将缓冲区绑定到名为 mVBOIds 的数组。 Then bind the VAO to it's own array then i setup the vertex with the buffers.然后将 VAO 绑定到它自己的数组,然后我使用缓冲区设置顶点。

To populate these buffers I have a file named torus2.raw that has data that looks like this:为了填充这些缓冲区,我有一个名为 torus2.raw 的文件,其中包含如下所示的数据:

# Data order:
# Vertex
# Normal vector
# Texture coordinate
12.329425 0.0 -8.957851 1.0
-0.809017 1.0E-6 0.587785 0.0
0.05 1.0

Where we have the order of data, Vertex has 4 data, Normal Vector has 4 and then Texture coordinate has 2 data.我们有数据的顺序,顶点有 4 个数据,法向量有 4 个,然后纹理坐标有 2 个数据。

Here is the code for that part that creates the buffers and VAO and its inside the method onSurfaceCreated:这是创建缓冲区和 VAO 的那部分代码及其在 onSurfaceCreated 方法中的代码:

        // Generate VBO Ids and load the VBOs with data
        GLES30.glGenBuffers ( 2, mVBOIds, 0 );

        GLES30.glBindBuffer ( GLES30.GL_ARRAY_BUFFER, mVBOIds[0] );
        mVertices.position ( 0 );
        GLES30.glBufferData ( GLES30.GL_ARRAY_BUFFER, mVertices.remaining() * 4,
                mVertices, GLES30.GL_STATIC_DRAW );

        GLES30.glBindBuffer ( GLES30.GL_ELEMENT_ARRAY_BUFFER, mVBOIds[1] );
        mNormals.position ( 0 );
        GLES30.glBufferData ( GLES30.GL_ELEMENT_ARRAY_BUFFER, 4 * mNormals.remaining(),
                mNormals, GLES30.GL_STATIC_DRAW );

        // Generate VAO Id
        GLES30.glGenVertexArrays ( 1, mVAOId, 0 );

        // Bind the VAO and then setup the vertex
        // attributes
        GLES30.glBindVertexArray ( mVAOId[0] );

        GLES30.glBindBuffer ( GLES30.GL_ARRAY_BUFFER, mVBOIds[0] );
        GLES30.glBindBuffer ( GLES30.GL_ELEMENT_ARRAY_BUFFER, mVBOIds[1] );

        GLES30.glEnableVertexAttribArray (VERTEX_POS_INDX);
        GLES30.glEnableVertexAttribArray (VERTEX_NORM_INDX);

        GLES30.glVertexAttribPointer ( VERTEX_POS_INDX, VERTEX_POS_SIZE,
                GLES30.GL_FLOAT, false, VERTEX_STRIDE,
                0 );

        GLES30.glVertexAttribPointer (VERTEX_NORM_INDX, VERTEX_NORM_SIZE,
                GLES30.GL_FLOAT, false, VERTEX_STRIDE,
                ( VERTEX_POS_SIZE * 4 ) );

        // Reset to the default VAO
        GLES30.glBindVertexArray ( 0 );

        GLES30.glClearColor ( 0.15f, 0.15f, 0.15f, 1.0f );
        GLES30.glEnable(GLES30.GL_DEPTH_TEST);

After this when I have the buffer and VAO setup, I use onDrawFrame method to get it to show in display:在此之后,当我设置了缓冲区和 VAO 时,我使用 onDrawFrame 方法让它显示在显示器中:

    public void onDrawFrame ( GL10 glUnused )
    {
        // Initiate the model-view matrix as identity matrix
        Matrix.setIdentityM(mViewMatrix, 0);

        // Define a translation transformation
        Matrix.translateM(mViewMatrix, 0, 0.0f, 0.0f, -60.0f);
        // Define a rotation transformation
        Matrix.rotateM(mViewMatrix, 0, 90.0f, 1.0f, 0.0f, 0.0f);

        // Calculate the model-view and projection transformation as composite transformation
        Matrix.multiplyMM (mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);

        // Clear the color buffer
        GLES30.glClear ( GLES30.GL_COLOR_BUFFER_BIT | GLES30.GL_DEPTH_BUFFER_BIT );

        // Use the program object
        GLES30.glUseProgram ( mProgramObject );

        // Make MVP matrix accessible in the vertex shader
        mMVPMatrixHandle = GLES30.glGetUniformLocation(mProgramObject, "uMVPMatrix");
        GLES30.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);

        // Light position:
        vLightPositionHandle = GLES30.glGetUniformLocation(mProgramObject, "vLightPosition");
        GLES30.glUniform4fv(vLightPositionHandle, 1, lightPosition, 0);

        // Light color:
        vLightColorDfHandle = GLES30.glGetUniformLocation(mProgramObject, "vLightColorDf");
        GLES30.glUniform4fv(vLightColorDfHandle, 1, lightColorDf, 0);

        // Material color:
        vMaterialColorDfHandle = GLES30.glGetUniformLocation(mProgramObject, "vMaterialColorDf");
        GLES30.glUniform4fv(vMaterialColorDfHandle, 1, materialColorDf, 0);

        GLES30.glBindVertexArray ( mVAOId[0] );

        // Draw with the VAO settings
        GLES30.glDrawElements ( GLES30.GL_TRIANGLES, mNormals.remaining(), GLES30.GL_UNSIGNED_SHORT, 0 );

        // Return to the default VAO
        GLES30.glBindVertexArray ( 0 );
    }

But the problem is that I can't get anything to display.但问题是我无法显示任何内容。 I've tried to double check the variabels, check if if the variabels are empty etc but I could not find the culprit.我试图仔细检查变量,检查变量是否为空等,但我找不到罪魁祸首。 It could also be that I've understood the code differently and made a logical error but I can't see what it is.也可能是我对代码的理解不同并犯了逻辑错误,但我看不到它是什么。 The result should be a blue-ish donut shaped model.结果应该是一个蓝色的甜甜圈形状 model。

This is the whole code:这是整个代码:

    import android.content.Context;
    import android.opengl.GLES30;
    import android.opengl.GLSurfaceView;
    import android.opengl.Matrix;
    import android.util.Log;

    import java.io.IOException;
    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 se.hig.dvg306.modul3app.tools.ResourceHandler;

    public class Modul3Renderer implements GLSurfaceView.Renderer
    {
    //
    // Constructor - loads model data from a res file and creates byte buffers for
    // vertex data and for normal data
    //
    public Modul3Renderer (Context context)
    {
        appContext = context;

        Log.e(TAG, "--->>>      Creating ModelLoader...");
        ModelLoader modelLoader = new ModelLoaderImpl ();
        Log.e(TAG, "--->>>      ...finished.");

        Log.e(TAG, "--->>>      Loading model...");
        Log.e(TAG, "--->>>      Starting with vertices...");
        float[] mVerticesData; //= new float[0];

        try {
            mVerticesData = modelLoader.loadModel (context, R.raw.torus2, 0, 10, 0);
        } catch (IOException e) {
            throw new RuntimeException (e);
        }
        Log.e(TAG, "--->>>      ...finished.");

        // Process vertex data
        // 4: because of 4 elements per vertex position
        nbrOfVertices = mVerticesData.length / 10;

        mVertices = ByteBuffer.allocateDirect(mVerticesData.length * 4)
                .order(ByteOrder.nativeOrder()).asFloatBuffer();
        mVertices.put(mVerticesData).position(0);

        Log.e(TAG, "--->>>      Starting with normals...");
        float[] mNormalData; //= new float[0];

        try {
            mNormalData = modelLoader.loadModel (context, R.raw.torus2, 4, 4, 6);
        } catch (IOException e) {
            throw new RuntimeException (e);
        }
        Log.e(TAG, "--->>>      ...finished.");

        // Process normal data
        // 4: because of 4 elements per vertex position
        nbrOfNormals = mNormalData.length / 4;

        mNormals = ByteBuffer.allocateDirect(mNormalData.length * 4)
                .order(ByteOrder.nativeOrder()).asFloatBuffer();
        mNormals.put(mNormalData).position(0);
    }

    ///
    // Create a shader object, load the shader source, and
    // compile the shader.
    //
    private int createShader(int type, String shaderSrc )
    {
        int shader;
        int[] compiled = new int[1];

        // Create the shader object
        shader = GLES30.glCreateShader ( type );

        if ( shader == 0 )
        {
            return 0;
        }

        // Load the shader source
        GLES30.glShaderSource ( shader, shaderSrc );

        // Compile the shader
        GLES30.glCompileShader ( shader );

        // Check the compile status
        GLES30.glGetShaderiv ( shader, GLES30.GL_COMPILE_STATUS, compiled, 0 );

        if ( compiled[0] == 0 )
        {
            Log.e ( TAG, GLES30.glGetShaderInfoLog ( shader ) );
            GLES30.glDeleteShader ( shader );
            return 0;
        }

        return shader;
    }

    ///
    // Initialize the shader and program object
    //
    public void onSurfaceCreated ( GL10 glUnused, EGLConfig config )
    {
        int vertexShader;
        int fragmentShader;
        int programObject;
        int[] linked = new int[1];


        // Load the source code for the vertex shader program from a res file:
        try {
            vShaderStr = ResourceHandler.readTextData(appContext, R.raw.vertex_shader);
        } catch (IOException e) {
            Log.e ( TAG, "--->>>      Could not load source code for vertex shader.");
            throw new RuntimeException (e);
        }
        Log.e ( TAG, "--->>>      Loaded vertex shader: " + vShaderStr);

        // Load the source code for the fragment shader program from a res file:
        try {
            fShaderStr = ResourceHandler.readTextData(appContext, R.raw.fragment_shader);
        } catch (IOException e) {
            Log.e ( TAG, "--->>>      Could not load source code for fragment shader.");
            throw new RuntimeException (e);
        }
        Log.e ( TAG, "--->>>      Loaded fragment shader: " + fShaderStr);

        // Create the vertex/fragment shaders
        vertexShader = createShader( GLES30.GL_VERTEX_SHADER, vShaderStr );
        fragmentShader = createShader( GLES30.GL_FRAGMENT_SHADER, fShaderStr );

        // Create the program object
        programObject = GLES30.glCreateProgram();

        if ( programObject == 0 )
        {
            return;
        }

        GLES30.glAttachShader ( programObject, vertexShader );
        GLES30.glAttachShader ( programObject, fragmentShader );

        // Bind vPosition to attribute 0
        GLES30.glBindAttribLocation ( programObject, 0, "vPosition" );

        // Bind vNormal to attribute 1
        GLES30.glBindAttribLocation ( programObject, 1, "vNormal" );

        // Link the program
        GLES30.glLinkProgram ( programObject );

        // Check the link status
        GLES30.glGetProgramiv ( programObject, GLES30.GL_LINK_STATUS, linked, 0 );

        if ( linked[0] == 0 )
        {
            Log.e ( TAG, "Error linking program:" );
            Log.e ( TAG, GLES30.glGetProgramInfoLog ( programObject ) );
            GLES30.glDeleteProgram ( programObject );
            return;
        }

        // Store the program object
        mProgramObject = programObject;

        // Generate VBO Ids and load the VBOs with data
        GLES30.glGenBuffers ( 2, mVBOIds, 0 );

        GLES30.glBindBuffer ( GLES30.GL_ARRAY_BUFFER, mVBOIds[0] );
        mVertices.position ( 0 );
        GLES30.glBufferData ( GLES30.GL_ARRAY_BUFFER, mVertices.remaining() * 4,
                mVertices, GLES30.GL_STATIC_DRAW );

        GLES30.glBindBuffer ( GLES30.GL_ELEMENT_ARRAY_BUFFER, mVBOIds[1] );
        mNormals.position ( 0 );
        GLES30.glBufferData ( GLES30.GL_ELEMENT_ARRAY_BUFFER, 4 * mNormals.remaining(),
                mNormals, GLES30.GL_STATIC_DRAW );

        // Generate VAO Id
        GLES30.glGenVertexArrays ( 1, mVAOId, 0 );

        // Bind the VAO and then setup the vertex
        // attributes
        GLES30.glBindVertexArray ( mVAOId[0] );

        GLES30.glBindBuffer ( GLES30.GL_ARRAY_BUFFER, mVBOIds[0] );
        GLES30.glBindBuffer ( GLES30.GL_ELEMENT_ARRAY_BUFFER, mVBOIds[1] );

        GLES30.glEnableVertexAttribArray (VERTEX_POS_INDX);
        GLES30.glEnableVertexAttribArray (VERTEX_NORM_INDX);

        GLES30.glVertexAttribPointer ( VERTEX_POS_INDX, VERTEX_POS_SIZE,
                GLES30.GL_FLOAT, false, VERTEX_STRIDE,
                0 );

        GLES30.glVertexAttribPointer (VERTEX_NORM_INDX, VERTEX_NORM_SIZE,
                GLES30.GL_FLOAT, false, VERTEX_STRIDE,
                ( VERTEX_POS_SIZE * 4 ) );

        // Reset to the default VAO
        GLES30.glBindVertexArray ( 0 );

        GLES30.glClearColor ( 0.15f, 0.15f, 0.15f, 1.0f );
        GLES30.glEnable(GLES30.GL_DEPTH_TEST);
    }

    //
    // Draw a torus using the shader pair created in onSurfaceCreated()
    //
    public void onDrawFrame ( GL10 glUnused )
    {
        // Initiate the model-view matrix as identity matrix
        Matrix.setIdentityM(mViewMatrix, 0);

        // Define a translation transformation
        Matrix.translateM(mViewMatrix, 0, 0.0f, 0.0f, -60.0f);
        // Define a rotation transformation
        Matrix.rotateM(mViewMatrix, 0, 90.0f, 1.0f, 0.0f, 0.0f);

        // Calculate the model-view and projection transformation as composite transformation
        Matrix.multiplyMM (mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);

        // Clear the color buffer
        GLES30.glClear ( GLES30.GL_COLOR_BUFFER_BIT | GLES30.GL_DEPTH_BUFFER_BIT );

        // Use the program object
        GLES30.glUseProgram ( mProgramObject );

        // Make MVP matrix accessible in the vertex shader
        mMVPMatrixHandle = GLES30.glGetUniformLocation(mProgramObject, "uMVPMatrix");
        GLES30.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);

        // Light position:
        vLightPositionHandle = GLES30.glGetUniformLocation(mProgramObject, "vLightPosition");
        GLES30.glUniform4fv(vLightPositionHandle, 1, lightPosition, 0);

        // Light color:
        vLightColorDfHandle = GLES30.glGetUniformLocation(mProgramObject, "vLightColorDf");
        GLES30.glUniform4fv(vLightColorDfHandle, 1, lightColorDf, 0);

        // Material color:
        vMaterialColorDfHandle = GLES30.glGetUniformLocation(mProgramObject, "vMaterialColorDf");
        GLES30.glUniform4fv(vMaterialColorDfHandle, 1, materialColorDf, 0);

        GLES30.glBindVertexArray ( mVAOId[0] );

        // Draw with the VAO settings
        GLES30.glDrawElements ( GLES30.GL_TRIANGLES, mNormals.remaining(), GLES30.GL_UNSIGNED_SHORT, 0 );

        // Return to the default VAO
        GLES30.glBindVertexArray ( 0 );
    }

    //
    // Handle surface changes
    //
    public void onSurfaceChanged ( GL10 glUnused, int width, int height )
    {
        mWidth = width;
        mHeight = height;

        GLES30.glViewport(0, 0, width, height);

        float ratio = (float) width / height;

        // this projection matrix is applied to object coordinates
        Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1.0f, 1.0f, 0.5f, 1000.0f);
    }

    // Member variables

    private Context appContext;

    private int mWidth;
    private int mHeight;

    private int nbrOfVertices;
    private FloatBuffer mVertices;

    final int VERTEX_POS_SIZE   = 4; // x, y and z
    final int VERTEX_NORM_SIZE = 4; // r, g, b, and a

    final int VERTEX_POS_INDX   = 0;
    final int VERTEX_NORM_INDX = 1;

    private int [] mVBOIds = new int[2];
    private int [] mVAOId = new int[1];

    private int nbrOfNormals;
    private FloatBuffer mNormals;

    private int mProgramObject;
    private int mMVPMatrixHandle;

    // Transformation data:
    private final float[] mMVPMatrix = new float[16];
    private final float[] mProjectionMatrix = new float[16];
    private final float[] mViewMatrix = new float[16];

    final int VERTEX_STRIDE = ( 4 * ( VERTEX_POS_SIZE +  VERTEX_NORM_SIZE ) );

    // Light position and color (only diffuse term now):
    private int vLightPositionHandle;
    private final float lightPosition [] = {175.0f, 75.0f, 125.0f, 0.0f};
    // Light color (only diffuse term now):
    private int vLightColorDfHandle;
    private final float lightColorDf [] = {0.98f, 0.98f, 0.98f, 1.0f};
    // Material color (only diffuse term now):
    private int vMaterialColorDfHandle;
    private final float materialColorDf [] = {0.62f, 0.773f, 0.843f, 1.0f};

    // To be read when creating the instance:
    private String vShaderStr;
    private String fShaderStr;

    private static String TAG = "Modul3Renderer";
    }

A GL_ELEMENT_ARRAY_BUFFER object is meant for the indices and should conitain integral data. GL_ELEMENT_ARRAY_BUFFER object 用于索引,应包含完整数据。 You should use a GL_ARRAY_BUFFER for the normal vectors:您应该为法向量使用GL_ARRAY_BUFFER

GLES30.glBindBuffer ( GLES30.GL_ARRAY_BUFFER, mVBOIds[1] );
        mNormals.position ( 0 );
GLES30.glBufferData ( GLES30.GL_ARRAY_BUFFER, 4 * mNormals.remaining(),
        mNormals, GLES30.GL_STATIC_DRAW );

When glVertexAttribPointer is called the buffer which is currently bound to the target ARRAY_BUFFER , is associated to the specified attribute index and the ID of the object is stored in the state vector of the currently bound VAO.当调用glVertexAttribPointer时,当前绑定到目标ARRAY_BUFFER的缓冲区与指定的属性索引相关联,并且 object 的 ID 存储在当前绑定的 VAO 的 state 向量中。 So you have to bind the buffer object before calling glVertexAttribPointer :所以你必须在调用glVertexAttribPointer之前绑定缓冲区 object :

GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, mVBOIds[0]);
GLES30.glVertexAttribPointer ( VERTEX_POS_INDX, VERTEX_POS_SIZE,
                GLES30.GL_FLOAT, false, VERTEX_STRIDE,
                0 );

GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, mVBOIds[1]);
GLES30.glVertexAttribPointer (VERTEX_NORM_INDX, VERTEX_NORM_SIZE,
                GLES30.GL_FLOAT, false, VERTEX_STRIDE,
                ( VERTEX_POS_SIZE * 4 ) );

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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