OpenGL +无法使用buffersubdata更新缓冲区数据

Posted

技术标签:

【中文标题】OpenGL +无法使用buffersubdata更新缓冲区数据【英文标题】:OpenGL + Can't update buffer data with buffersubdata 【发布时间】:2016-01-29 04:22:24 【问题描述】:

我正在尝试使用 glNamedBufferSubData 或 glBufferSubData 来覆盖缓冲区中的顶点值,但它似乎没有做任何事情。

我有我想从 renderGeometry 函数调用的函数 updateGeometry 修改我的 SpringMass 对象的变量之一。我希望数据被完全覆盖,因此使用 - 作为偏移量。

const int NUM_VERTICES_PER_LINE = 2;
const int NUMFLOATSPERVERTICES = 6;
const int VERTEX_BYTE_SIZE = NUMFLOATSPERVERTICES * sizeof(float);

GLint numSpringIndices, numMassIndices;
#define NUM_ARRAY_ELEMENTS(a) sizeof(a) / sizeof(*a);
Spring::Spring() : anchorPosition 0.0f, 1.0f, 0.0f , mPosition 0.0f, 0.0f, 0.0f , displacement 0.0f, -0.3f, 0.0f  
    USING_ATLAS_GL_NS; //Short for atlas GL namespace
    USING_ATLAS_MATH_NS;
    glGenVertexArrays(1, &mVertexArrayObject);
    glBindVertexArray(mVertexArrayObject);

    //mSpringMass = ObjectGenerator::makeSpring(anchorPosition, stretch, d);
    //mMass = ObjectGenerator::makeMass(calculateConnectionPoint(anchorPosition), massWidth, massHeight);
    mSpringMass = ObjectGenerator::makeSpringMass(anchorPosition, stretch, d, massWidth, massHeight);
    numSpringIndices = mSpringMass.numIndices;

    glGenBuffers(1, &mVertexBufferObject);
    glBindBuffer(GL_ARRAY_BUFFER, mVertexBufferObject);
    glBufferData(GL_ARRAY_BUFFER, mSpringMass.vertexBufferSize(), mSpringMass.vertices, GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, VERTEX_BYTE_SIZE, 0);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, VERTEX_BYTE_SIZE, (char*)(sizeof(float) * 3));

    glGenBuffers(1, &springIndexBufferID);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, springIndexBufferID);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, mSpringMass.indexBufferSize(), mSpringMass.indices, GL_STATIC_DRAW);
    // Get the path where our shaders are stored.
    std::string shaderDir = generated::ShaderPaths::getShaderDirectory();

    // Now set up the information for our shaders.
    std::vector<ShaderInfo> shaders
    
        ShaderInfo GL_VERTEX_SHADER, shaderDir + "Spring.vs.glsl" ,
        ShaderInfo GL_FRAGMENT_SHADER, shaderDir + "Spring.fs.glsl" 
    ;
    // Create a new shader and add it to our list.
    mShaders.push_back(ShaderPointer(new Shader));
    mShaders[0]->compileShaders(shaders);
    mShaders[0]->linkShaders();
    mShaders[0]->disableShaders();


Spring::~Spring()

    glDeleteVertexArrays(1, &mVertexArrayObject);
    glDeleteBuffers(1, &mSpringBuffer);


void Spring::renderGeometry(atlas::math::Matrix4 projection, atlas::math::Matrix4 view) 
    // To avoid warnings from unused variables, you can use the 
    //UNUSED macro.
    UNUSED(projection);
    UNUSED(view);
    mShaders[0]->enableShaders();
    updateGeometry();
    GLint dispLocation = mShaders[0]->getUniformVariable("displacement");
    GLint anchorLocation = mShaders[0]->getUniformVariable("anchorPosition");
    glUniform3fv(anchorLocation, 1, &anchorPosition[0]);
    glUniform3fv(dispLocation, 1, &displacement[0]);
    glBindVertexArray(mVertexArrayObject);

    glDrawElements(GL_LINES, numSpringIndices, GL_UNSIGNED_SHORT, 0);

    mShaders[0]->disableShaders();


void Spring::updateGeometry() 
    //glBindBuffer(GL_ARRAY_BUFFER, mVertexBufferObject);
    GLfloat newD = d * 0;
    mSpringMass = ObjectGenerator::makeSpringMass(anchorPosition, stretch, newD, massWidth, massHeight);
    //glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(mSpringMass.vertices), mSpringMass.vertices);
    glNamedBufferSubData(mVertexBufferObject, 0, sizeof(mSpringMass.vertices), mSpringMass.vertices);

