我正在尝试使用纹理渲染obj模型。这是我的工作:
model
和相应的视图矩阵view_mat
以及投影矩阵proj_mat
。proj_mat * view_mat * model
将3d模型投影到图像,这样我就可以在图像中为3d模型中的每个顶点获取uv坐标。Here是我得到的(左边是渲染结果),我认为我应该正确完成主要步骤,因为整体纹理看起来正确。但看起来三角形不处于旋转模式。
以下是我认为与纹理映射相关的代码部分。
int main() {
Tracker tracker;
tracker.set_image("clooney.jpg");
Viewer viewer(tracker.get_width(), tracker.get_height());
while (tracker.track()) {
Model* model = tracker.get_model();
glm::mat4x4 proj_mat = tracker.get_proj_mat();
proj_mat = glm::transpose(proj_mat);
glm::mat4x4 view_mat = tracker.get_view_mat();
view_mat = glm::transpose(view_mat);
// render 3d shape
viewer.set_model(model);
viewer.draw(view_mat, proj_mat);
waitKey(0);
}
return 0;
}
// initialization of the render part
Viewer::Viewer(int width, int height) {
glfwInit();
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
m_window = glfwCreateWindow(width, height, "demo", NULL, NULL);
if (!m_window)
{
fprintf(stderr, "Failed to open GLFW window\n");
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(m_window);
glfwGetWindowSize(m_window, &m_width, &m_height);
glfwSetFramebufferSizeCallback(m_window, reshape_callback);
gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);
glfwSwapInterval(1);
config();
}
void Viewer::config() {
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glDisable(GL_CULL_FACE);
glShadeModel(GL_FLAT);
}
// entry of the drawing function
void Viewer::draw(glm::mat4x4 view_mat, glm::mat4x4 proj_mat) {
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
proj_mat = glm::transpose(proj_mat);
glLoadMatrixf(&proj_mat[0][0]);
glMatrixMode(GL_MODELVIEW);
view_mat = glm::transpose(view_mat);
glLoadMatrixf(&view_mat[0][0]);
// m_pmodel is an instance of Model Class
// set texture
m_pmodel->set_texture(m_image);
// set model uvs
m_pmodel->set_uvs(view_mat, proj_mat);
m_pmodel->draw();
glfwSwapBuffers(m_window);
glfwPollEvents();
}
// set the texture for the model from the image
void Model::set_texture(cv::Mat img) {
glGenTextures(1, &m_texture);
glBindTexture(GL_TEXTURE_2D, m_texture);
glTexImage2D(GL_TEXTURE_2D, 0, 3, img.cols, img.rows, 0, GL_BGR, GL_UNSIGNED_BYTE, img.data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glGenerateMipmap(GL_TEXTURE_2D);
glEnable(GL_TEXTURE_2D);
}
// specify correspondence between image and the model
void Model::set_uvs(glm::mat4x4 view_mat, glm::mat4x4 proj_mat) {
for (int i = 0; i < m_uvs.size(); i++) {
glm::vec4 clip_coord = proj_mat * view_mat * glm::vec4(m_vertices[i], 1);
float w = clip_coord.w;
glm::vec3 normal_coord = glm::vec3(clip_coord.x, clip_coord.y, clip_coord.z) / w;
m_uvs[i] = glm::vec2(normal_coord.x * 0.5f + 0.5f, normal_coord.y * 0.5f + 0.5f);
}
}
// render the 3d model
void Model::draw() const {
glBindTexture(GL_TEXTURE_2D, m_texture);
for (unsigned long i = 0; i < m_faces.size(); ++i) {
glm::ivec3 face = this->m_faces[i];
glBegin(GL_TRIANGLES);
for (int j = 0; j < 3; j++) {
glm::vec3 v = this->m_vertices[face[j]];
glm::vec2 uv = this->m_uvs[face[j]];
glVertex3f(v.x, v.y, v.z);
glTexCoord2f(1 - uv.x,1 - uv.y);
}
glEnd();
}
}
答案 0 :(得分:1)
你需要设置当前纹理坐标(glTexCoord
)之前指定顶点(glVertex
),因为当前颜色,法线,纹理坐标和雾在调用glVertex
时,坐标与顶点相关联。
这意味着您必须交换glVertex3f
和glTexCoord2f
:
glTexCoord2f(1 - uv.x,1 - uv.y);
glVertex3f(v.x, v.y, v.z);
否则,您将设置与下一个顶点位置关联的纹理坐标。
见OpenGL 2.0 API Specification, 2.6 Begin/End Paradigm, page 13:
每个顶点用两个,三个或四个坐标指定。 此外,可以使用当前法线,多个当前纹理坐标设置,多个当前通用顶点属性,当前颜色,当前辅助颜色和当前雾坐标处理每个顶点。