Opengl为什么这个着色器不起作用?

时间:2017-08-16 19:26:12

标签: c++ opengl shader

我试图创建一个类来绘制一个正方形,这个类将被实例化一次,每次我想绘制一个正方形我只会... Square :: draw(float posx,float posy,float sizex,float sizey)。 我这样做的方法是在着色器上有一个unifor vec4,我将传输pos和大小。 并且在vbo上:GLint _vertID [4] = {0,1,2,3}一个识别,这样我就知道着色器正在处理哪个顶点所以我可以放置正确的位置

问题在于它不绘制正方形而是随机绘制一些三角形。(有些错误)。 我想知道我的逻辑是错误的,还是执行错误。

以下是代码:

void Square::initVertex(){
    GLint _vertID[4] = {0,1,2,3};
    GLfloat _uvs[8] = {0,0,1,0,1,1,0,1};
    glGenVertexArrays(1, vao);
    glBindVertexArray(vao[0]);

    glGenBuffers(2, vbo);

    glBindBuffer( GL_ARRAY_BUFFER, vbo[0]);
    glBufferData( GL_ARRAY_BUFFER, 4 * sizeof(GLint), _vertID, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 1, GL_INT, false, 0, 0);
    glEnableVertexAttribArray(0);

    glBindBuffer( GL_ARRAY_BUFFER, vbo[1]);
    glBufferData( GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), _uvs, GL_STATIC_DRAW);
    glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 0);
    glEnableVertexAttribArray(1);
}

和VertexShader: posSh是vec4,我每次想要绘制一个正方形时都会传递位置,而vertID是让我知道正在处理哪个顶点的vbo

#version 150
in int vertID;
in vec2 uvs;
in vec4 posSh;
out vec2 ex_uvs;

void main(void){
    vec2 pos;

    if(vertID == 0){
        pos = vec2(posSh.x, posSh.y);
    }else if(vertID == 1){
        pos = vec2(posSh.x + posSh.z, posSh.y);
    }else if(vertID == 2){
        pos = vec2(posSh.x + posSh.z, posSh.y + posSh.w);
    }else if(vertID == 3){
        pos = vec2(posSh.x, posSh.y + posSh.w);
    }

    gl_Position = vec4(pos.x, pos.y, 1,1);
    ex_uvs = uvs;
}

1 个答案:

答案 0 :(得分:0)

我希望删除这些_vertID索引。 对我来说,看起来你试图通过使用单个vec4渲染4个顶点而不是4x vec2(或vec3,如果需要)来节省内存。 vertIDuvsposSh都是属性,这意味着它们必须具有相同的元素数。例如:

position: 1[x, y, z], 2[x, y, z], 3[x, y, z]
uvCoords: 1[x, y]   , 2[x, y]   , 3[x, y]

如果我是对的,posSh就不是这样了。 这就是我在你设置和安装中看到的内容。着色器代码:

vertID: 1[n]          , 2[n]      , 3[n]    , 4[n]
uvs:    1[x, y]       , 2[x, y]   , 3[x, y] , 4[x, y]
posSh:  1[x, y, z, w] , ???       , ???     , ???

所以,如果是这种情况,我们现在就解决这个问题。

  • vbo[0]GL_ARRAY_BUFFER更改为GL_ELEMENT_ARRAY_BUFFER。元素数组缓冲区包含您绑定的数组缓冲区的每个元素的索引(查看上面的代码部分,数字是您可以指定的索引)。 (请记住,vbo[0]将保持绑定,直到另一个GL_ELEMENT_ARRAY_BUFFER被绑定为止)
  • 从GL_ELEMENT_ARRAY_BUFFER中删除glVertexAttribPointer和glEnableVertexAttribArray,因为它只是必须绑定且已经存在。
  • vbo[]数组中创建第3个vbo,其中包含四元组的所有位置。这将取代posSh。您必须像_uvs的数组缓冲区一样进行设置(这将是一个vec2位置)
  • 在第3次vbo上使用glVertexAttribPointer和glEnableVertexAttribArray。

这就是你怎么做的。 试试这段代码(我还没有测试过):

void Square::initVertex(){
    GLint _vertID[4] = {0,1,2,3};
    GLfloat _uvs[8] = {0,0,1,0,1,1,0,1};
    GLfloat _pos[8] = {0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f };
    glGenVertexArrays(1, vao); 
    glBindVertexArray(vao[0]);

    glGenBuffers(3, vbo); // the first index is an Element Array Buffer!

    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vbo[0]);
    glBufferData( GL_ELEMENT_ARRAY_BUFFER, 4 * sizeof(GLint), _vertID, GL_STATIC_DRAW);

    glBindBuffer( GL_ARRAY_BUFFER, vbo[1]);
    glBufferData( GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), _pos, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
    glEnableVertexAttribArray(0);

    glBindBuffer( GL_ARRAY_BUFFER, vbo[2]);
    glBufferData( GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), _pos, GL_STATIC_DRAW);
    glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 0);
    glEnableVertexAttribArray(1);
}

着色器代码:

#version 150
in vec2 uvs;
in vec2 pos;
out vec2 ex_uvs;

void main(void){
    gl_Position = vec4(pos.x, pos.y, 1,1);
    ex_uvs = uvs;
}

您的绘图代码:

 glDrawElements(
     GL_QUADS,      // mode
     4,    // count
     GL_UNSIGNED_INT,   // type
     (void*)0           // element array buffer offset
 );

我希望它对你有所帮助。尝试代码,我不知道是否有任何拼写错误,我用记事本++编写。

这是一个关于如何正确渲染VBO的进展教程:Tutorial 9 : VBO Indexing