OpenGL计算着色器不更改缓冲区

时间:2019-03-09 17:04:46

标签: c opengl shader

我想在计算着色器中更改多个着色器之间共享的缓冲区的内容。特别是在这种情况下的法线。

无论我将缓冲区中一个或多个顶点的值设置为什么,它似乎都不会在其他任何着色器中生效。可能我只是忘记了一些东西或什么都没看到(我是计算着色器的新手)

这是代码的相关部分。如果您需要代码的更多部分,请询问。请理解,尽管很难给出一段有效的代码,因为这需要安静的代码,而不仅仅是几行。

utils_createComputeProgram(&g_simulateWaterProgram, "content/shaders/simulatewater/simulatewater.comp");

// Initialize first position buffer
{
    glGenBuffers(1, &app->positionBufferOne);
    glBindBuffer(GL_ARRAY_BUFFER, app->positionBufferOne);
    glBufferData(GL_ARRAY_BUFFER, NUM_VERTICES*sizeof(MLvec4), NULL, GL_STATIC_DRAW);

    MLvec4* positions = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);
    for (int i = 0; i < NUM_VERTICES; ++i) {
        ...            
        positions[i] = mlMakeVec4(x, y, z, v);
    }

    glUnmapBuffer(GL_ARRAY_BUFFER);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

// Initialize second position buffer with 0
{
    glGenBuffers(1, &app->positionBufferTwo);
    glBindBuffer(GL_ARRAY_BUFFER, app->positionBufferTwo);
    glBufferData(GL_ARRAY_BUFFER, NUM_VERTICES*sizeof(MLvec4), NULL, GL_STATIC_DRAW);

    MLvec4* positions = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);
    for (int i = 0; i < NUM_VERTICES; ++i) {
        positions[i] = mlMakeVec4(0, 0, 0, 0);
    }

    glUnmapBuffer(GL_ARRAY_BUFFER);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

// initialize normal buffer
{
    glGenBuffers(1, &app->normalBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, app->normalBuffer);
    glBufferData(GL_ARRAY_BUFFER, NUM_VERTICES*sizeof(MLvec4), NULL, GL_STATIC_DRAW);

    MLvec4* normals = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);
    for (int i = 0; i < NUM_VERTICES; ++i) {
        normals[i] = mlMakeVec4(0, 0, 1, 0);
    }

    glUnmapBuffer(GL_ARRAY_BUFFER);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

// Attach buffers to program
{
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, app->positionBufferOne);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, app->positionBufferTwo);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, app->normalBuffer);
}

utils_createProgramVertexFragment(&g_renderWaterProgram, "content/shaders/renderwater/renderwater.vert", "content/shaders/renderwater/renderwater.frag");

// initialize VAO
{
    glGenVertexArrays(1, &g_waterVertexArrayObject);
    utils_setAttributePointer(g_waterVertexArrayObject, app->positionBufferOne, 0, 4, GL_FLOAT, GL_FALSE, 0, 0);
    utils_setAttributePointer(g_waterVertexArrayObject, app->positionBufferTwo, 1, 4, GL_FLOAT, GL_FALSE, 0, 0);    
    utils_setAttributePointer(g_waterVertexArrayObject, app->normalBuffer, 2, 4, GL_FLOAT, GL_FALSE, 0, 0);
}

// initialize index array
{
    ...
    glBindVertexArray(g_waterVertexArrayObject);
    glGenBuffers(1, &g_elementArrayBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_elementArrayBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * NUM_INDICES, g_waterIndices, GL_STATIC_DRAW);
}

