0

我正在使用 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,
};

VertexColor 定义为:

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) 或任何无效数字之类的东西时,我会收到必要的错误消息,但否则,我只会看到一个白色的单位正方形!

抱歉,这篇文章太长了,但我被这个帖子难住了……无论我对 vert 或 frag 着色器进行什么更改,我都会得到一个白色的单位方块。我怀疑 GL 默认使用 FFP,并且由于某种原因我的着色器程序没有生效。我希望这是一个愚蠢的错误,但任何指针将不胜感激。

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

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

4

2 回答 2

0

问题解决了。

是的,这是一个愚蠢的错误,但是您的所有评论都帮助我再次浏览了整个代码。我开始使用 FFP 重做所有事情,然后转向 PFP。所以这里是错误:

我错过glAttachShader(pid, sid)了为着色器程序创建的字典,所以当程序生效时,顶点着色器和片段着色器从未被应用。

于 2013-10-31T07:03:08.987 回答
0

看这条线

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

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

于 2013-10-30T11:45:52.333 回答