glUseProgram不影响渲染状态

时间:2013-10-30 10:55:06

标签: c++ opengl ubuntu

我正在使用基于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
}

Fragment Shader - 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;

然后我使用以下代码渲染quad:

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的调用中添加了最后一个参数,我之前错过了,但结果仍然相同。

2 个答案:

答案 0 :(得分:0)

看看这一行

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

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

答案 1 :(得分:0)

问题解决了。

是的,这是一个愚蠢的错误,但是你的所有评论都帮助我再次完成整个代码。我开始用FFP重做所有内容并转移到PFP上。所以这是错误:

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