繁体   English   中英

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

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

我是新手,但我想做的是使用顶点数组 object 在手机模拟器上显示一些东西。 但问题是它没有在手机上显示任何内容。 我对使用顶点数组对象的理解是,VAO 类似于一个文件夹,可以指向不同的缓冲区,并且在 VAO 内部有顶点缓冲区对象。 我在代码中所做的是创建两个缓冲区和一个 VAO。 将缓冲区绑定到名为 mVBOIds 的数组。 然后将 VAO 绑定到它自己的数组,然后我使用缓冲区设置顶点。

为了填充这些缓冲区,我有一个名为 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

我们有数据的顺序,顶点有 4 个数据,法向量有 4 个,然后纹理坐标有 2 个数据。

这是创建缓冲区和 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);

在此之后,当我设置了缓冲区和 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 );
    }

但问题是我无法显示任何内容。 我试图仔细检查变量,检查变量是否为空等,但我找不到罪魁祸首。 也可能是我对代码的理解不同并犯了逻辑错误,但我看不到它是什么。 结果应该是一个蓝色的甜甜圈形状 model。

这是整个代码:

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

GL_ELEMENT_ARRAY_BUFFER object 用于索引,应包含完整数据。 您应该为法向量使用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 );

当调用glVertexAttribPointer时,当前绑定到目标ARRAY_BUFFER的缓冲区与指定的属性索引相关联,并且 object 的 ID 存储在当前绑定的 VAO 的 state 向量中。 所以你必须在调用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