当前位置: 首页 > 知识库问答 >
问题:

OpenGL 4,缓冲区偏移值错误

苗烈
2023-03-14

我目前的方法是用所有粒子填充一个数组(称为vertexData),这样数组的结构将是:[particle,particle,particle,...],其中每个粒子都有上面给出的布局。

我的计划是简单地将初始信息提供给顶点着色器,然后让它根据初始信息计算位置偏移量和颜色。我希望大多数的计算是在GPU上完成的。

我想通过将所有数据放在一个缓冲区对象中来传递数据到着色器,然后使用偏移量来获取正确的值来传递到顶点着色器。

代码:现在关于如何填充数据的一些代码,创建缓冲区对象、呈现和着色器代码。数组的initalization和填充如下所示:

const int PARTICLE_COUNT = 1;
const int PARTICLE_COMPONENTS_COUNT = 12;
...
GLfloat* vertexData;
...

void InitVertexData(){

    vertexData = new GLfloat[PARTICLE_COUNT * PARTICLE_COMPONENTS_COUNT];

    for (int i = 0; i < PARTICLE_COUNT; i++)
{       
        vertexData[i * PARTICLE_COMPONENTS_COUNT + 0] = 0.5f; //0: posX
        vertexData[i * PARTICLE_COMPONENTS_COUNT + 1] = 0.5f; //1: posY
        vertexData[i * PARTICLE_COMPONENTS_COUNT + 2] = 0.0f; //2: posZ
        vertexData[i * PARTICLE_COMPONENTS_COUNT + 3] = 1.0f; //3: posW

        vertexData[i * PARTICLE_COMPONENTS_COUNT + 4] = 1.0f; //4: red
        vertexData[i * PARTICLE_COMPONENTS_COUNT + 5] = 1.0f; //5: green
        vertexData[i * PARTICLE_COMPONENTS_COUNT + 6] = 1.0f; //6: blue
        vertexData[i * PARTICLE_COMPONENTS_COUNT + 7] = 1.0f; //7: alpha

        vertexData[i * PARTICLE_COMPONENTS_COUNT + 8] = 0.0f; //8: velX
        vertexData[i * PARTICLE_COMPONENTS_COUNT + 9] = 0.0f; //9: velY
        vertexData[i * PARTICLE_COMPONENTS_COUNT + 10] = 0.0f; //10: velZ

        vertexData[i * PARTICLE_COMPONENTS_COUNT + 11] = 5.0f; //11: lifetime
    }
}

注意:粒子的值现在只是硬编码的。我还没有实现计算初始值的函数。

然后,我生成一个缓冲区,我想保存所有粒子的所有数据。初始化时调用一次以下函数:

bool CreateBufferObject()
{
    //VertexShader attribute variable handles.
    GLint positionLocation = glGetAttribLocation(programId, "position");
    GLint colorLocation = glGetAttribLocation(programId, "color");
    GLint velocityLocation = glGetAttribLocation(programId, "velocity");
    GLint lifetimeLocation = glGetAttribLocation(programId, "lifetime");

    //Number of components (floats) in a particle element (such as position, color etc).
    GLint positionComponentCount = 4; //posX, posY, posZ, posW
    GLint colorComponentCount = 4; //r, g, b, a
    GLint velocityComponentCount = 3; //velX, velY, velZ
    GLint lifetimeComponentCount = 1; //lifetime (in seconds)

    //Size (in bytes) of the vertexData array and the elements inside.
    GLsizeiptr sizeofVertexDataArray = sizeof(GLfloat) * PARTICLE_COUNT * PARTICLE_COMPONENTS_COUNT; //4 * 2 * 12 = 96
    GLsizeiptr sizeofPosition = sizeof(GLfloat) * positionComponentCount; //4*4 = 16
    GLsizeiptr sizeofColor = sizeof(GLfloat) * colorComponentCount; //4*4 = 16
    GLsizeiptr sizeofVelocity = sizeof(GLfloat) * velocityComponentCount; //4*3 = 12
    GLsizeiptr sizeofLifetime = sizeof(GLfloat) * lifetimeComponentCount; //4*1 = 4

    //Generate one buffer in GPU memory and get handle.
    glGenBuffers(1, &vertexDataBufferId);

    //Generate VAO, a descriptor of vertex data (not the actual object), and get handle.
    glGenVertexArrays(1, &vaoId);
    glBindVertexArray(vaoId);

    //Bind the generated buffer to VAO as the current target.
    glBindBuffer(GL_ARRAY_BUFFER, vertexDataBufferId);

    //Copy the actual data from the vertexData array to GPU memory. TODO: Not sure what to pick instead of GL_STREAM_DRAW
    glBufferData(GL_ARRAY_BUFFER, sizeofVertexDataArray, vertexData, GL_STREAM_DRAW);

    //Guide Vertex Shader to where attributes are at in the memory, giving size and offset (in bytes) of the different elements of a particle.
    glVertexAttribPointer(positionLocation, positionComponentCount, GL_FLOAT, GL_FALSE, sizeofPosition, 0); //offset 0
    glVertexAttribPointer(colorLocation, colorComponentCount, GL_FLOAT, GL_FALSE, sizeofColor, (void*)positionComponentCount); //ofset 4
    glVertexAttribPointer(velocityLocation, velocityComponentCount, GL_FLOAT, GL_FALSE, sizeofVelocity, (void*)(positionComponentCount + colorComponentCount)); //offset 8
    glVertexAttribPointer(lifetimeLocation, lifetimeComponentCount, GL_FLOAT, GL_FALSE, sizeofLifetime, (void*)(positionComponentCount + colorComponentCount + velocityComponentCount)); //offset 11

    glEnableVertexAttribArray(positionLocation);
    glEnableVertexAttribArray(colorLocation);
    glEnableVertexAttribArray(velocityLocation);
    glEnableVertexAttribArray(lifetimeLocation);
//Error checks and debug prints omitted
}