编辑

为了澄清,这里是 ObjectGenerator 代码。

#include "ObjectGenerator.h"
#define NUM_ARRAY_ELEMENTS(a) sizeof(a) / sizeof(*a);
ShapeData ObjectGenerator::makeSpringMass(glm::vec3 anchorPosition, GLfloat stretch, GLfloat d, GLfloat width, GLfloat height) 
    ShapeData ret;
    glm::vec3 springColor 1.0f, 0.0f, 0.0f , massColor 0.0f, 1.0f, 0.0f , connectionPoint anchorPosition.x, anchorPosition.y - (18 * d), 0.0f ;
    static const Vertex vertices[] = 
        glm::vec3(anchorPosition.x, anchorPosition.y, 0.0f), // 0
        springColor,
        glm::vec3(anchorPosition.x, anchorPosition.y - d,0.0f), // 1
        springColor,
        glm::vec3(anchorPosition.x + stretch, anchorPosition.y - (2 * d), 0.0f), // 2
        springColor,
        glm::vec3(anchorPosition.x - stretch, anchorPosition.y - (4 * d), 0.0f), // 3
        springColor,
        glm::vec3(anchorPosition.x + stretch, anchorPosition.y - (6 * d), 0.0f), // 4
        springColor,
        glm::vec3(anchorPosition.x - stretch, anchorPosition.y - (8 * d), 0.0f), // 5
        springColor,
        glm::vec3(anchorPosition.x + stretch, anchorPosition.y - (10 * d), 0.0f), // 6
        springColor,
        glm::vec3(anchorPosition.x - stretch, anchorPosition.y - (12 * d), 0.0f), // 7
        springColor,
        glm::vec3(anchorPosition.x + stretch, anchorPosition.y - (14 * d), 0.0f), // 8
        springColor,
        glm::vec3(anchorPosition.x - stretch, anchorPosition.y - (16 * d), 0.0f), // 9
        springColor,
        glm::vec3(anchorPosition.x, anchorPosition.y - (17 * d), 0.0f), // 10
        springColor,
        connectionPoint, // 11
        springColor,
        //=================Mass==============//
        glm::vec3(connectionPoint.x - width, connectionPoint.y, 0.0f), //top Left 12
        massColor,
        glm::vec3(connectionPoint.x + width, connectionPoint.y, 0.0f), //top Right 13
        massColor,
        glm::vec3(connectionPoint.x + width, connectionPoint.y - height, 0.0f), // bottom right 14
        massColor,
        glm::vec3(connectionPoint.x - width, connectionPoint.y - height, 0.0f), // bottom left 15
        massColor,
    ;
    ret.numVertices = NUM_ARRAY_ELEMENTS(vertices);
    ret.vertices = new Vertex[ret.numVertices];
    memcpy(ret.vertices, vertices, sizeof(vertices)); //memcpy(dest, source, size);

    GLushort indices[] =  0,1 ,1,2, 2,3, 3,4, 4,5, 5,6, 6,7, 7,8, 8,9, 9,10, 10,11, 11,12, 12,13, 13,14, 14,15, 15,12;
    //GLushort indices[] =  0,1 ,1,2, 2,3, 3,4, 4,5, 5,6, 6,7, 7,8, 8,9, 9,10, 10,11 ;
    ret.numIndices = NUM_ARRAY_ELEMENTS(indices);
    ret.indices = new GLushort[ret.numIndices];
    memcpy(ret.indices, indices, sizeof(indices));

    return ret;
 

【问题讨论】:

mSpringMass.vertices 的类型是什么?根据它是什么,sizeof(mSpringMass.vertices) 可能不是缓冲区的实际大小。你在原来的glBufferData() 调用中使用了mSpringMass.vertexBufferSize() 你试过GL_DYNAMIC_DRAW而不是GL_STATIC_DRAW,也许某些gl实现冻结了静态缓冲区... mSpringMass.vertices 是一个 GLfloats 数组 【参考方案1】:

我想通了。

在我的对象生成器类中,顶点数据从未更新,因为我离开了static constqualifiers。 glBuffersubData 运行良好,但它只是覆盖了完全相同的数据......

【讨论】:

以上是关于OpenGL +无法使用buffersubdata更新缓冲区数据的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 OpenGL 显示纹理

关于opengl无法运行的问题

无法使用 SceneKit 从 OpenGL 获取 CVPixelBufferRef 数据

OpenGL 着色器无法编译

如何使用 OpenGL 保存 OpenGL 绘制?

无法使用 OpenGL 渲染 FBX 导入的纹理模型