Android 三角测量后 OpenGL UV 贴图错误

Android OpenGL UV mapping error after triangulating

我正在构建一个 Android 应用程序来渲染 3d (wavefront.obj) 模型。通过使用 tinyobjloader,我可以成功加载模型。

代码:

std::vector<glm::vec3> vertices;
std::vector<glm::vec2> uvs;
std::vector<glm::vec3> normals;

tinyobj::attrib_t attrib;
std::vector<tinyobj::shape_t> shapes;
std::vector<tinyobj::material_t> materials;
for(size_t s =0; s < shapes.size(); s++)
    {
        size_t index_offset = 0;
        for(size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++)
        {
            int fv = shapes[s].mesh.num_face_vertices[f];
            for(size_t v = 0; v < fv; v++)
            {
                tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v];
                tinyobj::real_t vx = attrib.vertices[3*idx.vertex_index+0];
                tinyobj::real_t vy = attrib.vertices[3*idx.vertex_index+1];
                tinyobj::real_t vz = attrib.vertices[3*idx.vertex_index+2];
                tinyobj::real_t nx = attrib.normals[3*idx.normal_index+0];
                tinyobj::real_t ny = attrib.normals[3*idx.normal_index+1];
                tinyobj::real_t nz = attrib.normals[3*idx.normal_index+2];
                tinyobj::real_t ux = attrib.texcoords[2*idx.texcoord_index+0];
                tinyobj::real_t uy = attrib.texcoords[2*idx.texcoord_index+1];
                vertices.push_back(glm::vec3(vx,vy,vz));
                normals.push_back(glm::vec3(nx,ny,nz));
                uvs.push_back(glm::vec2(ux,uy));
            }
            index_offset += fv;
        }
    }

因为原来的.obj文件是多面格式,即:

f 1/2/3 3/2/1 3/2/3
f 1/2/3 1/3/4 1/4/5 6/7/2

所以我使用带 'Beauty' 选项的 Blender Triangulate 将四边形转换为三角形。但是渲染出来的结果很奇怪

我已经为 initOpenGL(运行 一次)和 render() 构建了两个函数。

initOpenGL代码:

glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW);


glGenBuffers(1, &UVBO);
glBindBuffer(GL_ARRAY_BUFFER, UVBO);
glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(glm::vec2), &uvs[0], GL_STATIC_DRAW);

//Linking Vertex Attribute
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);

//bind texture
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, UVBO);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);

//load texture
//texture1
glGenTextures(1, &texture1);
glBindTexture(GL_TEXTURE_2D, texture1);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if(patternSrc1)
{

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, patWidth1, patHeight1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
                 patternSrc1);
    //glGenerateMipmap(GL_TEXTURE_2D);
}

渲染()代码:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shaderProgram);

camera.ProcessOneFinger(moveStpX, moveStpY);
camera.ProcessTwoFinger(move2X, move2Y);
projection = glm::perspective(camera.GetZoom(), (GLfloat)600/(GLfloat)1024, nearPlane, farPlane);
view = camera.GetViewMatrix();
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "view"), 1, GL_FALSE, glm::value_ptr(view));
glm::mat4 model;
model = glm::translate(model, glm::vec3(0.0f, 0.0f, 0.0f));
GLfloat angle = 20.0f;
model = glm::rotate(model, angle, glm::vec3( 1.0f, 0.3f, 0.5f));
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, glm::value_ptr( model ) );

glDrawArrays(GL_TRIANGLES, 0, vertices.size());

模型详情

质地:

Model.obj 三角化后的文件:

https://pastebin.com/vUjHv8Fr

谢谢!!!

在我看来,你的纹理是颠倒的。基本上有两种可能导致这种情况发生的潜在错误。最有可能的是,纹理图像本身是颠倒的,例如,因为传递给 glTexImage2D() 的图像数据顺序错误。与大多数其他 API 不同,OpenGL(默认情况下)期望像素数据按行顺序 从底行 开始。检查加载纹理数据的方式以确保其顺序正确。

如果这不是问题,则可能是您的纹理坐标适用于左手纹理坐标系。然而,OpenGL 使用右手纹理坐标,其中原点是纹理图像的左下角而不是左上角。我不是 Blender 的人,但可能有一个导出设置…