OpenGL材质未完全覆盖物体表面问题排查求助
OpenGL材质未完全覆盖物体面的问题
我正在为课程项目编写OpenGL材质相关代码,以下是初始测试代码:
glEnable(GL_COLOR_MATERIAL); glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,_selected_object->material.ambient); glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,_selected_object->material.diffuse); glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,_selected_object->material.specular); _selected_object->material.shininess=128.0f; glMaterialfv(GL_FRONT_AND_BACK,GL_SHININESS,_selected_object->material.shininess);
物体的渲染结果显示面未被材质完全覆盖,请问这是什么原因?
我设置的光源参数如下:
l->A1[0]=0.0; l->A1[1]=0.0; l->A1[2]=0.0; l->A1[3]=1.0; l->RDifusa[0]=1.0; l->RDifusa[1]=1.0; l->RDifusa[2]=1.0; l->RDifusa[3]=1.0; l->REspecular[0]=1.0; l->REspecular[1]=1.0; l->REspecular[2]=1.0; l->REspecular[3]=1.0; l->position[0]=1.0; l->position[1]=1.0; l->position[2]=1.0; l->position[3]=0.0;
初始化函数中启用光源的代码:
glEnable(GL_LIGHTING); glLightfv(GL_LIGHT0, GL_AMBIENT, l->A1); glLightfv(GL_LIGHT0, GL_DIFFUSE, l->RDifusa); glLightfv(GL_LIGHT0, GL_SPECULAR, l->REspecular); glLightfv(GL_LIGHT0, GL_POSITION, l->position); glEnable(GL_LIGHT0);
物体绘制代码:
while (aux_obj != 0) { glPushMatrix(); // glLoadIdentity(); glMultMatrixd(aux_obj->mtptr->M); /* Select the color, depending on whether the current object is the selected one or not */ if (aux_obj == _selected_object){ glColor3f(KG_COL_SELECTED_R,KG_COL_SELECTED_G,KG_COL_SELECTED_B); }else{ glColor3f(KG_COL_NONSELECTED_R,KG_COL_NONSELECTED_G,KG_COL_NONSELECTED_B); } /* Draw the object; for each face create a new polygon with the corresponding vertices */ //glLoadIdentity(); for (f = 0; f < aux_obj->num_faces; f++) { glBegin(GL_POLYGON); vector3 N,A,B,C,ABAC; for (v = 0; v < aux_obj->face_table[f].num_vertices; v++) { v_index = aux_obj->face_table[f].vertex_table[v]; glVertex3d(aux_obj->vertex_table[v_index].coord.x, aux_obj->vertex_table[v_index].coord.y, aux_obj->vertex_table[v_index].coord.z); } } glEnd(); glEnable(GL_COLOR_MATERIAL); glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,_selected_object->material.ambient); glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,_selected_object->material.diffuse); glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,_selected_object->material.specular); //Draw vertex normal vectors-> for(v=0;v<aux_obj->num_vertices;v++){ glBegin(GL_LINE); glVertex3d(aux_obj->vertex_table[v].coord.x,aux_obj->vertex_table[v].coord.y,aux_obj->vertex_table[v].coord.z); //Point A= vertex //Point B = A - 10000*D glVertex3d(aux_obj->vertex_table[v].coord.x+(aux_obj->vertex_table[v].normal.x),aux_obj->vertex_table[v].coord.y+(aux_obj->vertex_table[v].normal.y),aux_obj->vertex_table[v].coord.z+(aux_obj->vertex_table[v].normal.z)); glEnd(); } //Set object material values-> glPopMatrix(); aux_obj = aux_obj->next; }
问题原因及修正方案
1. 材质设置时机错误
OpenGL是状态机,绘制物体时使用的是当前状态下的材质参数。你现在的代码是在绘制完物体(glEnd()之后)才设置材质,参数无法影响之前的绘制结果。
2. GL_COLOR_MATERIAL的冲突
启用GL_COLOR_MATERIAL后,默认情况下glColor3f会直接覆盖材质的GL_DIFFUSE属性。你在绘制前调用了glColor3f,会把自定义的漫反射材质完全覆盖,导致材质不生效。
3. 缺少法线设置
OpenGL光照计算依赖法线向量确定面与光源的夹角,没有法线的话,光照计算会异常,部分面显示不正确的材质效果。
4. glEnd()位置错误
原代码中glEnd()放在面循环外,会导致所有面被合并成一个多边形,绘制逻辑错误,每个glBegin(GL_POLYGON)必须对应一个glEnd()。
修正后的核心代码示例
while (aux_obj != 0) { glPushMatrix(); glMultMatrixd(aux_obj->mtptr->M); // 先设置材质,再绘制 if (aux_obj == _selected_object){ // 关闭COLOR_MATERIAL,避免颜色覆盖自定义材质 glDisable(GL_COLOR_MATERIAL); glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,_selected_object->material.ambient); glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,_selected_object->material.diffuse); glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,_selected_object->material.specular); glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,128.0f); // SHININESS是单值,用glMaterialf }else{ // 非选中物体用颜色区分,启用COLOR_MATERIAL关联颜色与漫反射 glEnable(GL_COLOR_MATERIAL); glColor3f(KG_COL_NONSELECTED_R,KG_COL_NONSELECTED_G,KG_COL_NONSELECTED_B); } // 绘制每个面 for (f = 0; f < aux_obj->num_faces; f++) { glBegin(GL_POLYGON); vector3 N,A,B,C,AB,AC; // 计算并设置面法线(以三角形面为例) if(aux_obj->face_table[f].num_vertices >=3){ v_index = aux_obj->face_table[f].vertex_table[0]; A = aux_obj->vertex_table[v_index].coord; v_index = aux_obj->face_table[f].vertex_table[1]; B = aux_obj->vertex_table[v_index].coord; v_index = aux_obj->face_table[f].vertex_table[2]; C = aux_obj->vertex_table[v_index].coord; AB = B - A; AC = C - A; N = cross(AB, AC); N.normalize(); glNormal3f(N.x, N.y, N.z); } // 绘制顶点 for (v = 0; v < aux_obj->face_table[f].num_vertices; v++) { v_index = aux_obj->face_table[f].vertex_table[v]; // 若有顶点法线,可在此替换为glNormal3f(顶点法线) glVertex3d(aux_obj->vertex_table[v_index].coord.x, aux_obj->vertex_table[v_index].coord.y, aux_obj->vertex_table[v_index].coord.z); } glEnd(); // 每个面对应一个glEnd } // 绘制法线向量(保留原逻辑) for(v=0;v<aux_obj->num_vertices;v++){ glBegin(GL_LINE); glVertex3d(aux_obj->vertex_table[v].coord.x,aux_obj->vertex_table[v].coord.y,aux_obj->vertex_table[v].coord.z); glVertex3d(aux_obj->vertex_table[v].coord.x+aux_obj->vertex_table[v].normal.x, aux_obj->vertex_table[v].coord.y+aux_obj->vertex_table[v].normal.y, aux_obj->vertex_table[v].coord.z+aux_obj->vertex_table[v].normal.z); glEnd(); } glPopMatrix(); aux_obj = aux_obj->next; }
内容的提问来源于stack exchange,提问作者martqqqqq
相关产品推荐
相关产品推荐