void rendering_render(Application* app, int framebufferWidth, int framebufferHeight) {    
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glViewport(0, 0, framebufferWidth, framebufferHeight);

    MLvec3 center = mlMakeVec3(app->camera.cx, app->camera.cy, app->camera.cz);
    MLvec3 eye = positionOfCamera(app->camera);

    MLmat4 modelMatrix = mlIdentity4;
    MLmat4 projectionMatrix = mlMakePerspectiveFromFOV(100, (float)framebufferWidth / framebufferHeight, 0.01, 100.0);
    MLmat4 viewMatrix = mlMakeLookAt(eye, center, mlMakeVec3(0, 1, 0));

    // Hier muss gewartet werden, bis der Compute Shader alle Schreiboperationen auf die Shader Storage Buffer ausgeführt hat.
    //glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
    glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);

    glUseProgram(g_renderWaterProgram);

    utils_setUniformMat4(renderWaterProgram_ProjectionMatrix, &projectionMatrix);
    utils_setUniformMat4(renderWaterProgram_ViewMatrix, &viewMatrix);
    utils_setUniformMat4(renderWaterProgram_ModelMatrix, &modelMatrix);

    if (app->debug) {
        glDrawElements(GL_POINTS, NUM_INDICES, GL_UNSIGNED_INT, NULL);
    }
    else {
        glDrawElements(GL_TRIANGLES, NUM_INDICES, GL_UNSIGNED_INT, NULL);
    }    

    glUseProgram(0);
}

计算着色器:

layout (local_size_x = 1000, local_size_y = 1, local_size_z = 1) in;

layout (location = 0) uniform float Dt; 

layout (std430, binding = 0) buffer PositionBufferOne {
vec4 positions[];
};

layout (std430, binding = 1) buffer PositionBufferTwo {
vec4 positionsNew[];
};

layout (std430, binding = 2) buffer NormalBuffer {
vec4 normals[];
};

vec3 calcNormal() {
return normalize(vec3(1, 1, 1));
}

void main() {
uint index = gl_GlobalInvocationID.x;
normals[index] = vec4(calcNormal(), 0.0);
}

实用程序:

GLuint utils_createShader(GLenum shaderType, const char* filename) {
    GLuint shader = glCreateShader(shaderType);

    const char* sources[2];
    sources[0] = common_readfile("content/shaders/utils.glsl");
    sources[1] = common_readfile(filename);

    glShaderSource(shader, 2, sources, NULL);
    free((void*)sources[0]);
    free((void*)sources[1]);

    glCompileShader(shader);
    utils_checkShaderLog(filename, shader);

    return shader;
}

void utils_createComputeProgram(GLuint *program, const char* computeShaderFilename) {
    glDeleteProgram(*program);

    GLuint computeShader = utils_createShader(GL_COMPUTE_SHADER, computeShaderFilename);

    *program = glCreateProgram();
    glAttachShader(*program, computeShader);

    glLinkProgram(*program);
    utils_checkProgramLog(*program);

    glDeleteShader(computeShader);
}

void utils_setAttributePointer(GLuint vertexArrayObject, GLuint buffer, GLint location, GLint size, GLenum type, GLboolean normalized, GLsizei stride, unsigned offset) {
    GLint previousVertexArrayObject;
    glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &previousVertexArrayObject);
    GLint previousArrayBuffer;
    glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &previousArrayBuffer);

    glBindVertexArray(vertexArrayObject);
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    glEnableVertexAttribArray(location);
    glVertexAttribPointer(location, size, type, normalized, stride, (void*)(intptr_t)offset);

    glBindBuffer(GL_ARRAY_BUFFER, previousArrayBuffer);
    glBindVertexArray(previousVertexArrayObject);
}

void utils_setUniformMat4(GLuint location, MLmat4* m) {
    glUniformMatrix4fv(location, 1, GL_FALSE, (GLfloat*)m);
}

我使用法线作为片段的颜色来测试更改。

在此示例中,我在初始化期间将法线设置为0/0/0,并且在计算着色器中,我将每个法线的值更改为归一化的1/1/1,因此可以这样看,所以请看一下呈灰色的几何图形,但它保持黑色。

//编辑

从头开始并基本上在我添加的每一行代码之后测试结果之后,我发现问题出在这一行:glDispatchCompute(NUM_VERTICES / NUM_PARTICLES_PER_LOCAL_WORK_GROUP,1,1);我猜这算为零,这是有意义的,因为“顶点”数量“少”,每个工作组的粒子数量相对较多。

这导致我在计算着色器中所做的任何操作都从未真正执行过,因此没有更改缓冲区内容。

0 个答案:

没有答案