这可能看起来像一个愚蠢的问题,但我觉得我需要问它所以我能理解openGl缓冲如何工作。
我有两个缓冲区,顶点缓冲区和索引缓冲区。为了填充这些缓冲区,我正在解析一个obj文件。
解析数据后,我用我认为正确的数据和数据顺序填充缓冲区。
然而,当我调试代码时,我在缓冲区中看到了一些奇怪的东西。
首先是顶点缓冲区。我放在Vbuffer中的前三个值是 0.99,-0.99,-0.7741 但是当我通过逐步检查缓冲区来检查缓冲区时 -92,112,125 这是因为这是一个FloatBuffer但作为字节缓冲区?
this.vertexBuffer = ByteBuffer.allocateDirect(VertexList.length * mBytesPerFloat).order(ByteOrder.nativeOrder()).asFloatBuffer();
this.vertexBuffer.put(VertexList);
this.vertexBuffer.position(0);
我输入的索引缓冲区不同 4,1,2 当我检查它时,我似乎在每个值之间得到额外的0 4,0,1,0,2
this.IndexBuffer = ByteBuffer.allocateDirect(IndexList.length * 2).order(ByteOrder.nativeOrder()).asShortBuffer();
this.IndexBuffer.put(IndexList);
this.IndexBuffer.position(0);
在这个缓冲区中我可以将数据读取为ShortBuffer,即使它是一个字节缓冲区。 另外,为什么其他每个值都为0?
理解这一点的任何帮助都将受到赞赏。
UPDATE!
这是我完整的代码,用于解析obj文件中的数据并填充缓冲区。放入缓冲区的数据似乎是正确的。
public class RBLoadModelFromFile
{
/** How many bytes per float. */
private final int mBytesPerFloat = 4;
private Context context;
public FloatBuffer vertexBuffer;
public ShortBuffer IndexBuffer;
public float[] vertices;
public float[] normals;
public float[] uVs;
public short[] Ind;
private ArrayList<Short> indicies;
public int NumVertices;
public int NumIndicies;
public RBLoadModelFromFile(Context c)
{
context = c;
}
public void loadModel(String filename)
{
ArrayList<RBVector3> tempVertices = new ArrayList<RBVector3>();
ArrayList<RBVector3> tempNormals = new ArrayList<RBVector3>();
ArrayList<RBVector3> tempUVs = new ArrayList<RBVector3>();
ArrayList<Short> vertexIndices = new ArrayList<Short>();
ArrayList<Short> normalIndices = new ArrayList<Short>();
ArrayList<Short> textureIndices = new ArrayList<Short>();
indicies = new ArrayList<Short>();
try {
AssetManager manager = context.getAssets();
BufferedReader reader = new BufferedReader(new InputStreamReader(manager.open(filename)));
String line;
while ((line = reader.readLine()) != null)
{
if (line.startsWith("v "))
{
RBVector3 tempVert = new RBVector3(0f,0f,0f);
tempVert.add(Float.valueOf(line.split(" ")[2]),Float.valueOf(line.split(" ")[3]),Float.valueOf(line.split(" ")[4]));
tempVertices.add(tempVert);
}
else if (line.startsWith("vn"))
{
RBVector3 tempNorm = new RBVector3(0f,0f,0f);
tempNorm.add(Float.valueOf(line.split(" ")[1]),Float.valueOf(line.split(" ")[2]),Float.valueOf(line.split(" ")[3]));
tempNormals.add(tempNorm);
}
else if (line.startsWith("vt"))
{
RBVector3 tempUV = new RBVector3(0f,0f,0f);
tempUV.add(Float.valueOf(line.split(" ")[1]),Float.valueOf(line.split(" ")[2]), 0f);
tempUVs.add(tempUV);
}
else if (line.startsWith("f"))
{
String tmp[] = line.split(" ");
vertexIndices.add(Short.valueOf(tmp[1].split("/")[0]));
textureIndices.add(Short.valueOf(tmp[1].split("/")[1]));
normalIndices.add(Short.valueOf(tmp[1].split("/")[2]));
vertexIndices.add(Short.valueOf(tmp[2].split("/")[0]));
textureIndices.add(Short.valueOf(tmp[2].split("/")[1]));
normalIndices.add(Short.valueOf(tmp[2].split("/")[2]));
vertexIndices.add(Short.valueOf(tmp[3].split("/")[0]));
textureIndices.add(Short.valueOf(tmp[3].split("/")[1]));
normalIndices.add(Short.valueOf(tmp[3].split("/")[2]));
}
}
Ind = new short[vertexIndices.size() + normalIndices.size() + textureIndices.size()];
vertices = new float[(vertexIndices.size() * 3) + (normalIndices.size() * 3) + (textureIndices.size() * 2)];
ArrayList<Float> vertInfo = new ArrayList<Float>();
for (int i = 0; i < vertexIndices.size(); i++)
{
Short v = vertexIndices.get(i);
vertInfo.add(tempVertices.get(v-1).x);
vertInfo.add(tempVertices.get(v-1).y);
vertInfo.add(tempVertices.get(v-1).z);
indicies.add((short) (v-1));
Short n = normalIndices.get(i);
vertInfo.add(tempNormals.get(n-1).x);
vertInfo.add(tempNormals.get(n-1).y);
vertInfo.add(tempNormals.get(n-1).z);
indicies.add((short) (n-1));
Short t = textureIndices.get(i);
vertInfo.add(tempUVs.get(t-1).x);
vertInfo.add(tempUVs.get(t-1).y);
indicies.add((short) (t-1));
}
for(int i = 0; i < indicies.size(); i++)
{
Ind[i] = indicies.get(i);
}
for (int i = 0; i < vertInfo.size(); i++)
{
vertices[i] = vertInfo.get(i);
}
createIndexBuffer(Ind);
createVertexBuffer(vertices);
NumIndicies = Ind.length;
NumVertices = vertices.length;
}
catch (Exception e)
{
Log.d("DEBUG", "Error.", e);
}
}
private void createVertexBuffer(float[] VertexList)
{
this.vertexBuffer = ByteBuffer.allocateDirect(VertexList.length * mBytesPerFloat).order(ByteOrder.nativeOrder()).asFloatBuffer();
this.vertexBuffer.put(VertexList);
this.vertexBuffer.position(0);
}
private void createIndexBuffer(short[] IndexList)
{
this.IndexBuffer = ByteBuffer.allocateDirect(IndexList.length * 2).order(ByteOrder.nativeOrder()).asShortBuffer();
this.IndexBuffer.put(IndexList);
this.IndexBuffer.position(0);
}
}
这是一个简单的立方体obj文件,我试图解析
v -0.500000 -0.500000 0.500000
v 0.500000 -0.500000 0.500000
v -0.500000 0.500000 0.500000
v 0.500000 0.500000 0.500000
v -0.500000 0.500000 -0.500000
v 0.500000 0.500000 -0.500000
v -0.500000 -0.500000 -0.500000
v 0.500000 -0.500000 -0.500000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 0.000000 1.000000
vt 1.000000 1.000000
vn 0.000000 0.000000 1.000000
vn 0.000000 1.000000 0.000000
vn 0.000000 0.000000 -1.000000
vn 0.000000 -1.000000 0.000000
vn 1.000000 0.000000 0.000000
vn -1.000000 0.000000 0.000000
f 1/1/1 2/2/1 3/3/1
f 3/3/1 2/2/1 4/4/1
f 3/1/2 4/2/2 5/3/2
f 5/3/2 4/2/2 6/4/2
f 5/4/3 6/3/3 7/2/3
f 7/2/3 6/3/3 8/1/3
f 7/1/4 8/2/4 1/3/4
f 1/3/4 8/2/4 2/4/4
f 2/1/5 8/2/5 4/3/5
f 4/3/5 8/2/5 6/4/5
f 7/1/6 1/2/6 5/3/6
f 5/3/6 1/2/6 3/4/6
我现在正在画画,但顶点似乎已经过了。
这是我的绘图方法
public void DrawModel(float[] mProjectionMatrix, float[] mViewMatrix, float[] mMVPMatrix, int mProgramHandle, int mMVPMatrixHandle, int mMVMatrixHandle, int mLightPosHandle, float[] mLightPosInEyeSpace)
{
mPositionHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_Position");
mNormalHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_Normal");
mTextureUniformHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_Texture");
mTextureCoordinateHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_TexCoordinate");
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
// Bind the texture to this unit.
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataHandle);
// Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 0.
GLES20.glUniform1i(mTextureUniformHandle, 0);
// This multiplies the view matrix by the model matrix, and stores the result in the MVP matrix
// (which currently contains model * view).
Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
// Pass in the modelview matrix.
GLES20.glUniformMatrix4fv(mMVMatrixHandle, 1, false, mMVPMatrix, 0);
// This multiplies the modelview matrix by the projection matrix, and stores the result in the MVP matrix
// (which now contains model * view * projection).
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
// Pass in the combined matrix.
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
// Pass in the light position in eye space.
GLES20.glUniform3f(mLightPosHandle, mLightPosInEyeSpace[0], mLightPosInEyeSpace[1], mLightPosInEyeSpace[2]);
// the vertex coordinates
VertexBuffer.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT, false,
TRIANGLE_VERTICES_DATA_STRIDE_BYTES, VertexBuffer);
GLES20.glEnableVertexAttribArray(mPositionHandle);
// the normal info
VertexBuffer.position(TRIANGLE_VERTICES_DATA_NOR_OFFSET);
GLES20.glVertexAttribPointer(mNormalHandle, 3, GLES20.GL_FLOAT, false,
TRIANGLE_VERTICES_DATA_STRIDE_BYTES, VertexBuffer);
GLES20.glEnableVertexAttribArray(mNormalHandle);
// texture coordinates
VertexBuffer.position(TRIANGLE_VERTICES_DATA_TEX_OFFSET);
GLES20.glVertexAttribPointer(mTextureCoordinateHandle, 2, GLES20.GL_FLOAT, false,
TRIANGLE_VERTICES_DATA_STRIDE_BYTES, VertexBuffer);
GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle);//GLES20.glEnableVertexAttribArray(shader.maTextureHandle);
// Draw with indices
GLES20.glDrawElements(GLES20.GL_TRIANGLES, NumIndicies , GLES20.GL_UNSIGNED_SHORT, IndexBuffer);
//checkGlError("glDrawElements");
}
答案 0 :(得分:1)
没有完整的代码来判断问题的位置是相当复杂的。
在我看来,您正在使用混合数据类型。
浮点数相当棘手,如果不将它们作为浮点数处理,则无法轻易“读取”浮点存储单元的内容。
Float,根据标准是基于3个不同的组件,位符号(最有意义的),指数和尾数。
通常是浮点数,现在最常见的平台用32位(4字节)表示,其中:
1为标志 指数为8位 尾数为23位(通常是打包的,但这将是一个很长的讨论)
如果你没有“读取”或“写”一个浮点数作为一个浮点数(有些方法可以处理整数浮点作为整数知道它们的属性,但这会有太大的偏离性)你以不可预测的方式解释它们的风险。 / p>
我的建议是将这些值读/写为float,不要以读/写操作的字节/整数方式进行。
答案 1 :(得分:0)
好的,我终于设法解决了渲染问题。我非常感谢@MaurizioBenedetti评论并回答了我的一些问题,这些问题帮助我了解了我的情况。
首先,我在缓冲区中放入的内容在某种程度上是正确的。我的问题来了,因为我创建了一个交错的顶点缓冲区 - 这意味着数据已经按正确的顺序VVVNNNTT。然后我去创建了索引缓冲区,其中包含实际的索引数据,这是无交错缓冲区的指示
例如,如果面包含2/4/6 4/7/9 2/1/3,那么我的索引缓冲区包含这些确切的值,但因为我的顶点缓冲区是交错的,所以它应该包含一个有序列表的数量indicies。
所以这意味着如果上面的面是唯一的指标,那么索引缓冲区应该包含 0,1,2,3,4,5,6,7,8
在我填充顶点信息时总结上面的代码
我应该说过这样的话
indicies.add(index++);
而不是分配每个标记值
我希望对于那些坚持这种事情并希望有所帮助的人来说这是明确的。