使用GL_ARRAY_BUFFER更新顶点数据

时间:2015-06-22 20:35:13

标签: c++ opengl

这是初学者级别的OpenGL C ++问题

我尝试使用GL_ARRAY_BUFFER更新三角形偏移。这是一个简单的例子,说明了我的问题。 #define crashversion用于启用我认为应该可以运行但导致崩溃的版本。将#define删除,其余的源代码将被删除。我还是初学者,所以我使用的是一些在这里看不到的功能。 AyOpenGL::GlShader; AyOpenGL::GlProgram;是瘦辅助类,用于管理着色器和程序的内存和加载。它们已被证明可以与我的所有其他功能一起使用。 sb6::application是OpenGL超级圣经第6版的助手类。我非常确定那些是合理的无bug,我对opengl缓冲区的理解是问题的核心。我可以编辑和支持片段,如果这有助于anser。

class stackexample : public sb6::application
{
private:
    GLuint vertex_array_Object;
    GLuint buffer;
    std::unique_ptr<AyOpenGL::GlProgram> program;
public:
    void render(double currentTime);
    void startup();
    void shutdown();
};

#define crashversion

void stackexample::startup()
{
    vector<shared_ptr<GlShader>> shaders;
    shaders.push_back(make_shared<GlShader>("Shaders//VS_Triangle_IN_offset.c", GL_VERTEX_SHADER));
    shaders.push_back(make_shared<GlShader>("Shaders//FS_CyanColor.c", GL_FRAGMENT_SHADER));
    program = std::make_unique<GlProgram>("program", shaders);
    glGenVertexArrays(1, &vertex_array_Object);
    glBindVertexArray(vertex_array_Object);
#ifdef crashversion
    glGenBuffers(1, &buffer);
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    glBufferData(GL_ARRAY_BUFFER, 1000, NULL, GL_STATIC_DRAW);
#endif
}

void stackexample::render(double currentTime)
{
    GLfloat black[] = { 0.0f, 0.0f, 0.0f, 1.0f };
    GLfloat offset[] = { (float)std::sin(currentTime), 0.0f, 0.0f, 1.0f };
    glClearBufferfv(GL_COLOR, 0, black);
    glUseProgram(*program);
#ifdef crashversion
    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(offset), offset);
    glEnableVertexAttribArray(0);
#else
    glVertexAttrib4fv(0, offset);
#endif
    glDrawArrays(GL_TRIANGLES, 0, 3);
}

void stackexample::shutdown()
{
    glDeleteVertexArrays(1, &vertex_array_Object);
}

VS_Triangle_IN_offset.c:

#version 430 core                                                 

layout (location = 0) in vec4 offset;

void main(void)                                                   
{                                                                 
    const vec4 vertices[] = vec4[](vec4( 0.25, -0.25, 0.5, 1.0),
                                   vec4(-0.25, -0.25, 0.5, 1.0),
                                   vec4( 0.25,  0.25, 0.5, 1.0));
    gl_Position = vertices[gl_VertexID] + offset;
}                                                                 

FS_CyanColor.c:

#version 430 core    

out vec4 color;

void main(void)      
{
    color = vec4(0.0, 0.8, 1.0, 1.0);
}

我的理解是我在两个版本中通过缓冲区将偏移量推入着色器。不知怎的,虽然第二个版本不起作用,我不知道为什么。我尝试了不同的代码星座并尝试研究这个,但我无法在这里教育自己。

如何编写crashversion以使其与普通版本完全相同?

编辑: 我在使用崩溃这个词时非常松散。它崩溃有些未定义,但大多是这样的:OpenGLDemo.exe中0x04A025AD(nvoglv32.dll)的未处理异常:0xC0000005:访问冲突读取位置0x00000000。

所以它看起来像一个nullpointer问题

2 个答案:

答案 0 :(得分:1)

您永远不会为属性0设置顶点属性指针,因此您永远不会使用您创建的VBO。但是,您为属性零启用数组,这将导致GL访问一些完全无效的内存位置 - 这可能会崩溃。

也许OpenGL wiki entry on Vertex Specification可能会帮助您理解这些概念。

答案 1 :(得分:0)

正如@derhass所指出的那样,阅读其他文档可以解决一些问题。

以下是我对代码所做的更改,以使其运行。

void stackexample::startup()
{
    vector<shared_ptr<GlShader>> shaders;
    shaders.push_back(make_shared<GlShader>("Shaders//VS_Triangle_IN_offset.c", GL_VERTEX_SHADER));
    shaders.push_back(make_shared<GlShader>("Shaders//FS_CyanColor.c", GL_FRAGMENT_SHADER));
    program = std::make_unique<GlProgram>("program", shaders);
    glGenVertexArrays(1, &vertex_array_Object);
    glBindVertexArray(vertex_array_Object);
    glGenBuffers(1, &buffer);
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    glBufferData(GL_ARRAY_BUFFER, 1000, NULL, GL_STATIC_DRAW);
}

void stackexample::render(double currentTime)
{
    GLfloat black[] = { 0.0f, 0.0f, 0.0f, 1.0f };
    GLfloat vertex_offset[] = { (float)std::sin(currentTime), 0.0f, 0.0f, 1.0f };
    glClearBufferfv(GL_COLOR, 0, black);
    glUseProgram(*program);
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertex_offset), vertex_offset);
    glBufferSubData(GL_ARRAY_BUFFER, sizeof(vertex_offset), sizeof(vertex_offset), vertex_offset);
    glBufferSubData(GL_ARRAY_BUFFER, 2 * sizeof(vertex_offset), sizeof(vertex_offset), vertex_offset);
    glEnableVertexAttribArray(0);
    glDrawArrays(GL_TRIANGLES, 0, 3);
}

我可以看到额外的改进潜力,但我在示例中进行了最小的改变。