Android OpenGL ES 2 随机模型变形
Android OpenGL ES 2 Random Model Deformation
我已经将桌面 OpenGL 应用程序移植到 Android NDK(在 OpenGL ES 2 下),我的网格似乎随机变形。在大多数应用程序运行中,它看起来 100% 完美,但有时看起来如下:
问题的不一致性是我最关心的。不知道是我的Android模拟器的问题,还是别的原因。通过我的测试,我可以确定它是:
- 一个 OpenGL 设置,在 Android 上表现不佳,但在其他所有方面都表现出色
- Open Asset Import Library (Assimp) 中的一个错误,我手工编译了它来处理 Android
- Android 模拟器中的错误
我的模型流程如下:
每次开奖:
- bind the program
- change the uniforms
- if (has vao support)
- bind vao
- enable all vertex attribute arrays
- for every mesh
- bind array buffer
- set the attribute pointer for each vertex array
- bind element buffer
- bind texture & set uniform of texture location
- glDrawElements
- disable all vertex attribute arrays
这是实际代码:
glUseProgram(program_);
if (loaded_vao_)
{
#if !defined(TARGET_OS_IPHONE) && !defined(__ANDROID__)
glBindVertexArray(vao_);
#else
glBindVertexArrayOES(vao_);
#endif
}
glEnableVertexAttribArray(vPosition_);
glEnableVertexAttribArray(vTexCoord_);
glEnableVertexAttribArray(boneids_);
glEnableVertexAttribArray(weights_);
for (unsigned int i = 0; i < vbo_.size(); i++)
{
glBindBuffer(GL_ARRAY_BUFFER, vbo_[i]);
glVertexAttribPointer(vPosition_, 3, GL_FLOAT, GL_FALSE, 0, 0);
glVertexAttribPointer(vTexCoord_, 2, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void*>(texcoord_locations_[i]));
#if !defined(TARGET_OS_IPHONE) && !defined(__ANDROID__)
glVertexAttribIPointer(boneids_, 4, GL_INT, 0, reinterpret_cast<void*>(bone_id_locations_[i]));
#else // APPLE OR ANDROID
glVertexAttribPointer(boneids_, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void*>(bone_id_locations_[i]));
#endif
glVertexAttribPointer(weights_, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void*>(bone_weight_locations_[i]));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_[i]);
// Textures
if (!textures_.empty())
{
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textures_[texture_numbers_[i]]);
glUniform1i(textureSample_, 0);
}
glDrawElements(GL_TRIANGLES, ind_size_[i], GL_UNSIGNED_SHORT, 0);
}
glDisableVertexAttribArray(vPosition_);
glDisableVertexAttribArray(vTexCoord_);
glDisableVertexAttribArray(boneids_);
glDisableVertexAttribArray(weights_);
此外,我的顶点着色器如下所示:
precision mediump float;
attribute vec3 vPosition;
attribute vec2 vTexCoord;
attribute vec4 boneids;
attribute vec4 weights;
uniform mat4 pos;
uniform mat4 view;
uniform mat4 scale;
uniform mat4 rotate;
uniform mat4 proj;
uniform mat4 bones[50];
uniform int has_bones;
varying vec4 color;
varying vec2 texcoord;
void main()
{
color = vec4(1.0f);
texcoord = vTexCoord;
vec4 newPos = vec4(vPosition,1.0);
if (has_bones == 1)
{
mat4 bone_transform = bones[int(boneids[0])]*weights[0];
bone_transform += bones[int(boneids[1])]*weights[1];
bone_transform += bones[int(boneids[2])]*weights[2];
bone_transform += bones[int(boneids[3])]*weights[3];
newPos = bone_transform * newPos;
}
gl_Position = proj * view * pos * scale * rotate * newPos;
}
请注意,我已经尝试在顶点着色器中注释掉 bone_transform
,但问题仍然存在。
编辑:
看来我能够通过删除任何 assimp 优化 post 进程标志在我的 Linux OpenGL 3.3 版本上重新创建一些变形:
scene = importer.ReadFile(file_path.c_str(), aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_LimitBoneWeights | aiProcess_ValidateDataStructure);
根据 Assimp::DefaultLogger 的输出,没有错误或顶点警告。
问题似乎是 Blender 的 COLLADA 导出或 Assimp 的 COLLADA reader。
通过导出到 FBX 并使用 Autodesk 的免费 FBX 到 DAE 工具,变形得到修复。
- Blender 是 2.71 版
- Assimp 是版本 3.1.1
Assimp,即使启用了所有日志记录和数据完整性标志,也没有 post 任何关于损坏的错误,所以我不知道应该归咎于哪个组件。无论如何,我很高兴我找到了解决方法。
我已经将桌面 OpenGL 应用程序移植到 Android NDK(在 OpenGL ES 2 下),我的网格似乎随机变形。在大多数应用程序运行中,它看起来 100% 完美,但有时看起来如下:
问题的不一致性是我最关心的。不知道是我的Android模拟器的问题,还是别的原因。通过我的测试,我可以确定它是:
- 一个 OpenGL 设置,在 Android 上表现不佳,但在其他所有方面都表现出色
- Open Asset Import Library (Assimp) 中的一个错误,我手工编译了它来处理 Android
- Android 模拟器中的错误
我的模型流程如下:
每次开奖:
- bind the program
- change the uniforms
- if (has vao support)
- bind vao
- enable all vertex attribute arrays
- for every mesh
- bind array buffer
- set the attribute pointer for each vertex array
- bind element buffer
- bind texture & set uniform of texture location
- glDrawElements
- disable all vertex attribute arrays
这是实际代码:
glUseProgram(program_);
if (loaded_vao_)
{
#if !defined(TARGET_OS_IPHONE) && !defined(__ANDROID__)
glBindVertexArray(vao_);
#else
glBindVertexArrayOES(vao_);
#endif
}
glEnableVertexAttribArray(vPosition_);
glEnableVertexAttribArray(vTexCoord_);
glEnableVertexAttribArray(boneids_);
glEnableVertexAttribArray(weights_);
for (unsigned int i = 0; i < vbo_.size(); i++)
{
glBindBuffer(GL_ARRAY_BUFFER, vbo_[i]);
glVertexAttribPointer(vPosition_, 3, GL_FLOAT, GL_FALSE, 0, 0);
glVertexAttribPointer(vTexCoord_, 2, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void*>(texcoord_locations_[i]));
#if !defined(TARGET_OS_IPHONE) && !defined(__ANDROID__)
glVertexAttribIPointer(boneids_, 4, GL_INT, 0, reinterpret_cast<void*>(bone_id_locations_[i]));
#else // APPLE OR ANDROID
glVertexAttribPointer(boneids_, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void*>(bone_id_locations_[i]));
#endif
glVertexAttribPointer(weights_, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void*>(bone_weight_locations_[i]));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_[i]);
// Textures
if (!textures_.empty())
{
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textures_[texture_numbers_[i]]);
glUniform1i(textureSample_, 0);
}
glDrawElements(GL_TRIANGLES, ind_size_[i], GL_UNSIGNED_SHORT, 0);
}
glDisableVertexAttribArray(vPosition_);
glDisableVertexAttribArray(vTexCoord_);
glDisableVertexAttribArray(boneids_);
glDisableVertexAttribArray(weights_);
此外,我的顶点着色器如下所示:
precision mediump float;
attribute vec3 vPosition;
attribute vec2 vTexCoord;
attribute vec4 boneids;
attribute vec4 weights;
uniform mat4 pos;
uniform mat4 view;
uniform mat4 scale;
uniform mat4 rotate;
uniform mat4 proj;
uniform mat4 bones[50];
uniform int has_bones;
varying vec4 color;
varying vec2 texcoord;
void main()
{
color = vec4(1.0f);
texcoord = vTexCoord;
vec4 newPos = vec4(vPosition,1.0);
if (has_bones == 1)
{
mat4 bone_transform = bones[int(boneids[0])]*weights[0];
bone_transform += bones[int(boneids[1])]*weights[1];
bone_transform += bones[int(boneids[2])]*weights[2];
bone_transform += bones[int(boneids[3])]*weights[3];
newPos = bone_transform * newPos;
}
gl_Position = proj * view * pos * scale * rotate * newPos;
}
请注意,我已经尝试在顶点着色器中注释掉 bone_transform
,但问题仍然存在。
编辑:
看来我能够通过删除任何 assimp 优化 post 进程标志在我的 Linux OpenGL 3.3 版本上重新创建一些变形:
scene = importer.ReadFile(file_path.c_str(), aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_LimitBoneWeights | aiProcess_ValidateDataStructure);
根据 Assimp::DefaultLogger 的输出,没有错误或顶点警告。
问题似乎是 Blender 的 COLLADA 导出或 Assimp 的 COLLADA reader。
通过导出到 FBX 并使用 Autodesk 的免费 FBX 到 DAE 工具,变形得到修复。
- Blender 是 2.71 版
- Assimp 是版本 3.1.1
Assimp,即使启用了所有日志记录和数据完整性标志,也没有 post 任何关于损坏的错误,所以我不知道应该归咎于哪个组件。无论如何,我很高兴我找到了解决方法。