我的理解是:在glBufferData中,我指定整个数据集(所有粒子)的大小,并将数据复制到GPU内存中。

void Render()
{
    ...
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    GLuint elapsedTimeUniformLoc = glGetUniformLocation(programId, "time");

    glUniform1f(elapsedTimeUniformLoc, glutGet(GLUT_ELAPSED_TIME) / 1000.0f); //Divide by 1000 to get time in seconds.
    glDrawArrays(GL_POINTS, 0, PARTICLE_COUNT)

    glutSwapBuffers();
    glutPostRedisplay();
}
const GLchar* VertexShader2 =
{
    "#version 400\n"\

    "uniform float time;\n"\
    "in vec4 position;\n"\
    "in vec4 color;\n"\
    "in vec3 velocity;\n"\
    "in float lifetime;\n"\

    "out vec4 myColor;\n"\

    "void main()\n"\
    "{\n"\
    "   float dummy = velocity.x;\n"
    "   float timeScale = 0.1f;\n"\
    "   float currentAge = mod(time, lifetime);\n"\
    "   vec4 accumulatedOffset = vec4(timeScale*currentAge, 0.0f, 0.0f, 0.0f);\n"
    "   gl_Position = position + accumulatedOffset;\n"\


    " if(lifetime ==0) { color.y = 1.0f; }\n"\
    "   //color.w = 1.0f - ((1.0f/lifetime) * currentAge)\n"\
    "   color.w = 1.0f - (0.2f * currentAge);\n"\
    "   myColor = color;\n"\
    "}\n"\
};

const GLchar* FragmentShader =
{
    "#version 400\n"\

    "in vec4 myColor;\n"\
    "out vec4 outColor;\n"\

    "void main()\n"\
    "{\n"\
    "   outColor = myColor;\n"\
    "}\n"\
};

注意:由于velocity的值不正确,我使用虚拟变量只是为了确保着色器编译器不会丢弃该属性。

如果你需要看到更多的代码,我会更新帖子。我希望我把我的问题和我的情况说清楚了。

回复@Ben Voight好吧,所以从你的评论来看,我认为stride参数表示该属性下一个值在数据中的偏移量。所以必须是

particle_components_count*sizeof(GLfloat)用于所有glvertexattribpointer

然而,它仍然给我提供了错误的数据。由以下元素组成的粒子

[-0.5,0.5,0.5,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,5.0],

我期望一个职位(-0.5,0.5,0.5),一个白色的颜色和5年的寿命。(不考虑以前的速度)

如果生存期==0,我让顶点着色器改变颜色,它报告生存期确实为0。我不明白它是从哪里得到0的,它甚至不在数据中。颜色也不对。只有位置似乎是正确的。事实上,它的工作原理和以前一模一样。

解决后的结果是,我在GLVertexattribPointer中传递了错误的步幅和偏移量值。

可能重复:Opengl顶点属性步幅

共有1个答案

相化
2023-03-14

glvertexattribpointer的步幅参数需要为particle_components_count*sizeof(GLfloat)

偏移量参数以字节为单位。所有的值都是sizeof(GLfloat)的一个因数。

您为什么要使用花哨的索引,而不是一个包含所有正确字段的结构数组?

 类似资料:
  • 一切都清楚一次是UTC中的日期:

  • 我有一个应用程序,在PHP中使用openssl_encrypt加密文本,方法如下。(使用与“239422AE7940144F”相同的盐和iv值) 密码“abc123”加密提供“xup9pwhcxm5xbkifisxmca==”,解密则返回“abc123”。

  • 我试图安装Caffe库,但我有一个编译问题,由于一个错误的原型版本安装在我的系统。 我在论坛上遵循了许多提议的方法,我认为在这篇帖子中讨论了最类似的问题。 在caffe.pb.h中控件是: 但是在我的系统标头(/usr/include/google/cript buf/stubs/Common. h)中: 命令protoc--version从终端返回libprotoc 3.2.0。 所以我安装了3

  • 有时我对api的get请求失败,会出现以下错误消息(顺便说一下,我使用请求模块触发我的请求) 这一直困扰着我,因为我不知道是什么导致了这一点,也无法在github页面中找到任何明确的解决方案。如有任何帮助,我们将不胜感激。

  • 纯JavaScript是Unicode友好的,但二进制数据却不是这样。 在处理TCP流或文件系统时,必须处理八位字节流。 Node提供了Buffer类,它提供了存储类似于整数数组的原始数据的实例,但对应于V8堆外部的原始内存分配。 Buffer类是一个全局类,可以在应用程序中访问而无需导入缓冲区模块。 创建缓冲区 节点缓冲区可以以多种方式构建。 Method 1 以下是创建10个八位字节的无启动缓

  • 我有一个正在开发的OpenGL应用程序。正在渲染的地形似乎没有遵循深度缓冲规则,所以我猜我在某个地方搞砸了 我的代码中有GL11.glEnable(GL11.GL_CULL_FACE) 这是飞机在没有四边形在另一个后面的情况下的样子,所以即使没有z缓冲区,事情看起来也很正常。请注意,这是从“自上而下”的视图中,其中“相机”在飞机上方 而现在,从不同的角度看 离场景最远的四边形正在更靠近计算机的四边