glUseProgram 不影响渲染状态

glUseProgram unaffecting the rendering state

本文关键字:状态 影响 glUseProgram      更新时间:2023-10-16

我正在使用 ubuntu 13 上的 GL 编写一个基本的视图管理器,并使用 nvidia ION2 编写 eeepc(使用 bumblebee 项目的 optimus)。我有一个XML文件,当系统启动时,从中创建着色器(如插件)并将其添加到字典中。一旦这些被编译和链接并准备好使用,包装器函数就会使用一个包装器函数根据传递的程序名称选择适当的着色器程序。

void ShadingProgramManager::useProgram(const std::string& program){
    GLuint id = getProgramId(program);
    glUseProgram(id);
    if(GL_INVALID_VALUE == glGetError() || GL_INVALID_OPERATION == glGetError()){
        printf("Problem Loading Shader Program");
        return;
    }
    printf("%s is in use", program.c_str());
}

其中 getProgramId 只是查看预先创建的字典并返回着色器程序的 id。

当我渲染对象时,我通过调用以下命令来使用程序:

ShadingProgramManager::getInstance()->useProgram('vc');

"VC"由以下着色器组成

顶点着色器 - vc.vert

#version 330
layout(location = 0) in vec3 position;
layout(location = 1) in vec4 color;
out vec4 vertcolor;
void main(){
    vertcolor = color;
    gl_Position = vec4(position, 1.0);   //I've tried setting this as position * 10 also for any apparent changes on screen, but nothing changes
}

片段着色器 - vc.frag:

#version 330
in vec4 vertcolor;
out vec4 outputcolor;
void main(){
    outputcolor = vertcolor;
}

我的顶点缓冲区交错为:

VertexColor vertices[] = 
{
    {-1.0, -1.0, 0.0, 1.0, 1.0, 1.0, 1.0},  /*first 3 floats for pos, 4 for color */
    { 1.0, -1.0, 0.0, 1.0, 0.0, 0.0, 1.0},
    { 1.0,  1.0, 0.0, 0.0, 1.0, 0.0, 1.0},
    {-1.0,  1.0, 0.0, 0.0, 0.0, 1.0, 1.0},
};

索引缓冲区为:

GLuint indices[] = 
{
    0, 1, 2,
    0, 2, 3,
};

顶点颜色定义为:

class VertexColor{
    GLfloat x;
    GLfloat y;
    GLfloat z;
    GLfloat r;
    GLfloat g;
    GLfloat b;
    GLfloat a;
    /** some constants as below **/
};
const int VertexColor::OFFSET_POSITION =0;
const int VertexColor::OFFSET_COLOR =12;
const int VertexColor::SIZE_POSITION =3;
const int VertexColor::SIZE_COLOR =4;
const int VertexColor::STRIDE =28;

然后我使用以下代码来呈现四边形:

ShadingProgramManager::getInstance()->useProgram('vc');
glBindBuffer(GL_ARRAY_BUFFER, &vb);
glBufferData(GL_ARRAY_BUFFER, size_of_vertices_array, vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, &ib);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, size_of_indices_array, indices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribArrayPointer(0, VertexColor::SIZE_POSITION, GL_FLOAT, GL_FALSE, VertexColor::STRIDE, (GLvoid*)VertexColor::OFFSET_POSITION);
glVertexAttribArrayPointer(1, VertexColor::SIZE_COLOR, GL_FLOAT, GL_FALSE, VertexColor::STRIDE, (GLvoid*)VertexColor::OFFSET_COLOR);
glDrawElements(GL_TRIANGLES, size_of_indices, GL_UNSIGNED_INT, 0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);

但是,我只看到一个白色的四边形。我怀疑是固定的函数管道生效。

即使我删除了对 glUseProgram(id) 的调用或使用 glUseProgram(0),我仍然得到相同的结果。我还尝试将顶点着色器中的位置乘以 10.0,但对屏幕没有影响。我相信着色器也在编译和链接。当我更改为使用 glUseProgram(40) 或任何无效数字时,我会收到必要的错误消息,但除此之外,我只看到一个白色单位正方形!

很抱歉这篇突兀的长帖子,但我被这个难住了......无论我对顶点着色器或碎片着色器进行什么更改,我都会得到一个白色单位正方形。我怀疑 GL 默认为 FFP,并且由于某种原因,我的着色器程序没有生效。我希望这是一个菜鸟错误,但任何指示将不胜感激。

PS:没有编译错误,所以请原谅代码中的任何语法错误。我已经在上面输入了完整的代码。

更新:我已经按照Andon,Dinesh和Spektre的建议在对glVertexAttribArrayPointer 的调用中添加了最后一个参数,我之前错过了,但仍然相同的结果。

看这一行

glVertexAttribArrayPointer(1, VertexColor::SIZE_COLOR, GL_FLOAT, GL_FALSE, VertexColor::STRIDE);

其中 是指向的指针 指定数组中第一个通用顶点属性的第一个组件的偏移量。在顶点数组中,颜色数据从第 4 位开始。您必须指定颜色数据的第一个分量的起始位置。初始指针值为 0,因此程序从第一个位置读取颜色数据到第 4 个位置,这不是颜色数据。但它可以正确读取顶点数据,因为程序将顶点数据从第一个位置读取到第三个位置,这是正确的值。这样你只能看到白色的四边形。

问题解决了。

是的,这是一个菜鸟错误,但您的所有评论都帮助我再次浏览了整个代码。我从重做FFP的所有内容开始,然后转向PFP。 所以这是错误:

我错过了在为着色器程序创建的字典中输入glAttachShader(pid, sid),因此当程序生效时,顶点着色器和碎片着色器从未被应用。