簡體   English   中英

如何將代碼從頂點數組重構為頂點數組 Object 方法

[英]How to refactor code from Vertex Array to Vertex Array Object methods

我正在學習 Opengl,我一直在使用的書是 OpenGL(R) ES 3.0 Programming Guide, 2nd Edition。 在第 6 章,他們討論了 Vertex arrays,他們有一個使用 Vertex Array 方法的示例代碼,即下面的代碼。 在該章的后面,他們討論了頂點數組 Object,我想嘗試的是采用此示例代碼並將代碼重構為使用頂點數組 Object 方法的代碼。 問題是我不知道頂點數組 Object 是如何工作的,如果有人能把我推向正確的方向,我將不勝感激。

示例代碼在這里:

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 android.content.Context;
import android.opengl.GLES30;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import android.util.Log;

import se.hig.dvg306.modul3app.R;
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, 4, 6);
        } 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 / 4;

        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;

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

        // Load the vertex data from mVertices
        GLES30.glVertexAttribPointer ( 0, 4, GLES30.GL_FLOAT, false, 0, mVertices );



        // Assign vertex data to 'in' variable bound to attribute with index 0:
        GLES30.glEnableVertexAttribArray ( 0 );

        // Load the normal data from mNormals
        GLES30.glVertexAttribPointer ( 1, 4, GLES30.GL_FLOAT, false, 0, mNormals );
        // Assign normal data to 'in' variable bound to attribute with index 1:
        GLES30.glEnableVertexAttribArray ( 1 );

        GLES30.glDrawArrays (GLES30.GL_TRIANGLES, 0, nbrOfVertices);

        GLES30.glDisableVertexAttribArray ( 1 );
        GLES30.glDisableVertexAttribArray ( 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;

    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];

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

在過去的幾天里,我一直在嘗試了解如何編寫使用 Object 方法的代碼,但我無法理解它並決定詢問。 所以我希望通過詢問我可以了解如何開始。

當你想使用頂點數組 Object時,你必須創建並綁定 VAO。 頂點規范存儲在當前綁定的 VAO 的 state 向量中。 因此,綁定VAO時必須進行頂點指定。 我還建議將屬性放在Vertex Buffer Objects中:

int vao;
int vboVertices;
int vboNormals;
vao = GLES30.glGenVertexArray();
GLES30.glBindVertexArray(vao);

vboVertices = GLES30.glGenBuffer();
GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vboVertices);
GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, mVertices.remaining() * 4, mVertices, GLES30.GL_STATIC_DRAW);
GLES30.glVertexAttribPointer(0, 4, GLES30.GL_FLOAT, false, 0, 0);
GLES30.glEnableVertexAttribArray(0);

vboNormals = GLES30.glGenBuffer();
GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vboNormals);
GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, mNormals.remaining() * 4, mNormals, GLES30.GL_STATIC_DRAW);
GLES30.glVertexAttribPointer(1, 4, GLES30.GL_FLOAT, false, 0, 0);
GLES30.glEnableVertexAttribArray(1);

稍后您可以使用 VAO 繪制幾何圖形。 為此,綁定 VAO 就足夠了:

GLES30.glBindVertexArray(vao);
GLES30.glDrawArrays (GLES30.GL_TRIANGLES, 0, nbrOfVertices);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM