代码协助,OpenGL VAO/VBO类无法绘制

3

编辑2:
目前的代码运行良好!谢谢大家。我在最下面包含了我的着色器代码供参考,但实际上它们目前完全没有作用。

我正在尝试开始使用OpenGL 4.1,并且仍处于开发的早期阶段。目前,在此项目中我甚至还没有真正使用4.0的功能,因此这同样是一个关于OpenGL 3的问题。

我最初的目标是简单地处理两个类来处理VAO和VBO。我有一些误解,但终于克服了空白屏幕的问题。

/* THIS CODE IS NOW FULLY FUNCTIONAL */
/* well, fully is questionable lol, should work out of the box with glew and glfw */

/* A simple function that will read a file into an allocated char pointer buffer */
/* Borrowed from OpenGL.org tutorial */
char* filePull(char *file)
{
    FILE *fptr;
    long length;
    char *buf;

    fptr = fopen(file, "r"); /* Open file for reading */
    if (!fptr) /* Return NULL on failure */
        return NULL;
    fseek(fptr, 0, SEEK_END); /* Seek to the end of the file */
    length = ftell(fptr); /* Find out how many bytes into the file we are */
    buf = (char*)malloc(length+1); /* Allocate a buffer for the entire length of the file and a null terminator */
    fseek(fptr, 0, SEEK_SET); /* Go back to the beginning of the file */
    fread(buf, length, 1, fptr); /* Read the contents of the file in to the buffer */
    fclose(fptr); /* Close the file */
    buf[length] = 0; /* Null terminator */

    return buf; /* Return the buffer */
}


class VBO
{
    public:

    GLuint buffer;
    bool isBound;
    vector<void*> belongTo;
    vector<GLfloat> vertex;
    GLenum usage;

    void Load()
    {   glBufferData(GL_ARRAY_BUFFER, vertex.size()*sizeof(GLfloat), &vertex[0], usage);    }
    void Create(void* parent)
    {
        glGenBuffers(1, &buffer);
        glBindBuffer(GL_ARRAY_BUFFER, buffer);
        glBufferData(GL_ARRAY_BUFFER, vertex.size()*sizeof(GLfloat), &vertex[0], usage);
        isBound=true;
        belongTo.push_back(parent);

    }
    void Activate()
    {
        if(!isBound)    glBindBuffer(GL_ARRAY_BUFFER, buffer);
        isBound=true;
    }
    void Deactivate(){  glBindBuffer(GL_ARRAY_BUFFER, 0);  }

    VBO() : isBound(false), usage(GL_STATIC_DRAW)
    {      }
    ~VBO()  {   }

    private:
};

class VAO
{
    public:
    GLuint buffer;
    string key;
    unsigned long long cursor;

    vector<VBO> child;

    void Create()
    {
        glGenVertexArrays(1, &buffer);
        for(unsigned int i=0; i<child.size(); i++)
            child[i].Create(this);
    }
    void Activate()
    {
        glBindVertexArray(buffer);
        for(unsigned int i=0; i<child.size(); i++)
            child[i].Activate();
    }
    void Release(){ glBindVertexArray(0); }
    void Remove(){  glDeleteVertexArrays(1, &buffer);   }

    VAO() : buffer(1)   {     }
    ~VAO()  {       }

    private:
};

