使用GL_ARRAY_BUFFER更新垂直数据

Using GL_ARRAY_BUFFER to update vertice data

本文关键字:垂直 数据 更新 ARRAY GL 使用 BUFFER      更新时间:2023-10-16

这是一个初级OpenGL C++问题

我尝试使用GL_ARRAY_BUFFER更新三角形偏移。这里有一个简单的例子来说明我的问题。#define crashversion用于启用我认为应该工作但会导致崩溃的版本。如果CCD_ 2被移除,则源工作的剩余部分。我还是一个初学者,所以我使用了一些在这里看不到的功能。AyOpenGL::GlShader; AyOpenGL::GlProgram;是管理内存以及着色器和程序加载的瘦辅助类。它们已经被证明可以与我的所有其他功能配合使用。sb6::application是OpenGL超级圣经第6版中的一个辅助类。我非常确信这些都是合理的无错误,并且我对opengl缓冲区的理解是问题的核心。我可以编辑和支持片段,如果这将有助于回答。

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的访问冲突。

所以它看起来像是一个空指针问题

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

也许顶点规范上的OpenGL wiki条目可能有助于您理解这些概念。

正如@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);
}

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