在OpenGL中使用glDrawArrays()绘制形状时,如何使用GLMATERIALV()设置材质属性

在OpenGL中使用glDrawArrays()绘制形状时,如何使用GLMATERIALV()设置材质属性,opengl,rendering,procedural,Opengl,Rendering,Procedural,我在glDrawArrays()之前调用glMaterialfv(),然后我将所有内容设置回默认值,但它似乎对我的材质没有任何影响。我知道glMaterial()应该在glBegin()和glEnd()之间调用,那么我如何不调用这些函数呢? 以下是我的渲染功能: glPushMatrix(); { glScalef(scale.x, scale.y, scale.z); glTranslatef(translate.x, translate.y, translate.z);

我在
glDrawArrays()
之前调用
glMaterialfv()
,然后我将所有内容设置回默认值,但它似乎对我的材质没有任何影响。我知道
glMaterial()
应该在
glBegin()
glEnd()
之间调用,那么我如何不调用这些函数呢? 以下是我的渲染功能:

 glPushMatrix(); {
    glScalef(scale.x, scale.y, scale.z);
    glTranslatef(translate.x, translate.y, translate.z);
    glRotatef(rot_angle, rotation.x, rotation.y, rotation.z);

    glEnableClientState(GL_VERTEX_ARRAY);
    //glEnableClientState(GL_COLOR_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    //glColorPointer(4, GL_FLOAT, 0, colors.data());
    glVertexPointer(3, GL_FLOAT, 0, verts.data());
    glNormalPointer(GL_FLOAT, 0, norms.data());
    glTexCoordPointer(2, GL_FLOAT, 0, texcoords.data());

    glMaterialfv(GL_FRONT, GL_AMBIENT, ambient.data());         // set ambient to what is defined in scene
    glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse.data());         // set diffuse to what is defined in scene
    glMaterialfv(GL_FRONT, GL_SPECULAR, specular.data());       // set specular to what is defined in scene
    glMaterialfv(GL_FRONT, GL_EMISSION, emission.data());       // set emission to what is defined in scene
    glMaterialfv(GL_FRONT, GL_SHININESS, shininess.data());     // set shininess to what is defined in scene

    glColor4f(R, G, B, A);
    glBindTexture(GL_TEXTURE_2D, *texture);
    glDrawArrays(primitive, 0, verts.size() / 3);
    glBindTexture(GL_TEXTURE_2D, NULL);
    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

    glMaterialfv(GL_FRONT, GL_AMBIENT, ambient_def);        // set ambient to default values
    glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse_def);        // set diffuse to default values
    glMaterialfv(GL_FRONT, GL_SPECULAR, specular_def);      // set specular to default values
    glMaterialfv(GL_FRONT, GL_EMISSION, emission_def);      // set emission to default values
    glMaterialfv(GL_FRONT, GL_SHININESS, shininess_def);    // set shininess to default value

    glDisableClientState(GL_VERTEX_ARRAY);
    //glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
} glPopMatrix();

首先,您在这里似乎主要使用不推荐的功能。我强烈建议学习OpenGL4,使用带有制服的着色器来实现所需的效果。为了回答您的问题,我认为您可能缺少光源的定义(请参见glLight()。或者,您也可以尝试实现一个着色器(相对于我前面提到的使用OpenGL4,这也更好)。在这种情况下,您可以完全控制最终颜色的外观,并避免与默认管道工作方式相关的花招。由于glBegin()/glEnd()表示绘制调用,因此不应在此类块中使用glMaterial()函数。事实上,glBegin()/glEnd()现在已经被彻底弃用了,它们永远不应该被用在新编写的程序中。是的,我听说过,但现在我试着用老方法来看看它是什么样子。我有我的光定义。它看起来像这样://Light 1 setLightAmbient(0.2,0.2,0.2,0.2,Light_Ambient_1);设置灯光漫反射(0.6,0.6,0.6,1,灯光漫反射1);//浅色设置lightposition(0,4,0,1,Light\u Position\u 1);setLightSpecular(0.5,0.5,0.5,1.0,Light_Specular_1);帧缓冲区与着色器不同。着色器最重要的任务是定义顶点如何变换(平移、缩放、旋转等),以及单个像素的颜色。它们本质上是在渲染几何体时在GPU上运行的小程序。我强烈建议您在这里通读这一页:帧缓冲区本质上是一个可以绘制到的“虚拟屏幕”,就像绘制到实际屏幕一样。不同之处在于,您绘制到备用帧缓冲区的内容不会立即显示在屏幕上。但是,它们的要点是,您可以使用生成的图像作为场景中的纹理。例如,如果要渲染浴室镜子,可以从镜子的角度将浴室渲染为纹理,然后将其显示在浴室墙上,使其看起来像是场景的反射。首先,您似乎主要使用了不推荐使用的功能。我强烈建议学习OpenGL4,使用带有制服的着色器来实现所需的效果。为了回答您的问题,我认为您可能缺少光源的定义(请参见glLight()。或者,您也可以尝试实现一个着色器(相对于我前面提到的使用OpenGL4,这也更好)。在这种情况下,您可以完全控制最终颜色的外观,并避免与默认管道工作方式相关的花招。由于glBegin()/glEnd()表示绘制调用,因此不应在此类块中使用glMaterial()函数。事实上,glBegin()/glEnd()现在已经被彻底弃用了,它们永远不应该被用在新编写的程序中。是的,我听说过,但现在我试着用老方法来看看它是什么样子。我有我的光定义。它看起来像这样://Light 1 setLightAmbient(0.2,0.2,0.2,0.2,Light_Ambient_1);设置灯光漫反射(0.6,0.6,0.6,1,灯光漫反射1);//浅色设置lightposition(0,4,0,1,Light\u Position\u 1);setLightSpecular(0.5,0.5,0.5,1.0,Light_Specular_1);帧缓冲区与着色器不同。着色器最重要的任务是定义顶点如何变换(平移、缩放、旋转等),以及单个像素的颜色。它们本质上是在渲染几何体时在GPU上运行的小程序。我强烈建议您在这里通读这一页:帧缓冲区本质上是一个可以绘制到的“虚拟屏幕”,就像绘制到实际屏幕一样。不同之处在于,您绘制到备用帧缓冲区的内容不会立即显示在屏幕上。但是,它们的要点是,您可以使用生成的图像作为场景中的纹理。例如,如果要渲染浴室镜子,可以从镜子的角度将浴室渲染为纹理,然后将其显示在浴室墙上,使其看起来是场景的反射。