int main()
{
    int     width=640, height=480, frame=1;    bool    running = true;

    glfwInit();

    if( !glfwOpenWindow( width, height, 0, 0, 0, 0, 0, 0, GLFW_WINDOW ) )
    {        glfwTerminate();   return 13;   }
    glfwSetWindowTitle("Genesis");

    glewInit();
    cout<<(GLEW_VERSION_4_1?"yes":"no"); //yes


    GLchar *vsource, *fsource;
    GLuint _vs, _fs;
    GLuint Shader;

    vsource = filePull("base.vert");
    fsource = filePull("base.frag");

    /* Compile Shaders */
    _vs = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(_vs, 1, (const GLchar**)&vsource, 0);
    glCompileShader(_vs);
//    glGetShaderiv(_vs, GL_COMPILE_STATUS, &IsCompiled_VS);
    _fs = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(_fs, 1, (const GLchar**)&fsource, 0);
    glCompileShader(_fs);
/***************** ^ Vertex | Fragment v *********************/
    glAttachShader(Shader, _vs);
    glAttachShader(Shader, _fs);
//    glGetShaderiv(_fs, GL_COMPILE_STATUS, &IsCompiled_FS);
    glBindAttribLocation(Shader, 0, "posIn");
    glLinkProgram(Shader);
//    glGetProgramiv(shaderprogram, GL_LINK_STATUS, (int *)&IsLinked);

    VAO Object3D;
    VBO myVBO[3];

    glUseProgram(Shader);

    for(int i=0; i<9; i++)
        myVBO[0].vertex.push_back((i%9)*.11); //Arbitrary vertex values

    Object3D.child.push_back(myVBO[0]);
    Object3D.Create();

    glClearColor( 0.7f, 0.74f, 0.77f, 0.0f ); //Black got lonely

   int i=0; while(running)
    {
        frame++;

        glfwGetWindowSize( &width, &height );
        height = height > 0 ? height : 1;
        glViewport( 0, 0, width, height );
        glClear( GL_COLOR_BUFFER_BIT );

        /*   Bind, Draw, Unbind */
        Object3D.Activate();
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 9);

        Object3D.Release();
        glfwSwapBuffers();

        // exit if ESC was pressed or window was closed
        running = !glfwGetKey(GLFW_KEY_ESC) && glfwGetWindowParam( GLFW_OPENED);
        i++;
    }

    glUseProgram(0); glDisableVertexAttribArray(0);
    glDetachShader(Shader, _vs); glDetachShader(Shader, _fs);
    glDeleteProgram(Shader); glDeleteShader(_vs); glDeleteShader(_fs);
    glDeleteVertexArrays(1, &Object3D.buffer);

    glfwTerminate();
    return 0;
}

基本上,我只是希望在屏幕上得到任何东西。我正在使用glfw和glew。我是完全遗漏了一些东西还是只需要更正一些东西?目前代码有些混乱,抱歉。

base.vert

// Fragment Shader – file "base.vert"    
#version 300

in  vec3 posIn;
out vec4 colorOut;

void main(void)
{
    gl_Position = vec4(posIn, 1.0);
    colorOut = vec4(3.0,6.0,4.0,1.0);
}

base.frag

// Vertex Shader – file "base.frag"
#version 300

out vec3 colorOut;

void main(void)
{
    colorOut = vec3(1.0,10,1.0);
}

你是否百分之百确定你的“视图”和“相机”设置是正确的? - tauran
完全没有头绪,所以可能不行,等我有时间再研究一下,谢谢。 - That Realty Programmer Guy
也许只需要画一个简单的三角形,就能知道你的其他“对象”应该在哪里。 - tauran
2个回答

5
&vertex

vertex是一个向量。取其地址将不会给你一个指向数据的指针。

编辑以添加: 没错。它仍然无法工作,因为您至少还有两个问题:

  1. 您没有调用任何gl*Pointer调用。GL不知道它需要从您的顶点缓冲对象中提取什么
  2. 您放入顶点数组的顶点数据是3倍相同的顶点。一个三角形,其三个点在同一位置:

    for(int i=0; i<9; i++) myVBO[0].vertex.push_back((i%3)*.2); //任意顶点值

它创建了3个(.0 .2 .4)向量,都在同一位置。


啊哈,是的,我有点知道!感谢你的指出和修正。不过还是出现了空白窗口。=/ - That Realty Programmer Guy

1
那个 VBO 的成员 iBound 看起来很可疑。OpenGL 绑定状态可能会发生变化,例如在切换绑定的 VAO 后,但是 VBO 类实例仍然认为它是活动的。完全删除 iBound ,每次需要对象时重新绑定即可。使用现代驱动程序重新绑定已经绑定的对象几乎不需要额外的开销。

在客户端优化中真的没有用处吗?我主要是想到当设置客户端/服务器之间的分页时会很有用,但我真的认为它会派上用场。 - That Realty Programmer Guy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接