![](/img/trans.png)
[英]Are OpenGL ES Vertex Array Objects supported in any Android Emulator?
[英]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.